Index: s390-tools-1.8.0/dasdfmt/dasdfmt.8
===================================================================
--- s390-tools-1.8.0.orig/dasdfmt/dasdfmt.8
+++ s390-tools-1.8.0/dasdfmt/dasdfmt.8
@@ -5,9 +5,9 @@ dasdfmt \- formatting of DASD (ECKD) dis
 .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
@@ -89,6 +89,20 @@ 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 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 
Index: s390-tools-1.8.0/dasdfmt/dasdfmt.c
===================================================================
--- s390-tools-1.8.0.orig/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 @@ static void program_interrupt_signal (in
 
 /*
  * 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 @@ static void get_device_name(dasdfmt_info
 				    "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,9 +208,9 @@ static void init_info(dasdfmt_info_t *in
         info->cdl_format        = 0;
 	info->blksize_specified = 0;
 	info->node_specified    = 0;
-	info->devno_specified   = 0;
 	info->device_id         = 0;
 	info->keep_volser	= 0;
+	info->yast_mode         = 0;
 }
 
 
@@ -217,16 +250,9 @@ static void check_disk(dasdfmt_info_t *i
 	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 +370,7 @@ static void dasdfmt_print_info(dasdfmt_i
 	       (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 +582,7 @@ static void dasdfmt_format(dasdfmt_info_
 			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 +591,7 @@ static void dasdfmt_format(dasdfmt_info_
 		
 	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 +629,7 @@ static void dasdfmt_format(dasdfmt_info_
 		
 		if (info->print_hashmarks)
 			if (cyl % info->hashstep == 0) {
-				printf("#");
+				printf("%d|",info->procnum);
 				fflush(stdout);
 			}
 
@@ -621,7 +644,7 @@ static void dasdfmt_format(dasdfmt_info_
 			break;
 	}
 
-	if (info->print_progressbar || info->print_hashmarks)
+	if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
 		printf("\n\n");	
 }
 
@@ -745,18 +768,18 @@ static void do_format_dasd(dasdfmt_info_
 		
 		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 +790,8 @@ int main(int argc,char *argv[]) 
 	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 +799,10 @@ int main(int argc,char *argv[]) 
 	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 +914,19 @@ int main(int argc,char *argv[]) 
 			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 +946,127 @@ int main(int argc,char *argv[]) 
 	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;
 }
Index: s390-tools-1.8.0/dasdfmt/dasdfmt.h
===================================================================
--- s390-tools-1.8.0.orig/dasdfmt/dasdfmt.h
+++ s390-tools-1.8.0/dasdfmt/dasdfmt.h
@@ -130,6 +130,7 @@ struct hd_geometry {
 #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 @@ struct hd_geometry {
 	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 @@ static struct option dasdfmt_getopt_long
         { "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 @@ typedef struct dasdfmt_info {
         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;
 
 
