Commit b44b0ab3bac16356f03e94b1b49ba9305710c445

Authored by Stefan Weinhuber
Committed by Martin Schwidefsky
1 parent f9a28f7bc5

[S390] dasd: add large volume support

The dasd device driver will now support ECKD devices with more then
65520 cylinders.
In the traditional ECKD adressing scheme each track is addressed
by a 16-bit cylinder and 16-bit head number. The new addressing
scheme makes use of the fact that the actual number of heads is
never larger then 15, so 12 bits of the head number can be redefined
to be part of the cylinder address.

Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

Showing 8 changed files with 171 additions and 99 deletions Side-by-side Diff

arch/s390/include/asm/dasd.h
... ... @@ -162,15 +162,15 @@
162 162 unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
163 163 } dasd_profile_info_t;
164 164  
165   -/*
  165 +/*
166 166 * struct format_data_t
167 167 * represents all data necessary to format a dasd
168 168 */
169 169 typedef struct format_data_t {
170   - int start_unit; /* from track */
171   - int stop_unit; /* to track */
172   - int blksize; /* sectorsize */
173   - int intensity;
  170 + unsigned int start_unit; /* from track */
  171 + unsigned int stop_unit; /* to track */
  172 + unsigned int blksize; /* sectorsize */
  173 + unsigned int intensity;
174 174 } format_data_t;
175 175  
176 176 /*
arch/s390/include/asm/vtoc.h
... ... @@ -39,7 +39,7 @@
39 39 __u16 day;
40 40 } __attribute__ ((packed));
41 41  
42   -struct vtoc_volume_label
  42 +struct vtoc_volume_label_cdl
43 43 {
44 44 char volkey[4]; /* volume key = volume label */
45 45 char vollbl[4]; /* volume label */
... ... @@ -56,6 +56,14 @@
56 56 char res3[29]; /* reserved */
57 57 } __attribute__ ((packed));
58 58  
  59 +struct vtoc_volume_label_ldl {
  60 + char vollbl[4]; /* volume label */
  61 + char volid[6]; /* volume identifier */
  62 + char res3[69]; /* reserved */
  63 + char ldl_version; /* version number, valid for ldl format */
  64 + __u64 formatted_blocks; /* valid when ldl_version >= f2 */
  65 +} __attribute__ ((packed));
  66 +
59 67 struct vtoc_extent
60 68 {
61 69 __u8 typeind; /* extent type indicator */
... ... @@ -140,7 +148,11 @@
140 148 char res2[10]; /* reserved */
141 149 __u8 DS4EFLVL; /* extended free-space management level */
142 150 struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */
143   - char res3[9]; /* reserved */
  151 + char res3; /* reserved */
  152 + __u32 DS4DCYL; /* number of logical cyls */
  153 + char res4[2]; /* reserved */
  154 + __u8 DS4DEVF2; /* device flags */
  155 + char res5; /* reserved */
144 156 } __attribute__ ((packed));
145 157  
146 158 struct vtoc_ds5ext
drivers/s390/block/dasd_eckd.c
... ... @@ -159,6 +159,14 @@
159 159 return 0;
160 160 }
161 161  
  162 +static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head)
  163 +{
  164 + geo->cyl = (__u16) cyl;
  165 + geo->head = cyl >> 16;
  166 + geo->head <<= 4;
  167 + geo->head |= head;
  168 +}
  169 +
162 170 static int
163 171 check_XRC (struct ccw1 *de_ccw,
164 172 struct DE_eckd_data *data,
165 173  
... ... @@ -186,11 +194,12 @@
186 194 }
187 195  
188 196 static int
189   -define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
190   - int totrk, int cmd, struct dasd_device * device)
  197 +define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk,
  198 + unsigned int totrk, int cmd, struct dasd_device *device)
