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(-) diff --git a/dasdfmt/dasdfmt.8 b/dasdfmt/dasdfmt.8 index e7fc501..07c674b 100644 --- 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 @@ -96,7 +96,7 @@ Do not use this option if you are using a 3270 console, 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. @@ -153,6 +153,18 @@ Specify blocksize to be used. \fIblksize\fR must be a positive integer 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 diff --git a/dasdfmt/dasdfmt.c b/dasdfmt/dasdfmt.c index 607fd1c..6dd28fa 100644 --- a/dasdfmt/dasdfmt.c +++ b/dasdfmt/dasdfmt.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "lib/dasd_sys.h" #include "lib/util_opt.h" @@ -68,6 +69,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' }, @@ -120,7 +126,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"), @@ -254,7 +260,7 @@ static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders, if (info->print_hashmarks && (cyl / info->hashstep - hashcount) != 0) { - printf("#"); + printf("%d|", info->procnum); fflush(stdout); hashcount++; } @@ -1533,7 +1539,8 @@ int main(int argc, char *argv[]) char *reqsize_param_str = NULL; char *hashstep_str = NULL; - int rc, numdev = 0, i; + int max_parallel = 1, running = 0; + int rc, numdev = 0, i, status; /* Establish a handler for interrupt signals. */ signal(SIGTERM, program_interrupt_signal); @@ -1600,7 +1607,7 @@ int main(int argc, char *argv[]) info.print_hashmarks = 1; } break; - case 'P': + case 'Q': if (!(info.print_hashmarks || info.print_progressbar)) info.print_percentage = 1; break; @@ -1658,6 +1665,9 @@ int main(int argc, char *argv[]) "more information.\n", prog_name, optarg); break; + case 'P': + max_parallel = atoi(optarg); + break; case OPT_CHECK: info.check = 1; break; @@ -1673,6 +1683,9 @@ break; /* exit loop if finished */ } + /* Reset the value of rc since we're going to use it again later. */ + rc = 0; + CHECK_SPEC_MAX_ONCE(info.blksize_specified, "blocksize"); CHECK_SPEC_MAX_ONCE(info.labelspec, "label"); CHECK_SPEC_MAX_ONCE(info.writenolabel, "omit-label-writing flag"); @@ -1707,7 +1717,33 @@ int main(int argc, char *argv[]) ERRMSG_EXIT(EXIT_MISUSE, "%s: No device specified!\n", prog_name); - for (i = 0; i < numdev; i++) - do_dasdfmt(dev_filename[i], &info, &vlabel); - return 0; + for (i = 0; i < numdev; i++) { + int chpid; + int tmp; + + chpid = fork(); + if (chpid == -1) + ERRMSG_EXIT(EXIT_FAILURE, + "%s: Unable to create child process: %s\n", + prog_name, strerror(errno)); + if (!chpid) { + info.procnum = i; + do_dasdfmt(dev_filename[i], &info, &vlabel); + 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(&status) > 0) + if (WEXITSTATUS(status)) + rc = WEXITSTATUS(status); + + return rc; } diff --git a/dasdfmt/dasdfmt.h b/dasdfmt/dasdfmt.h index a5581f1..fb6fc34 100644 --- a/dasdfmt/dasdfmt.h +++ b/dasdfmt/dasdfmt.h @@ -307,6 +307,7 @@ typedef struct dasdfmt_info { int force_host; int layout_specified; int check; + int procnum; } dasdfmt_info_t; -- 1.7.12.4