[parted/f18] - change partition UUID to use partX-UUID (#858704) - fixup losetup usage in tests - add support for

Brian C. Lane bcl at fedoraproject.org
Tue Oct 16 23:54:49 UTC 2012


commit 68f2aab138cd95a9aa657720ae0c3af02f979f96
Author: Brian C. Lane <bcl at redhat.com>
Date:   Tue Oct 16 16:53:14 2012 -0700

    - change partition UUID to use partX-UUID (#858704)
    - fixup losetup usage in tests
    - add support for implicit FBA DASD partitions (#707027)
    - add support for EAV DASD partitions (#707032)

 ...arted-add-support-for-EAV-DASD-partitions.patch | 1058 ++++++++++++++++++++
 ...-support-for-implicit-FBA-DASD-partitions.patch |  187 ++++
 ...parted-preserve-the-uuid-on-dm-partitions.patch |   14 +-
 ...1-tests-Make-sure-dm-UUIDs-are-not-erased.patch |    2 +-
 parted-3.1-tests-cleanup-losetup-usage.patch       |  137 +++
 parted.spec                                        |   11 +-
 6 files changed, 1400 insertions(+), 9 deletions(-)
---
diff --git a/parted-3.1-libparted-add-support-for-EAV-DASD-partitions.patch b/parted-3.1-libparted-add-support-for-EAV-DASD-partitions.patch
new file mode 100644
index 0000000..81f73a8
--- /dev/null
+++ b/parted-3.1-libparted-add-support-for-EAV-DASD-partitions.patch
@@ -0,0 +1,1058 @@
+Subject: [PATCH] libparted: add support for EAV DASD partitions
+
+From: Nageswara R Sastry <rnsastry at linux.vnet.ibm.com>
+
+Extended Address Volume (EAV) DASDs are ECKD DASDs with more than
+65520 cylinders. This patch adds support for recognizing and
+modifying partitions on EAV DASDs to Parted. The changes are
+based on the EAV support added to version 1.8.1 [1] of the
+s390-tools package.
+
+[1] http://www.ibm.com/developerworks/linux/linux390/s390-tools-1.8.1.html
+
+Signed-off-by: Nageswara R Sastry <rnsastry at linux.vnet.ibm.com>
+Signed-off-by: Peter Oberparleiter <oberpar at linux.vnet.ibm.com>
+
+---
+ include/parted/fdasd.h   |   89 ++++++++++++++++--
+ include/parted/vtoc.h    |   58 ++++++++++--
+ libparted/labels/dasd.c  |    1 
+ libparted/labels/fdasd.c |  226 ++++++++++++++++++++++++++++++++---------------
+ libparted/labels/vtoc.c  |  173 ++++++++++++++++++++++++++++++-----
+ 5 files changed, 435 insertions(+), 112 deletions(-)
+
+--- a/include/parted/fdasd.h
++++ b/include/parted/fdasd.h
+@@ -74,6 +74,80 @@ typedef struct dasd_information_t {
+ 	char configuration_data[256]; /* from read_configuration_data        */
+ } dasd_information_t;
+ 
++struct dasd_eckd_characteristics {
++	unsigned short cu_type;
++	struct {
++		unsigned char support:2;
++		unsigned char async:1;
++		unsigned char reserved:1;
++		unsigned char cache_info:1;
++		unsigned char model:3;
++	} __attribute__ ((packed)) cu_model;
++	unsigned short dev_type;
++	unsigned char dev_model;
++	struct {
++		unsigned char mult_burst:1;
++		unsigned char RT_in_LR:1;
++		unsigned char reserved1:1;
++		unsigned char RD_IN_LR:1;
++		unsigned char reserved2:4;
++		unsigned char reserved3:8;
++		unsigned char defect_wr:1;
++		unsigned char XRC_supported:1;
++		unsigned char reserved4:1;
++		unsigned char striping:1;
++		unsigned char reserved5:4;
++		unsigned char cfw:1;
++		unsigned char reserved6:2;
++		unsigned char cache:1;
++		unsigned char dual_copy:1;
++		unsigned char dfw:1;
++		unsigned char reset_alleg:1;
++		unsigned char sense_down:1;
++	} __attribute__ ((packed)) facilities;
++	unsigned char dev_class;
++	unsigned char unit_type;
++	unsigned short no_cyl;
++	unsigned short trk_per_cyl;
++	unsigned char sec_per_trk;
++	unsigned char byte_per_track[3];
++	unsigned short home_bytes;
++	unsigned char formula;
++	union {
++		struct {
++			unsigned char f1;
++			unsigned short f2;
++			unsigned short f3;
++		} __attribute__ ((packed)) f_0x01;
++		struct {
++			unsigned char f1;
++			unsigned char f2;
++			unsigned char f3;
++			unsigned char f4;
++			unsigned char f5;
++		} __attribute__ ((packed)) f_0x02;
++	} __attribute__ ((packed)) factors;
++	unsigned short first_alt_trk;
++	unsigned short no_alt_trk;
++	unsigned short first_dia_trk;
++	unsigned short no_dia_trk;
++	unsigned short first_sup_trk;
++	unsigned short no_sup_trk;
++	unsigned char MDR_ID;
++	unsigned char OBR_ID;
++	unsigned char director;
++	unsigned char rd_trk_set;
++	unsigned short max_rec_zero;
++	unsigned char reserved1;
++	unsigned char RWANY_in_LR;
++	unsigned char factor6;
++	unsigned char factor7;
++	unsigned char factor8;
++	unsigned char reserved2[3];
++	unsigned char reserved3[6];
++	unsigned int long_no_cyl;
++} __attribute__ ((packed));
++
+ /*
+  * struct format_data_t
+  * represents all data necessary to format a dasd
+@@ -116,18 +190,6 @@ typedef struct format_data_t {
+ #define BLKRRPART  _IO(0x12,95)
+ /* get block device sector size */
+ #define BLKSSZGET  _IO(0x12,104)
+-
+-/*****************************************************************************
+- * SECTION: Definition from hdreq.h                                          *
+- *****************************************************************************/
+-
+-struct fdasd_hd_geometry {
+-      unsigned char heads;
+-      unsigned char sectors;
+-      unsigned short cylinders;
+-      unsigned long start;
+-};
+-
+ /* get device geometry */
+ #define HDIO_GETGEO		0x0301
+ 
+@@ -189,10 +251,13 @@ typedef struct fdasd_anchor {
+ 	format4_label_t  *f4;
+ 	format5_label_t  *f5;
+ 	format7_label_t  *f7;
++	format9_label_t  *f9; /* template for all f9 labels */
+ 	partition_info_t *first;
+ 	partition_info_t *last;
+ 	volume_label_t   *vlabel;
+ 	config_data_t confdata[USABLE_PARTITIONS];
++	u_int32_t hw_cylinders;
++	u_int32_t formatted_cylinders;
+ 	struct fdasd_hd_geometry geo;
+ 	unsigned int label_block;
+ 	unsigned int FBA_layout;
+--- a/include/parted/vtoc.h
++++ b/include/parted/vtoc.h
+@@ -42,7 +42,18 @@
+ 
+ #define VOLSER_LENGTH 6
+ #define BIG_DISK_SIZE 0x10000
++#define LV_COMPAT_CYL 0xFFFE
+ 
++/*****************************************************************************
++ * SECTION: Definition from hdreq.h                                          *
++ *****************************************************************************/
++
++struct fdasd_hd_geometry {
++      unsigned char heads;
++      unsigned char sectors;
++      unsigned short cylinders;
++      unsigned long start;
++};
+ 
+ typedef struct ttr              ttr_t;
+ typedef struct cchhb            cchhb_t;
+@@ -59,6 +70,7 @@ typedef struct ds5ext           ds5ext_t
+ typedef struct format5_label    format5_label_t;
+ typedef struct ds7ext           ds7ext_t;
+ typedef struct format7_label    format7_label_t;
++typedef struct format9_label    format9_label_t;
+ 
+ struct __attribute__ ((packed)) ttr {
+         u_int16_t tt;
+@@ -169,6 +181,10 @@ struct __attribute__ ((packed)) dev_cons
+         u_int8_t  DS4DEVDB;     /* number of directory blocks per track */
+ };
+ 
++/*
++ * format 1 and format 8 label have the same layout so we use the following
++ * structure for both.
++ */
+ struct __attribute__ ((packed)) format1_label {
+ 	char  DS1DSNAM[44];     /* data set name                           */
+ 	u_int8_t  DS1FMTID;     /* format identifier                       */
+@@ -229,7 +245,11 @@ struct __attribute__ ((packed)) format4_
+ 	char res2[10];          /* reserved                                */
+ 	u_int8_t DS4EFLVL;      /* extended free-space management level    */
+ 	cchhb_t DS4EFPTR;       /* pointer to extended free-space info     */
+-	char res3[9];           /* reserved                                */
++	char res3;              /* reserved */
++	u_int32_t DS4DCYL;      /* number of logical cyls */
++	char res4[2];           /* reserved */
++	u_int8_t DS4DEVF2;      /* device flags */
++	char res5;              /* reserved */
+ };
+ 
+ struct __attribute__ ((packed)) ds5ext {
+@@ -261,12 +281,28 @@ struct __attribute__ ((packed)) format7_
+ 	cchhb_t DS7PTRDS;       /* pointer to next FMT7 DSCB               */
+ };
+ 
++struct __attribute__ ((packed)) format9_label {
++	u_int8_t  DS9KEYID;     /* key code for format 9 labels (0x09) */
++	u_int8_t  DS9SUBTY;     /* subtype (0x01) */
++	u_int8_t  DS9NUMF9;     /* number of F9 datasets  */
++	u_int8_t  res1[41];     /* reserved  */
++	u_int8_t  DS9FMTID;     /* format identifier  */
++	u_int8_t  res2[95];     /* reserved */
++};
++
+ char *vtoc_ebcdic_enc (char const *source, char *target, int l);
+ char *vtoc_ebcdic_dec (char const *source, char *target, int l);
+ void vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno,
+                       cchh_t *lower, cchh_t *upper);
+-void vtoc_set_cchh (cchh_t *addr, u_int16_t cc, u_int16_t hh);
+-void vtoc_set_cchhb (cchhb_t *addr, u_int16_t cc, u_int16_t hh, u_int8_t b);
++void vtoc_set_cchh (cchh_t *addr, u_int32_t cc, u_int16_t hh);
++u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
++u_int16_t vtoc_get_head_from_cchh(cchh_t *addr);
++void vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b);
++u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
++u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
++u_int64_t cchhb2blk(cchhb_t *p, struct fdasd_hd_geometry *geo);
++u_int64_t cchh2blk (cchh_t *p, struct fdasd_hd_geometry *geo);
++u_int32_t cchh2trk (cchh_t *p, struct fdasd_hd_geometry *geo);
+ void vtoc_set_date (labeldate_t *d, u_int8_t year, u_int16_t day);
+ 
+ void vtoc_volume_label_init (volume_label_t *vlabel);
+@@ -295,14 +331,16 @@ void vtoc_write_label (int fd, unsigned
+ 		       format1_label_t const *f1,
+                        format4_label_t const *f4,
+ 		       format5_label_t const *f5,
+-                       format7_label_t const *f7);
++                       format7_label_t const *f7,
++                       format9_label_t const *f9);
+ 
+ void vtoc_init_format1_label (char *volid, unsigned int blksize,
+                               extent_t *part_extent, format1_label_t *f1);
+ 
+ void vtoc_init_format4_label (format4_label_t *f4lbl,
+                               unsigned int usable_partitions,
+-                              unsigned int cylinders,
++                              unsigned int compat_cylinders,
++                              unsigned int real_cylinders,
+                               unsigned int tracks,
+                               unsigned int blocks,
+                               unsigned int blksize,
+@@ -329,8 +367,16 @@ void vtoc_update_format7_label_add (form
+ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
+                                     u_int32_t a, u_int32_t b);
+ 
++void vtoc_init_format8_label (char *volid, unsigned int blksize,
++                              extent_t *part_extent, format1_label_t *f1);
++
++void vtoc_update_format8_label (cchhb_t *associated_f9, format1_label_t *f8);
++
++void vtoc_init_format9_label (format9_label_t *f9);
++
+ void vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
+                         format7_label_t *f7, char ch, int verbose,
+-                        u_int32_t start, u_int32_t stop, int cyl, int trk);
++                        u_int32_t start, u_int32_t stop, u_int32_t cyl,
++                        u_int32_t trk);
+ 
+ #endif /* VTOC_H */
+--- a/libparted/labels/dasd.c
++++ b/libparted/labels/dasd.c
+@@ -631,6 +631,7 @@ dasd_write (const PedDisk* disk)
+ 	/* initialize the anchor */
+ 	fdasd_initialize_anchor(&anchor);
+ 	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
++	fdasd_check_volume(&anchor, arch_specific->fd);
+ 	memcpy(anchor.vlabel, &disk_specific->vlabel, sizeof(volume_label_t));
+ 	anchor.vlabel_changed++;
+ 
+--- a/libparted/labels/fdasd.c
++++ b/libparted/labels/fdasd.c
+@@ -59,6 +59,48 @@ setpos (fdasd_anchor_t *anc, int dsn, in
+ 	anc->partno[dsn] = pos;
+ }
+ 
++static u_int32_t
++get_usable_cylinders (fdasd_anchor_t *anc)
++{
++	u_int32_t cyl;
++
++	/* large volume */
++	if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
++	    anc->f4->DS4DCYL > anc->f4->DS4DEVCT.DS4DSCYL)
++		return anc->f4->DS4DCYL;
++	/* normal volume */
++	if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
++		cyl = anc->f4->DS4DEVCT.DS4DSCYL -
++			(u_int16_t) anc->f4->DS4DEVAC;
++	else
++		cyl = anc->f4->DS4DEVCT.DS4DSCYL;
++	return cyl;
++}
++
++static void
++get_addr_of_highest_f1_f8_label (fdasd_anchor_t *anc, cchhb_t *addr)
++{
++
++	u_int8_t record;
++	/* We have to count the follwing labels:
++	 * one format 4
++	 * one format 5
++	 * format 7 only if we have moren then BIG_DISK_SIZE tracks
++	 * one for each format 1 or format 8 label == one for each partition
++	 * one for each format 9 label before the last format 8
++	 * We assume that all partitions use format 8 labels when
++	 *  anc->formatted_cylinders > LV_COMPAT_CYL
++	 * Note: Record zero is special, so block 0 on our disk is record 1!
++	 */
++
++	record = anc->used_partitions + 2;
++	if (anc->big_disk)
++		record++;
++	if (anc->formatted_cylinders > LV_COMPAT_CYL)
++		record += anc->used_partitions - 1;
++	vtoc_set_cchhb(addr, VTOC_START_CC, VTOC_START_HH, record);
++}
++
+ void
+ fdasd_cleanup (fdasd_anchor_t *anchor)
+ {
+@@ -72,6 +114,7 @@ fdasd_cleanup (fdasd_anchor_t *anchor)
+         free(anchor->f4);
+         free(anchor->f5);
+         free(anchor->f7);
++        free(anchor->f9);
+         free(anchor->vlabel);
+ 
+ 	p = anchor->first;
+@@ -82,6 +125,7 @@ fdasd_cleanup (fdasd_anchor_t *anchor)
+ 		if (p == NULL)
+ 			return;
+ 		q = p->next;
++		free(p->f1);
+ 		free(p);
+ 		p = q;
+ 	}
+@@ -154,17 +198,6 @@ fdasd_error (fdasd_anchor_t *anc, enum f
+ }
+ 
+ /*
+- * converts cyl-cyl-head-head-blk to blk
+- */
+-static unsigned long
+-cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo)
+-{
+-	PDEBUG
+-	return (unsigned long) (p->cc * geo->heads * geo->sectors
+-	                        + p->hh * geo->sectors + p->b);
+-}
+-
+-/*
+  * initializes the anchor structure and allocates some
+  * memory for the labels
+  */
+@@ -216,9 +249,16 @@ fdasd_initialize_anchor (fdasd_anchor_t
+ 	if (anc->f7 == NULL)
+ 		fdasd_error(anc, malloc_failed, "FMT7 DSCB.");
+ 
++       /* template for all format 9 labels */
++	anc->f9 = malloc(sizeof(format9_label_t));
++	if (anc->f9 == NULL)
++		fdasd_error(anc, malloc_failed, "FMT9 DSCB.");
++
+ 	bzero(anc->f4, sizeof(format4_label_t));
+ 	bzero(anc->f5, sizeof(format5_label_t));
+ 	bzero(anc->f7, sizeof(format7_label_t));
++	bzero(anc->f9, sizeof(format9_label_t));
++	vtoc_init_format9_label(anc->f9);
+ 
+ 	v = malloc(sizeof(volume_label_t));
+ 	if (v == NULL)
+@@ -259,6 +299,8 @@ fdasd_initialize_anchor (fdasd_anchor_t
+ 
+ 		q = p;
+ 	}
++	anc->hw_cylinders = 0;
++	anc->formatted_cylinders = 0;
+ }
+ 
+ /*
+@@ -269,44 +311,46 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
+ {
+ 	PDEBUG
+ 	partition_info_t *p;
+-	unsigned long b;
++	unsigned long b, maxblk;
+ 	char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
+ 	int i = 0, k = 0;
++	cchhb_t f9addr;
++	format1_label_t emptyf1;
+ 
+ 	b = (cchhb2blk (&anc->vlabel->vtoc, &anc->geo) - 1) * anc->blksize;
+ 	if (b <= 0)
+ 		fdasd_error (anc, vlabel_corrupted, "");
++	maxblk = b + anc->blksize * 9; /* f4+f5+f7+3*f8+3*f9 */
+ 
+ 	/* write FMT4 DSCB */
+-	vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL);
++	vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL, NULL);
++	b += anc->blksize;
+ 
+ 	/* write FMT5 DSCB */
++	vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL, NULL);
+ 	b += anc->blksize;
+-	vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL);
+ 
+ 	/* write FMT7 DSCB */
+ 	if (anc->big_disk) {
++		vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7, NULL);
+ 		b += anc->blksize;
+-		vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7);
+ 	}
+ 
+-	/* loop over all FMT1 DSCBs */
+-	p = anc->first;
+-	for (i = 0; i < USABLE_PARTITIONS; i++) {
+-		b += anc->blksize;
++	/* loop over all partitions (format 1 or format 8 DCB) */
++	for (p = anc->first; p != NULL; p = p->next) {
+ 
+ 		if (p->used != 0x01) {
+-			vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
+ 			continue;
+ 		}
+ 
++		i++;
+ 		strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
+ 
+ 		ch = p->f1->DS1DSNAM;
+ 		vtoc_ebcdic_dec (ch, ch, 44);
+ 		c1 = ch + 7;
+ 
+-		if (getdsn (anc, i) > -1) {
++		if (getdsn (anc, i-1) > -1) {
+ 			/* re-use the existing data set name */
+ 			c2 = strchr (c1, '.');
+ 			if (c2 != NULL)
+@@ -325,11 +369,7 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
+ 			while (getpos (anc, k) > -1)
+ 				k++;
+ 
+-			setpos (anc, k, i);
+-
+-			strncpy (s2, ch, 44);
+-			s2[44] = 0;
+-			vtoc_ebcdic_dec (s2, s2, 44);
++			setpos (anc, k, i-1);
+ 
+ 			strncpy (ch, "LINUX.V               " "                      ", 44);
+ 
+@@ -366,8 +406,32 @@ fdasd_write_vtoc_labels (fdasd_anchor_t
+ 
+ 		vtoc_ebcdic_enc (ch, ch, 44);
+ 
+-		vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
+-		p = p->next;
++		if (p->f1->DS1FMTID == 0xf8 ) {
++			/* Now as we know where which label will be written, we
++			 * can add the address of the format 9 label to the
++			 * format 8 label. The f9 record will be written to the
++			 * block after the current blk. Remember: records are of
++			 * by one, so we have to add 2 and not just one.
++			 */
++			vtoc_set_cchhb(&f9addr, VTOC_START_CC, VTOC_START_HH,
++				((b / anc->blksize) % anc->geo.sectors) + 2);
++			vtoc_update_format8_label(&f9addr, p->f1);
++			vtoc_write_label(fd, b, p->f1, NULL, NULL, NULL, NULL);
++			b += anc->blksize;
++			vtoc_write_label(fd, b, NULL, NULL, NULL, NULL,
++					 anc->f9);
++			b += anc->blksize;
++		} else {
++			vtoc_write_label(fd, b, p->f1, NULL, NULL, NULL, NULL);
++			b += anc->blksize;
++		}
++	}
++
++	/* write empty labels to the rest of the blocks */
++	bzero(&emptyf1, sizeof(emptyf1));
++	while (b < maxblk) {
++		vtoc_write_label(fd, b, &emptyf1, NULL, NULL, NULL, NULL);
++		b += anc->blksize;
+ 	}
+ }
+ 
+@@ -394,20 +458,25 @@ int
+ fdasd_prepare_labels (fdasd_anchor_t *anc, int fd)
+ {
+ 	PDEBUG
+-	partition_info_t *p = anc->first;
++	partition_info_t *p;
+ 	char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
+ 	int i = 0, k = 0;
+ 
+-	/* loop over all FMT1 DSCBs */
+-	p = anc->first;
+-	for (i = 0; i < USABLE_PARTITIONS; i++) {
++	/* loop over all partitions (format 1 or format 8 DCB) */
++	for (p = anc->first; p != NULL; p = p->next) {
++
++		if (p->used != 0x01) {
++			continue;
++		}
++
++		i++;
+ 		strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
+ 
+ 		ch = p->f1->DS1DSNAM;
+ 		vtoc_ebcdic_dec (ch, ch, 44);
+ 		c1 = ch + 7;
+ 
+-		if (getdsn (anc, i) > -1) {
++		if (getdsn (anc, i-1) > -1) {
+ 			/* re-use the existing data set name */
+ 			c2 = strchr (c1, '.');
+ 			if (c2 != NULL)
+@@ -426,11 +495,7 @@ fdasd_prepare_labels (fdasd_anchor_t *an
+ 			while (getpos (anc, k) > -1)
+ 				k++;
+ 
+-			setpos (anc, k, i);
+-
+-			strncpy (s2, ch, 44);
+-			s2[44] = 0;
+-			vtoc_ebcdic_dec (s2, s2, 44);
++			setpos (anc, k, i-1);
+ 
+ 			strncpy (ch, "LINUX.V               " "                      ", 44);
+ 
+@@ -466,7 +531,6 @@ fdasd_prepare_labels (fdasd_anchor_t *an
+ 		}
+ 
+ 		vtoc_ebcdic_enc (ch, ch, 44);
+-		p = p->next;
+ 	}
+ 
+ 	return 1;
+@@ -482,6 +546,7 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
+ 	vtoc_init_format4_label(anc->f4,
+ 							USABLE_PARTITIONS,
+ 							anc->geo.cylinders,
++						anc->formatted_cylinders,
+ 							anc->geo.heads,
+ 							anc->geo.sectors,
+ 							anc->blksize,
+@@ -492,8 +557,8 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
+ 	vtoc_set_freespace(anc->f4, anc->f5, anc->f7,
+ 					   '+', anc->verbose,
+ 					   FIRST_USABLE_TRK,
+-					   anc->geo.cylinders * anc->geo.heads - 1,
+-					   anc->geo.cylinders, anc->geo.heads);
++				anc->formatted_cylinders * anc->geo.heads - 1,
++				anc->formatted_cylinders, anc->geo.heads);
+ 
+ 	for (i = 0; i < USABLE_PARTITIONS; i++) {
+ 		bzero(p->f1, sizeof(format1_label_t));
+@@ -507,7 +572,8 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc
+ 	}
+ 
+ 	anc->used_partitions = 0;
+-	anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
++	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads -
++			  FIRST_USABLE_TRK;
+ 
+ 	for (i=0; i<USABLE_PARTITIONS; i++)
+ 		setpos(anc, i, -1);
+@@ -526,15 +592,15 @@ fdasd_update_partition_info (fdasd_ancho
+ {
+ 	PDEBUG
+ 	partition_info_t *q = NULL, *p = anc->first;
+-	unsigned int h = anc->geo.heads;
+-	unsigned long max = anc->geo.cylinders * h - 1;
++	unsigned long max = anc->formatted_cylinders * anc->geo.heads - 1;
+ 	int i;
+ 	char *ch;
+ 
+ 	anc->used_partitions = anc->geo.sectors - 2 - anc->f4->DS4DSREC;
+ 
+ 	for (i = 1; i <= USABLE_PARTITIONS; i++) {
+-		if (p->f1->DS1FMTID != 0xf1) {
++		if (p->f1->DS1FMTID != 0xf1 &&
++		    p->f1->DS1FMTID != 0xf8) {
+ 			if (i == 1)
+ 				/* there is no partition at all */
+ 				anc->fspace_trk = max - FIRST_USABLE_TRK + 1;
+@@ -546,8 +612,8 @@ fdasd_update_partition_info (fdasd_ancho
+ 
+ 		/* this is a valid format 1 label */
+ 		p->used = 0x01;
+-		p->start_trk = p->f1->DS1EXT1.llimit.cc * h + p->f1->DS1EXT1.llimit.hh;
+-		p->end_trk   = p->f1->DS1EXT1.ulimit.cc * h + p->f1->DS1EXT1.ulimit.hh;
++		p->start_trk = cchh2trk(&p->f1->DS1EXT1.llimit,	&anc->geo);
++		p->end_trk = cchh2trk(&p->f1->DS1EXT1.ulimit, &anc->geo);
+ 		p->len_trk   = p->end_trk - p->start_trk + 1;
+ 
+ 		if (i == 1) {
+@@ -618,14 +684,22 @@ fdasd_process_valid_vtoc (fdasd_anchor_t
+ 	format1_label_t q;
+ 	char s[5], *ch;
+ 
++	if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
++	    anc->f4->DS4DCYL > anc->f4->DS4DEVCT.DS4DSCYL)
++		anc->formatted_cylinders = anc->f4->DS4DCYL;
++	else
++		anc->formatted_cylinders = anc->f4->DS4DEVCT.DS4DSCYL;
++	anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads -
++			  FIRST_USABLE_TRK;
+ 	b += anc->blksize;
+ 
+-	for (i = 1; i <= anc->geo.sectors; i++) {
++	for (i = 1; i < anc->geo.sectors; i++) {
+ 		bzero (&q, f1size);
+ 		vtoc_read_label (fd, b, &q, NULL, NULL, NULL);
+ 
+ 		switch (q.DS1FMTID) {
+ 			case 0xf1:
++			case 0xf8:
+ 				if (p == NULL)
+ 					break;
+ 				memcpy (p->f1, &q, f1size);
+@@ -669,6 +743,12 @@ fdasd_process_valid_vtoc (fdasd_anchor_t
+ 					memcpy (anc->f7, &q, f1size);
+ 				f7_counter++;
+ 				break;
++			case 0xf9:
++				/* each format 8 lable has an associated
++				 * format 9 lable, but they are of no further
++				 * use to us.
++				 */
++				break;
+ 		}
+ 
+ 		b += anc->blksize;
+@@ -718,7 +798,7 @@ fdasd_check_volume (fdasd_anchor_t *anc,
+ {
+ 	PDEBUG
+ 	volume_label_t *v = anc->vlabel;
+-	unsigned long b = -1;
++	long long b = -1;
+ 	char str[LINE_LENGTH];
+ 
+ 	memset(v, 0, sizeof(volume_label_t));
+@@ -784,6 +864,7 @@ fdasd_get_geometry (const PedDevice *dev
+ 	PDEBUG
+ 	int blksize = 0;
+ 	dasd_information_t dasd_info;
++	struct dasd_eckd_characteristics *characteristics;
+ 
+ 	/* We can't get geometry from a regular file,
+ 	   so simulate something usable, for the sake of testing.  */
+@@ -803,6 +884,8 @@ fdasd_get_geometry (const PedDevice *dev
+ 	    dasd_info.devno = 513;
+ 	    dasd_info.label_block = 2;
+ 	    dasd_info.FBA_layout = 0;
++	    anc->hw_cylinders = ((st.st_size / blksize) / anc->geo.sectors) /
++				anc->geo.heads;
+ 	} else {
+ 		if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
+ 			fdasd_error(anc, unable_to_ioctl,
+@@ -816,13 +899,20 @@ fdasd_get_geometry (const PedDevice *dev
+ 		if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
+ 			fdasd_error(anc, unable_to_ioctl,
+ 				    _("Could not retrieve disk information."));
++
++		characteristics = (struct dasd_eckd_characteristics *)
++					&dasd_info.characteristics;
++		if (characteristics->no_cyl == LV_COMPAT_CYL &&
++		    characteristics->long_no_cyl)
++			anc->hw_cylinders = characteristics->long_no_cyl;
++		else
++			anc->hw_cylinders = characteristics->no_cyl;
+ 	}
+ 
+ 	anc->dev_type   = dasd_info.dev_type;
+ 	anc->blksize    = blksize;
+ 	anc->label_pos  = dasd_info.label_block * blksize;
+ 	anc->devno      = dasd_info.devno;
+-	anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
+ 	anc->label_block = dasd_info.label_block;
+ 	anc->FBA_layout = dasd_info.FBA_layout;
+ }
+@@ -850,20 +940,17 @@ fdasd_get_partition_data (fdasd_anchor_t
+                           unsigned int *stop_ptr)
+ {
+ 	PDEBUG
+-	unsigned int limit, cc, hh;
++	unsigned int limit;
++	u_int32_t cc, c;
++	u_int16_t hh, h;
+ 	cchh_t llimit, ulimit;
+ 	partition_info_t *q;
+ 	u_int8_t b1, b2;
+-	u_int16_t c, h;
+ 	unsigned int start = *start_ptr, stop = *stop_ptr;
+ 	int i;
+ 	char *ch;
+ 
+-	if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
+-		c = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t) anc->f4->DS4DEVAC;
+-	else
+-		c = anc->f4->DS4DEVCT.DS4DSCYL;
+-
++	c = get_usable_cylinders(anc);
+ 	h = anc->f4->DS4DEVCT.DS4DSTRK;
+ 	limit = (h * c - 1);
+ 
+@@ -1019,7 +1106,6 @@ fdasd_add_partition (fdasd_anchor_t *anc
+ 	cchhb_t hf1;
+ 	partition_info_t *p;
+ 	extent_t ext;
+-	int i;
+ 
+ 	PDEBUG;
+ 
+@@ -1032,8 +1118,14 @@ fdasd_add_partition (fdasd_anchor_t *anc
+ 	if (fdasd_get_partition_data(anc, &ext, p, &start, &stop) != 0)
+ 		return 0;
+ 
+-	PDEBUG;
+-	vtoc_init_format1_label(anc->vlabel->volid, anc->blksize, &ext, p->f1);
++	if (anc->formatted_cylinders > LV_COMPAT_CYL) {
++		vtoc_init_format8_label(anc->vlabel->volid, anc->blksize, &ext,
++					p->f1);
++	} else {
++		PDEBUG;
++		vtoc_init_format1_label(anc->vlabel->volid, anc->blksize, &ext,
++					p->f1);
++	}
+ 
+ 	PDEBUG;
+ 	fdasd_enqueue_new_partition(anc);
+@@ -1041,23 +1133,17 @@ fdasd_add_partition (fdasd_anchor_t *anc
+ 	PDEBUG;
+ 	anc->used_partitions += 1;
+ 
+-	i = anc->used_partitions + 2;
+-	if (anc->big_disk)
+-		i++;
+-	PDEBUG;
+-
+-	vtoc_set_cchhb(&hf1, VTOC_START_CC, VTOC_START_HH, i);
+-
++	get_addr_of_highest_f1_f8_label(anc, &hf1);
+ 	vtoc_update_format4_label(anc->f4, &hf1, anc->f4->DS4DSREC - 1);
+ 
+ 	PDEBUG;
+ 
+-	start = ext.llimit.cc * anc->geo.heads + ext.llimit.hh;
+-	stop  = ext.ulimit.cc * anc->geo.heads + ext.ulimit.hh;
++	start = cchh2trk(&ext.llimit, &anc->geo);
++	stop = cchh2trk(&ext.ulimit, &anc->geo);
+ 
+ 	PDEBUG;
+ 	vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '-', anc->verbose,
+-					   start, stop, anc->geo.cylinders, anc->geo.heads);
++			start, stop, anc->formatted_cylinders, anc->geo.heads);
+ 
+ 	anc->vtoc_changed++;
+ 
+--- a/libparted/labels/vtoc.c
++++ b/libparted/labels/vtoc.c
+@@ -218,11 +218,32 @@ vtoc_set_extent (extent_t *ext, u_int8_t
+ }
+ 
+ void
+-vtoc_set_cchh (cchh_t *addr, u_int16_t cc, u_int16_t hh)
++vtoc_set_cchh (cchh_t *addr, u_int32_t cc, u_int16_t hh)
+ {
+ 	PDEBUG
+-	addr->cc = cc;
+-	addr->hh = hh;
++	addr->cc = (u_int16_t) cc;
++	addr->hh = cc >> 16;
++	addr->hh <<= 4;
++	addr->hh |= hh;
++}
++
++u_int32_t
++vtoc_get_cyl_from_cchh (cchh_t *addr)
++{
++	u_int32_t cyl;
++
++	/*decode cylinder for large volumes */
++	cyl = addr->hh & 0xFFF0;
++	cyl <<= 12;
++	cyl |= addr->cc;
++	return cyl;
++}
++
++u_int16_t
++vtoc_get_head_from_cchh (cchh_t *addr)
++{
++	/* decode heads for large volumes */
++	return addr->hh & 0x000F;
+ }
+ 
+ static void
+@@ -234,12 +255,63 @@ vtoc_set_ttr (ttr_t *addr, u_int16_t tt,
+ }
+ 
+ void
+-vtoc_set_cchhb (cchhb_t *addr, u_int16_t cc, u_int16_t hh, u_int8_t b)
++vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b)
+ {
+ 	PDEBUG
+-	addr->cc = cc;
+-	addr->hh = hh;
+-	addr->b = b;
++	addr->cc = (u_int16_t) cc;
++	addr->hh = cc >> 16;
++	addr->hh <<= 4;
++	addr->hh |= hh;
++	addr->b  = b;
++}
++
++u_int32_t
++vtoc_get_cyl_from_cchhb(cchhb_t *addr)
++{
++	u_int32_t cyl;
++
++	/* decode cylinder for large volumes */
++	cyl = addr->hh & 0xFFF0;
++	cyl <<= 12;
++	cyl |= addr->cc;
++	return cyl;
++}
++
++u_int16_t
++vtoc_get_head_from_cchhb(cchhb_t *addr)
++{
++	/* decode heads for large volumes */
++	return addr->hh & 0x000F;
++}
++
++/*
++ * some functions to convert cyl-cyl-head-head addresses to
++ * block or track numbers
++ * Note: Record zero is special, so first block on a track is
++ * in record 1!
++ */
++u_int64_t
++cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo)
++{
++	return (u_int64_t) vtoc_get_cyl_from_cchhb(p) *
++		geo->heads * geo->sectors +
++		vtoc_get_head_from_cchhb(p) * geo->sectors +
++		p->b;
++}
++
++u_int64_t
++cchh2blk (cchh_t *p, struct fdasd_hd_geometry *geo)
++{
++	return (u_int64_t) vtoc_get_cyl_from_cchh(p) *
++		geo->heads * geo->sectors +
++		vtoc_get_head_from_cchh(p) * geo->sectors;
++}
++
++u_int32_t
++cchh2trk (cchh_t *p, struct fdasd_hd_geometry *geo)
++{
++	return  vtoc_get_cyl_from_cchh(p) * geo->heads +
++		vtoc_get_head_from_cchh(p);
+ }
+ 
+ void
+@@ -506,7 +578,8 @@ vtoc_write_label (int f, unsigned long p
+ 		  format1_label_t const *f1,
+                   format4_label_t const *f4,
+ 		  format5_label_t const *f5,
+-		  format7_label_t const *f7)
++		  format7_label_t const *f7,
++		  format9_label_t const *f9)
+ {
+ 	PDEBUG
+ 	int t;
+@@ -542,6 +615,17 @@ vtoc_write_label (int f, unsigned long p
+ 			vtoc_error(unable_to_write, "vtoc_write_label",
+ 				   _("Could not write VTOC FMT7 DSCB."));
+ 	}
++
++	if (f9 != NULL)
++	{
++		t = sizeof(format9_label_t);
++		if (write(f, f9, t) != t)
++		{
++			close(f);
++			vtoc_error(unable_to_write, "vtoc_write_label",
++				   _("Could not write VTOC FMT9 DSCB."));
++		}
++	}
+ }
+ 
+ /*
+@@ -549,7 +633,8 @@ vtoc_write_label (int f, unsigned long p
+  */
+ void
+ vtoc_init_format4_label (format4_label_t *f4, unsigned int usable_partitions,
+-                         unsigned int cylinders, unsigned int tracks,
++                         unsigned int compat_cylinders,
++                         unsigned int real_cylinders, unsigned int tracks,
+                          unsigned int blocks, unsigned int blksize,
+                          u_int16_t dev_type)
+ {
+@@ -574,7 +659,7 @@ vtoc_init_format4_label (format4_label_t
+ 	f4->DS4DEVAC = 0x00;
+ 
+ 	/* -- begin f4->DS4DEVCT -- */
+-	f4->DS4DEVCT.DS4DSCYL = cylinders;
++	f4->DS4DEVCT.DS4DSCYL = compat_cylinders;
+ 	f4->DS4DEVCT.DS4DSTRK = tracks;
+ 
+ 	switch (dev_type) {
+@@ -613,7 +698,11 @@ vtoc_init_format4_label (format4_label_t
+ 	bzero(f4->res2, sizeof(f4->res2));
+ 	f4->DS4EFLVL = 0x00;
+ 	bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
+-	bzero(f4->res3, sizeof(f4->res3));
++	bzero(&f4->res3, sizeof(f4->res3));
++	f4->DS4DCYL = real_cylinders;
++	bzero(f4->res4, sizeof(f4->res4));
++	f4->DS4DEVF2 = 0x40; /* allow format 8 and 9 labels */
++	bzero(&f4->res5, sizeof(f4->res5));
+ }
+ 
+ /*
+@@ -647,11 +736,12 @@ vtoc_init_format7_label (format7_label_t
+ }
+ 
+ /*
+- * initializes a format1 label
++ * helper function that initializes a most parts of a
++ * format1 or format 8 label, all but the field DS1FMTID
+  */
+ void
+-vtoc_init_format1_label (char *volid, unsigned int blksize,
+-                         extent_t *part_extent, format1_label_t *f1)
++vtoc_init_format_1_8_label (char *volid, unsigned int blksize,
++                            extent_t *part_extent, format1_label_t *f1)
+ {
+ 	PDEBUG
+ 	struct tm * creatime;
+@@ -666,7 +756,6 @@ vtoc_init_format1_label (char *volid, un
+ 	sprintf(str, "PART    .NEW                                ");
+ 	vtoc_ebcdic_enc(str, str, 44);
+ 	strncpy(f1->DS1DSNAM, str, 44);
+-	f1->DS1FMTID = 0xf1;
+ 	strncpy(f1->DS1DSSN, "      ", 6);
+ 	f1->DS1VOLSQ = 0x0001;
+ 
+@@ -704,6 +793,37 @@ vtoc_init_format1_label (char *volid, un
+ 	vtoc_set_cchhb(&f1->DS1PTRDS, 0x0000, 0x0000, 0x00);
+ }
+ 
++void
++vtoc_init_format1_label (char *volid, unsigned int blksize,
++                         extent_t *part_extent, format1_label_t *f1)
++{
++	vtoc_init_format_1_8_label(volid, blksize, part_extent, f1);
++	f1->DS1FMTID = 0xf1;
++}
++
++void
++vtoc_init_format8_label (char *volid, unsigned int blksize,
++                         extent_t *part_extent, format1_label_t *f8)
++{
++	vtoc_init_format_1_8_label(volid, blksize, part_extent, f8);
++	f8->DS1FMTID = 0xf8;
++}
++
++void
++vtoc_update_format8_label (cchhb_t *associated_f9, format1_label_t *f8)
++{
++	memcpy(&f8->DS1PTRDS, associated_f9, sizeof(*associated_f9));
++}
++
++void
++vtoc_init_format9_label (format9_label_t *f9)
++{
++	f9->DS9KEYID = 0x09;
++	f9->DS9SUBTY = 0x01;
++	f9->DS9NUMF9 = 1;
++	f9->DS9FMTID = 0xf9;
++}
++
+ /*
+  * do some updates to the VTOC format4 label
+  */
+@@ -1060,7 +1180,7 @@ vtoc_update_format7_label_add (format7_l
+ 		if ((ext->a + ext->b) == 0x00000000)
+ 			continue;
+ 
+-		if ((ext->b + 1) == tmp->a) {
++		if (ext->b == tmp->a) {
+ 			/* this extent precedes the new one */
+ 			ext->b = tmp->b;
+ 			bzero(tmp, sizeof(ds7ext_t));
+@@ -1074,7 +1194,7 @@ vtoc_update_format7_label_add (format7_l
+ 			continue;
+ 		}
+ 
+-		if (ext->a == (tmp->b + 1)) {
++		if (ext->a == tmp->b) {
+ 			/* this extent succeeds the new one */
+ 			ext->a = tmp->a;
+ 			bzero(tmp, sizeof(ds7ext_t));
+@@ -1119,7 +1239,7 @@ vtoc_update_format7_label_del (format7_l
+ 
+ 		if ((a == ext->a) && (b < ext->b)) {
+ 			/* left-bounded in free space gap */
+-			ext->a = b + 1;
++			ext->a = b;
+ 
+ 			if (verbose)
+ 				puts ("FMT7 add extent: left-bounded");
+@@ -1130,7 +1250,7 @@ vtoc_update_format7_label_del (format7_l
+ 
+ 		if ((a > ext->a) && (b == ext->b)) {
+ 			/* right-bounded in free space gap */
+-			ext->b = a - 1;
++			ext->b = a;
+ 
+ 			if (verbose)
+ 				puts ("FMT7 add extent: right-bounded");
+@@ -1141,8 +1261,8 @@ vtoc_update_format7_label_del (format7_l
+ 
+ 		if ((a > ext->a) && (b < ext->b)) {
+ 			/* partition devides free space into 2 pieces */
+-			vtoc_update_format7_label_add(f7, verbose, b+1, ext->b);
+-			ext->b = a - 1;
++			vtoc_update_format7_label_add(f7, verbose, b, ext->b);
++			ext->b = a;
+ 
+ 			if (verbose)
+ 				puts ("FMT7 add extent: 2 pieces");
+@@ -1172,14 +1292,19 @@ vtoc_update_format7_label_del (format7_l
+ void
+ vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
+                    format7_label_t *f7, char ch, int verbose,
+-                   u_int32_t start, u_int32_t stop, int cyl, int trk)
++                   u_int32_t start, u_int32_t stop, u_int32_t cyl,
++                   u_int32_t trk)
+ {
+ 	PDEBUG
+ 	if ((cyl * trk) > BIG_DISK_SIZE) {
+ 		if (ch == '+')
+-			vtoc_update_format7_label_add(f7, verbose, start, stop);
++			vtoc_update_format7_label_add(f7, verbose, start,
++						      /* ds7ext RTA + 1 */
++						      stop + 1);
+ 		else if (ch == '-')
+-			vtoc_update_format7_label_del(f7, verbose, start, stop);
++			vtoc_update_format7_label_del(f7, verbose, start,
++						      /* ds7ext RTA + 1 */
++						      stop + 1);
+ 		else
+ 			puts ("BUG: syntax error in vtoc_set_freespace call");
+ 
diff --git a/parted-3.1-libparted-add-support-for-implicit-FBA-DASD-partitions.patch b/parted-3.1-libparted-add-support-for-implicit-FBA-DASD-partitions.patch
new file mode 100644
index 0000000..95d2551
--- /dev/null
+++ b/parted-3.1-libparted-add-support-for-implicit-FBA-DASD-partitions.patch
@@ -0,0 +1,187 @@
+Subject: [PATCH] libparted: add support for implicit FBA DASD partitions
+
+From: Nageswara R Sastry <rnsastry at linux.vnet.ibm.com>
+
+Fixed Block Access (FBA) DASDs are mainframe-specific disk devices
+which are layed out as a sequence of 512-byte sectors. In contrast
+to ECKD DASDs, these disks do not require formatting and resemble
+the LBA layout of non-mainframe disks. Despite this resemblance,
+the Linux kernel applies special handling during partition detection
+for FBA DASDs, resulting in a single, immutable partition being
+reported.
+
+While actual FBA DASD hardware is no longer available, the z/VM
+hypervisor can simulate FBA DASD disks, backed by either ECKD or
+SCSI devices.
+
+This patch adds support for recognizing FBA DASD partitions
+to parted.
+
+Signed-off-by: Nageswara R Sastry <rnsastry at linux.vnet.ibm.com>
+Signed-off-by: Peter Oberparleiter <oberpar at linux.vnet.ibm.com>
+
+---
+ include/parted/fdasd.h   |    2 +
+ libparted/labels/dasd.c  |   63 ++++++++++++++++++++++++++++++++++++++++-------
+ libparted/labels/fdasd.c |    5 +++
+ 3 files changed, 61 insertions(+), 9 deletions(-)
+
+--- a/include/parted/fdasd.h
++++ b/include/parted/fdasd.h
+@@ -194,6 +194,8 @@ typedef struct fdasd_anchor {
+ 	volume_label_t   *vlabel;
+ 	config_data_t confdata[USABLE_PARTITIONS];
+ 	struct fdasd_hd_geometry geo;
++	unsigned int label_block;
++	unsigned int FBA_layout;
+ } fdasd_anchor_t;
+ 
+ enum offset {lower, upper};
+--- a/libparted/labels/dasd.c
++++ b/libparted/labels/dasd.c
+@@ -71,6 +71,7 @@ typedef struct {
+ 
+ typedef struct {
+ 	unsigned int format_type;
++	unsigned int label_block;
+ 	volume_label_t vlabel;
+ } DasdDiskSpecific;
+ 
+@@ -151,6 +152,7 @@ dasd_alloc (const PedDevice* dev)
+ 
+ 	/* CDL format, newer */
+ 	disk_specific->format_type = 2;
++	disk_specific->label_block = 2;
+ 
+ 	/* Setup volume label (for fresh disks) */
+ 	snprintf(volser, sizeof(volser), "0X%04X", arch_specific->devno);
+@@ -226,7 +228,9 @@ dasd_probe (const PedDevice *dev)
+ 
+ 	fdasd_check_api_version(&anchor, arch_specific->fd);
+ 
+-	if (fdasd_check_volume(&anchor, arch_specific->fd))
++	/* Labels are required on CDL formatted DASDs. */
++	if (fdasd_check_volume(&anchor, arch_specific->fd) &&
++	    anchor.FBA_layout == 0)
+ 		goto error_cleanup;
+ 
+ 	fdasd_cleanup(&anchor);
+@@ -273,17 +277,53 @@ dasd_read (PedDisk* disk)
+ 	fdasd_initialize_anchor(&anchor);
+ 
+ 	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
++	disk_specific->label_block = anchor.label_block;
++
++	if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
++		anchor.big_disk++;
+ 
+ 	/* check dasd for labels and vtoc */
+-	if (fdasd_check_volume(&anchor, arch_specific->fd))
+-		goto error_close_dev;
++	if (fdasd_check_volume(&anchor, arch_specific->fd)) {
++		DasdPartitionData* dasd_data;
++
++		/* Kernel partitioning code will report 'implicit' partitions
++		 * for non-CDL format DASDs even when there is no
++		 * label/VTOC.  */
++		if (anchor.FBA_layout == 0)
++			goto error_close_dev;
++
++		disk_specific->format_type = 1;
++
++		/* Register implicit partition */
++		ped_disk_delete_all (disk);
++
++		start = (PedSector) arch_specific->real_sector_size /
++			(PedSector) disk->dev->sector_size *
++			(PedSector) (anchor.label_block + 1);
++		end = disk->dev->length - 1;
++		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
++					  start, end);
++		if (!part)
++			goto error_close_dev;
++
++		part->num = 1;
++		part->fs_type = ped_file_system_probe (&part->geom);
++		dasd_data = part->disk_specific;
++		dasd_data->raid = 0;
++		dasd_data->lvm = 0;
++		dasd_data->type = 0;
++
++		if (!ped_disk_add_partition (disk, part, NULL))
++			goto error_close_dev;
++
++		fdasd_cleanup(&anchor);
++
++		return 1;
++	}
+ 
+ 	/* Save volume label (read by fdasd_check_volume) for writing */
+ 	memcpy(&disk_specific->vlabel, anchor.vlabel, sizeof(volume_label_t));
+ 
+-	if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
+-		anchor.big_disk++;
+-
+ 	ped_disk_delete_all (disk);
+ 
+ 	bool is_ldl = strncmp(anchor.vlabel->volkey,
+@@ -348,7 +388,7 @@ dasd_read (PedDisk* disk)
+ 			    / (long long) disk->dev->sector_size
+ 			    * (long long) (cms_ptr->block_count - 1) - 1;
+ 
+-		part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end);
++		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, start, end);
+ 		if (!part)
+ 			goto error_close_dev;
+ 
+@@ -923,7 +963,12 @@ dasd_alloc_metadata (PedDisk* disk)
+ 	   the start of the first partition */
+ 	if (disk_specific->format_type == 1) {
+ 	        part = ped_disk_get_partition(disk, 1);
+-		vtoc_end = part->geom.start - 1;
++		if (part)
++			vtoc_end = part->geom.start - 1;
++		else
++			vtoc_end = (PedSector) arch_specific->real_sector_size /
++				   (PedSector) disk->dev->sector_size *
++				   (PedSector) disk_specific->label_block;
+ 	}
+ 	else {
+                 if (disk->dev->type == PED_DEVICE_FILE)
+@@ -943,7 +988,7 @@ dasd_alloc_metadata (PedDisk* disk)
+ 		goto error;
+ 	}
+ 
+-	if (disk_specific->format_type == 1) {
++	if (disk_specific->format_type == 1 && part) {
+ 	   /*
+ 	      For LDL or CMS there may be trailing metadata as well.
+ 	      For example: the last block of a CMS reserved file,
+--- a/libparted/labels/fdasd.c
++++ b/libparted/labels/fdasd.c
+@@ -721,6 +721,7 @@ fdasd_check_volume (fdasd_anchor_t *anc,
+ 	unsigned long b = -1;
+ 	char str[LINE_LENGTH];
+ 
++	memset(v, 0, sizeof(volume_label_t));
+ 	vtoc_read_volume_label (fd, anc->label_pos, v);
+ 
+ 	if (strncmp(v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0) {
+@@ -800,6 +801,8 @@ fdasd_get_geometry (const PedDevice *dev
+ 	    dasd_info.dev_type = 13200;
+ 	    dasd_info.label_block = 2;
+ 	    dasd_info.devno = 513;
++	    dasd_info.label_block = 2;
++	    dasd_info.FBA_layout = 0;
+ 	} else {
+ 		if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
+ 			fdasd_error(anc, unable_to_ioctl,
+@@ -820,6 +823,8 @@ fdasd_get_geometry (const PedDevice *dev
+ 	anc->label_pos  = dasd_info.label_block * blksize;
+ 	anc->devno      = dasd_info.devno;
+ 	anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
++	anc->label_block = dasd_info.label_block;
++	anc->FBA_layout = dasd_info.FBA_layout;
+ }
+ 
+ /*
diff --git a/parted-3.1-libparted-preserve-the-uuid-on-dm-partitions.patch b/parted-3.1-libparted-preserve-the-uuid-on-dm-partitions.patch
index 805ee07..d33a272 100644
--- a/parted-3.1-libparted-preserve-the-uuid-on-dm-partitions.patch
+++ b/parted-3.1-libparted-preserve-the-uuid-on-dm-partitions.patch
@@ -1,16 +1,16 @@
-From 399cfc2a9cfc60a46ab9094b4c999bb11a36033e Mon Sep 17 00:00:00 2001
-From: Fedora Ninjas <parted-owner at fedoraproject.org>
+From e2b9f9051c8d9905b15af0f7fa79c85502370b25 Mon Sep 17 00:00:00 2001
+From: Brian C. Lane <bcl at redhat.com>
 Date: Fri, 3 Aug 2012 17:03:50 -0700
 Subject: [PATCH] libparted: preserve the uuid on dm partitions (#832145)
 
 * libparted/arch/linux.c (_dm_add_partition): Set the uuid if there was
   one.
 ---
- libparted/arch/linux.c |   11 +++++++++++
- 1 files changed, 11 insertions(+), 0 deletions(-)
+ libparted/arch/linux.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
 
 diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
-index 37ddb5f..9f0434a 100644
+index 37ddb5f..2c410a0 100644
 --- a/libparted/arch/linux.c
 +++ b/libparted/arch/linux.c
 @@ -2803,6 +2803,8 @@ _dm_add_partition (PedDisk* disk, PedPartition* part)
@@ -35,7 +35,7 @@ index 37ddb5f..9f0434a 100644
                  goto err;
  
 +        if ( dev_uuid && (strlen(dev_uuid) > 0) \
-+             && ! (vol_uuid = zasprintf ("%sp%d", dev_uuid, part->num)))
++             && ! (vol_uuid = zasprintf ("part%d-%s", part->num, dev_uuid)))
 +                goto err;
 +
          /* Caution: dm_task_destroy frees dev_name.  */
@@ -67,5 +67,5 @@ index 37ddb5f..9f0434a 100644
          return 0;
  }
 -- 
-1.7.7.6
+1.7.11.4
 
diff --git a/parted-3.1-tests-Make-sure-dm-UUIDs-are-not-erased.patch b/parted-3.1-tests-Make-sure-dm-UUIDs-are-not-erased.patch
index 342225d..c24bfaf 100644
--- a/parted-3.1-tests-Make-sure-dm-UUIDs-are-not-erased.patch
+++ b/parted-3.1-tests-Make-sure-dm-UUIDs-are-not-erased.patch
@@ -1,5 +1,5 @@
 From cc96f793bb4fb088123a40fb9d802e7db1fdbffb Mon Sep 17 00:00:00 2001
-From: Fedora Ninjas <parted-owner at fedoraproject.org>
+From: Brian C. Lane <bcl at redhat.com>
 Date: Tue, 7 Aug 2012 10:14:03 -0700
 Subject: [PATCH] tests: Make sure dm UUIDs are not erased
 
diff --git a/parted-3.1-tests-cleanup-losetup-usage.patch b/parted-3.1-tests-cleanup-losetup-usage.patch
new file mode 100644
index 0000000..06f13c8
--- /dev/null
+++ b/parted-3.1-tests-cleanup-losetup-usage.patch
@@ -0,0 +1,137 @@
+From a1aa9eb26f357bb1a5111eb332594dfb7b39ace0 Mon Sep 17 00:00:00 2001
+From: "Brian C. Lane" <bcl at redhat.com>
+Date: Mon, 15 Oct 2012 17:27:18 -0700
+Subject: [PATCH 1/2] tests: cleanup losetup usage
+
+The unsafe_losetup_ function was failing because losetup didn't
+recognize that the 'private' /dev/loopX devices were the same as
+/dev/loopX, it would fail even if one was in use. Switch to using
+losetup --show which is a cleaner solution.
+Also use sparse file for loop_setup to save space.
+---
+ tests/lvm-utils.sh     | 24 ++----------------------
+ tests/t-lvm.sh         | 24 ++----------------------
+ tests/t6001-psep.sh    |  8 ++------
+ tests/t6003-dm-uuid.sh |  3 +--
+ 4 files changed, 7 insertions(+), 52 deletions(-)
+
+diff --git a/tests/lvm-utils.sh b/tests/lvm-utils.sh
+index 456d265..a204b08 100644
+--- a/tests/lvm-utils.sh
++++ b/tests/lvm-utils.sh
+@@ -16,34 +16,14 @@ export LVM_SUPPRESS_FD_WARNINGS=1
+ ME=$(basename "$0")
+ warn() { echo >&2 "$ME: $@"; }
+ 
+-unsafe_losetup_()
+-{
+-  f=$1
+-
+-  test -n "$G_dev_" \
+-    || fail_ "Internal error: unsafe_losetup_ called before init_root_dir_"
+-
+-  # Iterate through $G_dev_/loop{,/}{0,1,2,3,4,5,6,7,8,9}
+-  for slash in '' /; do
+-    for i in 0 1 2 3 4 5 6 7 8 9; do
+-      dev=$G_dev_/loop$slash$i
+-      losetup $dev > /dev/null 2>&1 && continue;
+-      losetup "$dev" "$f" > /dev/null && { echo "$dev"; return 0; }
+-      break
+-    done
+-  done
+-
+-  return 1
+-}
+-
+ loop_setup_()
+ {
+   file=$1
+-  dd if=/dev/zero of="$file" bs=1M count=1 seek=1000 > /dev/null 2>&1 \
++  dd if=/dev/null of="$file" bs=1M count=1 seek=1000 > /dev/null 2>&1 \
+     || { warn "loop_setup_ failed: Unable to create tmp file $file"; return 1; }
+ 
+   # NOTE: this requires a new enough version of losetup
+-  dev=$(unsafe_losetup_ "$file") \
++  dev=$(losetup --show -f "$file") 2>/dev/null \
+     || { warn "loop_setup_ failed: Unable to create loopback device"; return 1; }
+ 
+   echo "$dev"
+diff --git a/tests/t-lvm.sh b/tests/t-lvm.sh
+index b08f934..3c7657b 100644
+--- a/tests/t-lvm.sh
++++ b/tests/t-lvm.sh
+@@ -16,34 +16,14 @@ export LVM_SUPPRESS_FD_WARNINGS=1
+ ME=$(basename "$0")
+ warn() { echo >&2 "$ME: $@"; }
+ 
+-unsafe_losetup_()
+-{
+-  f=$1
+-
+-  test -n "$G_dev_" \
+-    || error "Internal error: unsafe_losetup_ called before init_root_dir_"
+-
+-  # Iterate through $G_dev_/loop{,/}{0,1,2,3,4,5,6,7,8,9}
+-  for slash in '' /; do
+-    for i in 0 1 2 3 4 5 6 7 8 9; do
+-      dev=$G_dev_/loop$slash$i
+-      losetup $dev > /dev/null 2>&1 && continue;
+-      losetup "$dev" "$f" > /dev/null && { echo "$dev"; return 0; }
+-      break
+-    done
+-  done
+-
+-  return 1
+-}
+-
+ loop_setup_()
+ {
+   file=$1
+-  dd if=/dev/zero of="$file" bs=1M count=1 seek=1000 > /dev/null 2>&1 \
++  dd if=/dev/null of="$file" bs=1M count=1 seek=1000 > /dev/null 2>&1 \
+     || { warn "loop_setup_ failed: Unable to create tmp file $file"; return 1; }
+ 
+   # NOTE: this requires a new enough version of losetup
+-  dev=$(unsafe_losetup_ "$file" 2>/dev/null) \
++  dev=$(losetup --show -f "$file") 2>/dev/null \
+     || { warn "loop_setup_ failed: Unable to create loopback device"; return 1; }
+ 
+   echo "$dev"
+diff --git a/tests/t6001-psep.sh b/tests/t6001-psep.sh
+index 490c6d2..1859ac9 100644
+--- a/tests/t6001-psep.sh
++++ b/tests/t6001-psep.sh
+@@ -44,14 +44,10 @@ cleanup_fn_() {
+ # create a file of size N bytes
+ N=10M
+ 
+-# create the test file
+-f1=$(pwd)/1; dd if=/dev/null of=$f1 bs=1 seek=$N 2> /dev/null || fail=1
+-f2=$(pwd)/2; dd if=/dev/null of=$f2 bs=1 seek=$N 2> /dev/null || fail=1
+-
+-d1=$(loop_setup_ "$f1") \
++f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \
+   || skip_ "is this partition mounted with 'nodev'?"
+ 
+-d2=$(loop_setup_ "$f2") \
++f2=$(pwd)/2 ;d2=$(loop_setup_ "$f2") \
+   || skip_ "is this partition mounted with 'nodev'?"
+ 
+ dmsetup_cmd="0 `blockdev --getsz $d1` linear $d1 0"
+diff --git a/tests/t6003-dm-uuid.sh b/tests/t6003-dm-uuid.sh
+index 1751cb4..f58cb06 100755
+--- a/tests/t6003-dm-uuid.sh
++++ b/tests/t6003-dm-uuid.sh
+@@ -36,8 +36,7 @@ cleanup_() {
+ }
+ 
+ # create a file large enough to hold a GPT partition table
+-dd if=/dev/null of=$loop_file bs=$ss seek=$ns || framework_failure
+-dev=$(losetup --show -f $loop_file) || framework_failure
++dev=$(loop_setup_ $loop_file) || framework_failure
+ dmsetup create $dm_name --table "0 $ns linear $dev 0" || framework_failure
+ dmsetup rename $dm_name --setuuid f139317b-f98a-45d7-ab3b-9b4e0a336872 || framework_failure
+ 
+-- 
+1.7.11.4
+
diff --git a/parted.spec b/parted.spec
index 77645af..ab4cc49 100644
--- a/parted.spec
+++ b/parted.spec
@@ -4,7 +4,7 @@
 Summary: The GNU disk partition manipulation program
 Name:    parted
 Version: 3.1
-Release: 7%{?dist}
+Release: 8%{?dist}
 License: GPLv3+
 Group:   Applications/System
 URL:     http://www.gnu.org/software/parted
@@ -23,6 +23,9 @@ patch6: parted-3.1-test-creating-20-device-mapper-partitions.patch
 Patch7: parted-3.1-libparted-preserve-the-uuid-on-dm-partitions.patch
 Patch8: parted-3.1-tests-Make-sure-dm-UUIDs-are-not-erased.patch
 Patch9: parted-3.1-libparted-reallocate-buf-after-_disk_analyse_block_s.patch
+Patch10: parted-3.1-tests-cleanup-losetup-usage.patch
+Patch11: parted-3.1-libparted-add-support-for-implicit-FBA-DASD-partitions.patch
+Patch12: parted-3.1-libparted-add-support-for-EAV-DASD-partitions.patch
 
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: e2fsprogs-devel
@@ -158,6 +161,12 @@ fi
 
 
 %changelog
+* Tue Oct 16 2012 Brian C. Lane <bcl at redhat.com> 3.1-8
+- change partition UUID to use partX-UUID (#858704)
+- fixup losetup usage in tests
+- add support for implicit FBA DASD partitions (#707027)
+- add support for EAV DASD partitions (#707032)
+
 * Tue Sep 04 2012 Brian C. Lane <bcl at redhat.com> 3.1-7
 - reallocate buf after _disk_analyse_block_size (#835601)
 


More information about the scm-commits mailing list