Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes From: Jan Höppner Summary: dasdfmt: Add new formatting modes Description: Introduce new formatting modes 'quick' and 'expand' to either format an earlier formatted DASD that could potentially be re-initialized very easily or format unformatted tracks at the end of a device that was previously extended. Also add the command line argument --check to provide a function that checks a DASD volume for correct formatting. Upstream-ID: - Problem-ID: LS1501 Upstream-Description: dasdfmt: Use enhanced DASD information Currently dasdfmt uses BIODASDINFO as the IOCTL command to retrieve information about a DASD and stores them in dasd_information_t. However, BIODASDINFO2 offers a few more useful information (which are then stored in dasd_information2_t). - Replace dasd_information_t with dasd_information2_t. - Make the corresponding variable part of dasdfmt_info_t, since it is used in several functions anyway and we can save a few parameters and IOCTL calls. - Change the initialization of dasdfmt_info_t. A separate function isn't necessary for that. - Put the BIODASDINFO2 IOCTL call in a separate function which is then called only once. Signed-off-by: Jan Höppner Signed-off-by: Stefan Haberland Signed-off-by: Jan Höppner --- dasdfmt/dasdfmt.c | 132 ++++++++++++++++++------------------------------------ dasdfmt/dasdfmt.h | 21 ++++++-- 2 files changed, 61 insertions(+), 92 deletions(-) --- a/dasdfmt/dasdfmt.c +++ b/dasdfmt/dasdfmt.c @@ -237,30 +237,18 @@ static void get_device_name(dasdfmt_info } /* - * initialize the dasdfmt info structure + * Retrieve DASD information */ -static void init_info(dasdfmt_info_t *info) +static void get_device_info(dasdfmt_info_t *info) { - info->devno = 0x0; - info->usage_count = 0; - info->testmode = 0; - info->verbosity = 0; - info->withoutprompt = 0; - info->print_progressbar = 0; - info->print_hashmarks = 0; - info->print_percentage = 0; - info->hashstep = 0; - info->force = 0; - info->writenolabel = 0; - info->labelspec = 0; - info->cdl_format = 0; - info->blksize_specified = 0; - info->reqsize_specified = 0; - info->node_specified = 0; - info->device_id = 0; - info->keep_volser = 0; - info->force_host = 0; - info->yast_mode = 0; + dasd_information2_t dasd_info; + + if (ioctl(filedes, BIODASDINFO2, &dasd_info)) + ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve " + "device information failed (%s).\n", + prog_name, strerror(errno)); + + info->dasd_info = dasd_info; } /* @@ -268,7 +256,6 @@ static void init_info(dasdfmt_info_t *in */ static void check_disk(dasdfmt_info_t *info) { - dasd_information_t dasd_info; int ro, errno_save, i = 0; if (ioctl(filedes, BLKROGET, &ro) != 0) { @@ -283,15 +270,6 @@ static void check_disk(dasdfmt_info_t *i ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n"); retry: - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) { - errno_save = errno; - close(filedes); - ERRMSG_EXIT(EXIT_FAILURE, - "%s: the ioctl call to retrieve device " - "information failed (%s)\n", - prog_name, strerror(errno_save)); - } - if (!info->force) /* * udev strikes again. @@ -302,7 +280,7 @@ retry: * And confusing the hell out ouf anyone else. * Bah. */ - if (dasd_info.open_count > 1) { + if (info->dasd_info.open_count > 1) { if (i < 5) { ++i; sleep(1); @@ -311,9 +289,7 @@ retry: ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n"); } - info->usage_count = dasd_info.open_count; - info->devno = dasd_info.devno; - if (strncmp(dasd_info.type, "ECKD", 4) != 0) { + if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) { ERRMSG_EXIT(EXIT_FAILURE, "%s: Unsupported disk type\n%s is not an " "ECKD disk!\n", prog_name, info->devname); @@ -442,7 +418,7 @@ static void dasdfmt_print_info(dasdfmt_i printf("\nI am going to format the device "); printf("%s in the following way:\n", info->devname); - printf(" Device number of device : 0x%x\n", info->devno); + printf(" Device number of device : 0x%x\n", info->dasd_info.devno); printf(" Labelling device : %s\n", (info->writenolabel) ? "no" : "yes"); @@ -465,21 +441,16 @@ static void dasdfmt_print_info(dasdfmt_i /* * get volser */ -static int dasdfmt_get_volser(char *devname, char *volser) +static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser) { - dasd_information_t dasd_info; int blksize; int f; volume_label_t vlabel; - f = open(devname, O_RDONLY); + f = open(info->devname, O_RDONLY); if (f == -1) ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, devname, strerror(errno)); - - if (ioctl(f, BIODASDINFO, &dasd_info) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD" - "INFO failed (%s).\n", prog_name, strerror(errno)); + prog_name, info->devname, strerror(errno)); if (ioctl(f, BLKSSZGET, &blksize) != 0) ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET " @@ -489,10 +460,12 @@ static int dasdfmt_get_volser(char *devn ERRMSG("%s: error during close: %s\ncontinuing...\n", prog_name, strerror(errno)); - if ((strncmp(dasd_info.type, "ECKD", 4) == 0) && - (!dasd_info.FBA_layout)) { + if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) && + (!info->dasd_info.FBA_layout)) { /* OS/390 and zOS compatible disk layout */ - vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel); + vtoc_read_volume_label(info->devname, + info->dasd_info.label_block * blksize, + &vlabel); vtoc_volume_label_get_volser(&vlabel, volser); return 0; } else { @@ -507,7 +480,6 @@ static void dasdfmt_write_labels(dasdfmt unsigned int cylinders, unsigned int heads) { int label_position; - dasd_information_t dasd_info; struct hd_geometry geo; format4_label_t f4; format5_label_t f5; @@ -520,11 +492,6 @@ static void dasdfmt_write_labels(dasdfmt if (info->verbosity > 0) printf("Retrieving dasd information... "); - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL " - "BIODASDINFO failed (%s).\n", - prog_name, strerror(errno)); - if (ioctl(filedes, BLKSSZGET, &blksize) != 0) ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET " "failed (%s).\n", prog_name, strerror(errno)); @@ -586,14 +553,14 @@ static void dasdfmt_write_labels(dasdfmt /* write VTOC */ vtoc_init_format4_label(&f4, geo.cylinders, cylinders, heads, - geo.sectors, blksize, dasd_info.dev_type); + geo.sectors, blksize, info->dasd_info.dev_type); vtoc_init_format5_label(&f5); vtoc_init_format7_label(&f7); vtoc_set_freespace(&f4, &f5, &f7, '+', 0, FIRST_USABLE_TRK, (cylinders * heads - 1), cylinders, heads); - label_position = dasd_info.label_block * blksize; + label_position = info->dasd_info.label_block * blksize; if (info->verbosity > 0) printf("Writing label...\n"); @@ -831,7 +798,6 @@ static void do_format_dasd(dasdfmt_info_ volume_label_t *vlabel) { char inp_buffer[5]; - dasd_information_t dasd_info; struct dasd_eckd_characteristics *characteristics; unsigned int cylinders, heads; int count; @@ -839,13 +805,9 @@ static void do_format_dasd(dasdfmt_info_ if (info->verbosity > 0) printf("Retrieving disk geometry...\n"); - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) " - "IOCTL BIODASDINFO failed (%s).\n", - prog_name, strerror(errno)); - characteristics = - (struct dasd_eckd_characteristics *) &dasd_info.characteristics; + (struct dasd_eckd_characteristics *) + &info->dasd_info.characteristics; if (characteristics->no_cyl == LV_COMPAT_CYL && characteristics->long_no_cyl) cylinders = characteristics->long_no_cyl; @@ -878,8 +840,8 @@ static void do_format_dasd(dasdfmt_info_ if (!info->labelspec && !info->keep_volser) { char buf[7]; - sprintf(buf, "0X%04x", info->devno); - check_volser(buf, info->devno); + sprintf(buf, "0X%04x", info->dasd_info.devno); + check_volser(buf, info->dasd_info.devno); vtoc_volume_label_set_volser(vlabel, buf); } @@ -959,7 +921,10 @@ static void do_format_dasd(dasdfmt_info_ int main(int argc, char *argv[]) { - dasdfmt_info_t info; + dasdfmt_info_t info = { + .dasd_info = {0}, + {0} + }; volume_label_t vlabel; char old_volser[7]; @@ -986,7 +951,6 @@ int main(int argc, char *argv[]) prog_name = argv[0]; /* set default values */ - init_info(&info); vtoc_volume_label_init(&vlabel); format_params.blksize = DEFAULT_BLOCKSIZE; @@ -1137,30 +1101,24 @@ int main(int argc, char *argv[]) if(info.yast_mode) { for(i=0;ino_cyl == LV_COMPAT_CYL && characteristics->long_no_cyl) cylinders = characteristics->long_no_cyl; @@ -1204,6 +1162,13 @@ int main(int argc, char *argv[]) get_device_name(&info, dev_filename[i]); + filedes = open(info.devname, O_RDWR); + if (filedes == -1) + ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", + prog_name, info.devname, strerror(errno)); + + get_device_info(&info); + if (!info.blksize_specified) format_params = ask_user_for_blksize(format_params); @@ -1214,7 +1179,7 @@ int main(int argc, char *argv[]) exit(1); } - if (dasdfmt_get_volser(info.devname, old_volser) == 0) + if (dasdfmt_get_volser(&info, old_volser) == 0) vtoc_volume_label_set_volser(&vlabel, old_volser); else ERRMSG_EXIT(EXIT_FAILURE, @@ -1223,11 +1188,6 @@ int main(int argc, char *argv[]) } - filedes = open(info.devname, O_RDWR); - if (filedes == -1) - ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, info.devname, strerror(errno)); - check_disk(&info); if (check_param(str, ERR_LENGTH, &format_params) < 0) --- a/dasdfmt/dasdfmt.h +++ b/dasdfmt/dasdfmt.h @@ -32,11 +32,11 @@ #define DASD_IOCTL_LETTER 'D' /* - * struct dasd_information_t + * struct dasd_information2_t * represents any data about the device, which is visible to userspace. * including format and features. */ -typedef struct dasd_information_t { +typedef struct dasd_information2_t { unsigned int devno; /* S/390 devno */ unsigned int real_devno; /* for aliases */ unsigned int schid; /* S/390 subchannel identifier */ @@ -56,7 +56,17 @@ typedef struct dasd_information_t { unsigned int confdata_size; char characteristics[64]; /* from read_device_characteristics */ char configuration_data[256]; /* from read_configuration_data */ -} dasd_information_t; + unsigned int format; /* format info like formatted/cdl/ldl/... */ + unsigned int features; /* dasd features like 'ro',... */ + unsigned int reserved0; /* reserved for further use ,... */ + unsigned int reserved1; /* reserved for further use ,... */ + unsigned int reserved2; /* reserved for further use ,... */ + unsigned int reserved3; /* reserved for further use ,... */ + unsigned int reserved4; /* reserved for further use ,... */ + unsigned int reserved5; /* reserved for further use ,... */ + unsigned int reserved6; /* reserved for further use ,... */ + unsigned int reserved7; /* reserved for further use ,... */ +} dasd_information2_t; struct dasd_eckd_characteristics { @@ -165,7 +175,7 @@ typedef struct format_data_t { #define BIODASDENABLE _IO(DASD_IOCTL_LETTER,1) /* Get information on a dasd device (enhanced) */ -#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t) +#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t) /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t) @@ -251,9 +261,8 @@ typedef struct bootstrap2 { } __attribute__ ((packed)) bootstrap2_t; typedef struct dasdfmt_info { - int devno; + dasd_information2_t dasd_info; char devname[PATH_MAX]; - int usage_count; int verbosity; int testmode; int withoutprompt;