From a61154fd93122f5a0f2b74f21c3ac29eb437f150 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 6 Oct 2017 09:39:36 +0200 Subject: [PATCH] dasdfmt: Format devices in parallel Allow dasdfmt to run in parallel when several devices are specified. Signed-off-by: Hannes Reinecke --- dasdfmt/dasdfmt.8 | 16 ++++++++++++++-- dasdfmt/dasdfmt.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- dasdfmt/dasdfmt.h | 1 + 3 files changed, 58 insertions(+), 9 deletions(-) Index: s390-tools-2.30.0/dasdfmt/dasdfmt.8 =================================================================== --- s390-tools-2.30.0.orig/dasdfmt/dasdfmt.8 +++ s390-tools-2.30.0/dasdfmt/dasdfmt.8 @@ -7,7 +7,7 @@ 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] [-P] [-m \fIstep\fR] .br [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] .br @@ -96,7 +96,7 @@ Do not use this option if you are using 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. @@ -164,6 +164,18 @@ Specify blocksize to be used. \fIblksize 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 processed, +independent on the overall number of disks to be formatted. +The maximum value for \fInumdisks\fR is 512. 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 Index: s390-tools-2.30.0/dasdfmt/dasdfmt.c =================================================================== --- s390-tools-2.30.0.orig/dasdfmt/dasdfmt.c +++ s390-tools-2.30.0/dasdfmt/dasdfmt.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "lib/dasd_base.h" #include "lib/dasd_sys.h" @@ -81,6 +82,7 @@ static struct dasdfmt_globals { int mode_specified; int ese; int no_discard; + int procnum; } g = { .dasd_info = { 0 }, }; @@ -105,6 +107,11 @@ static struct util_opt opt_vec[] = { .desc = "Perform complete format check on device", .flags = UTIL_OPT_FLAG_NOSHORT, }, + { + .option = { "max_parallel", required_argument, NULL, 'P' }, + .desc = "Format devices in parallel", + .flags = UTIL_OPT_FLAG_NOLONG, + }, UTIL_OPT_SECTION("FORMAT OPTIONS"), { .option = { "blocksize", required_argument, NULL, 'b' }, @@ -162,7 +169,7 @@ static struct util_opt opt_vec[] = { .desc = "Show a progressbar", }, { - .option = { "percentage", no_argument, NULL, 'P' }, + .option = { "percentage", no_argument, NULL, 'Q' }, .desc = "Show progress in percent", }, UTIL_OPT_SECTION("MISC"), @@ -311,7 +318,7 @@ static void draw_progress(int cyl, unsig } if (g.print_hashmarks && (cyl / g.hashstep - hashcount) != 0) { - printf("#"); + printf("%d|", g.procnum); fflush(stdout); hashcount++; } @@ -1573,7 +1580,11 @@ int main(int argc, char *argv[]) char *reqsize_param_str = NULL; char *hashstep_str = NULL; - int rc, numdev = 0, i; + int rc, numdev = 0, numproc = 0, status; + int max_parallel =1 ; + int running = 0; + int chpid; + int tmp; /* Establish a handler for interrupt signals. */ signal(SIGTERM, program_interrupt_signal); @@ -1636,7 +1647,7 @@ int main(int argc, char *argv[]) g.print_hashmarks = 1; } break; - case 'P': + case 'Q': if (!(g.print_hashmarks || g.print_progressbar)) g.print_percentage = 1; break; @@ -1695,6 +1706,9 @@ int main(int argc, char *argv[]) case OPT_NODISCARD: g.no_discard = 1; break; + case 'P': + max_parallel = atoi(optarg); + break; case OPT_CHECK: g.check = 1; break; @@ -1746,15 +1760,35 @@ int main(int argc, char *argv[]) if (numdev > 1 && g.labelspec) error("Specifying a volser to be written doesn't make sense when formatting multiple DASD volumes."); - for (i = 0; i < numdev; i++) - { - strncpy(g.dev_path, g.dev_path_array[i], strlen(g.dev_path_array[i])+1); - strncpy(g.dev_node, g.dev_node_array[i], strlen(g.dev_node_array[i])+1); - process_dasd(&vlabel, format_params); + for (numproc = 0; numproc < numdev; numproc++) { + chpid = fork(); + if (chpid == -1 ) + ERRMSG_EXIT(EXIT_FAILURE, + "%s: Unable to create child process: %s\n", + prog_name, strerror(errno)); + if (!chpid) { + g.procnum = numproc; + strncpy(g.dev_path, g.dev_path_array[numproc], strlen(g.dev_path_array[numproc])+1); + strncpy(g.dev_node, g.dev_node_array[numproc], strlen(g.dev_node_array[numproc])+1); + process_dasd(&vlabel, format_params); + + free(g.dev_path); + free(g.dev_node); + exit(0); + } else { + running++; + if (running >= max_parallel) { + if (wait(&tmp) > 0 && WEXITSTATUS(tmp)) + rc = WEXITSTATUS(tmp); + running--; + } + } } - free(g.dev_path); - free(g.dev_node); + /* wait until all formatting children have finished */ + while(wait(&status) > 0) + if (WEXITSTATUS(status)) + rc = WEXITSTATUS(status); - return 0; + return rc; }