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