]> git.pld-linux.org Git - packages/parted.git/blame - 0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch
- release 6 (by relup.sh)
[packages/parted.git] / 0021-fdasd-geometry-handling-updated-from-upstream-s390-t.patch
CommitLineData
c886eb9d
AM
1From 4d480d980a9b69b432b8d60df3c4397ba8cdc965 Mon Sep 17 00:00:00 2001
2From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
3Date: Thu, 17 Sep 2015 15:33:28 +0200
4Subject: [PATCH 21/22] fdasd: geometry handling updated from upstream
5 s390-tools
6
7Remove the necessity for DASD-specific ioctls for partition handling.
8This allows to correctly handle DASD-backed virtio block devices.
9
10Note that this is necessary because virtio is just the transport.
11A DASD, even if provided via virtio, still has it's unique
12characteristics, which means that only traditional DASD partition
13table formats can be used (no MBR, GPT, or similar).
14
15Use bzero for initialization to make sure all struct members are
16properly cleared. Also changed partition list handling code to be
17more similar to upstream s390-tools fdasd.
18
19Further, enhanced error handling capabilities by providing a
20return code by fdasd_get_geometry.
21
22Code is largely backported from s390-tools project.
23
24Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
25Acked-by: Stefan Haberland <stefan.haberland@de.ibm.com>
26Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
27Signed-off-by: Brian C. Lane <bcl@redhat.com>
28---
29 include/parted/fdasd.in.h | 4 +-
30 libparted/labels/fdasd.c | 166 ++++++++++++++++++++++++++++++++--------------
31 2 files changed, 119 insertions(+), 51 deletions(-)
32
33diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h
34index 6f6a7e0..4e351c4 100644
35--- a/include/parted/fdasd.in.h
36+++ b/include/parted/fdasd.in.h
37@@ -190,6 +190,8 @@ typedef struct format_data_t {
38 #define BLKRRPART _IO(0x12,95)
39 /* get block device sector size */
40 #define BLKSSZGET _IO(0x12,104)
41+/* device size in bytes (u64 *arg)*/
42+#define BLKGETSIZE64 _IOR(0x12,114,size_t)
43 /* get device geometry */
44 #define HDIO_GETGEO 0x0301
45
46@@ -285,7 +287,7 @@ enum fdasd_failure {
47
48 void fdasd_cleanup (fdasd_anchor_t *anchor);
49 void fdasd_initialize_anchor (fdasd_anchor_t * anc);
50-void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
51+int fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
52 void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
53 int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
54 int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
55diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c
56index 1f87937..7e6a77a 100644
57--- a/libparted/labels/fdasd.c
58+++ b/libparted/labels/fdasd.c
59@@ -210,27 +210,7 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc)
60 partition_info_t *p = NULL;
61 partition_info_t *q = NULL;
62
63- anc->devno = 0;
64- anc->dev_type = 0;
65- anc->used_partitions = 0;
66-
67- anc->silent = 0;
68- anc->verbose = 0;
69- anc->big_disk = 0;
70- anc->volid_specified = 0;
71- anc->config_specified = 0;
72- anc->auto_partition = 0;
73- anc->devname_specified = 0;
74- anc->print_table = 0;
75-
76- anc->option_reuse = 0;
77- anc->option_recreate = 0;
78-
79- anc->vlabel_changed = 0;
80- anc->vtoc_changed = 0;
81- anc->blksize = 0;
82- anc->fspace_trk = 0;
83- anc->label_pos = 0;
84+ bzero(anc, sizeof(fdasd_anchor_t));
85
86 for (i=0; i<USABLE_PARTITIONS; i++)
87 setpos(anc, i, -1);
88@@ -272,24 +252,18 @@ fdasd_initialize_anchor (fdasd_anchor_t * anc)
89 if (p == NULL)
90 fdasd_error(anc, malloc_failed,
91 _("No room for partition info."));
92- p->used = 0x00;
93- p->len_trk = 0;
94- p->start_trk = 0;
95- p->fspace_trk = 0;
96- p->type = 0;
97+ bzero(p, sizeof(partition_info_t));
98
99 /* add p to double pointered list */
100 if (i == 1) {
101- anc->first = p;
102- p->prev = NULL;
103+ anc->first = p;
104 } else if (i == USABLE_PARTITIONS) {
105- anc->last = p;
106- p->next = NULL;
107+ anc->last = p;
108 p->prev = q;
109 q->next = p;
110 } else {
111- p->prev = q;
112- q->next = p;
113+ p->prev = q;
114+ q->next = p;
115 }
116
117 p->f1 = malloc(sizeof(format1_label_t));
118@@ -947,15 +921,77 @@ fdasd_check_api_version (fdasd_anchor_t *anc, int f)
119 }
120
121 /*
122+ * The following two functions match those in the DASD ECKD device driver.
123+ * They are used to compute how many records of a given size can be stored
124+ * in one track.
125+ */
126+static unsigned int ceil_quot(unsigned int d1, unsigned int d2)
127+{
128+ return (d1 + (d2 - 1)) / d2;
129+}
130+
131+/* kl: key length, dl: data length */
132+static unsigned int recs_per_track(unsigned short dev_type, unsigned int kl,
133+ unsigned int dl)
134+{
135+ unsigned int dn, kn;
136+
137+ switch (dev_type) {
138+ case DASD_3380_TYPE:
139+ if (kl)
140+ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
141+ ceil_quot(dl + 12, 32));
142+ else
143+ return 1499 / (15 + ceil_quot(dl + 12, 32));
144+ case DASD_3390_TYPE:
145+ dn = ceil_quot(dl + 6, 232) + 1;
146+ if (kl) {
147+ kn = ceil_quot(kl + 6, 232) + 1;
148+ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
149+ 9 + ceil_quot(dl + 6 * dn, 34));
150+ } else
151+ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
152+ case DASD_9345_TYPE:
153+ dn = ceil_quot(dl + 6, 232) + 1;
154+ if (kl) {
155+ kn = ceil_quot(kl + 6, 232) + 1;
156+ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
157+ ceil_quot(dl + 6 * dn, 34));
158+ } else
159+ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
160+ }
161+ return 0;
162+}
163+
164+/*
165+ * Verify that number of tracks (heads) per cylinder and number of
166+ * sectors per track match the expected values for a given device type
167+ * and block size.
168+ * Returns 1 for a valid match and 0 otherwise.
169+ */
170+static int fdasd_verify_geometry(unsigned short dev_type, int blksize,
171+ struct fdasd_hd_geometry *geometry)
172+{
173+ unsigned int expected_sectors;
174+ if (geometry->heads != 15)
175+ return 0;
176+ expected_sectors = recs_per_track(dev_type, 0, blksize);
177+ if (geometry->sectors == expected_sectors)
178+ return 1;
179+ return 0;
180+}
181+
182+/*
183 * reads dasd geometry data
184 */
185-void
186+int
187 fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
188 {
189 PDEBUG
190 int blksize = 0;
191 dasd_information_t dasd_info;
192 struct dasd_eckd_characteristics *characteristics;
193+ unsigned long long size_in_bytes;
194
195 /* We can't get geometry from a regular file,
196 so simulate something usable, for the sake of testing. */
197@@ -979,6 +1015,12 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
198 anc->geo.heads;
199 anc->is_file = 1;
200 } else {
201+ if (ioctl(f, BLKGETSIZE64, &size_in_bytes) != 0) {
202+ fdasd_error(anc, unable_to_ioctl,
203+ _("Could not retrieve disk size."));
204+ goto error;
205+ }
206+
207 if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
208 fdasd_error(anc, unable_to_ioctl,
209 _("Could not retrieve disk geometry information."));
210@@ -988,27 +1030,51 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
211 _("Could not retrieve blocksize information."));
212
213 /* get disk type */
214- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
215- fdasd_error(anc, unable_to_ioctl,
216- _("Could not retrieve disk information."));
217-
218- characteristics = (struct dasd_eckd_characteristics *)
219- &dasd_info.characteristics;
220- if (characteristics->no_cyl == LV_COMPAT_CYL &&
221- characteristics->long_no_cyl)
222- anc->hw_cylinders = characteristics->long_no_cyl;
223- else
224- anc->hw_cylinders = characteristics->no_cyl;
225+ if (ioctl(f, BIODASDINFO, &dasd_info) != 0) {
226+ /* verify that the geometry matches a 3390 DASD */
227+ if (!fdasd_verify_geometry(DASD_3390_TYPE, blksize,
228+ &anc->geo)) {
229+ fdasd_error(anc, wrong_disk_type,
230+ _("Disk geometry does not match a " \
231+ "DASD device of type 3390."));
232+ goto error;
233+ }
234+ anc->dev_type = DASD_3390_TYPE;
235+ anc->hw_cylinders =
236+ size_in_bytes / (blksize * anc->geo.heads * anc->geo.sectors);
237+ /* The VOL1 label on a CDL formatted ECKD DASD is in block 2
238+ * It will be verified later, if this position actually holds a
239+ * valid label record.
240+ */
241+ anc->label_pos = 2 * blksize;
242+ /* A devno 0 is actually a valid devno, which could exist
243+ * in the system. Since we use this number only to create
244+ * a default volume serial, there is no serious conflict.
245+ */
246+ anc->devno = 0;
247+ } else {
248+ characteristics = (struct dasd_eckd_characteristics *)
249+ &dasd_info.characteristics;
250+ if (characteristics->no_cyl == LV_COMPAT_CYL &&
251+ characteristics->long_no_cyl)
252+ anc->hw_cylinders = characteristics->long_no_cyl;
253+ else
254+ anc->hw_cylinders = characteristics->no_cyl;
255+ anc->dev_type = dasd_info.dev_type;
256+ anc->label_pos = dasd_info.label_block * blksize;
257+ anc->devno = dasd_info.devno;
258+ anc->label_block = dasd_info.label_block;
259+ anc->FBA_layout = dasd_info.FBA_layout;
260+ }
261
262 anc->is_file = 0;
263 }
264
265- anc->dev_type = dasd_info.dev_type;
266- anc->blksize = blksize;
267- anc->label_pos = dasd_info.label_block * blksize;
268- anc->devno = dasd_info.devno;
269- anc->label_block = dasd_info.label_block;
270- anc->FBA_layout = dasd_info.FBA_layout;
271+ anc->blksize = blksize;
272+ return 1;
273+
274+ error:
275+ return 0;
276 }
277
278 /*
279--
2802.4.3
281
This page took 0.059021 seconds and 4 git commands to generate.