diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2007-07-10 11:24:11 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-07-10 11:24:44 +0200 |
commit | bf1a95a225c1349846274caebdca1bb8d20d5853 (patch) | |
tree | d76d2f7fb18ca4c8c947a40ef7d3656c87e46fc2 /fs/partitions | |
parent | 83119ad4a1ceacd99f380086c2855ae2c4268afc (diff) | |
download | linux-stable-bf1a95a225c1349846274caebdca1bb8d20d5853.tar.gz linux-stable-bf1a95a225c1349846274caebdca1bb8d20d5853.tar.bz2 linux-stable-bf1a95a225c1349846274caebdca1bb8d20d5853.zip |
[S390] fixed cdl-format detection.
CDL formated DASDs are now detected correctly even if no VOL1 label is
on the disk. This prevents possible loss of data.
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'fs/partitions')
-rw-r--r-- | fs/partitions/ibm.c | 167 |
1 files changed, 97 insertions, 70 deletions
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 9f7ad4244f63..1e064c4a4f86 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -45,7 +45,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) { int blocksize, offset, size,res; loff_t i_size; - dasd_information_t *info; + dasd_information2_t *info; struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; @@ -64,14 +64,17 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) if (i_size == 0) goto out_exit; - if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL) + info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); + if (info == NULL) goto out_exit; - if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) + geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL); + if (geo == NULL) goto out_nogeo; - if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL) + label = kmalloc(sizeof(union label_t), GFP_KERNEL); + if (label == NULL) goto out_nolab; - if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || + if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) goto out_freeall; @@ -96,84 +99,108 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) res = 1; /* - * Three different types: CMS1, VOL1 and LNX1/unlabeled + * Three different formats: LDL, CDL and unformated disk + * + * identified by info->format + * + * unformated disks we do not have to care about */ - if (strncmp(type, "CMS1", 4) == 0) { - /* - * VM style CMS1 labeled disk - */ - if (label->cms.disk_offset != 0) { - printk("CMS1/%8s(MDSK):", name); - /* disk is reserved minidisk */ - blocksize = label->cms.block_size; - offset = label->cms.disk_offset; - size = (label->cms.block_count - 1) * (blocksize >> 9); + if (info->format == DASD_FORMAT_LDL) { + if (strncmp(type, "CMS1", 4) == 0) { + /* + * VM style CMS1 labeled disk + */ + if (label->cms.disk_offset != 0) { + printk("CMS1/%8s(MDSK):", name); + /* disk is reserved minidisk */ + blocksize = label->cms.block_size; + offset = label->cms.disk_offset; + size = (label->cms.block_count - 1) + * (blocksize >> 9); + } else { + printk("CMS1/%8s:", name); + offset = (info->label_block + 1); + size = i_size >> 9; + } } else { - printk("CMS1/%8s:", name); + /* + * Old style LNX1 or unlabeled disk + */ + if (strncmp(type, "LNX1", 4) == 0) + printk ("LNX1/%8s:", name); + else + printk("(nonl)"); offset = (info->label_block + 1); size = i_size >> 9; } put_partition(state, 1, offset*(blocksize >> 9), - size-offset*(blocksize >> 9)); - } else if ((strncmp(type, "VOL1", 4) == 0) && - (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { + size-offset*(blocksize >> 9)); + } else if (info->format == DASD_FORMAT_CDL) { /* - * New style VOL1 labeled disk + * New style CDL formatted disk */ unsigned int blk; int counter; - printk("VOL1/%8s:", name); - - /* get block number and read then go through format1 labels */ - blk = cchhb2blk(&label->vol.vtoc, geo) + 1; - counter = 0; - while ((data = read_dev_sector(bdev, blk*(blocksize/512), - §)) != NULL) { - struct vtoc_format1_label f1; - - memcpy(&f1, data, sizeof(struct vtoc_format1_label)); - put_dev_sector(sect); - - /* skip FMT4 / FMT5 / FMT7 labels */ - if (f1.DS1FMTID == _ascebc['4'] - || f1.DS1FMTID == _ascebc['5'] - || f1.DS1FMTID == _ascebc['7']) { - blk++; - continue; - } - - /* only FMT1 valid at this point */ - if (f1.DS1FMTID != _ascebc['1']) - break; - - /* OK, we got valid partition data */ - offset = cchh2blk(&f1.DS1EXT1.llimit, geo); - size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - - offset + geo->sectors; - if (counter >= state->limit) - break; - put_partition(state, counter + 1, - offset * (blocksize >> 9), - size * (blocksize >> 9)); - counter++; - blk++; - } - if (!data) - /* Are we not supposed to report this ? */ - goto out_readerr; - } else { /* - * Old style LNX1 or unlabeled disk + * check if VOL1 label is available + * if not, something is wrong, skipping partition detection */ - if (strncmp(type, "LNX1", 4) == 0) - printk ("LNX1/%8s:", name); - else - printk("(nonl)/%8s:", name); - offset = (info->label_block + 1); - size = i_size >> 9; - put_partition(state, 1, offset*(blocksize >> 9), - size-offset*(blocksize >> 9)); + if (strncmp(type, "VOL1", 4) == 0) { + printk("VOL1/%8s:", name); + /* + * get block number and read then go through format1 + * labels + */ + blk = cchhb2blk(&label->vol.vtoc, geo) + 1; + counter = 0; + data = read_dev_sector(bdev, blk * (blocksize/512), + §); + while (data != NULL) { + struct vtoc_format1_label f1; + + memcpy(&f1, data, + sizeof(struct vtoc_format1_label)); + put_dev_sector(sect); + + /* skip FMT4 / FMT5 / FMT7 labels */ + if (f1.DS1FMTID == _ascebc['4'] + || f1.DS1FMTID == _ascebc['5'] + || f1.DS1FMTID == _ascebc['7']) { + blk++; + data = read_dev_sector(bdev, blk * + (blocksize/512), + §); + continue; + } + + /* only FMT1 valid at this point */ + if (f1.DS1FMTID != _ascebc['1']) + break; + + /* OK, we got valid partition data */ + offset = cchh2blk(&f1.DS1EXT1.llimit, geo); + size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - + offset + geo->sectors; + if (counter >= state->limit) + break; + put_partition(state, counter + 1, + offset * (blocksize >> 9), + size * (blocksize >> 9)); + counter++; + blk++; + data = read_dev_sector(bdev, + blk * (blocksize/512), + §); + } + + if (!data) + /* Are we not supposed to report this ? */ + goto out_readerr; + } else + printk(KERN_WARNING "Warning, expected Label VOL1 not " + "found, treating as CDL formated Disk"); + } printk("\n"); |