Subject: [PATCH 08/19] libparted: mklabel to support EAV DASD

From: "Brian C. Lane" <[email-masked]>
Date: Wed, 11 Sep 2013 12:24:58 -0700

From: Nageswara R Sastry <[email-masked]>

Extended Address Volume (EAV) DASDs are ECKD DASDs with more than
65520 cylinders. This patch adds support for mklabel to properly
handle unformatted EAV DASDs.

Signed-off-by: Nageswara R Sastry <[email-masked]>
---
 include/parted/fdasd.in.h |  1 -
 libparted/labels/fdasd.c  | 92 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h
index b4e7dd1..3692596 100644
--- a/include/parted/fdasd.in.h
+++ b/include/parted/fdasd.in.h
@@ -288,7 +288,6 @@ void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
 void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
 int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
 int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
-int fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc);
 void fdasd_recreate_vtoc(fdasd_anchor_t *anc);
 partition_info_t * fdasd_add_partition (fdasd_anchor_t *anc,
                                         unsigned int start, unsigned int stop);
diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c
index 2735b2a..b58b2be 100644
--- a/libparted/labels/fdasd.c
+++ b/libparted/labels/fdasd.c
@@ -581,6 +581,22 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc)
 	anc->vtoc_changed++;
 }
 
+ /*
+ * initialize the VOL1 volume label
+ */
+static void
+fdasd_init_volume_label(fdasd_anchor_t *anc, int fd)
+{
+	volume_label_t *vlabel = anc->vlabel;
+
+	vtoc_volume_label_init(vlabel);
+	vtoc_volume_label_set_key(vlabel, "VOL1");
+	vtoc_volume_label_set_label(vlabel, "VOL1");
+
+	vtoc_set_cchhb(&vlabel->vtoc, VTOC_START_CC, VTOC_START_HH, 0x01);
+}
+
+
 /*
  * sets some important partition data
  * (like used, start_trk, end_trk, len_trk)
@@ -769,6 +785,52 @@ fdasd_process_valid_vtoc (fdasd_anchor_t * anc, unsigned long b, int fd)
 	fdasd_update_partition_info (anc);
 }
 
+static void
+fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc)
+{
+	PDEBUG
+	anc->formatted_cylinders = anc->hw_cylinders;
+	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads
+			- FIRST_USABLE_TRK;
+	vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS,
+			anc->geo.cylinders, anc->formatted_cylinders,
+			anc->geo.heads, anc->geo.sectors,
+			anc->blksize, anc->dev_type);
+
+	vtoc_init_format5_label(anc->f5);
+	vtoc_init_format7_label(anc->f7);
+
+	vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose,
+			FIRST_USABLE_TRK,
+			anc->formatted_cylinders * anc->geo.heads - 1,
+			anc->formatted_cylinders, anc->geo.heads);
+
+	vtoc_set_cchhb(&anc->vlabel->vtoc, VTOC_START_CC, VTOC_START_HH, 0x01);
+}
+
+/*
+ * we have a invalid FMT4 DSCB and therefore we will re-create the VTOC
+ */
+static void
+fdasd_process_invalid_vtoc(fdasd_anchor_t *anc)
+{
+	anc->formatted_cylinders = anc->hw_cylinders;
+	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads
+			- FIRST_USABLE_TRK;
+	vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS,
+			anc->geo.cylinders, anc->formatted_cylinders,
+			anc->geo.heads, anc->geo.sectors,
+			anc->blksize, anc->dev_type);
+
+	vtoc_init_format5_label(anc->f5);
+	vtoc_init_format7_label(anc->f7);
+	vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose,
+			FIRST_USABLE_TRK,
+			anc->formatted_cylinders * anc->geo.heads - 1,
+			anc->formatted_cylinders, anc->geo.heads);
+}
+
+
 static int
 fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd)
 {
@@ -781,6 +843,8 @@ fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd)
 	if (anc->f4->DS4IDFMT == 0xf4) {
 		fdasd_process_valid_vtoc (anc, b, fd);
 		return 0;
+	} else {
+		fdasd_process_invalid_vtoc(anc);
 	}
 	if (strncmp(anc->vlabel->volkey, vtoc_ebcdic_enc("LNX1",str,4),4) == 0 ||
 	    strncmp(anc->vlabel->volkey, vtoc_ebcdic_enc("CMS1",str,4),4) == 0)
@@ -817,13 +881,37 @@ fdasd_check_volume (fdasd_anchor_t *anc, int fd)
 			else
 				return 0;
 		} else {
-			return 1;
+			fdasd_invalid_vtoc_pointer(anc);
 		}
 	} else if (strncmp (v->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0 ||
 	           strncmp (v->volkey, vtoc_ebcdic_enc ("CMS1", str, 4), 4) == 0) {
 		return 0;
-	}
+	} else if (anc->FBA_layout == 1) {
+		/* Some times LDL formatted disks does not
+		   contain any volume label */
+		return 1;
+	} else {
+	/* didn't find VOL1 volume label */
+		anc->formatted_cylinders = anc->hw_cylinders;
+		anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads
+					- FIRST_USABLE_TRK;
+
+		fdasd_init_volume_label(anc, fd);
 
+		vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS,
+				anc->geo.cylinders, anc->formatted_cylinders,
+				anc->geo.heads, anc->geo.sectors,
+				anc->blksize, anc->dev_type);
+
+		vtoc_init_format5_label(anc->f5);
+		vtoc_init_format7_label(anc->f7);
+
+		vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+',
+			anc->verbose, FIRST_USABLE_TRK,
+			anc->formatted_cylinders * anc->geo.heads - 1,
+			anc->formatted_cylinders, anc->geo.heads);
+		return 0;
+	}
 	return 1;
 }
 
-- 
1.8.3.1