Blame SOURCES/parted-3.1-libparted-add-support-for-implicit-FBA-DASD-partitions.patch

8dc857
Subject: [PATCH] libparted: add support for implicit FBA DASD partitions
8dc857
8dc857
From: Nageswara R Sastry <rnsastry@linux.vnet.ibm.com>
8dc857
8dc857
Fixed Block Access (FBA) DASDs are mainframe-specific disk devices
8dc857
which are layed out as a sequence of 512-byte sectors. In contrast
8dc857
to ECKD DASDs, these disks do not require formatting and resemble
8dc857
the LBA layout of non-mainframe disks. Despite this resemblance,
8dc857
the Linux kernel applies special handling during partition detection
8dc857
for FBA DASDs, resulting in a single, immutable partition being
8dc857
reported.
8dc857
8dc857
While actual FBA DASD hardware is no longer available, the z/VM
8dc857
hypervisor can simulate FBA DASD disks, backed by either ECKD or
8dc857
SCSI devices.
8dc857
8dc857
This patch adds support for recognizing FBA DASD partitions
8dc857
to parted.
8dc857
8dc857
Signed-off-by: Nageswara R Sastry <rnsastry@linux.vnet.ibm.com>
8dc857
Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
8dc857
8dc857
---
8dc857
 include/parted/fdasd.h   |    2 +
8dc857
 libparted/labels/dasd.c  |   63 ++++++++++++++++++++++++++++++++++++++++-------
8dc857
 libparted/labels/fdasd.c |    5 +++
8dc857
 3 files changed, 61 insertions(+), 9 deletions(-)
8dc857
8dc857
--- a/include/parted/fdasd.h
8dc857
+++ b/include/parted/fdasd.h
8dc857
@@ -194,6 +194,8 @@ typedef struct fdasd_anchor {
8dc857
 	volume_label_t   *vlabel;
8dc857
 	config_data_t confdata[USABLE_PARTITIONS];
8dc857
 	struct fdasd_hd_geometry geo;
8dc857
+	unsigned int label_block;
8dc857
+	unsigned int FBA_layout;
8dc857
 } fdasd_anchor_t;
8dc857
 
8dc857
 enum offset {lower, upper};
8dc857
--- a/libparted/labels/dasd.c
8dc857
+++ b/libparted/labels/dasd.c
8dc857
@@ -71,6 +71,7 @@ typedef struct {
8dc857
 
8dc857
 typedef struct {
8dc857
 	unsigned int format_type;
8dc857
+	unsigned int label_block;
8dc857
 	volume_label_t vlabel;
8dc857
 } DasdDiskSpecific;
8dc857
 
8dc857
@@ -151,6 +152,7 @@ dasd_alloc (const PedDevice* dev)
8dc857
 
8dc857
 	/* CDL format, newer */
8dc857
 	disk_specific->format_type = 2;
8dc857
+	disk_specific->label_block = 2;
8dc857
 
8dc857
 	/* Setup volume label (for fresh disks) */
8dc857
 	snprintf(volser, sizeof(volser), "0X%04X", arch_specific->devno);
8dc857
@@ -226,7 +228,9 @@ dasd_probe (const PedDevice *dev)
8dc857
 
8dc857
 	fdasd_check_api_version(&anchor, arch_specific->fd);
8dc857
 
8dc857
-	if (fdasd_check_volume(&anchor, arch_specific->fd))
8dc857
+	/* Labels are required on CDL formatted DASDs. */
8dc857
+	if (fdasd_check_volume(&anchor, arch_specific->fd) &&
8dc857
+	    anchor.FBA_layout == 0)
8dc857
 		goto error_cleanup;
8dc857
 
8dc857
 	fdasd_cleanup(&anchor);
8dc857
@@ -273,17 +277,53 @@ dasd_read (PedDisk* disk)
8dc857
 	fdasd_initialize_anchor(&anchor);
8dc857
 
8dc857
 	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
8dc857
+	disk_specific->label_block = anchor.label_block;
8dc857
+
8dc857
+	if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
8dc857
+		anchor.big_disk++;
8dc857
 
8dc857
 	/* check dasd for labels and vtoc */
8dc857
-	if (fdasd_check_volume(&anchor, arch_specific->fd))
8dc857
-		goto error_close_dev;
8dc857
+	if (fdasd_check_volume(&anchor, arch_specific->fd)) {
8dc857
+		DasdPartitionData* dasd_data;
8dc857
+
8dc857
+		/* Kernel partitioning code will report 'implicit' partitions
8dc857
+		 * for non-CDL format DASDs even when there is no
8dc857
+		 * label/VTOC.  */
8dc857
+		if (anchor.FBA_layout == 0)
8dc857
+			goto error_close_dev;
8dc857
+
8dc857
+		disk_specific->format_type = 1;
8dc857
+
8dc857
+		/* Register implicit partition */
8dc857
+		ped_disk_delete_all (disk);
8dc857
+
8dc857
+		start = (PedSector) arch_specific->real_sector_size /
8dc857
+			(PedSector) disk->dev->sector_size *
8dc857
+			(PedSector) (anchor.label_block + 1);
8dc857
+		end = disk->dev->length - 1;
8dc857
+		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
8dc857
+					  start, end);
8dc857
+		if (!part)
8dc857
+			goto error_close_dev;
8dc857
+
8dc857
+		part->num = 1;
8dc857
+		part->fs_type = ped_file_system_probe (&part->geom);
8dc857
+		dasd_data = part->disk_specific;
8dc857
+		dasd_data->raid = 0;
8dc857
+		dasd_data->lvm = 0;
8dc857
+		dasd_data->type = 0;
8dc857
+
8dc857
+		if (!ped_disk_add_partition (disk, part, NULL))
8dc857
+			goto error_close_dev;
8dc857
+
8dc857
+		fdasd_cleanup(&anchor);
8dc857
+
8dc857
+		return 1;
8dc857
+	}
8dc857
 
