Commit 17a2e5b1 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] 2.5.22: ibm partition support.

another resend of the partition patch for ibm.c. Nobody sent a veto so far
so please add it.
parent bf291a02
......@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
export-objs := check.o ibm.o msdos.o
export-objs := check.o msdos.o
obj-y := check.o
......
......@@ -83,13 +83,17 @@ static int (*check_part[])(struct gendisk *hd, struct block_device *bdev,
/*
* This is ucking fugly but its probably the best thing for 2.4.x
* Take it as a clear reminder than we should put the device name
* Take it as a clear reminder that: 1) we should put the device name
* generation in the object kdev_t points to in 2.5.
* and 2) ioctls better work on half-opened devices.
*/
#ifdef CONFIG_ARCH_S390
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
unsigned int no, unsigned long data);
EXPORT_SYMBOL(genhd_dasd_name);
EXPORT_SYMBOL(genhd_dasd_ioctl);
#endif
/*
......
......@@ -8,6 +8,7 @@
* History of changes (starts July 2000)
* 07/10/00 Fixed detection of CMS formatted disks
* 02/13/00 VTOC partition support added
* 12/27/01 fixed PL030593 (CMS reserved minidisk not detected on 64 bit)
*/
#include <linux/config.h>
......@@ -29,47 +30,6 @@
#include "check.h"
#include <asm/vtoc.h>
typedef enum {
ibm_partition_lnx1 = 0,
ibm_partition_vol1 = 1,
ibm_partition_cms1 = 2,
ibm_partition_none = 3
} ibm_partition_t;
static char* part_names[] = { [ibm_partition_lnx1] = "LNX1",
[ibm_partition_vol1] = "VOL1",
[ibm_partition_cms1] = "CMS1",
[ibm_partition_none] = "(nonl)"
};
static ibm_partition_t
get_partition_type ( char * type )
{
int i;
for ( i = 0; i < 3; i ++) {
if ( ! strncmp (type,part_names[i],4) )
break;
}
return i;
}
/*
* add the two default partitions
* - whole dasd
* - whole dasd without "offset"
*/
static inline void
two_partitions(struct gendisk *hd,
int minor,
int blocksize,
int offset,
int size) {
add_gd_partition( hd, minor, 0, size);
add_gd_partition( hd, minor+1, offset*blocksize, size-offset*blocksize);
}
/*
* compute the block number from a
* cyl-cyl-head-head structure
......@@ -92,115 +52,186 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
ptr->b;
}
/*
* We used to use ioctl_by_bdev in early 2.4, but it broke
* between 2.4.9 and 2.4.18 somewhere.
*/
extern int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
unsigned int no, unsigned long data);
static int
ibm_ioctl_unopened(struct block_device *bdev, unsigned cmd, unsigned long arg)
{
int res;
mm_segment_t old_fs = get_fs();
if (genhd_dasd_ioctl == NULL)
return -ENODEV;
#if 0
lock_kernel();
if (bd_ops->owner)
__MOD_INC_USE_COUNT(bdev->bd_op->owner);
unlock_kernel();
#endif
set_fs(KERNEL_DS);
res = (*genhd_dasd_ioctl)(bdev->bd_inode, NULL, cmd, arg);
set_fs(old_fs);
#if 0
lock_kernel();
if (bd_ops->owner)
__MOD_DEV_USE_COUNT(bd_ops->owner);
unlock_kernel();
#endif
return res;
}
/*
*/
int
ibm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
unsigned long first_sector, int first_part_minor)
{
Sector sect, sect2;
unsigned char *data;
ibm_partition_t partition_type;
int blocksize, offset, size;
dasd_information_t *info;
struct hd_geometry *geo;
char type[5] = {0,};
char name[7] = {0,};
struct hd_geometry *geo;
int blocksize;
int offset=0, size=0, psize=0, counter=0;
unsigned int blk;
format1_label_t f1;
volume_label_t vlabel;
dasd_information_t *info;
kdev_t dev = to_kdev_t(bdev->bd_dev);
volume_label_t *vlabel;
unsigned char *data;
Sector sect;
if ( first_sector != 0 )
BUG();
info = (struct dasd_information_t *)kmalloc(sizeof(dasd_information_t),
GFP_KERNEL);
if ( info == NULL )
return 0;
if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info)))
return 0;
geo = (struct hd_geometry *)kmalloc(sizeof(struct hd_geometry),
GFP_KERNEL);
if ( geo == NULL )
return 0;
if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
return 0;
blocksize = bdev_hardsect_size(bdev) >> 9;
if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
goto out_noinfo;
if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
goto out_nogeo;
if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL)
goto out_novlab;
if (ibm_ioctl_unopened(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
ibm_ioctl_unopened(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
goto out_noioctl;
data = read_dev_sector(bdev, inode->label_block*blocksize, &sect);
if (!data)
return 0;
if ((blocksize = bdev_hardsect_size(bdev)) <= 0)
goto out_badsect;
/*
* Get volume label, extract name and type.
*/
data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect);
if (data == NULL)
goto out_readerr;
strncpy (type, data, 4);
if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) {
strncpy ( name, data + 8, 6);
} else {
strncpy ( name, data + 4, 6);
}
memcpy (&vlabel, data, sizeof(volume_label_t));
if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
strncpy(name, data + 8, 6);
else
strncpy(name, data + 4, 6);
memcpy (vlabel, data, sizeof(volume_label_t));
put_dev_sector(sect);
EBCASC(type,4);
EBCASC(name,6);
partition_type = get_partition_type(type);
printk ( "%4s/%8s:",part_names[partition_type],name);
switch ( partition_type ) {
case ibm_partition_cms1:
if (* ((long *)data + 13) != 0) {
EBCASC(type, 4);
EBCASC(name, 6);
/*
* Three different types: CMS1, VOL1 and LNX1/unlabeled
*/
if (strncmp(type, "CMS1", 4) == 0) {
/*
* VM style CMS1 labeled disk
*/
int *label = (int *) data;
if (label[13] != 0) {
printk("CMS1/%8s(MDSK):", name);
/* disk is reserved minidisk */
long *label=(long*)data;
blocksize = label[3]>>9;
blocksize = label[3];
offset = label[13];
size = (label[7]-1)*blocksize;
printk ("(MDSK)");
size = (label[7] - 1)*(blocksize >> 9);
} else {
printk("CMS1/%8s:", name);
offset = (info->label_block + 1);
size = hd -> sizes[MINOR(dev)]<<1;
}
two_partitions( hd, MINOR(dev), blocksize, offset, size);
break;
case ibm_partition_lnx1:
case ibm_partition_none:
offset = (info->label_block + 1);
size = hd -> sizes[MINOR(dev)]<<1;
two_partitions( hd, MINOR(dev), blocksize, offset, size);
break;
case ibm_partition_vol1:
size = hd -> sizes[MINOR(dev)]<<1;
add_gd_partition(hd, MINOR(dev), 0, size);
/* get block number and read then first format1 label */
blk = cchhb2blk(&vlabel.vtoc, geo) + 1;
data = read_dev_sector(bdev, blk * blocksize, &sect2);
if (data) {
memcpy (&f1, data, sizeof(format1_label_t));
put_dev_sector(sect2);
size = bdev->bd_inode->i_size >> 9;
}
while (f1.DS1FMTID == _ascebc['1']) {
// add_gd_partition(hd, first_part_minor - 1, 0, size);
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
size-offset*(blocksize >> 9));
} else if (strncmp(type, "VOL1", 4) == 0) {
/*
* New style VOL1 labeled disk
*/
unsigned int blk;
int counter;
printk("VOL1/%8s:", name);
/* get block number and read then go through format1 labels */
blk = cchhb2blk(&vlabel->vtoc, geo) + 1;
counter = 0;
while ((data = read_dev_sector(bdev, blk*(blocksize/512),
&sect)) != NULL) {
format1_label_t f1;
memcpy(&f1, data, sizeof(format1_label_t));
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);
psize = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
offset + geo->sectors;
if (counter >= (1 << hd->minor_shift))
break;
add_gd_partition(hd, first_part_minor + counter,
offset * (blocksize >> 9),
size * (blocksize >> 9));
counter++;
add_gd_partition(hd, MINOR(dev) + counter,
offset * blocksize,
psize * blocksize);
blk++;
data = read_dev_sector(bdev, blk * blocksize, &sect2);
if (data) {
memcpy (&f1, data, sizeof(format1_label_t));
put_dev_sector(sect2);
}
}
break;
default:
add_gd_partition( hd, MINOR(dev), 0, 0);
add_gd_partition( hd, MINOR(dev) + 1, 0, 0);
} else {
/*
* Old style LNX1 or unlabeled disk
*/
if (strncmp(type, "LNX1", 4) == 0)
printk ("LNX1/%8s:", name);
else
printk("(nonl)/%8s:", name);
offset = (info->label_block + 1);
size = (bdev->bd_inode->i_size >> 9);
// add_gd_partition(hd, first_part_minor - 1, 0, size);
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
size-offset*(blocksize >> 9));
}
printk ( "\n" );
put_dev_sector(sect);
printk("\n");
kfree(vlabel);
kfree(geo);
kfree(info);
return 1;
out_readerr:
out_badsect:
out_noioctl:
kfree(vlabel);
out_novlab:
kfree(geo);
out_nogeo:
kfree(info);
out_noinfo:
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment