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

8dc857
Subject: [PATCH] libparted: add support for EAV DASD partitions
8dc857
8dc857
From: Nageswara R Sastry <rnsastry@linux.vnet.ibm.com>
8dc857
8dc857
Extended Address Volume (EAV) DASDs are ECKD DASDs with more than
8dc857
65520 cylinders. This patch adds support for recognizing and
8dc857
modifying partitions on EAV DASDs to Parted. The changes are
8dc857
based on the EAV support added to version 1.8.1 [1] of the
8dc857
s390-tools package.
8dc857
8dc857
[1] http://www.ibm.com/developerworks/linux/linux390/s390-tools-1.8.1.html
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   |   89 ++++++++++++++++--
8dc857
 include/parted/vtoc.h    |   58 ++++++++++--
8dc857
 libparted/labels/dasd.c  |    1 
8dc857
 libparted/labels/fdasd.c |  226 ++++++++++++++++++++++++++++++++---------------
8dc857
 libparted/labels/vtoc.c  |  173 ++++++++++++++++++++++++++++++-----
8dc857
 5 files changed, 435 insertions(+), 112 deletions(-)
8dc857
8dc857
--- a/include/parted/fdasd.h
8dc857
+++ b/include/parted/fdasd.h
8dc857
@@ -74,6 +74,80 @@ typedef struct dasd_information_t {
8dc857
 	char configuration_data[256]; /* from read_configuration_data        */
8dc857
 } dasd_information_t;
8dc857
 
8dc857
+struct dasd_eckd_characteristics {
8dc857
+	unsigned short cu_type;
8dc857
+	struct {
8dc857
+		unsigned char support:2;
8dc857
+		unsigned char async:1;
8dc857
+		unsigned char reserved:1;
8dc857
+		unsigned char cache_info:1;
8dc857
+		unsigned char model:3;
8dc857
+	} __attribute__ ((packed)) cu_model;
8dc857
+	unsigned short dev_type;
8dc857
+	unsigned char dev_model;
8dc857
+	struct {
8dc857
+		unsigned char mult_burst:1;
8dc857
+		unsigned char RT_in_LR:1;
8dc857
+		unsigned char reserved1:1;
8dc857
+		unsigned char RD_IN_LR:1;
8dc857
+		unsigned char reserved2:4;
8dc857
+		unsigned char reserved3:8;
8dc857
+		unsigned char defect_wr:1;
8dc857
+		unsigned char XRC_supported:1;
8dc857
+		unsigned char reserved4:1;
8dc857
+		unsigned char striping:1;
8dc857
+		unsigned char reserved5:4;
8dc857
+		unsigned char cfw:1;
8dc857
+		unsigned char reserved6:2;
8dc857
+		unsigned char cache:1;
8dc857
+		unsigned char dual_copy:1;
8dc857
+		unsigned char dfw:1;
8dc857
+		unsigned char reset_alleg:1;
8dc857
+		unsigned char sense_down:1;
8dc857
+	} __attribute__ ((packed)) facilities;
8dc857
+	unsigned char dev_class;
8dc857
+	unsigned char unit_type;
8dc857
+	unsigned short no_cyl;
8dc857
+	unsigned short trk_per_cyl;
8dc857
+	unsigned char sec_per_trk;
8dc857
+	unsigned char byte_per_track[3];
8dc857
+	unsigned short home_bytes;
8dc857
+	unsigned char formula;
8dc857
+	union {
8dc857
+		struct {
8dc857
+			unsigned char f1;
8dc857
+			unsigned short f2;
8dc857
+			unsigned short f3;
8dc857
+		} __attribute__ ((packed)) f_0x01;
8dc857
+		struct {
8dc857
+			unsigned char f1;
8dc857
+			unsigned char f2;
8dc857
+			unsigned char f3;
8dc857
+			unsigned char f4;
8dc857
+			unsigned char f5;
8dc857
+		} __attribute__ ((packed)) f_0x02;
8dc857
+	} __attribute__ ((packed)) factors;
8dc857
+	unsigned short first_alt_trk;
8dc857
+	unsigned short no_alt_trk;
8dc857
+	unsigned short first_dia_trk;
8dc857
+	unsigned short no_dia_trk;
8dc857
+	unsigned short first_sup_trk;
8dc857
+	unsigned short no_sup_trk;
8dc857
+	unsigned char MDR_ID;
8dc857
+	unsigned char OBR_ID;
8dc857
+	unsigned char director;
8dc857
+	unsigned char rd_trk_set;
8dc857
+	unsigned short max_rec_zero;
8dc857
+	unsigned char reserved1;
8dc857
+	unsigned char RWANY_in_LR;
8dc857
+	unsigned char factor6;
8dc857
+	unsigned char factor7;
8dc857
+	unsigned char factor8;
8dc857
+	unsigned char reserved2[3];
8dc857
+	unsigned char reserved3[6];
8dc857
+	unsigned int long_no_cyl;
8dc857
+} __attribute__ ((packed));
8dc857
+
8dc857
 /*
8dc857
  * struct format_data_t
8dc857
  * represents all data necessary to format a dasd
8dc857
@@ -116,18 +190,6 @@ typedef struct format_data_t {
8dc857
 #define BLKRRPART  _IO(0x12,95)
8dc857
 /* get block device sector size */
8dc857
 #define BLKSSZGET  _IO(0x12,104)
8dc857
-
8dc857
-/*****************************************************************************
8dc857
- * SECTION: Definition from hdreq.h                                          *
8dc857
- *****************************************************************************/
8dc857
-
8dc857
-struct fdasd_hd_geometry {
8dc857
-      unsigned char heads;
8dc857
-      unsigned char sectors;
8dc857
-      unsigned short cylinders;
8dc857
-      unsigned long start;
8dc857
-};
8dc857
-
8dc857
 /* get device geometry */
8dc857
 #define HDIO_GETGEO		0x0301
8dc857
 