191 199 {
192 200 struct dasd_eckd_private *private;
193   - struct ch_t geo, beg, end;
  201 + u32 begcyl, endcyl;
  202 + u16 heads, beghead, endhead;
194 203 int rc = 0;
195 204  
196 205 private = (struct dasd_eckd_private *) device->private;
197 206  
198 207  
199 208  
... ... @@ -248,27 +257,24 @@
248 257 && !(private->uses_cdl && trk < 2))
249 258 data->ga_extended |= 0x40; /* Regular Data Format Mode */
250 259  
251   - geo.cyl = private->rdc_data.no_cyl;
252   - geo.head = private->rdc_data.trk_per_cyl;
253   - beg.cyl = trk / geo.head;
254   - beg.head = trk % geo.head;
255   - end.cyl = totrk / geo.head;
256   - end.head = totrk % geo.head;
  260 + heads = private->rdc_data.trk_per_cyl;
  261 + begcyl = trk / heads;
  262 + beghead = trk % heads;
  263 + endcyl = totrk / heads;
  264 + endhead = totrk % heads;
257 265  
258 266 /* check for sequential prestage - enhance cylinder range */
259 267 if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
260 268 data->attributes.operation == DASD_SEQ_ACCESS) {
261 269  
262   - if (end.cyl + private->attrib.nr_cyl < geo.cyl)
263   - end.cyl += private->attrib.nr_cyl;
  270 + if (endcyl + private->attrib.nr_cyl < private->real_cyl)
  271 + endcyl += private->attrib.nr_cyl;
264 272 else
265   - end.cyl = (geo.cyl - 1);
  273 + endcyl = (private->real_cyl - 1);
266 274 }
267 275  
268   - data->beg_ext.cyl = beg.cyl;
269   - data->beg_ext.head = beg.head;
270   - data->end_ext.cyl = end.cyl;
271   - data->end_ext.head = end.head;
  276 + set_ch_t(&data->beg_ext, begcyl, beghead);
  277 + set_ch_t(&data->end_ext, endcyl, endhead);
272 278 return rc;
273 279 }
274 280  
275 281  
... ... @@ -294,13 +300,14 @@
294 300 return rc;
295 301 }
296 302  
297   -static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
298   - int totrk, int cmd, struct dasd_device *basedev,
299   - struct dasd_device *startdev)
  303 +static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata,
  304 + unsigned int trk, unsigned int totrk, int cmd,
  305 + struct dasd_device *basedev, struct dasd_device *startdev)
300 306 {
301 307 struct dasd_eckd_private *basepriv, *startpriv;
302 308 struct DE_eckd_data *data;
303   - struct ch_t geo, beg, end;
  309 + u32 begcyl, endcyl;
  310 + u16 heads, beghead, endhead;
304 311 int rc = 0;
305 312  
306 313 basepriv = (struct dasd_eckd_private *) basedev->private;
307 314  
308 315  
309 316  
310 317  
... ... @@ -374,33 +381,30 @@
374 381 && !(basepriv->uses_cdl && trk < 2))
375 382 data->ga_extended |= 0x40; /* Regular Data Format Mode */
376 383  
377   - geo.cyl = basepriv->rdc_data.no_cyl;
378   - geo.head = basepriv->rdc_data.trk_per_cyl;
379   - beg.cyl = trk / geo.head;
380   - beg.head = trk % geo.head;
381   - end.cyl = totrk / geo.head;
382   - end.head = totrk % geo.head;
  384 + heads = basepriv->rdc_data.trk_per_cyl;
  385 + begcyl = trk / heads;
  386 + beghead = trk % heads;
  387 + endcyl = totrk / heads;
  388 + endhead = totrk % heads;
383 389  
384 390 /* check for sequential prestage - enhance cylinder range */
385 391 if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
386 392 data->attributes.operation == DASD_SEQ_ACCESS) {
387 393  
388   - if (end.cyl + basepriv->attrib.nr_cyl < geo.cyl)
389   - end.cyl += basepriv->attrib.nr_cyl;
  394 + if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl)
  395 + endcyl += basepriv->attrib.nr_cyl;
390 396 else
391   - end.cyl = (geo.cyl - 1);
  397 + endcyl = (basepriv->real_cyl - 1);
392 398 }
393 399  
394   - data->beg_ext.cyl = beg.cyl;
395   - data->beg_ext.head = beg.head;
396   - data->end_ext.cyl = end.cyl;
397   - data->end_ext.head = end.head;
  400 + set_ch_t(&data->beg_ext, begcyl, beghead);
  401 + set_ch_t(&data->end_ext, endcyl, endhead);
