From 4f4200ec76f25a4590bc29f12268b1c4aee51c0bc4b46db6895f81735fff7264 Mon Sep 17 00:00:00 2001 From: Petr Uzel Date: Fri, 18 Jul 2014 09:34:42 +0000 Subject: [PATCH] - Improve DASD label handling; backport following patches from upstream (bnc#887333): - libparted-add-support-for-implicit-FBA-DASD-partition.patch - libparted-add-support-for-EAV-DASD-partitions.patch - libparted-mklabel-to-support-EAV-DASD.patch - libparted-Avoid-dasd-as-default-disk-type-while-probe.patch - libparted-mklabel-to-support-EDEV-DASD.patch OBS-URL: https://build.opensuse.org/package/show/Base:System/parted?expand=0&rev=96 --- ...asd-as-default-disk-type-while-probe.patch | 67 ++ ...-add-support-for-EAV-DASD-partitions.patch | 1071 +++++++++++++++++ ...port-for-implicit-FBA-DASD-partition.patch | 193 +++ libparted-mklabel-to-support-EAV-DASD.patch | 159 +++ libparted-mklabel-to-support-EDEV-DASD.patch | 56 + parted.changes | 11 + parted.spec | 10 + 7 files changed, 1567 insertions(+) create mode 100644 libparted-Avoid-dasd-as-default-disk-type-while-probe.patch create mode 100644 libparted-add-support-for-EAV-DASD-partitions.patch create mode 100644 libparted-add-support-for-implicit-FBA-DASD-partition.patch create mode 100644 libparted-mklabel-to-support-EAV-DASD.patch create mode 100644 libparted-mklabel-to-support-EDEV-DASD.patch diff --git a/libparted-Avoid-dasd-as-default-disk-type-while-probe.patch b/libparted-Avoid-dasd-as-default-disk-type-while-probe.patch new file mode 100644 index 0000000..5e9405c --- /dev/null +++ b/libparted-Avoid-dasd-as-default-disk-type-while-probe.patch @@ -0,0 +1,67 @@ +From 0673dabee6f5b19317b0d85e399e9f876a2c2ea7 Mon Sep 17 00:00:00 2001 +From: Nageswara R Sastry +Date: Wed, 21 Aug 2013 16:37:17 -0700 +Subject: [PATCH] libparted: Avoid dasd as default disk type while probe + +This patch avoids setting 'dasd' as a default disk type for +'disk image file' at the time of probe. + +Signed-off-by: Nageswara R Sastry +--- + include/parted/fdasd.in.h | 1 + + libparted/labels/fdasd.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h +index 3692596..6f6a7e0 100644 +--- a/include/parted/fdasd.in.h ++++ b/include/parted/fdasd.in.h +@@ -261,6 +261,7 @@ typedef struct fdasd_anchor { + struct fdasd_hd_geometry geo; + unsigned int label_block; + unsigned int FBA_layout; ++ bool is_file; + } fdasd_anchor_t; + + enum offset {lower, upper}; +diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c +index b58b2be..7de5f34 100644 +--- a/libparted/labels/fdasd.c ++++ b/libparted/labels/fdasd.c +@@ -301,6 +301,7 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc) + } + anc->hw_cylinders = 0; + anc->formatted_cylinders = 0; ++ anc->is_file = 0; + } + + /* +@@ -890,7 +891,7 @@ fdasd_check_volume (fdasd_anchor_t *anc, int fd) + /* Some times LDL formatted disks does not + contain any volume label */ + return 1; +- } else { ++ } else if (! anc->is_file) { + /* didn't find VOL1 volume label */ + anc->formatted_cylinders = anc->hw_cylinders; + anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads +@@ -974,6 +975,7 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f) + dasd_info.FBA_layout = 0; + anc->hw_cylinders = ((st.st_size / blksize) / anc->geo.sectors) / + anc->geo.heads; ++ anc->is_file = 1; + } else { + if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0) + fdasd_error(anc, unable_to_ioctl, +@@ -995,6 +997,8 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f) + anc->hw_cylinders = characteristics->long_no_cyl; + else + anc->hw_cylinders = characteristics->no_cyl; ++ ++ anc->is_file = 0; + } + + anc->dev_type = dasd_info.dev_type; +-- +1.8.4.5 + diff --git a/libparted-add-support-for-EAV-DASD-partitions.patch b/libparted-add-support-for-EAV-DASD-partitions.patch new file mode 100644 index 0000000..12fa8dc --- /dev/null +++ b/libparted-add-support-for-EAV-DASD-partitions.patch @@ -0,0 +1,1071 @@ +From cbec53fdb9c8b244b497e42b0b215a8276803a88 Mon Sep 17 00:00:00 2001 +From: Nageswara R Sastry +Date: Wed, 21 Aug 2013 16:27:13 -0700 +Subject: [PATCH] libparted: add support for EAV DASD partitions + +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 +Signed-off-by: Peter Oberparleiter +--- + include/parted/fdasd.in.h | 89 +++++++++++++++--- + include/parted/vtoc.in.h | 59 ++++++++++-- + libparted/labels/dasd.c | 1 + + libparted/labels/fdasd.c | 226 ++++++++++++++++++++++++++++++++-------------- + libparted/labels/vtoc.c | 173 ++++++++++++++++++++++++++++++----- + 5 files changed, 436 insertions(+), 112 deletions(-) + +diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h +index a755246..b4e7dd1 100644 +--- a/include/parted/fdasd.in.h ++++ b/include/parted/fdasd.in.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; +diff --git a/include/parted/vtoc.in.h b/include/parted/vtoc.in.h +index d79ce39..499c2d3 100644 +--- a/include/parted/vtoc.in.h ++++ b/include/parted/vtoc.in.h +@@ -42,6 +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; +@@ -59,6 +71,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 +182,10 @@ struct __attribute__ ((packed)) dev_const { + 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 +246,11 @@ struct __attribute__ ((packed)) format4_label { + 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 +282,28 @@ struct __attribute__ ((packed)) format7_label { + 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 +332,16 @@ void vtoc_write_label (int fd, unsigned long position, + 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 +368,16 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose, + 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 */ +diff --git a/libparted/labels/dasd.c b/libparted/labels/dasd.c +index b4e80b1..081b3c5 100644 +--- 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++; + +diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c +index f92065f..2735b2a 100644 +--- a/libparted/labels/fdasd.c ++++ b/libparted/labels/fdasd.c +@@ -59,6 +59,48 @@ setpos (fdasd_anchor_t *anc, int dsn, int pos) + 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 fdasd_failure why, char const *str) + } + + /* +- * 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 * anc) + 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 * anc) + + q = p; + } ++ anc->hw_cylinders = 0; ++ anc->formatted_cylinders = 0; + } + + /* +@@ -269,44 +311,46 @@ fdasd_write_vtoc_labels (fdasd_anchor_t * anc, int fd) + { + 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 * anc, int fd) + 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 * anc, int fd) + + 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 *anc, int fd) + 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 *anc, int fd) + } + + 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; ifirst; +- 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_anchor_t *anc) + + /* 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 * anc, unsigned long b, int fd) + 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 * anc, unsigned long b, int fd) + 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, int fd) + { + 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, fdasd_anchor_t *anc, int f) + 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, fdasd_anchor_t *anc, int f) + 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, fdasd_anchor_t *anc, int f) + 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 *anc, extent_t *part_extent, + 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, unsigned int start, + cchhb_t hf1; + partition_info_t *p; + extent_t ext; +- int i; + + PDEBUG; + +@@ -1032,8 +1118,14 @@ fdasd_add_partition (fdasd_anchor_t *anc, unsigned int start, + 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, unsigned int start, + 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++; + +diff --git a/libparted/labels/vtoc.c b/libparted/labels/vtoc.c +index cf2990e..fdfa94f 100644 +--- a/libparted/labels/vtoc.c ++++ b/libparted/labels/vtoc.c +@@ -218,11 +218,32 @@ vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno, + } + + 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, u_int8_t r) + } + + 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 position, + 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 position, + 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 position, + */ + 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, unsigned int usable_partitions, + 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 *f4, unsigned int usable_partitions, + 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 *f7) + } + + /* +- * 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, unsigned int blksize, + 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, unsigned int blksize, + 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_label_t *f7, int verbose, + 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_label_t *f7, int verbose, + 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_label_t *f7, int verbose, + + 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_label_t *f7, int verbose, + + 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_label_t *f7, int verbose, + + 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_label_t *f7, int verbose, + 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"); + +-- +1.8.4.5 + diff --git a/libparted-add-support-for-implicit-FBA-DASD-partition.patch b/libparted-add-support-for-implicit-FBA-DASD-partition.patch new file mode 100644 index 0000000..91cd8ea --- /dev/null +++ b/libparted-add-support-for-implicit-FBA-DASD-partition.patch @@ -0,0 +1,193 @@ +From f70ff1fc474764c3a71318ddb4e0d26afc52ac47 Mon Sep 17 00:00:00 2001 +From: Nageswara R Sastry +Date: Wed, 21 Aug 2013 16:09:56 -0700 +Subject: [PATCH] libparted: add support for implicit FBA DASD partitions + +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 +Signed-off-by: Peter Oberparleiter +--- + include/parted/fdasd.in.h | 2 + + libparted/labels/dasd.c | 63 +++++++++++++++++++++++++++++++++++++++------- + libparted/labels/fdasd.c | 5 +++ + 3 files changed, 61 insertions(+), 9 deletions(-) + +Index: parted-3.1/include/parted/fdasd.in.h +=================================================================== +--- parted-3.1.orig/include/parted/fdasd.in.h ++++ parted-3.1/include/parted/fdasd.in.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}; +Index: parted-3.1/libparted/labels/dasd.c +=================================================================== +--- parted-3.1.orig/libparted/labels/dasd.c ++++ parted-3.1/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; + +@@ -926,7 +966,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) +@@ -946,7 +991,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, +Index: parted-3.1/libparted/labels/fdasd.c +=================================================================== +--- parted-3.1.orig/libparted/labels/fdasd.c ++++ parted-3.1/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/libparted-mklabel-to-support-EAV-DASD.patch b/libparted-mklabel-to-support-EAV-DASD.patch new file mode 100644 index 0000000..9668d19 --- /dev/null +++ b/libparted-mklabel-to-support-EAV-DASD.patch @@ -0,0 +1,159 @@ +From 95649fc7d025a68074c8a00581bd24d2bd7751bc Mon Sep 17 00:00:00 2001 +From: Nageswara R Sastry +Date: Wed, 21 Aug 2013 16:36:08 -0700 +Subject: [PATCH] libparted: mklabel to support EAV DASD + +Extended Address Volume (EAV) DASDs are ECKD DASDs with more than +65520 cylinders. This patch adds support for mklabel to properly +handle unformatted EAV DASDs. + +Signed-off-by: Nageswara R Sastry +--- + include/parted/fdasd.in.h | 1 - + libparted/labels/fdasd.c | 92 +++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 90 insertions(+), 3 deletions(-) + +diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h +index b4e7dd1..3692596 100644 +--- a/include/parted/fdasd.in.h ++++ b/include/parted/fdasd.in.h +@@ -288,7 +288,6 @@ void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd); + void fdasd_check_api_version (fdasd_anchor_t *anc, int fd); + int fdasd_check_volume (fdasd_anchor_t *anc, int fd); + int fdasd_write_labels (fdasd_anchor_t *anc, int fd); +-int fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc); + void fdasd_recreate_vtoc(fdasd_anchor_t *anc); + partition_info_t * fdasd_add_partition (fdasd_anchor_t *anc, + unsigned int start, unsigned int stop); +diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c +index 2735b2a..b58b2be 100644 +--- a/libparted/labels/fdasd.c ++++ b/libparted/labels/fdasd.c +@@ -581,6 +581,22 @@ fdasd_recreate_vtoc (fdasd_anchor_t *anc) + anc->vtoc_changed++; + } + ++ /* ++ * initialize the VOL1 volume label ++ */ ++static void ++fdasd_init_volume_label(fdasd_anchor_t *anc, int fd) ++{ ++ volume_label_t *vlabel = anc->vlabel; ++ ++ vtoc_volume_label_init(vlabel); ++ vtoc_volume_label_set_key(vlabel, "VOL1"); ++ vtoc_volume_label_set_label(vlabel, "VOL1"); ++ ++ vtoc_set_cchhb(&vlabel->vtoc, VTOC_START_CC, VTOC_START_HH, 0x01); ++} ++ ++ + /* + * sets some important partition data + * (like used, start_trk, end_trk, len_trk) +@@ -769,6 +785,52 @@ fdasd_process_valid_vtoc (fdasd_anchor_t * anc, unsigned long b, int fd) + fdasd_update_partition_info (anc); + } + ++static void ++fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc) ++{ ++ PDEBUG ++ anc->formatted_cylinders = anc->hw_cylinders; ++ anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads ++ - FIRST_USABLE_TRK; ++ vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS, ++ anc->geo.cylinders, anc->formatted_cylinders, ++ anc->geo.heads, anc->geo.sectors, ++ anc->blksize, anc->dev_type); ++ ++ vtoc_init_format5_label(anc->f5); ++ vtoc_init_format7_label(anc->f7); ++ ++ vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose, ++ FIRST_USABLE_TRK, ++ anc->formatted_cylinders * anc->geo.heads - 1, ++ anc->formatted_cylinders, anc->geo.heads); ++ ++ vtoc_set_cchhb(&anc->vlabel->vtoc, VTOC_START_CC, VTOC_START_HH, 0x01); ++} ++ ++/* ++ * we have a invalid FMT4 DSCB and therefore we will re-create the VTOC ++ */ ++static void ++fdasd_process_invalid_vtoc(fdasd_anchor_t *anc) ++{ ++ anc->formatted_cylinders = anc->hw_cylinders; ++ anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads ++ - FIRST_USABLE_TRK; ++ vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS, ++ anc->geo.cylinders, anc->formatted_cylinders, ++ anc->geo.heads, anc->geo.sectors, ++ anc->blksize, anc->dev_type); ++ ++ vtoc_init_format5_label(anc->f5); ++ vtoc_init_format7_label(anc->f7); ++ vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose, ++ FIRST_USABLE_TRK, ++ anc->formatted_cylinders * anc->geo.heads - 1, ++ anc->formatted_cylinders, anc->geo.heads); ++} ++ ++ + static int + fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd) + { +@@ -781,6 +843,8 @@ fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd) + if (anc->f4->DS4IDFMT == 0xf4) { + fdasd_process_valid_vtoc (anc, b, fd); + return 0; ++ } else { ++ fdasd_process_invalid_vtoc(anc); + } + if (strncmp(anc->vlabel->volkey, vtoc_ebcdic_enc("LNX1",str,4),4) == 0 || + strncmp(anc->vlabel->volkey, vtoc_ebcdic_enc("CMS1",str,4),4) == 0) +@@ -817,13 +881,37 @@ fdasd_check_volume (fdasd_anchor_t *anc, int fd) + else + return 0; + } else { +- return 1; ++ fdasd_invalid_vtoc_pointer(anc); + } + } else if (strncmp (v->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0 || + strncmp (v->volkey, vtoc_ebcdic_enc ("CMS1", str, 4), 4) == 0) { + return 0; +- } ++ } else if (anc->FBA_layout == 1) { ++ /* Some times LDL formatted disks does not ++ contain any volume label */ ++ return 1; ++ } else { ++ /* didn't find VOL1 volume label */ ++ anc->formatted_cylinders = anc->hw_cylinders; ++ anc->fspace_trk = anc->formatted_cylinders * anc->geo.heads ++ - FIRST_USABLE_TRK; ++ ++ fdasd_init_volume_label(anc, fd); + ++ vtoc_init_format4_label(anc->f4, USABLE_PARTITIONS, ++ anc->geo.cylinders, anc->formatted_cylinders, ++ anc->geo.heads, anc->geo.sectors, ++ anc->blksize, anc->dev_type); ++ ++ vtoc_init_format5_label(anc->f5); ++ vtoc_init_format7_label(anc->f7); ++ ++ vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', ++ anc->verbose, FIRST_USABLE_TRK, ++ anc->formatted_cylinders * anc->geo.heads - 1, ++ anc->formatted_cylinders, anc->geo.heads); ++ return 0; ++ } + return 1; + } + +-- +1.8.4.5 + diff --git a/libparted-mklabel-to-support-EDEV-DASD.patch b/libparted-mklabel-to-support-EDEV-DASD.patch new file mode 100644 index 0000000..1451aca --- /dev/null +++ b/libparted-mklabel-to-support-EDEV-DASD.patch @@ -0,0 +1,56 @@ +From bdb439f660344404f27084c48fe7b9429436b9e9 Mon Sep 17 00:00:00 2001 +From: Nageswara R Sastry +Date: Wed, 21 Aug 2013 16:37:17 -0700 +Subject: [PATCH] libparted: mklabel to support EDEV DASD + +Fixed Block Access (FBA) DASDs are mainframe-specific disk devices +which are layed out as a sequence of 512-byte sectors. This patch adds +support for mklabel to properly handle FBA devices. + +Signed-off-by: Nageswara R Sastry +--- + libparted/labels/fdasd.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c +index 7de5f34..1f87937 100644 +--- a/libparted/labels/fdasd.c ++++ b/libparted/labels/fdasd.c +@@ -870,19 +870,21 @@ fdasd_check_volume (fdasd_anchor_t *anc, int fd) + vtoc_read_volume_label (fd, anc->label_pos, v); + + if (strncmp(v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0) { +- /* found VOL1 volume label */ +- b = (cchhb2blk (&v->vtoc, &anc->geo) - 1) * anc->blksize; +- +- if (b > 0) { +- int rc; +- rc = fdasd_valid_vtoc_pointer (anc, b, fd); +- +- if (rc < 0) +- return 1; +- else +- return 0; +- } else { +- fdasd_invalid_vtoc_pointer(anc); ++ if (anc->FBA_layout != 1 ) { ++ /* found VOL1 volume label */ ++ b = (cchhb2blk (&v->vtoc, &anc->geo) - 1) * anc->blksize; ++ ++ if (b > 0) { ++ int rc; ++ rc = fdasd_valid_vtoc_pointer (anc, b, fd); ++ ++ if (rc < 0) ++ return 1; ++ else ++ return 0; ++ } else { ++ fdasd_invalid_vtoc_pointer(anc); ++ } + } + } else if (strncmp (v->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0 || + strncmp (v->volkey, vtoc_ebcdic_enc ("CMS1", str, 4), 4) == 0) { +-- +1.8.4.5 + diff --git a/parted.changes b/parted.changes index 8b02706..c000ff4 100644 --- a/parted.changes +++ b/parted.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Wed Jul 16 13:14:09 UTC 2014 - puzel@suse.com + +- Improve DASD label handling; backport following patches + from upstream (bnc#887333): + - libparted-add-support-for-implicit-FBA-DASD-partition.patch + - libparted-add-support-for-EAV-DASD-partitions.patch + - libparted-mklabel-to-support-EAV-DASD.patch + - libparted-Avoid-dasd-as-default-disk-type-while-probe.patch + - libparted-mklabel-to-support-EDEV-DASD.patch + ------------------------------------------------------------------- Thu May 29 12:55:29 UTC 2014 - puzel@suse.com diff --git a/parted.spec b/parted.spec index fb91180..919aed9 100644 --- a/parted.spec +++ b/parted.spec @@ -59,6 +59,11 @@ Patch31: libparted-use-BLKRRPART-for-DASD.patch.patch Patch32: libparted-copy-pmbr_boot-when-duplicating-GPT-disk.patch Patch33: Fix-help-text-for-disk_-set-toggle.patch Patch34: libparted-allow-bigger-snap-radius-if-cylinders-are-used.patch +Patch35: libparted-add-support-for-implicit-FBA-DASD-partition.patch +Patch36: libparted-add-support-for-EAV-DASD-partitions.patch +Patch37: libparted-mklabel-to-support-EAV-DASD.patch +Patch38: libparted-Avoid-dasd-as-default-disk-type-while-probe.patch +Patch39: libparted-mklabel-to-support-EDEV-DASD.patch Patch100: parted-fatresize-autoconf.patch Requires: /sbin/udevadm BuildRequires: check-devel @@ -140,6 +145,11 @@ to develop applications that require these. %patch32 -p1 %patch33 -p1 %patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 %patch100 -p1 %build