8dc857
@@ -189,10 +251,13 @@ typedef struct fdasd_anchor {
8dc857
 	format4_label_t  *f4;
8dc857
 	format5_label_t  *f5;
8dc857
 	format7_label_t  *f7;
8dc857
+	format9_label_t  *f9; /* template for all f9 labels */
8dc857
 	partition_info_t *first;
8dc857
 	partition_info_t *last;
8dc857
 	volume_label_t   *vlabel;
8dc857
 	config_data_t confdata[USABLE_PARTITIONS];
8dc857
+	u_int32_t hw_cylinders;
8dc857
+	u_int32_t formatted_cylinders;
8dc857
 	struct fdasd_hd_geometry geo;
8dc857
 	unsigned int label_block;
8dc857
 	unsigned int FBA_layout;
8dc857
--- a/include/parted/vtoc.h
8dc857
+++ b/include/parted/vtoc.h
8dc857
@@ -42,7 +42,18 @@
8dc857
 
8dc857
 #define VOLSER_LENGTH 6
8dc857
 #define BIG_DISK_SIZE 0x10000
8dc857
+#define LV_COMPAT_CYL 0xFFFE
8dc857
 
8dc857
+/*****************************************************************************
8dc857
+ * SECTION: Definition from hdreq.h                                          *
8dc857
+ *****************************************************************************/
8dc857
+
8dc857
+struct fdasd_hd_geometry {
8dc857
+      unsigned char heads;
8dc857
+      unsigned char sectors;
8dc857
+      unsigned short cylinders;
8dc857
+      unsigned long start;
8dc857
+};
8dc857
 
8dc857
 typedef struct ttr              ttr_t;
8dc857
 typedef struct cchhb            cchhb_t;
8dc857
@@ -59,6 +70,7 @@ typedef struct ds5ext           ds5ext_t
8dc857
 typedef struct format5_label    format5_label_t;
8dc857
 typedef struct ds7ext           ds7ext_t;
8dc857
 typedef struct format7_label    format7_label_t;
8dc857
+typedef struct format9_label    format9_label_t;
8dc857
 
8dc857
 struct __attribute__ ((packed)) ttr {
8dc857
         u_int16_t tt;
8dc857
@@ -169,6 +181,10 @@ struct __attribute__ ((packed)) dev_cons
8dc857
         u_int8_t  DS4DEVDB;     /* number of directory blocks per track */
8dc857
 };
8dc857
 
8dc857
+/*
8dc857
+ * format 1 and format 8 label have the same layout so we use the following
8dc857
+ * structure for both.
8dc857
+ */
8dc857
 struct __attribute__ ((packed)) format1_label {
8dc857
 	char  DS1DSNAM[44];     /* data set name                           */
8dc857
 	u_int8_t  DS1FMTID;     /* format identifier                       */
8dc857
@@ -229,7 +245,11 @@ struct __attribute__ ((packed)) format4_
8dc857
 	char res2[10];          /* reserved                                */
8dc857
 	u_int8_t DS4EFLVL;      /* extended free-space management level    */
8dc857
 	cchhb_t DS4EFPTR;       /* pointer to extended free-space info     */
8dc857
-	char res3[9];           /* reserved                                */
8dc857
+	char res3;              /* reserved */
8dc857
+	u_int32_t DS4DCYL;      /* number of logical cyls */
8dc857
+	char res4[2];           /* reserved */
8dc857
+	u_int8_t DS4DEVF2;      /* device flags */
8dc857
+	char res5;              /* reserved */
8dc857
 };
8dc857
 
8dc857
 struct __attribute__ ((packed)) ds5ext {
8dc857
@@ -261,12 +281,28 @@ struct __attribute__ ((packed)) format7_
8dc857
 	cchhb_t DS7PTRDS;       /* pointer to next FMT7 DSCB               */
8dc857
 };
8dc857
 
8dc857
+struct __attribute__ ((packed)) format9_label {
8dc857
+	u_int8_t  DS9KEYID;     /* key code for format 9 labels (0x09) */
8dc857
+	u_int8_t  DS9SUBTY;     /* subtype (0x01) */
8dc857
+	u_int8_t  DS9NUMF9;     /* number of F9 datasets  */
8dc857
+	u_int8_t  res1[41];     /* reserved  */
8dc857
+	u_int8_t  DS9FMTID;     /* format identifier  */
8dc857
+	u_int8_t  res2[95];     /* reserved */
8dc857
+};
8dc857
+
8dc857
 char *vtoc_ebcdic_enc (char const *source, char *target, int l);
8dc857
 char *vtoc_ebcdic_dec (char const *source, char *target, int l);
8dc857
 void vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno,
8dc857
                       cchh_t *lower, cchh_t *upper);
8dc857
-void vtoc_set_cchh (cchh_t *addr, u_int16_t cc, u_int16_t hh);
8dc857
-void vtoc_set_cchhb (cchhb_t *addr, u_int16_t cc, u_int16_t hh, u_int8_t b);
8dc857
+void vtoc_set_cchh (cchh_t *addr, u_int32_t cc, u_int16_t hh);
8dc857
+u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
8dc857
+u_int16_t vtoc_get_head_from_cchh(cchh_t *addr);
8dc857
+void vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b);
8dc857
+u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
8dc857
+u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
8dc857
+u_int64_t cchhb2blk(cchhb_t *p, struct fdasd_hd_geometry *geo);
8dc857
+u_int64_t cchh2blk (cchh_t *p, struct fdasd_hd_geometry *geo);
8dc857
+u_int32_t cchh2trk (cchh_t *p, struct fdasd_hd_geometry *geo);
8dc857
 void vtoc_set_date (labeldate_t *d, u_int8_t year, u_int16_t day);
8dc857
 
8dc857
 void vtoc_volume_label_init (volume_label_t *vlabel);
8dc857
@@ -295,14 +331,16 @@ void vtoc_write_label (int fd, unsigned
8dc857
 		       format1_label_t const *f1,
8dc857
                        format4_label_t const *f4,
8dc857
 		       format5_label_t const *f5,
8dc857
-                       format7_label_t const *f7);
8dc857
+                       format7_label_t const *f7,
8dc857
+                       format9_label_t const *f9);
8dc857
 
8dc857
 void vtoc_init_format1_label (char *volid, unsigned int blksize,
8dc857
                               extent_t *part_extent, format1_label_t *f1);
8dc857
 
8dc857
 void vtoc_init_format4_label (format4_label_t *f4lbl,
8dc857
                               unsigned int usable_partitions,
8dc857
-                              unsigned int cylinders,
8dc857
+                              unsigned int compat_cylinders,
8dc857
+                              unsigned int real_cylinders,
8dc857
                               unsigned int tracks,
8dc857
                               unsigned int blocks,
8dc857
                               unsigned int blksize,
8dc857
@@ -329,8 +367,16 @@ void vtoc_update_format7_label_add (form
8dc857
 void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
8dc857
                                     u_int32_t a, u_int32_t b);
8dc857
 
8dc857
+void vtoc_init_format8_label (char *volid, unsigned int blksize,
8dc857
+                              extent_t *part_extent, format1_label_t *f1);
8dc857
+
8dc857
+void vtoc_update_format8_label (cchhb_t *associated_f9, format1_label_t *f8);
8dc857
+
8dc857
+void vtoc_init_format9_label (format9_label_t *f9);
8dc857
+
8dc857
 void vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
8dc857
                         format7_label_t *f7, char ch, int verbose,
8dc857
-                        u_int32_t start, u_int32_t stop, int cyl, int trk);
8dc857
+                        u_int32_t start, u_int32_t stop, u_int32_t cyl,
8dc857
+                        u_int32_t trk);
8dc857
 