398 402 return rc;
399 403 }
400 404  
401 405 static void
402   -locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
403   - int rec_on_trk, int no_rec, int cmd,
  406 +locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk,
  407 + unsigned int rec_on_trk, int no_rec, int cmd,
404 408 struct dasd_device * device, int reclen)
405 409 {
406 410 struct dasd_eckd_private *private;
... ... @@ -493,10 +497,11 @@
493 497 default:
494 498 DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
495 499 }
496   - data->seek_addr.cyl = data->search_arg.cyl =
497   - trk / private->rdc_data.trk_per_cyl;
498   - data->seek_addr.head = data->search_arg.head =
499   - trk % private->rdc_data.trk_per_cyl;
  500 + set_ch_t(&data->seek_addr,
  501 + trk / private->rdc_data.trk_per_cyl,
  502 + trk % private->rdc_data.trk_per_cyl);
  503 + data->search_arg.cyl = data->seek_addr.cyl;
  504 + data->search_arg.head = data->seek_addr.head;
500 505 data->search_arg.record = rec_on_trk;
501 506 }
502 507  
503 508  
... ... @@ -1002,13 +1007,20 @@
1002 1007 "rc=%d", rc);
1003 1008 goto out_err3;
1004 1009 }
  1010 + /* find the vaild cylinder size */
  1011 + if (private->rdc_data.no_cyl == LV_COMPAT_CYL &&
  1012 + private->rdc_data.long_no_cyl)
  1013 + private->real_cyl = private->rdc_data.long_no_cyl;
  1014 + else
  1015 + private->real_cyl = private->rdc_data.no_cyl;
  1016 +
