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 | 58 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 60 insertions(+), 14 deletions(-) --- a/dasdfmt/dasdfmt.8 +++ b/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 @@ -95,7 +95,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. @@ -164,6 +164,18 @@ .TP \fB\-l\fR \fIvolser\fR or \fB\-\-label\fR=\fIvolser\fR +\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 Specify the volume serial number or volume identifier to be written to disk after formatting. If no label is specified, a sensible default is used. \fIvolser\fR is interpreted as ASCII string and is automatically --- a/dasdfmt/dasdfmt.c +++ b/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 @@ int mode_specified; int ese; int no_discard; + int procnum; } g = { .dasd_info = { 0 }, }; @@ -105,6 +107,11 @@ .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 @@ .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 @@ } if (g.print_hashmarks && (cyl / g.hashstep - hashcount) != 0) { - printf("#"); + printf("%d|", g.procnum); fflush(stdout); hashcount++; } @@ -1560,7 +1567,11 @@ 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); @@ -1623,7 +1634,7 @@ g.print_hashmarks = 1; } break; - case 'P': + case 'Q': if (!(g.print_hashmarks || g.print_progressbar)) g.print_percentage = 1; break; @@ -1682,6 +1693,9 @@ case OPT_NODISCARD: g.no_discard = 1; break; + case 'P': + max_parallel = atoi(optarg); + break; case OPT_CHECK: g.check = 1; break; @@ -1733,15 +1747,35 @@ 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; }