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

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