1005 1017 DEV_MESSAGE(KERN_INFO, device,
1006 1018 "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
1007 1019 private->rdc_data.dev_type,
1008 1020 private->rdc_data.dev_model,
1009 1021 private->rdc_data.cu_type,
1010 1022 private->rdc_data.cu_model.model,
1011   - private->rdc_data.no_cyl,
  1023 + private->real_cyl,
1012 1024 private->rdc_data.trk_per_cyl,
1013 1025 private->rdc_data.sec_per_trk);
1014 1026 return 0;
... ... @@ -1157,8 +1169,6 @@
1157 1169 }
1158 1170  
1159 1171 private->uses_cdl = 1;
1160   - /* Calculate number of blocks/records per track. */
1161   - blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
1162 1172 /* Check Track 0 for Compatible Disk Layout */
1163 1173 count_area = NULL;
1164 1174 for (i = 0; i < 3; i++) {
1165 1175  
... ... @@ -1200,14 +1210,14 @@
1200 1210 block->s2b_shift++;
1201 1211  
1202 1212 blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
1203   - block->blocks = (private->rdc_data.no_cyl *
  1213 + block->blocks = (private->real_cyl *
1204 1214 private->rdc_data.trk_per_cyl *
1205 1215 blk_per_trk);
1206 1216  
1207 1217 DEV_MESSAGE(KERN_INFO, device,
1208 1218 "(%dkB blks): %dkB at %dkB/trk %s",
1209 1219 (block->bp_block >> 10),
1210   - ((private->rdc_data.no_cyl *
  1220 + ((private->real_cyl *
1211 1221 private->rdc_data.trk_per_cyl *
1212 1222 blk_per_trk * (block->bp_block >> 9)) >> 1),
1213 1223 ((blk_per_trk * block->bp_block) >> 10),
... ... @@ -1262,7 +1272,8 @@
1262 1272 struct eckd_count *ect;
1263 1273 struct ccw1 *ccw;
1264 1274 void *data;
1265   - int rpt, cyl, head;
  1275 + int rpt;
  1276 + struct ch_t address;
1266 1277 int cplength, datasize;
1267 1278 int i;
1268 1279 int intensity = 0;
1269 1280  
1270 1281  
1271 1282  
... ... @@ -1270,24 +1281,25 @@
1270 1281  
1271 1282 private = (struct dasd_eckd_private *) device->private;
1272 1283 rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
1273   - cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
1274   - head = fdata->start_unit % private->rdc_data.trk_per_cyl;
  1284 + set_ch_t(&address,
  1285 + fdata->start_unit / private->rdc_data.trk_per_cyl,
  1286 + fdata->start_unit % private->rdc_data.trk_per_cyl);
1275 1287  
1276 1288 /* Sanity checks. */
1277 1289 if (fdata->start_unit >=
1278   - (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) {
1279   - DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!",
  1290 + (private->real_cyl * private->rdc_data.trk_per_cyl)) {
  1291 + DEV_MESSAGE(KERN_INFO, device, "Track no %u too big!",
1280 1292 fdata->start_unit);
1281 1293 return ERR_PTR(-EINVAL);
1282 1294 }
1283 1295 if (fdata->start_unit > fdata->stop_unit) {
1284   - DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.",
  1296 + DEV_MESSAGE(KERN_INFO, device, "Track %u reached! ending.",
1285 1297 fdata->start_unit);
1286 1298 return ERR_PTR(-EINVAL);
1287 1299 }
1288 1300 if (dasd_check_blocksize(fdata->blksize) != 0) {
1289 1301 DEV_MESSAGE(KERN_WARNING, device,
1290   - "Invalid blocksize %d...terminating!",
  1302 + "Invalid blocksize %u...terminating!",
1291 1303 fdata->blksize);
1292 1304 return ERR_PTR(-EINVAL);
1293 1305 }
... ... @@ -1389,8 +1401,8 @@
1389 1401 if (intensity & 0x01) { /* write record zero */
1390 1402 ect = (struct eckd_count *) data;
1391 1403 data += sizeof(struct eckd_count);
1392   - ect->cyl = cyl;
1393   - ect->head = head;
  1404 + ect->cyl = address.cyl;
  1405 + ect->head = address.head;
1394 1406 ect->record = 0;
1395 1407 ect->kl = 0;
1396 1408 ect->dl = 8;
... ... @@ -1404,8 +1416,8 @@
1404 1416 if ((intensity & ~0x08) & 0x04) { /* erase track */
1405 1417 ect = (struct eckd_count *) data;
1406 1418 data += sizeof(struct eckd_count);
1407   - ect->cyl = cyl;
1408   - ect->head = head;
  1419 + ect->cyl = address.cyl;
  1420 + ect->head = address.head;
1409 1421 ect->record = 1;
1410 1422 ect->kl = 0;
1411 1423 ect->dl = 0;
... ... @@ -1418,8 +1430,8 @@
1418 1430 for (i = 0; i < rpt; i++) {
1419 1431 ect = (struct eckd_count *) data;
1420 1432 data += sizeof(struct eckd_count);
1421   - ect->cyl = cyl;
1422   - ect->head = head;
  1433 + ect->cyl = address.cyl;
  1434 + ect->head = address.head;
1423 1435 ect->record = i + 1;
1424 1436 ect->kl = 0;
1425 1437 ect->dl = fdata->blksize;
drivers/s390/block/dasd_eckd.h
... ... @@ -48,6 +48,11 @@
48 48 #define PSF_ORDER_PRSSD 0x18
49 49 #define PSF_ORDER_SSC 0x1D
50 50  
  51 +/*
  52 + * Size that is reportet for large volumes in the old 16-bit no_cyl field
  53 + */
  54 +#define LV_COMPAT_CYL 0xFFFE
  55 +
51 56 /*****************************************************************************
52 57 * SECTION: Type Definitions
53 58 ****************************************************************************/
... ... @@ -228,7 +233,8 @@
228 233 __u8 factor7;
229 234 __u8 factor8;
230 235 __u8 reserved2[3];
231   - __u8 reserved3[10];
  236 + __u8 reserved3[6];
  237 + __u32 long_no_cyl;
232 238 } __attribute__ ((packed));
233 239  
234 240 /* elements of the configuration data */
... ... @@ -406,6 +412,7 @@
406 412 int uses_cdl;
407 413 struct attrib_data_t attrib; /* e.g. cache operations */
408 414 struct dasd_rssd_features features;
  415 + u32 real_cyl;
409 416  
410 417 /* alias managemnet */
411 418 struct dasd_uid uid;
drivers/s390/block/dasd_int.h
... ... @@ -378,7 +378,7 @@
378 378 struct block_device *bdev;
379 379 atomic_t open_count;
380 380  
381   - unsigned long blocks; /* size of volume in blocks */
  381 + unsigned long long blocks; /* size of volume in blocks */
382 382 unsigned int bp_block; /* bytes per block */
383 383 unsigned int s2b_shift; /* log2 (bp_block/512) */
384 384  
drivers/s390/block/dasd_ioctl.c
... ... @@ -146,7 +146,7 @@
146 146 }
147 147  
148 148 DBF_DEV_EVENT(DBF_NOTICE, base,
149   - "formatting units %d to %d (%d B blocks) flags %d",
  149 + "formatting units %u to %u (%u B blocks) flags %u",
150 150 fdata->start_unit,
151 151 fdata->stop_unit, fdata->blksize, fdata->intensity);
152 152  
... ... @@ -170,7 +170,7 @@
170 170 if (rc) {
171 171 if (rc != -ERESTARTSYS)
172 172 DEV_MESSAGE(KERN_ERR, base,
173   - " Formatting of unit %d failed "
  173 + " Formatting of unit %u failed "
174 174 "with rc = %d",
175 175 fdata->start_unit, rc);
176 176 return rc;
drivers/s390/block/dasd_proc.c
... ... @@ -112,7 +112,7 @@
112 112 seq_printf(m, "n/f ");
113 113 else
114 114 seq_printf(m,
115   - "at blocksize: %d, %ld blocks, %ld MB",
  115 + "at blocksize: %d, %lld blocks, %lld MB",
116 116 block->bp_block, block->blocks,
117 117 ((block->bp_block >> 9) *
118 118 block->blocks) >> 11);
... ... @@ -21,20 +21,38 @@
21 21 * compute the block number from a
22 22 * cyl-cyl-head-head structure
23 23 */
24   -static inline int
  24 +static sector_t
25 25 cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
26   - return ptr->cc * geo->heads * geo->sectors +
27   - ptr->hh * geo->sectors;
  26 +
  27 + sector_t cyl;
  28 + __u16 head;
  29 +
  30 + /*decode cylinder and heads for large volumes */
  31 + cyl = ptr->hh & 0xFFF0;
  32 + cyl <<= 12;
  33 + cyl |= ptr->cc;
  34 + head = ptr->hh & 0x000F;
  35 + return cyl * geo->heads * geo->sectors +
  36 + head * geo->sectors;
28 37 }
29 38  
30 39 /*
31 40 * compute the block number from a
32 41 * cyl-cyl-head-head-block structure
33 42 */
34   -static inline int
  43 +static sector_t
35 44 cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
36   - return ptr->cc * geo->heads * geo->sectors +
37   - ptr->hh * geo->sectors +
  45 +
  46 + sector_t cyl;
  47 + __u16 head;
  48 +
  49 + /*decode cylinder and heads for large volumes */
  50 + cyl = ptr->hh & 0xFFF0;
  51 + cyl <<= 12;
  52 + cyl |= ptr->cc;
  53 + head = ptr->hh & 0x000F;
  54 + return cyl * geo->heads * geo->sectors +
  55 + head * geo->sectors +
38 56 ptr->b;
39 57 }
40 58  
41 59  
... ... @@ -43,14 +61,15 @@
43 61 int
44 62 ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
45 63 {
46   - int blocksize, offset, size,res;
47   - loff_t i_size;
  64 + int blocksize, res;
  65 + loff_t i_size, offset, size, fmt_size;
48 66 dasd_information2_t *info;
49 67 struct hd_geometry *geo;
50 68 char type[5] = {0,};
51 69 char name[7] = {0,};
52 70 union label_t {
53   - struct vtoc_volume_label vol;
  71 + struct vtoc_volume_label_cdl vol;
  72 + struct vtoc_volume_label_ldl lnx;
54 73 struct vtoc_cms_label cms;
55 74 } *label;
56 75 unsigned char *data;
57 76  
... ... @@ -85,14 +104,16 @@
85 104 if (data == NULL)
86 105 goto out_readerr;
87 106  
88   - strncpy (type, data, 4);
89   - if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
90   - strncpy(name, data + 8, 6);
91   - else
92   - strncpy(name, data + 4, 6);
93 107 memcpy(label, data, sizeof(union label_t));
94 108 put_dev_sector(sect);
95 109  
  110 + if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
  111 + strncpy(type, label->vol.vollbl, 4);
  112 + strncpy(name, label->vol.volid, 6);
  113 + } else {
  114 + strncpy(type, label->lnx.vollbl, 4);
  115 + strncpy(name, label->lnx.volid, 6);
  116 + }
96 117 EBCASC(type, 4);
97 118 EBCASC(name, 6);
98 119  
99 120  
100 121  
101 122  
102 123  
103 124  
104 125  
105 126  
... ... @@ -110,36 +131,54 @@
110 131 /*
111 132 * VM style CMS1 labeled disk
112 133 */
  134 + blocksize = label->cms.block_size;
113 135 if (label->cms.disk_offset != 0) {
114 136 printk("CMS1/%8s(MDSK):", name);
115 137 /* disk is reserved minidisk */
116   - blocksize = label->cms.block_size;
117 138 offset = label->cms.disk_offset;
118 139 size = (label->cms.block_count - 1)
119 140 * (blocksize >> 9);
120 141 } else {
121 142 printk("CMS1/%8s:", name);
122 143 offset = (info->label_block + 1);
123   - size = i_size >> 9;
  144 + size = label->cms.block_count
  145 + * (blocksize >> 9);
124 146 }
  147 + put_partition(state, 1, offset*(blocksize >> 9),
  148 + size-offset*(blocksize >> 9));
125 149 } else {
126   - /*
127   - * Old style LNX1 or unlabeled disk
128   - */
129   - if (strncmp(type, "LNX1", 4) == 0)
130   - printk ("LNX1/%8s:", name);
131   - else
  150 + if (strncmp(type, "LNX1", 4) == 0) {
  151 + printk("LNX1/%8s:", name);
  152 + if (label->lnx.ldl_version == 0xf2) {
  153 + fmt_size = label->lnx.formatted_blocks
  154 + * (blocksize >> 9);
  155 + } else if (!strcmp(info->type, "ECKD")) {
  156 + /* formated w/o large volume support */
  157 + fmt_size = geo->cylinders * geo->heads
  158 + * geo->sectors * (blocksize >> 9);
  159 + } else {
  160 + /* old label and no usable disk geometry
  161 + * (e.g. DIAG) */
  162 + fmt_size = i_size >> 9;
  163 + }
  164 + size = i_size >> 9;
  165 + if (fmt_size < size)
  166 + size = fmt_size;
  167 + offset = (info->label_block + 1);
  168 + } else {
  169 + /* unlabeled disk */
132 170 printk("(nonl)");
133   - offset = (info->label_block + 1);
134   - size = i_size >> 9;
135   - }
136   - put_partition(state, 1, offset*(blocksize >> 9),
  171 + size = i_size >> 9;
  172 + offset = (info->label_block + 1);
  173 + }
  174 + put_partition(state, 1, offset*(blocksize >> 9),
137 175 size-offset*(blocksize >> 9));
  176 + }
138 177 } else if (info->format == DASD_FORMAT_CDL) {
139 178 /*
140 179 * New style CDL formatted disk
141 180 */
142   - unsigned int blk;
  181 + sector_t blk;
143 182 int counter;
144 183  
145 184 /*
... ... @@ -166,7 +205,8 @@
166 205 /* skip FMT4 / FMT5 / FMT7 labels */
167 206 if (f1.DS1FMTID == _ascebc['4']
168 207 || f1.DS1FMTID == _ascebc['5']
169   - || f1.DS1FMTID == _ascebc['7']) {
  208 + || f1.DS1FMTID == _ascebc['7']
  209 + || f1.DS1FMTID == _ascebc['9']) {
170 210 blk++;
171 211 data = read_dev_sector(bdev, blk *
172 212 (blocksize/512),
... ... @@ -174,8 +214,9 @@
174 214 continue;
175 215 }
176 216  
177   - /* only FMT1 valid at this point */
178   - if (f1.DS1FMTID != _ascebc['1'])
  217 + /* only FMT1 and 8 labels valid at this point */
  218 + if (f1.DS1FMTID != _ascebc['1'] &&
  219 + f1.DS1FMTID != _ascebc['8'])
179 220 break;
180 221  
181 222 /* OK, we got valid partition data */