diff options
-rw-r--r-- | arch/s390/include/asm/dasd.h | 10 | ||||
-rw-r--r-- | arch/s390/include/asm/vtoc.h | 16 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 126 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.h | 9 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 2 | ||||
-rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 4 | ||||
-rw-r--r-- | drivers/s390/block/dasd_proc.c | 2 | ||||
-rw-r--r-- | fs/partitions/ibm.c | 101 |
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 | */ |
169 | typedef struct format_data_t { | 169 | typedef 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 | ||
42 | struct vtoc_volume_label | 42 | struct 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 | ||
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 | struct vtoc_extent | 67 | struct 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 | ||
146 | struct vtoc_ds5ext | 158 | struct 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 | ||
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 | static int | 170 | static int |
163 | check_XRC (struct ccw1 *de_ccw, | 171 | check_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 | ||
188 | static int | 196 | static int |
189 | define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | 197 | define_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 | ||
297 | static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, | 303 | static 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 | ||
401 | static void | 405 | static void |
402 | locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, | 406 | locate_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 | */ |
24 | static inline int | 24 | static sector_t |
25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { | 25 | cchh2blk (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 | */ |
34 | static inline int | 43 | static sector_t |
35 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | 44 | cchhb2blk (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) { | |||
43 | int | 61 | int |
44 | ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | 62 | ibm_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 */ |