8dc857
 	/* Save volume label (read by fdasd_check_volume) for writing */
8dc857
 	memcpy(&disk_specific->vlabel, anchor.vlabel, sizeof(volume_label_t));
8dc857
 
8dc857
-	if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
8dc857
-		anchor.big_disk++;
8dc857
-
8dc857
 	ped_disk_delete_all (disk);
8dc857
 
8dc857
 	bool is_ldl = strncmp(anchor.vlabel->volkey,
8dc857
@@ -348,7 +388,7 @@ dasd_read (PedDisk* disk)
8dc857
 			    / (long long) disk->dev->sector_size
8dc857
 			    * (long long) (cms_ptr->block_count - 1) - 1;
8dc857
 
8dc857
-		part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end);
8dc857
+		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, start, end);
8dc857
 		if (!part)
8dc857
 			goto error_close_dev;
8dc857
 
8dc857
@@ -923,7 +963,12 @@ dasd_alloc_metadata (PedDisk* disk)
8dc857
 	   the start of the first partition */
8dc857
 	if (disk_specific->format_type == 1) {
8dc857
 	        part = ped_disk_get_partition(disk, 1);
8dc857
-		vtoc_end = part->geom.start - 1;
8dc857
+		if (part)
8dc857
+			vtoc_end = part->geom.start - 1;
8dc857
+		else
8dc857
+			vtoc_end = (PedSector) arch_specific->real_sector_size /
8dc857
+				   (PedSector) disk->dev->sector_size *
8dc857
+				   (PedSector) disk_specific->label_block;
8dc857
 	}
8dc857
 	else {
8dc857
                 if (disk->dev->type == PED_DEVICE_FILE)
8dc857
@@ -943,7 +988,7 @@ dasd_alloc_metadata (PedDisk* disk)
8dc857
 		goto error;
8dc857
 	}
8dc857
 
8dc857
-	if (disk_specific->format_type == 1) {
8dc857
+	if (disk_specific->format_type == 1 && part) {
8dc857
 	   /*
8dc857
 	      For LDL or CMS there may be trailing metadata as well.
8dc857
 	      For example: the last block of a CMS reserved file,
8dc857
--- a/libparted/labels/fdasd.c
8dc857
+++ b/libparted/labels/fdasd.c
8dc857
@@ -721,6 +721,7 @@ fdasd_check_volume (fdasd_anchor_t *anc,
8dc857
 	unsigned long b = -1;
8dc857
 	char str[LINE_LENGTH];
8dc857
 
8dc857
+	memset(v, 0, sizeof(volume_label_t));
8dc857
 	vtoc_read_volume_label (fd, anc->label_pos, v);
8dc857
 
8dc857
 	if (strncmp(v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0) {
8dc857
@@ -800,6 +801,8 @@ fdasd_get_geometry (const PedDevice *dev
8dc857
 	    dasd_info.dev_type = 13200;
8dc857
 	    dasd_info.label_block = 2;
8dc857
 	    dasd_info.devno = 513;
8dc857
+	    dasd_info.label_block = 2;
8dc857
+	    dasd_info.FBA_layout = 0;
8dc857
 	} else {
8dc857
 		if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
8dc857
 			fdasd_error(anc, unable_to_ioctl,
8dc857
@@ -820,6 +823,8 @@ fdasd_get_geometry (const PedDevice *dev
8dc857
 	anc->label_pos  = dasd_info.label_block * blksize;
8dc857
 	anc->devno      = dasd_info.devno;
8dc857
 	anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
8dc857
+	anc->label_block = dasd_info.label_block;
8dc857
+	anc->FBA_layout = dasd_info.FBA_layout;
8dc857
 }
8dc857
 
8dc857
 /*