|
|
e96bde |
From 42944dd6be000d49d5e1178a576e269aac6f6335 Mon Sep 17 00:00:00 2001
|
|
|
e96bde |
From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
|
|
|
e96bde |
Date: Thu, 17 Sep 2015 15:33:28 +0200
|
|
|
e96bde |
Subject: [PATCH 51/54] fdasd: geometry handling updated from upstream
|
|
|
e96bde |
s390-tools
|
|
|
e96bde |
|
|
|
e96bde |
Remove the necessity for DASD-specific ioctls for partition handling.
|
|
|
e96bde |
This allows to correctly handle DASD-backed virtio block devices.
|
|
|
e96bde |
|
|
|
e96bde |
Note that this is necessary because virtio is just the transport.
|
|
|
e96bde |
A DASD, even if provided via virtio, still has it's unique
|
|
|
e96bde |
characteristics, which means that only traditional DASD partition
|
|
|
e96bde |
table formats can be used (no MBR, GPT, or similar).
|
|
|
e96bde |
|
|
|
e96bde |
Use bzero for initialization to make sure all struct members are
|
|
|
e96bde |
properly cleared. Also changed partition list handling code to be
|
|
|
e96bde |
more similar to upstream s390-tools fdasd.
|
|
|
e96bde |
|
|
|
e96bde |
Further, enhanced error handling capabilities by providing a
|
|
|
e96bde |
return code by fdasd_get_geometry.
|
|
|
e96bde |
|
|
|
e96bde |
Code is largely backported from s390-tools project.
|
|
|
e96bde |
|
|
|
e96bde |
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
|
|
|
e96bde |
Acked-by: Stefan Haberland <stefan.haberland@de.ibm.com>
|
|
|
e96bde |
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
|
|
|
e96bde |
Signed-off-by: Brian C. Lane <bcl@redhat.com>
|
|
|
e96bde |
|
|
|
e96bde |
(cherry picked from commit 4d480d980a9b69b432b8d60df3c4397ba8cdc965)
|
|
|
e96bde |
|
|
|
e96bde |
Resolves: rhbz#1676604
|
|
|
e96bde |
---
|
|
|
e96bde |
include/parted/fdasd.h | 4 +-
|
|
|
e96bde |
libparted/labels/fdasd.c | 166 +++++++++++++++++++++++++++------------
|
|
|
e96bde |
2 files changed, 119 insertions(+), 51 deletions(-)
|
|
|
e96bde |
|
|
|
e96bde |
diff --git a/include/parted/fdasd.h b/include/parted/fdasd.h
|
|
|
e96bde |
index 6f6a7e0..4e351c4 100644
|
|
|
e96bde |
--- a/include/parted/fdasd.h
|
|
|
e96bde |
+++ b/include/parted/fdasd.h
|
|
|
e96bde |
@@ -190,6 +190,8 @@ typedef struct format_data_t {
|
|
|
e96bde |
#define BLKRRPART _IO(0x12,95)
|
|
|
e96bde |
/* get block device sector size */
|
|
|
e96bde |
#define BLKSSZGET _IO(0x12,104)
|
|
|
e96bde |
+/* device size in bytes (u64 *arg)*/
|
|
|
e96bde |
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)
|
|
|
e96bde |
/* get device geometry */
|
|
|
e96bde |
#define HDIO_GETGEO 0x0301
|
|
|
e96bde |
|
|
|
e96bde |
@@ -285,7 +287,7 @@ enum fdasd_failure {
|
|
|
e96bde |
|
|
|
e96bde |
void fdasd_cleanup (fdasd_anchor_t *anchor);
|
|
|
e96bde |
void fdasd_initialize_anchor (fdasd_anchor_t * anc);
|
|
|
e96bde |
-void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
|
|
|
e96bde |
+int fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
|
|
|
e96bde |
void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
|
|
|
e96bde |
int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
|
|
|
e96bde |
int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
|
|
|
e96bde |
diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c
|
|
|
e96bde |
index 1f87937..7e6a77a 100644
|
|
|
e96bde |
--- a/libparted/labels/fdasd.c
|
|
|
e96bde |
+++ b/libparted/labels/fdasd.c
|
|
|
e96bde |
@@ -210,27 +210,7 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc)
|
|
|
e96bde |
partition_info_t *p = NULL;
|
|
|
e96bde |
partition_info_t *q = NULL;
|
|
|
e96bde |
|
|
|
e96bde |
- anc->devno = 0;
|
|
|
e96bde |
- anc->dev_type = 0;
|
|
|
e96bde |
- anc->used_partitions = 0;
|
|
|
e96bde |
-
|
|
|
e96bde |
- anc->silent = 0;
|
|
|
e96bde |
- anc->verbose = 0;
|
|
|
e96bde |
- anc->big_disk = 0;
|
|
|
e96bde |
- anc->volid_specified = 0;
|
|
|
e96bde |
- anc->config_specified = 0;
|
|
|
e96bde |
- anc->auto_partition = 0;
|
|
|
e96bde |
- anc->devname_specified = 0;
|
|
|
e96bde |
- anc->print_table = 0;
|
|
|
e96bde |
-
|
|
|
e96bde |
- anc->option_reuse = 0;
|
|
|
e96bde |
- anc->option_recreate = 0;
|
|
|
e96bde |
-
|
|
|
e96bde |
- anc->vlabel_changed = 0;
|
|
|
e96bde |
- anc->vtoc_changed = 0;
|
|
|
e96bde |
- anc->blksize = 0;
|
|
|
e96bde |
- anc->fspace_trk = 0;
|
|
|
e96bde |
- anc->label_pos = 0;
|
|
|
e96bde |
+ bzero(anc, sizeof(fdasd_anchor_t));
|
|
|
e96bde |
|
|
|
e96bde |
for (i=0; i
|
|
|
e96bde |
setpos(anc, i, -1);
|
|
|
e96bde |
@@ -272,24 +252,18 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc)
|
|
|
e96bde |
if (p == NULL)
|
|
|
e96bde |
fdasd_error(anc, malloc_failed,
|
|
|
e96bde |
_("No room for partition info."));
|
|
|
e96bde |
- p->used = 0x00;
|
|
|
e96bde |
- p->len_trk = 0;
|
|
|
e96bde |
- p->start_trk = 0;
|
|
|
e96bde |
- p->fspace_trk = 0;
|
|
|
e96bde |
- p->type = 0;
|
|
|
e96bde |
+ bzero(p, sizeof(partition_info_t));
|
|
|
e96bde |
|
|
|
e96bde |
/* add p to double pointered list */
|
|
|
e96bde |
if (i == 1) {
|
|
|
e96bde |
- anc->first = p;
|
|
|
e96bde |
- p->prev = NULL;
|
|
|
e96bde |
+ anc->first = p;
|
|
|
e96bde |
} else if (i == USABLE_PARTITIONS) {
|
|
|
e96bde |
- anc->last = p;
|
|
|
e96bde |
- p->next = NULL;
|
|
|
e96bde |
+ anc->last = p;
|
|
|
e96bde |
p->prev = q;
|
|
|
e96bde |
q->next = p;
|
|
|
e96bde |
} else {
|
|
|
e96bde |
- p->prev = q;
|
|
|
e96bde |
- q->next = p;
|
|
|
e96bde |
+ p->prev = q;
|
|
|
e96bde |
+ q->next = p;
|
|
|
e96bde |
}
|
|
|
e96bde |
|
|
|
e96bde |
p->f1 = malloc(sizeof(format1_label_t));
|
|
|
e96bde |
@@ -946,16 +920,78 @@ fdasd_check_api_version (fdasd_anchor_t *anc, int f)
|
|
|
e96bde |
}
|
|
|
e96bde |
}
|
|
|
e96bde |
|
|
|
e96bde |
+/*
|
|
|
e96bde |
+ * The following two functions match those in the DASD ECKD device driver.
|
|
|
e96bde |
+ * They are used to compute how many records of a given size can be stored
|
|
|
e96bde |
+ * in one track.
|
|
|
e96bde |
+ */
|
|
|
e96bde |
+static unsigned int ceil_quot(unsigned int d1, unsigned int d2)
|
|
|
e96bde |
+{
|
|
|
e96bde |
+ return (d1 + (d2 - 1)) / d2;
|
|
|
e96bde |
+}
|
|
|
e96bde |
+
|
|
|
e96bde |
+/* kl: key length, dl: data length */
|
|
|
e96bde |
+static unsigned int recs_per_track(unsigned short dev_type, unsigned int kl,
|
|
|
e96bde |
+ unsigned int dl)
|
|
|
e96bde |
+{
|
|
|
e96bde |
+ unsigned int dn, kn;
|
|
|
e96bde |
+
|
|
|
e96bde |
+ switch (dev_type) {
|
|
|
e96bde |
+ case DASD_3380_TYPE:
|
|
|
e96bde |
+ if (kl)
|
|
|
e96bde |
+ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
|
|
|
e96bde |
+ ceil_quot(dl + 12, 32));
|
|
|
e96bde |
+ else
|
|
|
e96bde |
+ return 1499 / (15 + ceil_quot(dl + 12, 32));
|
|
|
e96bde |
+ case DASD_3390_TYPE:
|
|
|
e96bde |
+ dn = ceil_quot(dl + 6, 232) + 1;
|
|
|
e96bde |
+ if (kl) {
|
|
|
e96bde |
+ kn = ceil_quot(kl + 6, 232) + 1;
|
|
|
e96bde |
+ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
|
|
|
e96bde |
+ 9 + ceil_quot(dl + 6 * dn, 34));
|
|
|
e96bde |
+ } else
|
|
|
e96bde |
+ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
|
|
|
e96bde |
+ case DASD_9345_TYPE:
|
|
|
e96bde |
+ dn = ceil_quot(dl + 6, 232) + 1;
|
|
|
e96bde |
+ if (kl) {
|
|
|
e96bde |
+ kn = ceil_quot(kl + 6, 232) + 1;
|
|
|
e96bde |
+ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
|
|
|
e96bde |
+ ceil_quot(dl + 6 * dn, 34));
|
|
|
e96bde |
+ } else
|
|
|
e96bde |
+ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
|
|
|
e96bde |
+ }
|
|
|
e96bde |
+ return 0;
|
|
|
e96bde |
+}
|
|
|
e96bde |
+
|
|
|
e96bde |
+/*
|
|
|
e96bde |
+ * Verify that number of tracks (heads) per cylinder and number of
|
|
|
e96bde |
+ * sectors per track match the expected values for a given device type
|
|
|
e96bde |
+ * and block size.
|
|
|
e96bde |
+ * Returns 1 for a valid match and 0 otherwise.
|
|
|
e96bde |
+ */
|
|
|
e96bde |
+static int fdasd_verify_geometry(unsigned short dev_type, int blksize,
|
|
|
e96bde |
+ struct fdasd_hd_geometry *geometry)
|
|
|
e96bde |
+{
|
|
|
e96bde |
+ unsigned int expected_sectors;
|
|
|
e96bde |
+ if (geometry->heads != 15)
|
|
|
e96bde |
+ return 0;
|
|
|
e96bde |
+ expected_sectors = recs_per_track(dev_type, 0, blksize);
|
|
|
e96bde |
+ if (geometry->sectors == expected_sectors)
|
|
|
e96bde |
+ return 1;
|
|
|
e96bde |
+ return 0;
|
|
|
e96bde |
+}
|
|
|
e96bde |
+
|
|
|
e96bde |
/*
|
|
|
e96bde |
* reads dasd geometry data
|
|
|
e96bde |
*/
|
|
|
e96bde |
-void
|
|
|
e96bde |
+int
|
|
|
e96bde |
fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
|
|
|
e96bde |
{
|
|
|
e96bde |
PDEBUG
|
|
|
e96bde |
int blksize = 0;
|
|
|
e96bde |
dasd_information_t dasd_info;
|
|
|
e96bde |
struct dasd_eckd_characteristics *characteristics;
|
|
|
e96bde |
+ unsigned long long size_in_bytes;
|
|
|
e96bde |
|
|
|
e96bde |
/* We can't get geometry from a regular file,
|
|
|
e96bde |
so simulate something usable, for the sake of testing. */
|
|
|
e96bde |
@@ -979,6 +1015,12 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
|
|
|
e96bde |
anc->geo.heads;
|
|
|
e96bde |
anc->is_file = 1;
|
|
|
e96bde |
} else {
|
|
|
e96bde |
+ if (ioctl(f, BLKGETSIZE64, &size_in_bytes) != 0) {
|
|
|
e96bde |
+ fdasd_error(anc, unable_to_ioctl,
|
|
|
e96bde |
+ _("Could not retrieve disk size."));
|
|
|
e96bde |
+ goto error;
|
|
|
e96bde |
+ }
|
|
|
e96bde |
+
|
|
|
e96bde |
if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
|
|
|
e96bde |
fdasd_error(anc, unable_to_ioctl,
|
|
|
e96bde |
_("Could not retrieve disk geometry information."));
|
|
|
e96bde |
@@ -988,27 +1030,51 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
|
|
|
e96bde |
_("Could not retrieve blocksize information."));
|
|
|
e96bde |
|
|
|
e96bde |
/* get disk type */
|
|
|
e96bde |
- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
|
|
|
e96bde |
- fdasd_error(anc, unable_to_ioctl,
|
|
|
e96bde |
- _("Could not retrieve disk information."));
|
|
|
e96bde |
-
|
|
|
e96bde |
- characteristics = (struct dasd_eckd_characteristics *)
|
|
|
e96bde |
- &dasd_info.characteristics;
|
|
|
e96bde |
- if (characteristics->no_cyl == LV_COMPAT_CYL &&
|
|
|
e96bde |
- characteristics->long_no_cyl)
|
|
|
e96bde |
- anc->hw_cylinders = characteristics->long_no_cyl;
|
|
|
e96bde |
- else
|
|
|
e96bde |
- anc->hw_cylinders = characteristics->no_cyl;
|
|
|
e96bde |
+ if (ioctl(f, BIODASDINFO, &dasd_info) != 0) {
|
|
|
e96bde |
+ /* verify that the geometry matches a 3390 DASD */
|
|
|
e96bde |
+ if (!fdasd_verify_geometry(DASD_3390_TYPE, blksize,
|
|
|
e96bde |
+ &anc->geo)) {
|
|
|
e96bde |
+ fdasd_error(anc, wrong_disk_type,
|
|
|
e96bde |
+ _("Disk geometry does not match a " \
|
|
|
e96bde |
+ "DASD device of type 3390."));
|
|
|
e96bde |
+ goto error;
|
|
|
e96bde |
+ }
|
|
|
e96bde |
+ anc->dev_type = DASD_3390_TYPE;
|
|
|
e96bde |
+ anc->hw_cylinders =
|
|
|
e96bde |
+ size_in_bytes / (blksize * anc->geo.heads * anc->geo.sectors);
|
|
|
e96bde |
+ /* The VOL1 label on a CDL formatted ECKD DASD is in block 2
|
|
|
e96bde |
+ * It will be verified later, if this position actually holds a
|
|
|
e96bde |
+ * valid label record.
|
|
|
e96bde |
+ */
|
|
|
e96bde |
+ anc->label_pos = 2 * blksize;
|
|
|
e96bde |
+ /* A devno 0 is actually a valid devno, which could exist
|
|
|
e96bde |
+ * in the system. Since we use this number only to create
|
|
|
e96bde |
+ * a default volume serial, there is no serious conflict.
|
|
|
e96bde |
+ */
|
|
|
e96bde |
+ anc->devno = 0;
|
|
|
e96bde |
+ } else {
|
|
|
e96bde |
+ characteristics = (struct dasd_eckd_characteristics *)
|
|
|
e96bde |
+ &dasd_info.characteristics;
|
|
|
e96bde |
+ if (characteristics->no_cyl == LV_COMPAT_CYL &&
|
|
|
e96bde |
+ characteristics->long_no_cyl)
|
|
|
e96bde |
+ anc->hw_cylinders = characteristics->long_no_cyl;
|
|
|
e96bde |
+ else
|
|
|
e96bde |
+ anc->hw_cylinders = characteristics->no_cyl;
|
|
|
e96bde |
+ anc->dev_type = dasd_info.dev_type;
|
|
|
e96bde |
+ anc->label_pos = dasd_info.label_block * blksize;
|
|
|
e96bde |
+ anc->devno = dasd_info.devno;
|
|
|
e96bde |
+ anc->label_block = dasd_info.label_block;
|
|
|
e96bde |
+ anc->FBA_layout = dasd_info.FBA_layout;
|
|
|
e96bde |
+ }
|
|
|
e96bde |
|
|
|
e96bde |
anc->is_file = 0;
|
|
|
e96bde |
}
|
|
|
e96bde |
|
|
|
e96bde |
- anc->dev_type = dasd_info.dev_type;
|
|
|
e96bde |
- anc->blksize = blksize;
|
|
|
e96bde |
- anc->label_pos = dasd_info.label_block * blksize;
|
|
|
e96bde |
- anc->devno = dasd_info.devno;
|
|
|
e96bde |
- anc->label_block = dasd_info.label_block;
|
|
|
e96bde |
- anc->FBA_layout = dasd_info.FBA_layout;
|
|
|
e96bde |
+ anc->blksize = blksize;
|
|
|
e96bde |
+ return 1;
|
|
|
e96bde |
+
|
|
|
e96bde |
+ error:
|
|
|
e96bde |
+ return 0;
|
|
|
e96bde |
}
|
|
|
e96bde |
|
|
|
e96bde |
/*
|
|
|
e96bde |
--
|
|
|
e96bde |
2.20.1
|
|
|
e96bde |
|