Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3110

kernel-2.6.18-194.11.1.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Fri, 27 Feb 2009 16:27:49 +0100
Subject: [s390] dasd: DASDFMT not operating like CPFMTXA
Message-id: 20090227152749.GA23486@redhat.com
O-Subject: [RHEL5 U4 PATCH 1/1] s390 - dasd: DASDFMT not operating like CPFMTXA
Bugzilla: 484836
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Description
============

Running zLinux RHEL5u2 64 bits s390x 64 bits s390x as guest
under zVM5.3/zVM5.4 running CKD DASD devices and  attached
to EMC DMX array we encountered some performing differ
between the DASDFMT vs. CPFMTXA not operating the same.

Permission is now granted to the subsystem to format write R0 with:
* an ID = CCHHR, where CC = physical cylinder number, HH = physical head
number, and R = 0
* a key length of zero
* a data length of eight
* a data field containing all zeros

Attached is the kernel side patch for RHEL 5.4. It grants per default
subsystems the permission to write the record 0. A second patch will be
part of the s390-tools/dasdfmt and will consist of an option to disable the
feature.

Bugzilla
=========

BZ 484836
https://bugzilla.redhat.com/show_bug.cgi?id=484836

Upstream status of the patch:
=============================
The patch has been posted upstream for review:
http://patchwork.kernel.org/patch/8753/
It will be included in 2.6.30 once the merge window is open.

Test status:
============

The patch has been tested and fixes the problem.
The kernel patch was tested on a RHEL 5.2 guest
running under z/VM 5.3.0 with APAR VM64603 applied

The fix has been verified by EMC and IBM.

Please ACK.

With best regards,

	--Hans

diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ddbba8a..d0ef493 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1031,6 +1031,8 @@ dasd_eckd_format_device(struct dasd_device * device,
 	int rpt, cyl, head;
 	int cplength, datasize;
 	int i;
+	int intensity = 0;
+	int r0_perm;
 
 	private = (struct dasd_eckd_private *) device->private;
 	rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
@@ -1062,9 +1064,18 @@ dasd_eckd_format_device(struct dasd_device * device,
 	 *   Bit 1: write home address, currently not supported
 	 *   Bit 2: invalidate tracks
 	 *   Bit 3: use OS/390 compatible disk layout (cdl)
+	 *   Bit 4: do not allow storage subsystem to modify record zero
 	 * Only some bit combinations do make sense.
 	 */
-	switch (fdata->intensity) {
+	if (fdata->intensity & 0x10) {
+		r0_perm = 0;
+		intensity = fdata->intensity & ~0x10;
+	} else {
+		r0_perm = 1;
+		intensity = fdata->intensity;
+	}
+
+	switch (intensity) {
 	case 0x00:	/* Normal format */
 	case 0x08:	/* Normal format, use cdl. */
 		cplength = 2 + rpt;
@@ -1089,7 +1100,7 @@ dasd_eckd_format_device(struct dasd_device * device,
 		break;
 	default:
 		DEV_MESSAGE(KERN_WARNING, device, "Invalid flags 0x%x.",
-			    fdata->intensity);
+			    intensity);
 		return ERR_PTR(-EINVAL);
 	}
 	/* Allocate the format ccw request. */
@@ -1101,11 +1112,14 @@ dasd_eckd_format_device(struct dasd_device * device,
 	data = fcp->data;
 	ccw = fcp->cpaddr;
 
-	switch (fdata->intensity & ~0x08) {
+	switch (intensity & ~0x08) {
 	case 0x00: /* Normal format. */
 		define_extent(ccw++, (struct DE_eckd_data *) data,
 			      fdata->start_unit, fdata->start_unit,
 			      DASD_ECKD_CCW_WRITE_CKD, device);
+		/* grant subsystem permission to format R0 */
+		if (r0_perm)
+			((struct DE_eckd_data *)data)->ga_extended |= 0x04;
 		data += sizeof(struct DE_eckd_data);
 		ccw[-1].flags |= CCW_FLAG_CC;
 		locate_record(ccw++, (struct LO_eckd_data *) data,
@@ -1139,7 +1153,7 @@ dasd_eckd_format_device(struct dasd_device * device,
 		data += sizeof(struct LO_eckd_data);
 		break;
 	}
-	if (fdata->intensity & 0x01) {	/* write record zero */
+	if (intensity & 0x01) {	/* write record zero */
 		ect = (struct eckd_count *) data;
 		data += sizeof(struct eckd_count);
 		ect->cyl = cyl;
@@ -1154,7 +1168,7 @@ dasd_eckd_format_device(struct dasd_device * device,
 		ccw->cda = (__u32)(addr_t) ect;
 		ccw++;
 	}
-	if ((fdata->intensity & ~0x08) & 0x04) {	/* erase track */
+	if ((intensity & ~0x08) & 0x04) {	/* erase track */
 		ect = (struct eckd_count *) data;
 		data += sizeof(struct eckd_count);
 		ect->cyl = cyl;
@@ -1177,14 +1191,14 @@ dasd_eckd_format_device(struct dasd_device * device,
 			ect->kl = 0;
 			ect->dl = fdata->blksize;
 			/* Check for special tracks 0-1 when formatting CDL */
-			if ((fdata->intensity & 0x08) &&
+			if ((intensity & 0x08) &&
 			    fdata->start_unit == 0) {
 				if (i < 3) {
 					ect->kl = 4;
 					ect->dl = sizes_trk0[i] - 4;
 				}
 			}
-			if ((fdata->intensity & 0x08) &&
+			if ((intensity & 0x08) &&
 			    fdata->start_unit == 1) {
 				ect->kl = 44;
 				ect->dl = LABEL_SIZE - 44;