8dc857
 #endif /* VTOC_H */
8dc857
--- a/libparted/labels/dasd.c
8dc857
+++ b/libparted/labels/dasd.c
8dc857
@@ -631,6 +631,7 @@ dasd_write (const PedDisk* disk)
8dc857
 	/* initialize the anchor */
8dc857
 	fdasd_initialize_anchor(&anchor);
8dc857
 	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
8dc857
+	fdasd_check_volume(&anchor, arch_specific->fd);
8dc857
 	memcpy(anchor.vlabel, &disk_specific->vlabel, sizeof(volume_label_t));
8dc857
 	anchor.vlabel_changed++;
8dc857
 
8dc857
--- a/libparted/labels/fdasd.c
8dc857
+++ b/libparted/labels/fdasd.c
8dc857
@@ -59,6 +59,48 @@ setpos (fdasd_anchor_t *anc, int dsn, in
8dc857
 	anc->partno[dsn] = pos;
8dc857
 }
8dc857
 
8dc857
+static u_int32_t
8dc857
+get_usable_cylinders (fdasd_anchor_t *anc)
8dc857
+{
8dc857
+	u_int32_t cyl;
8dc857
+
8dc857
+	/* large volume */
8dc857
+	if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
8dc857
+	    anc->f4->DS4DCYL > anc->f4->DS4DEVCT.DS4DSCYL)
8dc857
+		return anc->f4->DS4DCYL;
8dc857
+	/* normal volume */
8dc857
+	if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
8dc857
+		cyl = anc->f4->DS4DEVCT.DS4DSCYL -
8dc857
+			(u_int16_t) anc->f4->DS4DEVAC;
8dc857
+	else
8dc857
+		cyl = anc->f4->DS4DEVCT.DS4DSCYL;
8dc857
+	return cyl;
8dc857
+}
8dc857
+
8dc857
+static void
8dc857
+get_addr_of_highest_f1_f8_label (fdasd_anchor_t *anc, cchhb_t *addr)
8dc857
+{
8dc857
+
8dc857
+	u_int8_t record;
8dc857
+	/* We have to count the follwing labels:
8dc857
+	 * one format 4
8dc857
+	 * one format 5
8dc857
+	 * format 7 only if we have moren then BIG_DISK_SIZE tracks
8dc857
+	 * one for each format 1 or format 8 label == one for each partition
8dc857
+	 * one for each format 9 label before the last format 8
8dc857
+	 * We assume that all partitions use format 8 labels when
8dc857
+	 *  anc->formatted_cylinders > LV_COMPAT_CYL
8dc857
+	 * Note: Record zero is special, so block 0 on our disk is record 1!
8dc857
+	 */
8dc857
+
8dc857
+	record = anc->used_partitions + 2;
8dc857
+	if (anc->big_disk)
8dc857
+		record++;
8dc857
+	if (anc->formatted_cylinders > LV_COMPAT_CYL)
8dc857
+		record += anc->used_partitions - 1;
8dc857
+	vtoc_set_cchhb(addr, VTOC_START_CC, VTOC_START_HH, record);
8dc857
+}
8dc857
+
8dc857
 void
8dc857
 fdasd_cleanup (fdasd_anchor_t *anchor)
8dc857
 {
8dc857
@@ -72,6 +114,7 @@ fdasd_cleanup (fdasd_anchor_t *anchor)
8dc857
         free(anchor->f4);
8dc857
         free(anchor->f5);
8dc857
         free(anchor->f7);
8dc857
+        free(anchor->f9);
8dc857
         free(anchor->vlabel);
8dc857
 
8dc857
 	p = anchor->first;
8dc857
@@ -82,6 +125,7 @@ fdasd_cleanup (fdasd_anchor_t *anchor)
8dc857
 		if (p == NULL)
8dc857
 			return;
8dc857
 		q = p->next;
8dc857
+		free(p->f1);
8dc857
 		free(p);
8dc857
 		p = q;
8dc857
 	}
8dc857
@@ -154,17 +198,6 @@ fdasd_error (fdasd_anchor_t *anc, enum f
8dc857
 }
8dc857
 
8dc857
 /*
8dc857
- * converts cyl-cyl-head-head-blk to blk
8dc857
- */
8dc857
-static unsigned long
8dc857
-cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo)
8dc857
-{
8dc857
-	PDEBUG
8dc857
-	return (unsigned long) (p->cc * geo->heads * geo->sectors
8dc857
-	                        + p->hh * geo->sectors + p->b);
8dc857
-}
8dc857
-
8dc857
-/*
8dc857
  * initializes the anchor structure and allocates some
8dc857
  * memory for the labels
8dc857
  */
8dc857
@@ -216,9 +249,16 @@ fdasd_initialize_anchor (fdasd_anchor_t
8dc857
 	if (anc->f7 == NULL)
8dc857
 		fdasd_error(anc, malloc_failed, "FMT7 DSCB.");
8dc857
 
8dc857
+       /* template for all format 9 labels */
8dc857
+	anc->f9 = malloc(sizeof(format9_label_t));
8dc857
+	if (anc->f9 == NULL)
8dc857
+		fdasd_error(anc, malloc_failed, "FMT9 DSCB.");
8dc857
+
8dc857
 	bzero(anc->f4, sizeof(format4_label_t));
8dc857
 	bzero(anc->f5, sizeof(format5_label_t));
8dc857
 	bzero(anc->f7, sizeof(format7_label_t));
8dc857
+	bzero(anc->f9, sizeof(format9_label_t));
8dc857
+	vtoc_init_format9_label(anc->f9);
8dc857
 
8dc857
 	v = malloc(sizeof(volume_label_t));
8dc857
 	if (v == NULL)
8dc857
@@ -259,6 +299,8 @@ fdasd_initialize_anchor (fdasd_anchor_t
8dc857
 
8dc857
 		q = p;
8dc857
 	}
8dc857
+	anc->hw_cylinders = 0;
8dc857
+	anc->formatted_cylinders = 0;
8dc857
 }
8dc857
 
