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

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