diff --git a/0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch b/0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch new file mode 100644 index 0000000..f13ef02 --- /dev/null +++ b/0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch @@ -0,0 +1,281 @@ +From 4d480d980a9b69b432b8d60df3c4397ba8cdc965 Mon Sep 17 00:00:00 2001 +From: Viktor Mihajlovski +Date: Thu, 17 Sep 2015 15:33:28 +0200 +Subject: [PATCH 21/22] fdasd: geometry handling updated from upstream + s390-tools + +Remove the necessity for DASD-specific ioctls for partition handling. +This allows to correctly handle DASD-backed virtio block devices. + +Note that this is necessary because virtio is just the transport. +A DASD, even if provided via virtio, still has it's unique +characteristics, which means that only traditional DASD partition +table formats can be used (no MBR, GPT, or similar). + +Use bzero for initialization to make sure all struct members are +properly cleared. Also changed partition list handling code to be +more similar to upstream s390-tools fdasd. + +Further, enhanced error handling capabilities by providing a +return code by fdasd_get_geometry. + +Code is largely backported from s390-tools project. + +Signed-off-by: Viktor Mihajlovski +Acked-by: Stefan Haberland +Signed-off-by: Hendrik Brueckner +Signed-off-by: Brian C. Lane +--- + include/parted/fdasd.in.h | 4 +- + libparted/labels/fdasd.c | 166 ++++++++++++++++++++++++++++++++-------------- + 2 files changed, 119 insertions(+), 51 deletions(-) + +diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h +index 6f6a7e0..4e351c4 100644 +--- a/include/parted/fdasd.in.h ++++ b/include/parted/fdasd.in.h +@@ -190,6 +190,8 @@ typedef struct format_data_t { + #define BLKRRPART _IO(0x12,95) + /* get block device sector size */ + #define BLKSSZGET _IO(0x12,104) ++/* device size in bytes (u64 *arg)*/ ++#define BLKGETSIZE64 _IOR(0x12,114,size_t) + /* get device geometry */ + #define HDIO_GETGEO 0x0301 + +@@ -285,7 +287,7 @@ enum fdasd_failure { + + void fdasd_cleanup (fdasd_anchor_t *anchor); + void fdasd_initialize_anchor (fdasd_anchor_t * anc); +-void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd); ++int 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); +diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c +index 1f87937..7e6a77a 100644 +--- a/libparted/labels/fdasd.c ++++ b/libparted/labels/fdasd.c +@@ -210,27 +210,7 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc) + partition_info_t *p = NULL; + partition_info_t *q = NULL; + +- anc->devno = 0; +- anc->dev_type = 0; +- anc->used_partitions = 0; +- +- anc->silent = 0; +- anc->verbose = 0; +- anc->big_disk = 0; +- anc->volid_specified = 0; +- anc->config_specified = 0; +- anc->auto_partition = 0; +- anc->devname_specified = 0; +- anc->print_table = 0; +- +- anc->option_reuse = 0; +- anc->option_recreate = 0; +- +- anc->vlabel_changed = 0; +- anc->vtoc_changed = 0; +- anc->blksize = 0; +- anc->fspace_trk = 0; +- anc->label_pos = 0; ++ bzero(anc, sizeof(fdasd_anchor_t)); + + for (i=0; iused = 0x00; +- p->len_trk = 0; +- p->start_trk = 0; +- p->fspace_trk = 0; +- p->type = 0; ++ bzero(p, sizeof(partition_info_t)); + + /* add p to double pointered list */ + if (i == 1) { +- anc->first = p; +- p->prev = NULL; ++ anc->first = p; + } else if (i == USABLE_PARTITIONS) { +- anc->last = p; +- p->next = NULL; ++ anc->last = p; + p->prev = q; + q->next = p; + } else { +- p->prev = q; +- q->next = p; ++ p->prev = q; ++ q->next = p; + } + + p->f1 = malloc(sizeof(format1_label_t)); +@@ -947,15 +921,77 @@ fdasd_check_api_version (fdasd_anchor_t *anc, int f) + } + + /* ++ * The following two functions match those in the DASD ECKD device driver. ++ * They are used to compute how many records of a given size can be stored ++ * in one track. ++ */ ++static unsigned int ceil_quot(unsigned int d1, unsigned int d2) ++{ ++ return (d1 + (d2 - 1)) / d2; ++} ++ ++/* kl: key length, dl: data length */ ++static unsigned int recs_per_track(unsigned short dev_type, unsigned int kl, ++ unsigned int dl) ++{ ++ unsigned int dn, kn; ++ ++ switch (dev_type) { ++ case DASD_3380_TYPE: ++ if (kl) ++ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) + ++ ceil_quot(dl + 12, 32)); ++ else ++ return 1499 / (15 + ceil_quot(dl + 12, 32)); ++ case DASD_3390_TYPE: ++ dn = ceil_quot(dl + 6, 232) + 1; ++ if (kl) { ++ kn = ceil_quot(kl + 6, 232) + 1; ++ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) + ++ 9 + ceil_quot(dl + 6 * dn, 34)); ++ } else ++ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34)); ++ case DASD_9345_TYPE: ++ dn = ceil_quot(dl + 6, 232) + 1; ++ if (kl) { ++ kn = ceil_quot(kl + 6, 232) + 1; ++ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) + ++ ceil_quot(dl + 6 * dn, 34)); ++ } else ++ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34)); ++ } ++ return 0; ++} ++ ++/* ++ * Verify that number of tracks (heads) per cylinder and number of ++ * sectors per track match the expected values for a given device type ++ * and block size. ++ * Returns 1 for a valid match and 0 otherwise. ++ */ ++static int fdasd_verify_geometry(unsigned short dev_type, int blksize, ++ struct fdasd_hd_geometry *geometry) ++{ ++ unsigned int expected_sectors; ++ if (geometry->heads != 15) ++ return 0; ++ expected_sectors = recs_per_track(dev_type, 0, blksize); ++ if (geometry->sectors == expected_sectors) ++ return 1; ++ return 0; ++} ++ ++/* + * reads dasd geometry data + */ +-void ++int + 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; ++ unsigned long long size_in_bytes; + + /* We can't get geometry from a regular file, + so simulate something usable, for the sake of testing. */ +@@ -979,6 +1015,12 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f) + anc->geo.heads; + anc->is_file = 1; + } else { ++ if (ioctl(f, BLKGETSIZE64, &size_in_bytes) != 0) { ++ fdasd_error(anc, unable_to_ioctl, ++ _("Could not retrieve disk size.")); ++ goto error; ++ } ++ + if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0) + fdasd_error(anc, unable_to_ioctl, + _("Could not retrieve disk geometry information.")); +@@ -988,27 +1030,51 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f) + _("Could not retrieve blocksize information.")); + + /* get disk type */ +- 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; ++ if (ioctl(f, BIODASDINFO, &dasd_info) != 0) { ++ /* verify that the geometry matches a 3390 DASD */ ++ if (!fdasd_verify_geometry(DASD_3390_TYPE, blksize, ++ &anc->geo)) { ++ fdasd_error(anc, wrong_disk_type, ++ _("Disk geometry does not match a " \ ++ "DASD device of type 3390.")); ++ goto error; ++ } ++ anc->dev_type = DASD_3390_TYPE; ++ anc->hw_cylinders = ++ size_in_bytes / (blksize * anc->geo.heads * anc->geo.sectors); ++ /* The VOL1 label on a CDL formatted ECKD DASD is in block 2 ++ * It will be verified later, if this position actually holds a ++ * valid label record. ++ */ ++ anc->label_pos = 2 * blksize; ++ /* A devno 0 is actually a valid devno, which could exist ++ * in the system. Since we use this number only to create ++ * a default volume serial, there is no serious conflict. ++ */ ++ anc->devno = 0; ++ } else { ++ 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->label_pos = dasd_info.label_block * blksize; ++ anc->devno = dasd_info.devno; ++ anc->label_block = dasd_info.label_block; ++ anc->FBA_layout = dasd_info.FBA_layout; ++ } + + anc->is_file = 0; + } + +- anc->dev_type = dasd_info.dev_type; +- anc->blksize = blksize; +- anc->label_pos = dasd_info.label_block * blksize; +- anc->devno = dasd_info.devno; +- anc->label_block = dasd_info.label_block; +- anc->FBA_layout = dasd_info.FBA_layout; ++ anc->blksize = blksize; ++ return 1; ++ ++ error: ++ return 0; + } + + /* +-- +2.4.3 + diff --git a/0022-dasd-enhance-device-probing.patch b/0022-dasd-enhance-device-probing.patch new file mode 100644 index 0000000..e823fb3 --- /dev/null +++ b/0022-dasd-enhance-device-probing.patch @@ -0,0 +1,238 @@ +From 834713b5aee1edc004f863231dd489ee3a79f536 Mon Sep 17 00:00:00 2001 +From: Viktor Mihajlovski +Date: Thu, 17 Sep 2015 15:33:29 +0200 +Subject: [PATCH 22/22] dasd: enhance device probing + +Probe for all device/transport types as every block device +could be a DASD on s390. + +Since the calculation of the minimum and optimum alignment +is different between DASDs and common fixed block disks +we need a means other than dev->type == PED_DEVICE_DASD. +For that purpose a static function _ped_device_like_dasd() +offering a DASD detection heuristic has been added to +arch/linux.c. + +By always providing arch-specific alignment functions the +need for DASD-specific code could be removed from device.c. + +Observe fdasd_get_geometry return code for proper error +handling. + +Remove the obsolete API check as we no longer require the +DASD-specific IOCTLs. + +Signed-off-by: Viktor Mihajlovski +Acked-by: Stefan Haberland +Signed-off-by: Hendrik Brueckner +Signed-off-by: Brian C. Lane +--- + libparted/arch/linux.c | 85 ++++++++++++++++++++++++++++++++++++++++--------- + libparted/device.c | 14 +++----- + libparted/labels/dasd.c | 18 +++++------ + 3 files changed, 82 insertions(+), 35 deletions(-) + +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index adc368d..9344ceb 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -785,9 +785,13 @@ _device_set_sector_size (PedDevice* dev) + #endif + + #if defined __s390__ || defined __s390x__ ++ /* The real_sector_size is currently needed for DASD layouts, ++ * so we set it unconditionally. In the long run it should ++ * be considered to use the dev->phys_sector_size in label/dasd.c. ++ */ ++ arch_specific->real_sector_size = dev->sector_size; + /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */ + if (dev->type == PED_DEVICE_DASD) { +- arch_specific->real_sector_size = dev->sector_size; + dev->sector_size = PED_SECTOR_SIZE_DEFAULT; + } + #endif +@@ -3167,19 +3171,72 @@ linux_disk_commit (PedDisk* disk) + { + if (disk->dev->type != PED_DEVICE_FILE) { + +- /* We now require BLKPG support. If this assertion fails, +- please write to the mailing list describing your system. +- Assuming it's never triggered, ... +- FIXME: remove this assertion in 2012. */ +- assert (_have_blkpg ()); ++ /* We now require BLKPG support. If this assertion fails, ++ please write to the mailing list describing your system. ++ Assuming it's never triggered, ... ++ FIXME: remove this assertion in 2012. */ ++ assert (_have_blkpg ()); + +- if (!_disk_sync_part_table (disk)) +- return 0; ++ if (!_disk_sync_part_table (disk)) ++ return 0; + } + + return 1; + } + ++#if defined __s390__ || defined __s390x__ ++/** ++ * Check whether this device could be a DASD ++ * ++ * The device probing yields PED_DEVICE_DASD for native DASD transport ++ * If the block device uses a different transport (e.g. virtio) ++ * a simplified heuristic (assuming a model 3390 with 4K sectors) ++ * is applied (only) on s390x systems for this check. ++ * ++ * \return 1 if the geometry indicates this could be a DASD ++ * and 0 otherwise ++ */ ++static int ++_ped_device_like_dasd(const PedDevice *dev) ++{ ++ return (dev->type == PED_DEVICE_DASD) ++ || (dev->hw_geom.heads == 15 ++ && dev->hw_geom.sectors == 12 ++ && (dev->hw_geom.cylinders ++ * dev->hw_geom.heads ++ * dev->hw_geom.sectors ++ * dev->phys_sector_size ++ == dev->length * dev->sector_size)); ++} ++ ++ ++ ++static PedAlignment* ++s390_get_minimum_alignment(const PedDevice *dev) ++{ ++#if USE_BLKID ++ return linux_get_minimum_alignment(dev); ++#else ++ return ped_alignment_new(0, ++ dev->phys_sector_size ++ / dev->sector_size); ++#endif ++} ++ ++static PedAlignment* ++s390_get_optimum_alignment(const PedDevice *dev) ++{ ++ /* DASD needs to use minimum alignment */ ++ if (_ped_device_like_dasd(dev)) ++ return s390_get_minimum_alignment(dev); ++#if USE_BLKID ++ return linux_get_optimum_alignment(dev); ++#else ++ return NULL; ++#endif ++} ++#endif ++ + #if USE_BLKID + static PedAlignment* + linux_get_minimum_alignment(const PedDevice *dev) +@@ -3220,15 +3277,10 @@ linux_get_optimum_alignment(const PedDevice *dev) + && PED_DEFAULT_ALIGNMENT % optimal_io == 0) + || (!optimal_io && minimum_io + && PED_DEFAULT_ALIGNMENT % minimum_io == 0) +- ) { +- /* DASD needs to use minimum alignment */ +- if (dev->type == PED_DEVICE_DASD) +- return linux_get_minimum_alignment(dev); +- ++ ) + return ped_alignment_new( + blkid_topology_get_alignment_offset(tp) / dev->sector_size, + PED_DEFAULT_ALIGNMENT / dev->sector_size); +- } + + /* If optimal_io_size is 0 and we don't meet the other criteria + for using the device.c default, return the minimum alignment. */ +@@ -3255,7 +3307,10 @@ static PedDeviceArchOps linux_dev_ops = { + sync: linux_sync, + sync_fast: linux_sync_fast, + probe_all: linux_probe_all, +-#if USE_BLKID ++#if defined __s390__ || defined __s390x__ ++ get_minimum_alignment: s390_get_minimum_alignment, ++ get_optimum_alignment: s390_get_optimum_alignment, ++#elif USE_BLKID + get_minimum_alignment: linux_get_minimum_alignment, + get_optimum_alignment: linux_get_optimum_alignment, + #endif +diff --git a/libparted/device.c b/libparted/device.c +index cdcc117..36fecd2 100644 +--- a/libparted/device.c ++++ b/libparted/device.c +@@ -550,16 +550,10 @@ ped_device_get_optimum_alignment(const PedDevice *dev) + /* If the arch specific code could not give as an alignment + return a default value based on the type of device. */ + if (align == NULL) { +- switch (dev->type) { +- case PED_DEVICE_DASD: +- align = ped_device_get_minimum_alignment(dev); +- break; +- default: +- /* Align to a grain of 1MiB (like vista / win7) */ +- align = ped_alignment_new(0, +- (PED_DEFAULT_ALIGNMENT +- / dev->sector_size)); +- } ++ /* Align to a grain of 1MiB (like vista / win7) */ ++ align = ped_alignment_new(0, ++ (PED_DEFAULT_ALIGNMENT ++ / dev->sector_size)); + } + + return align; +diff --git a/libparted/labels/dasd.c b/libparted/labels/dasd.c +index fa9414f..bb32d66 100644 +--- a/libparted/labels/dasd.c ++++ b/libparted/labels/dasd.c +@@ -214,19 +214,13 @@ dasd_probe (const PedDevice *dev) + + PED_ASSERT(dev != NULL); + +- if (!(dev->type == PED_DEVICE_DASD +- || dev->type == PED_DEVICE_VIODASD +- || dev->type == PED_DEVICE_FILE)) +- return 0; +- + arch_specific = LINUX_SPECIFIC(dev); + + /* add partition test here */ + fdasd_initialize_anchor(&anchor); + +- fdasd_get_geometry(dev, &anchor, arch_specific->fd); +- +- fdasd_check_api_version(&anchor, arch_specific->fd); ++ if (fdasd_get_geometry(dev, &anchor, arch_specific->fd) == 0) ++ goto error_cleanup; + + /* Labels are required on CDL formatted DASDs. */ + if (fdasd_check_volume(&anchor, arch_specific->fd) && +@@ -276,7 +270,9 @@ dasd_read (PedDisk* disk) + + fdasd_initialize_anchor(&anchor); + +- fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd); ++ if (fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd) == 0) ++ goto error_close_dev; ++ + disk_specific->label_block = anchor.label_block; + + if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE) +@@ -630,7 +626,9 @@ dasd_write (const PedDisk* disk) + + /* initialize the anchor */ + fdasd_initialize_anchor(&anchor); +- fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd); ++ if (fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd) == 0) ++ goto error; ++ + fdasd_check_volume(&anchor, arch_specific->fd); + memcpy(anchor.vlabel, &disk_specific->vlabel, sizeof(volume_label_t)); + anchor.vlabel_changed++; +-- +2.4.3 + diff --git a/parted.spec b/parted.spec index e6f2a6e..dfb39d0 100644 --- a/parted.spec +++ b/parted.spec @@ -4,7 +4,7 @@ Summary: The GNU disk partition manipulation program Name: parted Version: 3.2 -Release: 11%{?dist} +Release: 12%{?dist} License: GPLv3+ Group: Applications/System URL: http://www.gnu.org/software/parted @@ -34,7 +34,8 @@ Patch0017: 0017-libparted-Fix-possible-memory-leaks.patch Patch0018: 0018-libparted-Stop-converting-.-in-sys-path-to.patch Patch0019: 0019-libparted-Use-read-only-when-probing-devices-on-linu.patch Patch0020: 0020-tests-Use-wait_for_dev_to_-functions.patch - +Patch0021: 0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch +Patch0022: 0022-dasd-enhance-device-probing.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel @@ -177,6 +178,10 @@ fi %changelog +* Tue Oct 27 2015 Brian C. Lane 3.2-12 +- dasd: enhance device probing +- fdasd: geometry handling updated from upstream s390-tools + * Fri Aug 07 2015 Brian C. Lane 3.2-11 - tests: Fix patch 0012 test for extended partition length - UI: Avoid memory leaks