--- s390-tools-1.34.0/dasdfmt/dasdfmt.8 2016-04-14 16:43:51.000000000 -0400 +++ s390-tools-1.34.0/dasdfmt/dasdfmt.8 2016-04-14 16:35:01.000000000 -0400 @@ -3,11 +3,11 @@ dasdfmt \- formatting of DASD (ECKD) disk drives. .SH SYNOPSIS -\fBdasdfmt\fR [-h] [-t] [-v] [-y] [-p] [-P] [-m \fIstep\fR] +\fBdasdfmt\fR [-h] [-t] [-v] [-y] [-p] [-Q] [-m \fIstep\fR] .br - [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] + [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] [-P maxpar] .br - [-L] [-V] [-F] [-k] [-C] \fIdevice\fR + [-L] [-V] [-F] [-k] [-C] \fIdevice\fR ... .SH DESCRIPTION \fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it @@ -91,7 +91,7 @@ running in background or redirecting the output to a file. .TP -\fB-P\fR or \fB--percentage\fR +\fB-Q\fR or \fB--percentage\fR Print one line for each formatted cylinder showing the number of the cylinder and percentage of formatting process. Intended to be used by higher level interfaces. @@ -123,6 +123,20 @@ and always be a power of two. The recommended blocksize is 4096 bytes. .TP +\fB-P\fR \fInumdisks\fR or \fB--max_parallel\fR=\fInumdisks\fR +Specify the number of disks to be formatted in +parallel. \FInumdisks\fR specifies the number of formatting processes +which is independent of the overall number of disks to be formatted as +specified on the commandline. The maximum value for \fInumdisks\fR is +1024. Default is 1. +.br +Using this option can +decrease overall processing time when formatting several disks. +Please note that the I/O throughput will dramatically increase when +using this option. Use with care. +.br + +.TP \fB-l\fR \fIvolser\fR or \fB--label\fR=\fIvolser\fR Specify the volume serial number or volume identifier to be written to disk after formatting. If no label is specified, a sensible default --- s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:43:51.000000000 -0400 +++ s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:35:01.000000000 -0400 @@ -195,6 +195,7 @@ #define LABEL_LENGTH 14 #define VLABEL_CHARS 84 #define LINE_LENGTH 80 +#define MAX_DEVICES 1024 #define ERR_LENGTH 90 #define DEFAULT_BLOCKSIZE 4096 @@ -214,7 +215,7 @@ if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ "is in invalid format\n",prog_name);} -#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC" +#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpQLtyvVFkCYP:" static struct option dasdfmt_getopt_long_options[]= { @@ -225,12 +226,14 @@ { "force", 0, 0, 'F'}, { "progressbar", 0, 0, 'p'}, { "hashmarks", 1, 0, 'm'}, - { "percentage", 0, 0, 'P'}, + { "percentage", 0, 0, 'Q'}, { "label", 1, 0, 'l'}, { "device", 1, 0, 'f'}, { "blocksize", 1, 0, 'b'}, { "requestsize", 1, 0, 'r'}, { "help", 0, 0, 'h'}, + { "max_parallel",1, 0, 'P'}, + { "yast_mode", 0, 0, 'Y'}, { "keep_volser", 0, 0, 'k'}, { "norecordzero", 0, 0, 'z'}, { "check_host_count", 0, 0, 'C'}, @@ -267,6 +270,8 @@ int device_id; int keep_volser; int force_host; + int yast_mode; + int procnum; } dasdfmt_info_t; --- s390-tools-1.34.0/dasdfmt/dasdfmt.c 2016-04-14 16:43:51.000000000 -0400 +++ s390-tools-1.34.0/dasdfmt/dasdfmt.c 2016-04-14 16:35:01.000000000 -0400 @@ -17,6 +17,7 @@ #include "vtoc.h" #include "util_proc.h" #include "dasd_sys.h" +#include #define BUSIDSIZE 8 @@ -48,7 +49,7 @@ */ static void exit_usage(int exitcode) { - printf("Usage: %s [-htvypPLVFkC]\n" + printf("Usage: %s [-htvypQLVFkC]\n" " [-l | --label=]\n" " [-b | --blocksize=]\n" " [-d | --disk_layout=]\n" @@ -59,7 +60,7 @@ " -V or --version means print version\n" " -L or --no_label means don't write disk label\n" " -p or --progressbar means show a progress bar\n" - " -P or --percentage means show a progress in percent\n" + " -Q or --percentage means show a progress in percent\n" " -m x or --hashmarks=x means show a hashmark every x " "cylinders\n" " -r x or --requestsize=x means use x cylinders in one " @@ -143,22 +144,33 @@ /* * check given device name for blanks and some special characters */ -static void get_device_name(dasdfmt_info_t *info, char *name, int argc, char * argv[]) +static char* getdev(char* sysfs_path) { - struct util_proc_dev_entry dev_entry; - struct stat dev_stat; - - if (info->node_specified && (info->device_id < argc)) - ERRMSG_EXIT(EXIT_MISUSE,"%s: Device can only specified once!\n", - prog_name); + DIR* d; + struct dirent* de; + + d = opendir(sysfs_path); + if(!d) ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not open directory %s.\n",prog_name,sysfs_path); + while((de = readdir(d))) + { + if(strncmp(de->d_name,"block:",6) == 0) + { + closedir(d); + return de->d_name+6; + } + } + return 0; +} - if (!info->node_specified && (info->device_id >= argc)) - ERRMSG_EXIT(EXIT_MISUSE,"%s: No device specified!\n", - prog_name); +static void get_device_name(dasdfmt_info_t *info, char *name) +{ + struct util_proc_dev_entry dev_entry; + struct stat dev_stat; + char buf[PATH_MAX]; + char devno[9]; + char* device; + int i; - if (info->device_id < argc) { - strcpy(info->devname, argv[info->device_id]); - } else { if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)|| (strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)|| (strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)|| @@ -169,9 +181,38 @@ "blanks or special characters!\n", prog_name); - strncpy(info->devname, name, PATH_MAX - 1); + if (isxdigit(name[0]) && name[1] == '.' && isxdigit(name[2]) && name[3] == '.' && strlen(name) == 8) + { /* x.x.xxxx format */ + for(i=0; i<8; i++) + devno[i] = tolower(name[i]); + devno[8] = 0; + sprintf(buf,"/sys/bus/ccw/devices/%s",devno); + device = getdev(buf); + if(device) + { + strcpy(info->devname,"/dev/"); + strcat(info->devname,device); + } + else ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not find device file for device no. %s\n",prog_name,name); + } + else if (isxdigit(name[0]) && isxdigit(name[1]) && isxdigit(name[2]) && isxdigit(name[3])) + { /* xxxx format */ + for(i=0; i<4; i++) + devno[i] = tolower(name[i]); + devno[4] = 0; + sprintf(buf,"/sys/bus/ccw/devices/0.0.%s",devno); + device = getdev(buf); + if(device) + { + strcpy(info->devname,"/dev/"); + strcat(info->devname,device); + } + else ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not find device file for device no. %s\n",prog_name,name); + } + else + strncpy(info->devname, name, PATH_MAX - 1); + info->devname[PATH_MAX - 1] = '\0'; - } if (stat(info->devname, &dev_stat) != 0) ERRMSG_EXIT(EXIT_MISUSE, @@ -217,8 +258,9 @@ info->reqsize_specified = 0; info->node_specified = 0; info->device_id = 0; - info->keep_volser = 0; + info->keep_volser = 0; info->force_host = 0; + info->yast_mode = 0; } @@ -271,7 +313,6 @@ } - /* * check the volume serial for special * characters and move blanks to the end @@ -640,7 +681,7 @@ info->hashstep = 10; } - printf("Printing hashmark every %d cylinders.\n", + if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n", info->hashstep); } @@ -649,7 +690,7 @@ k = 0; cyl = 1; - if (info->print_progressbar || info->print_hashmarks) + if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) printf("\n"); while (1) { @@ -688,7 +729,7 @@ if (info->print_hashmarks) if ((cyl / info->hashstep - hashcount) != 0) { - printf("#"); + printf("%d|",info->procnum); fflush(stdout); hashcount++; } @@ -709,7 +750,7 @@ break; } - if (info->print_progressbar || info->print_hashmarks) + if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) printf("\n\n"); } @@ -884,17 +925,21 @@ dasdfmt_prepare_and_format(info, cylinders, heads, p); - printf("Finished formatting the device.\n"); + if (!info->yast_mode) + printf("Finished formatting the device.\n"); if (!info->writenolabel) dasdfmt_write_labels(info, vlabel, cylinders, heads); - printf("Rereading the partition table... "); + if (!info->yast_mode) + printf("Rereading the partition table... "); if (reread_partition_table()) { ERRMSG("%s: error during rereading the partition " "table: %s.\n", prog_name, strerror(errno)); - } else - printf("ok\n"); + } else { + if (!info->yast_mode) + printf("ok\n"); + } } } @@ -905,7 +950,8 @@ volume_label_t vlabel; char old_volser[7]; - char dev_filename[PATH_MAX]; + char* dev_filename[MAX_DEVICES]; + int dev_count=0; char str[ERR_LENGTH]; char buf[7]; @@ -913,7 +959,10 @@ char *reqsize_param_str = NULL; char *hashstep_str = NULL; - int rc, index; + int rc, index, i; + + int max_parallel=1; + int running=0; /* Establish a handler for interrupt signals. */ signal (SIGTERM, program_interrupt_signal); @@ -990,7 +1039,7 @@ } break; - case 'P': + case 'Q': if (!(info.print_hashmarks || info.print_progressbar)) info.print_percentage = 1; break; @@ -1034,9 +1083,18 @@ info.reqsize_specified = 1; break; case 'f' : - strncpy(dev_filename, optarg, PATH_MAX); + if(dev_count>=MAX_DEVICES) + ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n", + prog_name); + dev_filename[dev_count++]=strdup(optarg); info.node_specified=1; break; + case 'Y' : /* YaST mode */ + info.yast_mode=1; + break; + case 'P' : /* max parallel formatting processes */ + max_parallel=atoi(optarg); + break; case 'k' : info.keep_volser=1; break; @@ -1059,58 +1117,147 @@ CHECK_SPEC_MAX_ONCE(info.labelspec, "label"); CHECK_SPEC_MAX_ONCE(info.writenolabel, "omit-label-writing flag"); - if (info.blksize_specified) - PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10, - "blocksize"); - if (info.reqsize_specified) { - PARSE_PARAM_INTO(reqsize, reqsize_param_str, 10, "requestsize"); - if (reqsize < 1 || reqsize > 255) - ERRMSG_EXIT(EXIT_FAILURE, - "invalid requestsize %d specified\n", - reqsize); - } else - reqsize = DEFAULT_REQUESTSIZE; - if (info.print_hashmarks) - PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep"); - - get_device_name(&info, dev_filename, argc, argv); + while(info.device_id < argc) { /* devices specified at the end of cmdline */ + if(dev_count>=MAX_DEVICES) + ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n", + prog_name); + dev_filename[dev_count++]=strdup(argv[info.device_id]); + info.node_specified=1; + info.device_id++; + } - if (!info.blksize_specified) - format_params = ask_user_for_blksize(format_params); + if (info.node_specified == 0) + ERRMSG_EXIT(EXIT_MISUSE,"%s: No device specified!\n", + prog_name); if (info.keep_volser) { if(info.labelspec) { ERRMSG_EXIT(EXIT_MISUSE,"%s: The -k and -l options are mutually exclusive\n", prog_name); } - if(!(format_params.intensity & DASD_FMT_INT_COMPAT)) { - printf("WARNING: VOLSER cannot be kept " \ - "when using the ldl format!\n"); - exit(1); + } + + if (info.labelspec && max_parallel > 1) { + ERRMSG_EXIT(EXIT_MISUSE,"%s: The -l option cannot be used with parallel formatting\n", + prog_name); + } + + if(info.yast_mode) { + for(i=0;ino_cyl == LV_COMPAT_CYL && + characteristics->long_no_cyl) + cylinders = characteristics->long_no_cyl; + else + cylinders = characteristics->no_cyl; + + printf("%d\n", cylinders); + close(filedes); } - - if(dasdfmt_get_volser(info.devname, old_volser) == 0) - vtoc_volume_label_set_volser(&vlabel, old_volser); - else - ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n", - prog_name, info.devname); - + fflush(stdout); } - if ((filedes = open(info.devname, O_RDWR)) == -1) - ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n", - prog_name, info.devname, strerror(errno)); + /* fork one formatting process for each device */ + rc = 0; + for(i=0;i 255) + ERRMSG_EXIT(EXIT_FAILURE, + "invalid requestsize %d specified\n", + reqsize); + } else + reqsize = DEFAULT_REQUESTSIZE; + if (info.print_hashmarks) + PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep"); + + get_device_name(&info, dev_filename[i]); + + if (!info.blksize_specified) + format_params = ask_user_for_blksize(format_params); + + if (info.keep_volser) { + if(format_params.intensity == 0x00) { + printf("WARNING: VOLSER cannot be kept " \ + "when using the ldl format!\n"); + exit(1); + } - if (close(filedes) != 0) - ERRMSG("%s: error during close: %s\ncontinuing...\n", - prog_name, strerror(errno)); + if(dasdfmt_get_volser(info.devname, old_volser) == 0) + vtoc_volume_label_set_volser(&vlabel, old_volser); + else + ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n", + prog_name, info.devname); - return 0; + } + + if ((filedes = open(info.devname, O_RDWR)) == -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) + ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str); + + do_format_dasd(&info, &format_params, &vlabel); + + if (close(filedes) != 0) + ERRMSG("%s: error during close: %s\ncontinuing...\n", + prog_name, strerror(errno)); + + exit(0); + } else { + running++; + if(running>=max_parallel) { + if(wait(&tmp) > 0 && WEXITSTATUS(tmp)) + rc = WEXITSTATUS(tmp); + running--; + } + } + } + + /* wait until all formatting children have finished */ + while(wait(&i) > 0) + if (WEXITSTATUS(i)) rc = WEXITSTATUS(i); + + return rc; }