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 @@ ...@@ -2,7 +2,7 @@
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
export-objs := check.o ibm.o msdos.o export-objs := check.o msdos.o
obj-y := check.o obj-y := check.o
......
...@@ -83,13 +83,17 @@ static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, ...@@ -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 * 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. * generation in the object kdev_t points to in 2.5.
* and 2) ioctls better work on half-opened devices.
*/ */
#ifdef CONFIG_ARCH_S390 #ifdef CONFIG_ARCH_S390
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL; 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_name);
EXPORT_SYMBOL(genhd_dasd_ioctl);
#endif #endif
/* /*
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* History of changes (starts July 2000) * History of changes (starts July 2000)
* 07/10/00 Fixed detection of CMS formatted disks * 07/10/00 Fixed detection of CMS formatted disks
* 02/13/00 VTOC partition support added * 02/13/00 VTOC partition support added
* 12/27/01 fixed PL030593 (CMS reserved minidisk not detected on 64 bit)
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -29,47 +30,6 @@ ...@@ -29,47 +30,6 @@
#include "check.h" #include "check.h"
#include <asm/vtoc.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 * compute the block number from a
* cyl-cyl-head-head structure * cyl-cyl-head-head structure
...@@ -92,115 +52,186 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) { ...@@ -92,115 +52,186 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
ptr->b; 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 int
ibm_partition(struct gendisk *hd, struct block_device *bdev, 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; int blocksize, offset, size;
unsigned char *data; dasd_information_t *info;
ibm_partition_t partition_type; struct hd_geometry *geo;
char type[5] = {0,}; char type[5] = {0,};
char name[7] = {0,}; char name[7] = {0,};
struct hd_geometry *geo; volume_label_t *vlabel;
int blocksize; unsigned char *data;
int offset=0, size=0, psize=0, counter=0; Sector sect;
unsigned int blk;
format1_label_t f1;
volume_label_t vlabel;
dasd_information_t *info;
kdev_t dev = to_kdev_t(bdev->bd_dev);
if ( first_sector != 0 ) if ( first_sector != 0 )
BUG(); BUG();
info = (struct dasd_information_t *)kmalloc(sizeof(dasd_information_t), if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
GFP_KERNEL); goto out_noinfo;
if ( info == NULL ) if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
return 0; goto out_nogeo;
if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info))) if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL)
return 0; goto out_novlab;
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;
data = read_dev_sector(bdev, inode->label_block*blocksize, &sect); if (ibm_ioctl_unopened(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
if (!data) ibm_ioctl_unopened(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
return 0; goto out_noioctl;
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); strncpy (type, data, 4);
if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) { if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
strncpy ( name, data + 8, 6); strncpy(name, data + 8, 6);
} else { else
strncpy ( name, data + 4, 6); strncpy(name, data + 4, 6);
} memcpy (vlabel, data, sizeof(volume_label_t));
memcpy (&vlabel, data, sizeof(volume_label_t)); put_dev_sector(sect);
EBCASC(type,4); EBCASC(type, 4);
EBCASC(name,6); EBCASC(name, 6);
partition_type = get_partition_type(type); /*
printk ( "%4s/%8s:",part_names[partition_type],name); * Three different types: CMS1, VOL1 and LNX1/unlabeled
switch ( partition_type ) { */
case ibm_partition_cms1: if (strncmp(type, "CMS1", 4) == 0) {
if (* ((long *)data + 13) != 0) { /*
* VM style CMS1 labeled disk
*/
int *label = (int *) data;
if (label[13] != 0) {
printk("CMS1/%8s(MDSK):", name);
/* disk is reserved minidisk */ /* disk is reserved minidisk */
long *label=(long*)data; blocksize = label[3];
blocksize = label[3]>>9;
offset = label[13]; offset = label[13];
size = (label[7]-1)*blocksize; size = (label[7] - 1)*(blocksize >> 9);
printk ("(MDSK)");
} else { } else {
printk("CMS1/%8s:", name);
offset = (info->label_block + 1); offset = (info->label_block + 1);
size = hd -> sizes[MINOR(dev)]<<1; size = bdev->bd_inode->i_size >> 9;
} }
two_partitions( hd, MINOR(dev), blocksize, offset, size); // add_gd_partition(hd, first_part_minor - 1, 0, size);
break; add_gd_partition(hd, first_part_minor,
case ibm_partition_lnx1: offset*(blocksize >> 9),
case ibm_partition_none: size-offset*(blocksize >> 9));
offset = (info->label_block + 1); } else if (strncmp(type, "VOL1", 4) == 0) {
size = hd -> sizes[MINOR(dev)]<<1; /*
two_partitions( hd, MINOR(dev), blocksize, offset, size); * New style VOL1 labeled disk
break; */
case ibm_partition_vol1: unsigned int blk;
size = hd -> sizes[MINOR(dev)]<<1; int counter;
add_gd_partition(hd, MINOR(dev), 0, size);
printk("VOL1/%8s:", name);
/* get block number and read then first format1 label */
blk = cchhb2blk(&vlabel.vtoc, geo) + 1; /* get block number and read then go through format1 labels */
data = read_dev_sector(bdev, blk * blocksize, &sect2); blk = cchhb2blk(&vlabel->vtoc, geo) + 1;
if (data) { counter = 0;
memcpy (&f1, data, sizeof(format1_label_t)); while ((data = read_dev_sector(bdev, blk*(blocksize/512),
put_dev_sector(sect2); &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;
} }
while (f1.DS1FMTID == _ascebc['1']) { /* only FMT1 valid at this point */
if (f1.DS1FMTID != _ascebc['1'])
break;
/* OK, we got valid partition data */
offset = cchh2blk(&f1.DS1EXT1.llimit, geo); offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
psize = cchh2blk(&f1.DS1EXT1.ulimit, geo) - size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
offset + geo->sectors; 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++; counter++;
add_gd_partition(hd, MINOR(dev) + counter,
offset * blocksize,
psize * blocksize);
blk++; blk++;
data = read_dev_sector(bdev, blk * blocksize, &sect2);
if (data) {
memcpy (&f1, data, sizeof(format1_label_t));
put_dev_sector(sect2);
} }
} } else {
break; /*
default: * Old style LNX1 or unlabeled disk
add_gd_partition( hd, MINOR(dev), 0, 0); */
add_gd_partition( hd, MINOR(dev) + 1, 0, 0); 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" ); printk("\n");
put_dev_sector(sect); kfree(vlabel);
kfree(geo);
kfree(info);
return 1; 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