File s390tools-160-pardasdfmt.patch of Package s390-tools
--- s390-tools-1.8.0/dasdfmt/dasdfmt.8
+++ s390-tools-1.8.0/dasdfmt/dasdfmt.8
@@ -5,9 +5,9 @@
.SH SYNOPSIS
\fBdasdfmt\fR [-h] [-t] [-v] [-y] [-p] [-m \fIstep\fR]
.br
- [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
+ [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] [-P maxpar]
.br
- [-L] [-V] [-F] [-k] {-n \fIdevno\fR | -f \fInode\fR} \fIdevice\fR
+ [-L] [-V] [-F] [-k] [-n \fIdevno\fR | -f \fInode\fR]... \fIdevice\fR
.SH DESCRIPTION
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
@@ -71,6 +71,11 @@
operating systems to access this device (e.g. for backup purposes).
.TP
+\fB-P\fR \fImaxpar\fR or \fB--max_parallel\fR=\fImaxpar\fR
+Specifies the maximum number of disks to format in parallel.
+Default is 1.
+
+.TP
\fB-p\fR or \fB--progressbar\fR
Print a progress bar while formatting.
Do not use this option if you are using a 3270 console,
@@ -89,6 +94,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.
+.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.8.0/dasdfmt/dasdfmt.c
+++ s390-tools-1.8.0/dasdfmt/dasdfmt.c
@@ -15,6 +15,7 @@
#include "zt_common.h"
#include "dasdfmt.h"
#include "vtoc.h"
+#include <sys/wait.h>
/* Full tool name */
static const char tool_name[] = "dasdfmt: zSeries DASD format program";
@@ -113,32 +114,35 @@
/*
* check given device name for blanks and some special characters
- * or create a devfs filename in case the devno was specified
+ * or create a device filename in case the devno was specified
*/
-static void get_device_name(dasdfmt_info_t *info, char *name, int argc, char * argv[])
+static char* getdev(char* sysfs_path)
{
- if (((info->node_specified + info->devno_specified) > 1) ||
- ((info->node_specified + info->devno_specified) > 0 &&
- info->device_id < argc))
- ERRMSG_EXIT(EXIT_MISUSE,"%s: Device can only specified once! "
- "(%#04x or %s)\n", prog_name, info->devno, name);
-
- if ((info->node_specified + info->devno_specified) == 0 &&
- info->device_id >= argc)
- ERRMSG_EXIT(EXIT_MISUSE,"%s: No device specified!\n",
- prog_name);
+ DIR* d;
+ struct dirent* de;
+
+ d = opendir(sysfs_path);
+ if(!d) ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not open directory %s.",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->devno_specified) &&
- ((info->devno < 0x0000) || (info->devno > 0xffff)))
- ERRMSG_EXIT(EXIT_MISUSE,"%s: Devno '%#04x' is not in range "
- "0x0000 - 0xFFFF!\n", prog_name, info->devno);
-
- if (info->devno_specified)
- sprintf(info->devname, "/dev/dasd/%04x/device", info->devno);
- else if (info->device_id < argc) {
- strcpy(info->devname, argv[info->device_id]);
- }
- else {
+static void get_device_name(dasdfmt_info_t *info, char *name, int argc, char * argv[])
+{
+ DIR* d;
+ struct dirent* de;
+ char buf[PATH_MAX];
+ char devno[9];
+ char* device;
+ int i;
+
if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)||
(strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)||
(strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)||
@@ -149,9 +153,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",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",prog_name,name);
+ }
+ else
+ strncpy(info->devname, name, PATH_MAX - 1);
+
info->devname[PATH_MAX - 1] = '\0';
- }
}
@@ -175,7 +208,6 @@
info->cdl_format = 0;
info->blksize_specified = 0;
info->node_specified = 0;
- info->devno_specified = 0;
info->device_id = 0;
info->keep_volser = 0;
}
@@ -217,16 +249,9 @@
info->usage_count = dasd_info.open_count;
info->devno = dasd_info.devno;
if (strncmp(dasd_info.type, "ECKD",4) != 0) {
- if (info->devno_specified) {
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: Unsupported disk type\n%x is not an "
- "ECKD disk!\n", prog_name, info->devno);
- }
- else {
ERRMSG_EXIT(EXIT_FAILURE,
"%s: Unsupported disk type\n%s is not an "
"ECKD disk!\n", prog_name, info->devname);
- }
}
}
@@ -344,10 +369,7 @@
(drive_geo->cylinders * drive_geo->heads));
printf("\nI am going to format the device ");
- if (info->devno_specified)
- printf("%x in the following way:\n", info->devno);
- else
- printf("%s in the following way:\n", info->devname);
+ printf("%s in the following way:\n", info->devname);
printf(" Device number of device : 0x%x\n",info->devno);
printf(" Labelling device : %s\n",
@@ -559,7 +581,7 @@
info->hashstep = 10;
}
- printf("Printing hashmark every %d cylinders.\n",
+ if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
info->hashstep);
}
@@ -568,7 +590,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) {
@@ -606,7 +628,7 @@
if (info->print_hashmarks)
if (cyl % info->hashstep == 0) {
- printf("#");
+ printf("%d|",info->procnum);
fflush(stdout);
}
@@ -621,7 +643,7 @@
break;
}
- if (info->print_progressbar || info->print_hashmarks)
+ if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
printf("\n\n");
}
@@ -745,18 +767,18 @@
dasdfmt_prepare_and_format(info, &drive_geo, 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);
- printf("Rereading the partition table... ");
+ if(!info->yast_mode) printf("Rereading the partition table... ");
if (ioctl(filedes, BLKRRPART, NULL) != 0) {
ERRMSG("%s: error during rereading the partition "
"table: %s.\n", prog_name, strerror(errno));
}
else
- printf("ok\n");
+ if(!info->yast_mode) printf("ok\n");
}
}
@@ -767,7 +789,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];
@@ -775,7 +798,10 @@
char *blksize_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);
@@ -887,14 +913,19 @@
break;
case 'n' :
- devno_param_str=optarg;
- info.devno_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;
@@ -914,53 +945,127 @@
CHECK_SPEC_MAX_ONCE(info.labelspec, "label");
CHECK_SPEC_MAX_ONCE(info.writenolabel, "omit-label-writing flag");
- if (info.devno_specified)
- PARSE_PARAM_INTO(info.devno, devno_param_str, 16,
- "device number");
- if (info.blksize_specified)
- PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
- "blocksize");
- 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);
+ prog_name);
}
- if(format_params.intensity == 0x00) {
- 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) {
+ struct hd_geometry drive_geo;
+ for(i=0;i<dev_count;i++) {
+ get_device_name(&info, dev_filename[i],argc,argv);
+ if ((filedes = open(info.devname, O_RDWR)) == -1) {
+ ERRMSG("%s: Unable to open device %s: %s\n",
+ prog_name, info.devname, strerror(errno));
+ free(dev_filename[i]);
+ dev_filename[i]=(char*)-1; /* ignore device */
+ continue;
+ }
+ if (ioctl(filedes, HDIO_GETGEO, &drive_geo) != 0) {
+ ERRMSG("%s: the ioctl call to get geometry "
+ "returned with the following error message:\n%s\n",
+ prog_name, strerror(errno));
+ free(dev_filename[i]);
+ dev_filename[i]=(char*)-1; /* ignore device */
+ close(filedes);
+ continue;
+ }
+ printf("%d\n",drive_geo.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);
}
+
+ /* fork one formatting process for each device */
+ rc = 0;
+ for(i=0;i<dev_count;i++) {
+ int chpid; /* child process ID */
+ int tmp;
+
+ if(dev_filename[i]==(char*)-1) continue; /* ignore device */
- 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));
+ 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;
+ if (info.blksize_specified)
+ PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
+ "blocksize");
+ if (info.print_hashmarks)
+ PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep");
+
+ get_device_name(&info, dev_filename[i],argc,argv);
+
+ 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);
+ }
- check_disk(&info);
+ 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);
- if (check_param(str, &format_params) < 0)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
+ }
- do_format_dasd(&info, &format_params, &vlabel);
+ 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));
- if (close(filedes) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
- prog_name, strerror(errno));
+ check_disk(&info);
- return 0;
+ if (check_param(str, &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;
}
--- s390-tools-1.8.0/dasdfmt/dasdfmt.h
+++ s390-tools-1.8.0/dasdfmt/dasdfmt.h
@@ -130,6 +130,7 @@
#define LABEL_LENGTH 14
#define VLABEL_CHARS 84
#define LINE_LENGTH 80
+#define MAX_DEVICES 1024
#define ERR_LENGTH 80
#define DEFAULT_BLOCKSIZE 4096
@@ -147,7 +148,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:hpLtyvVFk"
+#define dasdfmt_getopt_string "b:n:l:f:d:m:hpLtyvVFkYP:"
static struct option dasdfmt_getopt_long_options[]=
{
@@ -163,6 +164,8 @@
{ "device", 1, 0, 'f'},
{ "blocksize", 1, 0, 'b'},
{ "help", 0, 0, 'h'},
+ { "max_parallel",1, 0, 'P'},
+ { "yast_mode", 0, 0, 'Y'},
{ "keep_volser", 0, 0, 'k'},
{0, 0, 0, 0}
};
@@ -198,9 +201,10 @@
int cdl_format;
int blksize_specified;
int node_specified;
- int devno_specified;
int device_id;
int keep_volser;
+ int yast_mode;
+ int procnum;
} dasdfmt_info_t;