8dc857
 /*
8dc857
@@ -269,44 +311,46 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	partition_info_t *p;
8dc857
-	unsigned long b;
8dc857
+	unsigned long b, maxblk;
8dc857
 	char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
8dc857
 	int i = 0, k = 0;
8dc857
+	cchhb_t f9addr;
8dc857
+	format1_label_t emptyf1;
8dc857
 
8dc857
 	b = (cchhb2blk (&anc->vlabel->vtoc, &anc->geo) - 1) * anc->blksize;
8dc857
 	if (b <= 0)
8dc857
 		fdasd_error (anc, vlabel_corrupted, "");
8dc857
+	maxblk = b + anc->blksize * 9; /* f4+f5+f7+3*f8+3*f9 */
8dc857
 
8dc857
 	/* write FMT4 DSCB */
8dc857
-	vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL);
8dc857
+	vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL, NULL);
8dc857
+	b += anc->blksize;
8dc857
 
8dc857
 	/* write FMT5 DSCB */
8dc857
+	vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL, NULL);
8dc857
 	b += anc->blksize;
8dc857
-	vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL);
8dc857
 
8dc857
 	/* write FMT7 DSCB */
8dc857
 	if (anc->big_disk) {
8dc857
+		vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7, NULL);
8dc857
 		b += anc->blksize;
8dc857
-		vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7);
8dc857
 	}
8dc857
 
8dc857
-	/* loop over all FMT1 DSCBs */
8dc857
-	p = anc->first;
8dc857
-	for (i = 0; i < USABLE_PARTITIONS; i++) {
8dc857
-		b += anc->blksize;
8dc857
+	/* loop over all partitions (format 1 or format 8 DCB) */
8dc857
+	for (p = anc->first; p != NULL; p = p->next) {
8dc857
 
8dc857
 		if (p->used != 0x01) {
8dc857
-			vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
8dc857
 			continue;
8dc857
 		}
8dc857
 
8dc857
+		i++;
8dc857
 		strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
8dc857
 
8dc857
 		ch = p->f1->DS1DSNAM;
8dc857
 		vtoc_ebcdic_dec (ch, ch, 44);
8dc857
 		c1 = ch + 7;
8dc857
 
8dc857
-		if (getdsn (anc, i) > -1) {
8dc857
+		if (getdsn (anc, i-1) > -1) {
8dc857
 			/* re-use the existing data set name */
8dc857
 			c2 = strchr (c1, '.');
8dc857
 			if (c2 != NULL)
8dc857
@@ -325,11 +369,7 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
8dc857
 			while (getpos (anc, k) > -1)
8dc857
 				k++;
8dc857
 
8dc857
-			setpos (anc, k, i);
8dc857
-
8dc857
-			strncpy (s2, ch, 44);
8dc857
-			s2[44] = 0;
8dc857
-			vtoc_ebcdic_dec (s2, s2, 44);
8dc857
+			setpos (anc, k, i-1);
8dc857
 
8dc857
 			strncpy (ch, "LINUX.V               " "                      ", 44);
8dc857
 
8dc857
@@ -366,8 +406,32 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
8dc857
 
8dc857
 		vtoc_ebcdic_enc (ch, ch, 44);
8dc857
 
8dc857
-		vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
8dc857
-		p = p->next;
8dc857
+		if (p->f1->DS1FMTID == 0xf8 ) {
8dc857
+			/* Now as we know where which label will be written, we
8dc857
+			 * can add the address of the format 9 label to the
8dc857
+			 * format 8 label. The f9 record will be written to the
8dc857
+			 * block after the current blk. Remember: records are of
8dc857
+			 * by one, so we have to add 2 and not just one.
8dc857
+			 */
8dc857
+			vtoc_set_cchhb(&f9addr, VTOC_START_CC, VTOC_START_HH,
8dc857
+				((b / anc->blksize) % anc->geo.sectors) + 2);
8dc857
+			vtoc_update_format8_label(&f9addr, p->f1);
8dc857
+			vtoc_write_label(fd, b, p->f1, NULL, NULL, NULL, NULL);
8dc857
+			b += anc->blksize;
8dc857
+			vtoc_write_label(fd, b, NULL, NULL, NULL, NULL,
8dc857
+					 anc->f9);
8dc857
+			b += anc->blksize;
8dc857
+		} else {
8dc857
+			vtoc_write_label(fd, b, p->f1, NULL, NULL, NULL, NULL);
8dc857
+			b += anc->blksize;
8dc857
+		}
8dc857
+	}
8dc857
+
8dc857
+	/* write empty labels to the rest of the blocks */
8dc857
+	bzero(&emptyf1, sizeof(emptyf1));
8dc857
+	while (b < maxblk) {
8dc857
+		vtoc_write_label(fd, b, &emptyf1, NULL, NULL, NULL, NULL);
8dc857
+		b += anc->blksize;
8dc857
 	}
8dc857
 }
8dc857
 
8dc857
@@ -394,20 +458,25 @@ int
8dc857
 fdasd_prepare_labels (fdasd_anchor_t *anc, int fd)
8dc857
 {
8dc857
 	PDEBUG
8dc857
-	partition_info_t *p = anc->first;
8dc857
+	partition_info_t *p;
8dc857
 	char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
8dc857
 	int i = 0, k = 0;
8dc857
 
8dc857
-	/* loop over all FMT1 DSCBs */
8dc857
-	p = anc->first;
8dc857
-	for (i = 0; i < USABLE_PARTITIONS; i++) {
8dc857
+	/* loop over all partitions (format 1 or format 8 DCB) */
8dc857
+	for (p = anc->first; p != NULL; p = p->next) {
8dc857
+
8dc857
+		if (p->used != 0x01) {
8dc857
+			continue;
8dc857
+		}
8dc857
+
8dc857
+		i++;
8dc857
 		strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
8dc857
 
8dc857
 		ch = p->f1->DS1DSNAM;
8dc857
 		vtoc_ebcdic_dec (ch, ch, 44);
8dc857
 		c1 = ch + 7;
8dc857
 
8dc857
-		if (getdsn (anc, i) > -1) {
8dc857
+		if (getdsn (anc, i-1) > -1) {
8dc857
 			/* re-use the existing data set name */
8dc857
 			c2 = strchr (c1, '.');
8dc857
 			if (c2 != NULL)
8dc857
@@ -426,11 +495,7 @@ fdasd_prepare_labels (fdasd_anchor_t *an
8dc857
 			while (getpos (anc, k) > -1)
8dc857
 				k++;
8dc857
 
8dc857
-			setpos (anc, k, i);
8dc857
-
8dc857
-			strncpy (s2, ch, 44);
8dc857
-			s2[44] = 0;
8dc857
-			vtoc_ebcdic_dec (s2, s2, 44);
8dc857
+			setpos (anc, k, i-1);
8dc857
 
8dc857
 			strncpy (ch, "LINUX.V               " "                      ", 44);
8dc857
 
8dc857
@@ -466,7 +531,6 @@ fdasd_prepare_labels (fdasd_anchor_t *an
8dc857
 		}
8dc857
 
8dc857
 		vtoc_ebcdic_enc (ch, ch, 44);
8dc857
-		p = p->next;
8dc857
 	}
8dc857
 
8dc857
 	return 1;
8dc857
@@ -482,6 +546,7 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
8dc857
 	vtoc_init_format4_label(anc->f4,
8dc857
 							USABLE_PARTITIONS,
8dc857
 							anc->geo.cylinders,
8dc857
+						anc->formatted_cylinders,
8dc857
 							anc->geo.heads,
8dc857
 							anc->geo.sectors,
8dc857
 							anc->blksize,
8dc857
@@ -492,8 +557,8 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
8dc857
 	vtoc_set_freespace(anc->f4, anc->f5, anc->f7,
8dc857
 					   '+', anc->verbose,
8dc857
 					   FIRST_USABLE_TRK,
8dc857
-					   anc->geo.cylinders * anc->geo.heads - 1,
8dc857
-					   anc->geo.cylinders, anc->geo.heads);
8dc857
+				anc->formatted_cylinders * anc->geo.heads - 1,
8dc857
+				anc->formatted_cylinders, anc->geo.heads);
8dc857
 
8dc857
 	for (i = 0; i < USABLE_PARTITIONS; i++) {
8dc857
 		bzero(p->f1, sizeof(format1_label_t));
8dc857
@@ -507,7 +572,8 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
8dc857
 	}
8dc857
 
8dc857
 	anc->used_partitions = 0;
8dc857
-	anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
8dc857
+	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads -
8dc857
+			  FIRST_USABLE_TRK;
8dc857
 
8dc857
 	for (i=0; i
8dc857
 		setpos(anc, i, -1);
8dc857
@@ -526,15 +592,15 @@ fdasd_update_partition_info (fdasd_ancho
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	partition_info_t *q = NULL, *p = anc->first;
8dc857
-	unsigned int h = anc->geo.heads;
8dc857
-	unsigned long max = anc->geo.cylinders * h - 1;
8dc857
+	unsigned long max = anc->formatted_cylinders * anc->geo.heads - 1;
8dc857
 	int i;
8dc857
 	char *ch;
8dc857
 
8dc857
 	anc->used_partitions = anc->geo.sectors - 2 - anc->f4->DS4DSREC;
8dc857
 
8dc857
 	for (i = 1; i <= USABLE_PARTITIONS; i++) {
8dc857
-		if (p->f1->DS1FMTID != 0xf1) {
8dc857
+		if (p->f1->DS1FMTID != 0xf1 &&
8dc857
+		    p->f1->DS1FMTID != 0xf8) {
8dc857
 			if (i == 1)
8dc857
 				/* there is no partition at all */
8dc857
 				anc->fspace_trk = max - FIRST_USABLE_TRK + 1;
8dc857
@@ -546,8 +612,8 @@ fdasd_update_partition_info (fdasd_ancho
8dc857
 
8dc857
 		/* this is a valid format 1 label */
8dc857
 		p->used = 0x01;
8dc857
-		p->start_trk = p->f1->DS1EXT1.llimit.cc * h + p->f1->DS1EXT1.llimit.hh;
8dc857
-		p->end_trk   = p->f1->DS1EXT1.ulimit.cc * h + p->f1->DS1EXT1.ulimit.hh;
8dc857
+		p->start_trk = cchh2trk(&p->f1->DS1EXT1.llimit,	&anc->geo);
8dc857
+		p->end_trk = cchh2trk(&p->f1->DS1EXT1.ulimit, &anc->geo);
8dc857
 		p->len_trk   = p->end_trk - p->start_trk + 1;
8dc857
 
8dc857
 		if (i == 1) {
8dc857
@@ -618,14 +684,22 @@ fdasd_process_valid_vtoc (fdasd_anchor_t
8dc857
 	format1_label_t q;
8dc857
 	char s[5], *ch;
8dc857
 
8dc857
+	if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
8dc857
+	    anc->f4->DS4DCYL > anc->f4->DS4DEVCT.DS4DSCYL)
8dc857
+		anc->formatted_cylinders = anc->f4->DS4DCYL;
8dc857
+	else
8dc857
+		anc->formatted_cylinders = anc->f4->DS4DEVCT.DS4DSCYL;
8dc857
+	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads -
8dc857
+			  FIRST_USABLE_TRK;
8dc857
 	b += anc->blksize;
8dc857
 
8dc857
-	for (i = 1; i <= anc->geo.sectors; i++) {
8dc857
+	for (i = 1; i < anc->geo.sectors; i++) {
8dc857
 		bzero (&q, f1size);
8dc857
 		vtoc_read_label (fd, b, &q, NULL, NULL, NULL);
8dc857
 
8dc857
 		switch (q.DS1FMTID) {
8dc857
 			case 0xf1:
8dc857
+			case 0xf8:
8dc857
 				if (p == NULL)
8dc857
 					break;
8dc857
 				memcpy (p->f1, &q, f1size);
8dc857
@@ -669,6 +743,12 @@ fdasd_process_valid_vtoc (fdasd_anchor_t
8dc857
 					memcpy (anc->f7, &q, f1size);
8dc857
 				f7_counter++;
8dc857
 				break;
8dc857
+			case 0xf9:
8dc857
+				/* each format 8 lable has an associated
8dc857
+				 * format 9 lable, but they are of no further
8dc857
+				 * use to us.
8dc857
+				 */
8dc857
+				break;
8dc857
 		}
8dc857
 
8dc857
 		b += anc->blksize;
8dc857
@@ -718,7 +798,7 @@ fdasd_check_volume (fdasd_anchor_t *anc,
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	volume_label_t *v = anc->vlabel;
8dc857
-	unsigned long b = -1;
8dc857
+	long long b = -1;
8dc857
 	char str[LINE_LENGTH];
8dc857
 
8dc857
 	memset(v, 0, sizeof(volume_label_t));
8dc857
@@ -784,6 +864,7 @@ fdasd_get_geometry (const PedDevice *dev
8dc857
 	PDEBUG
8dc857
 	int blksize = 0;
8dc857
 	dasd_information_t dasd_info;
8dc857
+	struct dasd_eckd_characteristics *characteristics;
8dc857
 
8dc857
 	/* We can't get geometry from a regular file,
8dc857
 	   so simulate something usable, for the sake of testing.  */
8dc857
@@ -803,6 +884,8 @@ fdasd_get_geometry (const PedDevice *dev
8dc857
 	    dasd_info.devno = 513;
8dc857
 	    dasd_info.label_block = 2;
8dc857
 	    dasd_info.FBA_layout = 0;
8dc857
+	    anc->hw_cylinders = ((st.st_size / blksize) / anc->geo.sectors) /
8dc857
+				anc->geo.heads;
8dc857
 	} else {
8dc857
 		if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
8dc857
 			fdasd_error(anc, unable_to_ioctl,
8dc857
@@ -816,13 +899,20 @@ fdasd_get_geometry (const PedDevice *dev
8dc857
 		if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
8dc857
 			fdasd_error(anc, unable_to_ioctl,
8dc857
 				    _("Could not retrieve disk information."));
8dc857
+
8dc857
+		characteristics = (struct dasd_eckd_characteristics *)
8dc857
+					&dasd_info.characteristics;
8dc857
+		if (characteristics->no_cyl == LV_COMPAT_CYL &&
8dc857
+		    characteristics->long_no_cyl)
8dc857
+			anc->hw_cylinders = characteristics->long_no_cyl;
8dc857
+		else
8dc857
+			anc->hw_cylinders = characteristics->no_cyl;
8dc857
 	}
8dc857
 
8dc857
 	anc->dev_type   = dasd_info.dev_type;
8dc857
 	anc->blksize    = blksize;
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
@@ -850,20 +940,17 @@ fdasd_get_partition_data (fdasd_anchor_t
8dc857
                           unsigned int *stop_ptr)
8dc857
 {
8dc857
 	PDEBUG
8dc857
-	unsigned int limit, cc, hh;
8dc857
+	unsigned int limit;
8dc857
+	u_int32_t cc, c;
8dc857
+	u_int16_t hh, h;
8dc857
 	cchh_t llimit, ulimit;
8dc857
 	partition_info_t *q;
8dc857
 	u_int8_t b1, b2;
8dc857
-	u_int16_t c, h;
8dc857
 	unsigned int start = *start_ptr, stop = *stop_ptr;
8dc857
 	int i;
8dc857
 	char *ch;
8dc857
 
8dc857
-	if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
8dc857
-		c = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t) anc->f4->DS4DEVAC;
8dc857
-	else
8dc857
-		c = anc->f4->DS4DEVCT.DS4DSCYL;
8dc857
-
8dc857
+	c = get_usable_cylinders(anc);
8dc857
 	h = anc->f4->DS4DEVCT.DS4DSTRK;
8dc857
 	limit = (h * c - 1);
8dc857
 
8dc857
@@ -1019,7 +1106,6 @@ fdasd_add_partition (fdasd_anchor_t *anc
8dc857
 	cchhb_t hf1;
8dc857
 	partition_info_t *p;
8dc857
 	extent_t ext;
8dc857
-	int i;
8dc857
 
8dc857
 	PDEBUG;
8dc857
 
8dc857
@@ -1032,8 +1118,14 @@ fdasd_add_partition (fdasd_anchor_t *anc
8dc857
 	if (fdasd_get_partition_data(anc, &ext, p, &start, &stop) != 0)
8dc857
 		return 0;
8dc857
 
8dc857
-	PDEBUG;
8dc857
-	vtoc_init_format1_label(anc->vlabel->volid, anc->blksize, &ext, p->f1);
8dc857
+	if (anc->formatted_cylinders > LV_COMPAT_CYL) {
8dc857
+		vtoc_init_format8_label(anc->vlabel->volid, anc->blksize, &ext,
8dc857
+					p->f1);
8dc857
+	} else {
8dc857
+		PDEBUG;
8dc857
+		vtoc_init_format1_label(anc->vlabel->volid, anc->blksize, &ext,
8dc857
+					p->f1);
8dc857
+	}
8dc857
 
8dc857
 	PDEBUG;
8dc857
 	fdasd_enqueue_new_partition(anc);
8dc857
@@ -1041,23 +1133,17 @@ fdasd_add_partition (fdasd_anchor_t *anc
8dc857
 	PDEBUG;
8dc857
 	anc->used_partitions += 1;
8dc857
 
8dc857
-	i = anc->used_partitions + 2;
8dc857
-	if (anc->big_disk)
8dc857
-		i++;
8dc857
-	PDEBUG;
8dc857
-
8dc857
-	vtoc_set_cchhb(&hf1, VTOC_START_CC, VTOC_START_HH, i);
8dc857
-
8dc857
+	get_addr_of_highest_f1_f8_label(anc, &hf1;;
8dc857
 	vtoc_update_format4_label(anc->f4, &hf1, anc->f4->DS4DSREC - 1);
8dc857
 
8dc857
 	PDEBUG;
8dc857
 
8dc857
-	start = ext.llimit.cc * anc->geo.heads + ext.llimit.hh;
8dc857
-	stop  = ext.ulimit.cc * anc->geo.heads + ext.ulimit.hh;
8dc857
+	start = cchh2trk(&ext.llimit, &anc->geo);
8dc857
+	stop = cchh2trk(&ext.ulimit, &anc->geo);
8dc857
 
8dc857
 	PDEBUG;
8dc857
 	vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '-', anc->verbose,
8dc857
-					   start, stop, anc->geo.cylinders, anc->geo.heads);
8dc857
+			start, stop, anc->formatted_cylinders, anc->geo.heads);
8dc857
 
8dc857
 	anc->vtoc_changed++;
8dc857
 
8dc857
--- a/libparted/labels/vtoc.c
8dc857
+++ b/libparted/labels/vtoc.c
8dc857
@@ -218,11 +218,32 @@ vtoc_set_extent (extent_t *ext, u_int8_t
8dc857
 }
8dc857
 
8dc857
 void
8dc857
-vtoc_set_cchh (cchh_t *addr, u_int16_t cc, u_int16_t hh)
8dc857
+vtoc_set_cchh (cchh_t *addr, u_int32_t cc, u_int16_t hh)
8dc857
 {
8dc857
 	PDEBUG
8dc857
-	addr->cc = cc;
8dc857
-	addr->hh = hh;
8dc857
+	addr->cc = (u_int16_t) cc;
8dc857
+	addr->hh = cc >> 16;
8dc857
+	addr->hh <<= 4;
8dc857
+	addr->hh |= hh;
8dc857
+}
8dc857
+
8dc857
+u_int32_t
8dc857
+vtoc_get_cyl_from_cchh (cchh_t *addr)
8dc857
+{
8dc857
+	u_int32_t cyl;
8dc857
+
8dc857
+	/*decode cylinder for large volumes */
8dc857
+	cyl = addr->hh & 0xFFF0;
8dc857
+	cyl <<= 12;
8dc857
+	cyl |= addr->cc;
8dc857
+	return cyl;
8dc857
+}
8dc857
+
8dc857
+u_int16_t
8dc857
+vtoc_get_head_from_cchh (cchh_t *addr)
8dc857
+{
8dc857
+	/* decode heads for large volumes */
8dc857
+	return addr->hh & 0x000F;
8dc857
 }
8dc857
 
8dc857
 static void
8dc857
@@ -234,12 +255,63 @@ vtoc_set_ttr (ttr_t *addr, u_int16_t tt,
8dc857
 }
8dc857
 
8dc857
 void
8dc857
-vtoc_set_cchhb (cchhb_t *addr, u_int16_t cc, u_int16_t hh, u_int8_t b)
8dc857
+vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b)
8dc857
 {
8dc857
 	PDEBUG
8dc857
-	addr->cc = cc;
8dc857
-	addr->hh = hh;
8dc857
-	addr->b = b;
8dc857
+	addr->cc = (u_int16_t) cc;
8dc857
+	addr->hh = cc >> 16;
8dc857
+	addr->hh <<= 4;
8dc857
+	addr->hh |= hh;
8dc857
+	addr->b  = b;
8dc857
+}
8dc857
+
8dc857
+u_int32_t
8dc857
+vtoc_get_cyl_from_cchhb(cchhb_t *addr)
8dc857
+{
8dc857
+	u_int32_t cyl;
8dc857
+
8dc857
+	/* decode cylinder for large volumes */
8dc857
+	cyl = addr->hh & 0xFFF0;
8dc857
+	cyl <<= 12;
8dc857
+	cyl |= addr->cc;
8dc857
+	return cyl;
8dc857
+}
8dc857
+
8dc857
+u_int16_t
8dc857
+vtoc_get_head_from_cchhb(cchhb_t *addr)
8dc857
+{
8dc857
+	/* decode heads for large volumes */
8dc857
+	return addr->hh & 0x000F;
8dc857
+}
8dc857
+
8dc857
+/*
8dc857
+ * some functions to convert cyl-cyl-head-head addresses to
8dc857
+ * block or track numbers
8dc857
+ * Note: Record zero is special, so first block on a track is
8dc857
+ * in record 1!
8dc857
+ */
8dc857
+u_int64_t
8dc857
+cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo)
8dc857
+{
8dc857
+	return (u_int64_t) vtoc_get_cyl_from_cchhb(p) *
8dc857
+		geo->heads * geo->sectors +
8dc857
+		vtoc_get_head_from_cchhb(p) * geo->sectors +
8dc857
+		p->b;
8dc857
+}
8dc857
+
8dc857
+u_int64_t
8dc857
+cchh2blk (cchh_t *p, struct fdasd_hd_geometry *geo)
8dc857
+{
8dc857
+	return (u_int64_t) vtoc_get_cyl_from_cchh(p) *
8dc857
+		geo->heads * geo->sectors +
8dc857
+		vtoc_get_head_from_cchh(p) * geo->sectors;
8dc857
+}
8dc857
+
8dc857
+u_int32_t
8dc857
+cchh2trk (cchh_t *p, struct fdasd_hd_geometry *geo)
8dc857
+{
8dc857
+	return  vtoc_get_cyl_from_cchh(p) * geo->heads +
8dc857
+		vtoc_get_head_from_cchh(p);
8dc857
 }
8dc857
 
8dc857
 void
8dc857
@@ -506,7 +578,8 @@ vtoc_write_label (int f, unsigned long p
8dc857
 		  format1_label_t const *f1,
8dc857
                   format4_label_t const *f4,
8dc857
 		  format5_label_t const *f5,
8dc857
-		  format7_label_t const *f7)
8dc857
+		  format7_label_t const *f7,
8dc857
+		  format9_label_t const *f9)
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	int t;
8dc857
@@ -542,6 +615,17 @@ vtoc_write_label (int f, unsigned long p
8dc857
 			vtoc_error(unable_to_write, "vtoc_write_label",
8dc857
 				   _("Could not write VTOC FMT7 DSCB."));
8dc857
 	}
8dc857
+
8dc857
+	if (f9 != NULL)
8dc857
+	{
8dc857
+		t = sizeof(format9_label_t);
8dc857
+		if (write(f, f9, t) != t)
8dc857
+		{
8dc857
+			close(f);
8dc857
+			vtoc_error(unable_to_write, "vtoc_write_label",
8dc857
+				   _("Could not write VTOC FMT9 DSCB."));
8dc857
+		}
8dc857
+	}
8dc857
 }
8dc857
 
8dc857
 /*
8dc857
@@ -549,7 +633,8 @@ vtoc_write_label (int f, unsigned long p
8dc857
  */
8dc857
 void
8dc857
 vtoc_init_format4_label (format4_label_t *f4, unsigned int usable_partitions,
8dc857
-                         unsigned int cylinders, unsigned int tracks,
8dc857
+                         unsigned int compat_cylinders,
8dc857
+                         unsigned int real_cylinders, unsigned int tracks,
8dc857
                          unsigned int blocks, unsigned int blksize,
8dc857
                          u_int16_t dev_type)
8dc857
 {
8dc857
@@ -574,7 +659,7 @@ vtoc_init_format4_label (format4_label_t
8dc857
 	f4->DS4DEVAC = 0x00;
8dc857
 
8dc857
 	/* -- begin f4->DS4DEVCT -- */
8dc857
-	f4->DS4DEVCT.DS4DSCYL = cylinders;
8dc857
+	f4->DS4DEVCT.DS4DSCYL = compat_cylinders;
8dc857
 	f4->DS4DEVCT.DS4DSTRK = tracks;
8dc857
 
8dc857
 	switch (dev_type) {
8dc857
@@ -613,7 +698,11 @@ vtoc_init_format4_label (format4_label_t
8dc857
 	bzero(f4->res2, sizeof(f4->res2));
8dc857
 	f4->DS4EFLVL = 0x00;
8dc857
 	bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
8dc857
-	bzero(f4->res3, sizeof(f4->res3));
8dc857
+	bzero(&f4->res3, sizeof(f4->res3));
8dc857
+	f4->DS4DCYL = real_cylinders;
8dc857
+	bzero(f4->res4, sizeof(f4->res4));
8dc857
+	f4->DS4DEVF2 = 0x40; /* allow format 8 and 9 labels */
8dc857
+	bzero(&f4->res5, sizeof(f4->res5));
8dc857
 }
8dc857
 
8dc857
 /*
8dc857
@@ -647,11 +736,12 @@ vtoc_init_format7_label (format7_label_t
8dc857
 }
8dc857
 
8dc857
 /*
8dc857
- * initializes a format1 label
8dc857
+ * helper function that initializes a most parts of a
8dc857
+ * format1 or format 8 label, all but the field DS1FMTID
8dc857
  */
8dc857
 void
8dc857
-vtoc_init_format1_label (char *volid, unsigned int blksize,
8dc857
-                         extent_t *part_extent, format1_label_t *f1)
8dc857
+vtoc_init_format_1_8_label (char *volid, unsigned int blksize,
8dc857
+                            extent_t *part_extent, format1_label_t *f1)
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	struct tm * creatime;
8dc857
@@ -666,7 +756,6 @@ vtoc_init_format1_label (char *volid, un
8dc857
 	sprintf(str, "PART    .NEW                                ");
8dc857
 	vtoc_ebcdic_enc(str, str, 44);
8dc857
 	strncpy(f1->DS1DSNAM, str, 44);
8dc857
-	f1->DS1FMTID = 0xf1;
8dc857
 	strncpy(f1->DS1DSSN, "      ", 6);
8dc857
 	f1->DS1VOLSQ = 0x0001;
8dc857
 
8dc857
@@ -704,6 +793,37 @@ vtoc_init_format1_label (char *volid, un
8dc857
 	vtoc_set_cchhb(&f1->DS1PTRDS, 0x0000, 0x0000, 0x00);
8dc857
 }
8dc857
 
8dc857
+void
8dc857
+vtoc_init_format1_label (char *volid, unsigned int blksize,
8dc857
+                         extent_t *part_extent, format1_label_t *f1)
8dc857
+{
8dc857
+	vtoc_init_format_1_8_label(volid, blksize, part_extent, f1);
8dc857
+	f1->DS1FMTID = 0xf1;
8dc857
+}
8dc857
+
8dc857
+void
8dc857
+vtoc_init_format8_label (char *volid, unsigned int blksize,
8dc857
+                         extent_t *part_extent, format1_label_t *f8)
8dc857
+{
8dc857
+	vtoc_init_format_1_8_label(volid, blksize, part_extent, f8);
8dc857
+	f8->DS1FMTID = 0xf8;
8dc857
+}
8dc857
+
8dc857
+void
8dc857
+vtoc_update_format8_label (cchhb_t *associated_f9, format1_label_t *f8)
8dc857
+{
8dc857
+	memcpy(&f8->DS1PTRDS, associated_f9, sizeof(*associated_f9));
8dc857
+}
8dc857
+
8dc857
+void
8dc857
+vtoc_init_format9_label (format9_label_t *f9)
8dc857
+{
8dc857
+	f9->DS9KEYID = 0x09;
8dc857
+	f9->DS9SUBTY = 0x01;
8dc857
+	f9->DS9NUMF9 = 1;
8dc857
+	f9->DS9FMTID = 0xf9;
8dc857
+}
8dc857
+
8dc857
 /*
8dc857
  * do some updates to the VTOC format4 label
8dc857
  */
8dc857
@@ -1060,7 +1180,7 @@ vtoc_update_format7_label_add (format7_l
8dc857
 		if ((ext->a + ext->b) == 0x00000000)
8dc857
 			continue;
8dc857
 
8dc857
-		if ((ext->b + 1) == tmp->a) {
8dc857
+		if (ext->b == tmp->a) {
8dc857
 			/* this extent precedes the new one */
8dc857
 			ext->b = tmp->b;
8dc857
 			bzero(tmp, sizeof(ds7ext_t));
8dc857
@@ -1074,7 +1194,7 @@ vtoc_update_format7_label_add (format7_l
8dc857
 			continue;
8dc857
 		}
8dc857
 
8dc857
-		if (ext->a == (tmp->b + 1)) {
8dc857
+		if (ext->a == tmp->b) {
8dc857
 			/* this extent succeeds the new one */
8dc857
 			ext->a = tmp->a;
8dc857
 			bzero(tmp, sizeof(ds7ext_t));
8dc857
@@ -1119,7 +1239,7 @@ vtoc_update_format7_label_del (format7_l
8dc857
 
8dc857
 		if ((a == ext->a) && (b < ext->b)) {
8dc857
 			/* left-bounded in free space gap */
8dc857
-			ext->a = b + 1;
8dc857
+			ext->a = b;
8dc857
 
8dc857
 			if (verbose)
8dc857
 				puts ("FMT7 add extent: left-bounded");
8dc857
@@ -1130,7 +1250,7 @@ vtoc_update_format7_label_del (format7_l
8dc857
 
8dc857
 		if ((a > ext->a) && (b == ext->b)) {
8dc857
 			/* right-bounded in free space gap */
8dc857
-			ext->b = a - 1;
8dc857
+			ext->b = a;
8dc857
 
8dc857
 			if (verbose)
8dc857
 				puts ("FMT7 add extent: right-bounded");
8dc857
@@ -1141,8 +1261,8 @@ vtoc_update_format7_label_del (format7_l
8dc857
 
8dc857
 		if ((a > ext->a) && (b < ext->b)) {
8dc857
 			/* partition devides free space into 2 pieces */
8dc857
-			vtoc_update_format7_label_add(f7, verbose, b+1, ext->b);
8dc857
-			ext->b = a - 1;
8dc857
+			vtoc_update_format7_label_add(f7, verbose, b, ext->b);
8dc857
+			ext->b = a;
8dc857
 
8dc857
 			if (verbose)
8dc857
 				puts ("FMT7 add extent: 2 pieces");
8dc857
@@ -1172,14 +1292,19 @@ vtoc_update_format7_label_del (format7_l
8dc857
 void
8dc857
 vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
8dc857
                    format7_label_t *f7, char ch, int verbose,
8dc857
-                   u_int32_t start, u_int32_t stop, int cyl, int trk)
8dc857
+                   u_int32_t start, u_int32_t stop, u_int32_t cyl,
8dc857
+                   u_int32_t trk)
8dc857
 {
8dc857
 	PDEBUG
8dc857
 	if ((cyl * trk) > BIG_DISK_SIZE) {
8dc857
 		if (ch == '+')
8dc857
-			vtoc_update_format7_label_add(f7, verbose, start, stop);
8dc857
+			vtoc_update_format7_label_add(f7, verbose, start,
8dc857
+						      /* ds7ext RTA + 1 */
8dc857
+						      stop + 1);
8dc857
 		else if (ch == '-')
8dc857
-			vtoc_update_format7_label_del(f7, verbose, start, stop);
8dc857
+			vtoc_update_format7_label_del(f7, verbose, start,
8dc857
+						      /* ds7ext RTA + 1 */
8dc857
+						      stop + 1);
8dc857
 		else
8dc857
 			puts ("BUG: syntax error in vtoc_set_freespace call");
8dc857