Commit 664aa7b2 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] dasd per-disk gendisks

parent bedbeab4
...@@ -290,11 +290,9 @@ dasd_state_new_to_known(dasd_device_t *device) ...@@ -290,11 +290,9 @@ dasd_state_new_to_known(dasd_device_t *device)
gdp = dasd_gendisk_from_devindex(devmap->devindex); gdp = dasd_gendisk_from_devindex(devmap->devindex);
if (gdp == NULL) if (gdp == NULL)
return -ENODEV; return -ENODEV;
minor = devmap->devindex % DASD_PER_MAJOR;
/* Set kdev and the device name. */ /* Set kdev and the device name. */
device->kdev = mk_kdev(gdp->major, minor << DASD_PARTN_BITS); device->kdev = mk_kdev(gdp->major, gdp->first_minor);
dasd_device_name(device->name, minor, 0, gdp); strcpy(device->name, gdp->major_name);
/* Find a discipline for the device. */ /* Find a discipline for the device. */
rc = dasd_find_disc(device); rc = dasd_find_disc(device);
...@@ -304,7 +302,7 @@ dasd_state_new_to_known(dasd_device_t *device) ...@@ -304,7 +302,7 @@ dasd_state_new_to_known(dasd_device_t *device)
/* Add a proc directory and the dasd device entry to devfs. */ /* Add a proc directory and the dasd device entry to devfs. */
sprintf(buffer, "%04x", device->devinfo.devno); sprintf(buffer, "%04x", device->devinfo.devno);
dir = devfs_mk_dir(dasd_devfs_handle, buffer, device); dir = devfs_mk_dir(dasd_devfs_handle, buffer, device);
gdp->de_arr[minor(device->kdev) >> DASD_PARTN_BITS] = dir; gdp->de_arr[0] = dir;
if (devmap->features & DASD_FEATURE_READONLY) if (devmap->features & DASD_FEATURE_READONLY)
devfs_perm = S_IFBLK | S_IRUSR; devfs_perm = S_IFBLK | S_IRUSR;
else else
...@@ -324,19 +322,13 @@ dasd_state_new_to_known(dasd_device_t *device) ...@@ -324,19 +322,13 @@ dasd_state_new_to_known(dasd_device_t *device)
static inline void static inline void
dasd_state_known_to_new(dasd_device_t * device) dasd_state_known_to_new(dasd_device_t * device)
{ {
struct gendisk *gdp; dasd_devmap_t *devmap = dasd_devmap_from_devno(device->devinfo.devno);
dasd_devmap_t *devmap; struct gendisk *gdp = dasd_gendisk_from_devindex(devmap->devindex);
int minor;
devmap = dasd_devmap_from_devno(device->devinfo.devno);
gdp = dasd_gendisk_from_devindex(devmap->devindex);
if (gdp == NULL) if (gdp == NULL)
return; return;
minor = devmap->devindex % DASD_PER_MAJOR;
/* Remove device entry and devfs directory. */ /* Remove device entry and devfs directory. */
devfs_unregister(device->devfs_entry); devfs_unregister(device->devfs_entry);
devfs_unregister(gdp->de_arr[minor]); devfs_unregister(gdp->de_arr[0]);
/* Forget the discipline information. */ /* Forget the discipline information. */
device->discipline = NULL; device->discipline = NULL;
......
...@@ -32,7 +32,12 @@ static struct list_head dasd_major_info = LIST_HEAD_INIT(dasd_major_info); ...@@ -32,7 +32,12 @@ static struct list_head dasd_major_info = LIST_HEAD_INIT(dasd_major_info);
struct major_info { struct major_info {
struct list_head list; struct list_head list;
struct gendisk gendisk; /* actually contains the major number */ int major;
struct gendisk disks[DASD_PER_MAJOR];
devfs_handle_t de_arr[DASD_PER_MAJOR];
char flags[DASD_PER_MAJOR];
char names[DASD_PER_MAJOR * 8];
struct hd_struct part[1<<MINORBITS];
}; };
/* /*
...@@ -64,24 +69,17 @@ static int ...@@ -64,24 +69,17 @@ static int
dasd_register_major(int major) dasd_register_major(int major)
{ {
struct major_info *mi; struct major_info *mi;
struct hd_struct *gd_part;
devfs_handle_t *gd_de_arr;
char *gd_flags;
int new_major, rc; int new_major, rc;
struct list_head *l;
int index;
int i;
rc = 0; rc = 0;
/* Allocate major info structure. */ /* Allocate major info structure. */
mi = kmalloc(sizeof(struct major_info), GFP_KERNEL); mi = kmalloc(sizeof(struct major_info), GFP_KERNEL);
/* Allocate gendisk arrays. */
gd_de_arr = kmalloc(DASD_PER_MAJOR * sizeof(devfs_handle_t),
GFP_KERNEL);
gd_flags = kmalloc(DASD_PER_MAJOR * sizeof(char), GFP_KERNEL);
gd_part = kmalloc(sizeof (struct hd_struct) << MINORBITS, GFP_ATOMIC);
/* Check if one of the allocations failed. */ /* Check if one of the allocations failed. */
if (mi == NULL || gd_de_arr == NULL || gd_flags == NULL || if (mi == NULL) {
gd_part == NULL) {
MESSAGE(KERN_WARNING, "%s", MESSAGE(KERN_WARNING, "%s",
"Cannot get memory to allocate another " "Cannot get memory to allocate another "
"major number"); "major number");
...@@ -99,41 +97,48 @@ dasd_register_major(int major) ...@@ -99,41 +97,48 @@ dasd_register_major(int major)
} }
if (major != 0) if (major != 0)
new_major = major; new_major = major;
/* Initialize major info structure. */ /* Initialize major info structure. */
memset(mi, 0, sizeof(struct major_info)); memset(mi, 0, sizeof(struct major_info));
mi->gendisk.major = new_major; mi->major = new_major;
mi->gendisk.major_name = "dasd"; for (i = 0; i < DASD_PER_MAJOR; i++) {
mi->gendisk.minor_shift = DASD_PARTN_BITS; struct gendisk *disk = mi->disks + i;
mi->gendisk.nr_real = DASD_PER_MAJOR; disk->major = new_major;
mi->gendisk.fops = &dasd_device_operations; disk->first_minor = i << DASD_PARTN_BITS;
mi->gendisk.de_arr = gd_de_arr; disk->minor_shift = DASD_PARTN_BITS;
mi->gendisk.flags = gd_flags; disk->nr_real = 1;
mi->gendisk.part = gd_part; disk->fops = &dasd_device_operations;
disk->de_arr = mi->de_arr + i;
/* Initialize the gendisk arrays. */ disk->flags = mi->flags + i;
memset(gd_de_arr, 0, DASD_PER_MAJOR * sizeof(devfs_handle_t)); disk->part = mi->part + (i << DASD_PARTN_BITS);
memset(gd_flags, 0, DASD_PER_MAJOR * sizeof (char)); }
memset(gd_part, 0, sizeof (struct hd_struct) << MINORBITS);
/* Setup block device pointers for the new major. */ /* Setup block device pointers for the new major. */
blk_dev[new_major].queue = dasd_get_queue; blk_dev[new_major].queue = dasd_get_queue;
/* Insert the new major info structure into dasd_major_info list. */
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
index = 0;
list_for_each(l, &dasd_major_info)
index += DASD_PER_MAJOR;
for (i = 0; i < DASD_PER_MAJOR; i++, index++) {
char *name = mi->names + i * 8;
mi->disks[i].major_name = name;
sprintf(name, "dasd");
name += 4;
if (index > 701)
*name++ = 'a' + (((index - 702) / 676) % 26);
if (index > 25)
*name++ = 'a' + (((index - 26) / 26) % 26);
sprintf(name, "%c", 'a' + (index % 26));
}
list_add_tail(&mi->list, &dasd_major_info); list_add_tail(&mi->list, &dasd_major_info);
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
/* Make the gendisk known. */
add_gendisk(&mi->gendisk);
return 0; return 0;
/* Something failed. Do the cleanup and return rc. */ /* Something failed. Do the cleanup and return rc. */
out_error: out_error:
/* We rely on kfree to do the != NULL check. */ /* We rely on kfree to do the != NULL check. */
kfree(gd_part);
kfree(gd_flags);
kfree(gd_de_arr);
kfree(mi); kfree(mi);
return rc; return rc;
} }
...@@ -146,16 +151,13 @@ dasd_unregister_major(struct major_info * mi) ...@@ -146,16 +151,13 @@ dasd_unregister_major(struct major_info * mi)
if (mi == NULL) if (mi == NULL)
return; return;
/* Remove gendisk information. */
del_gendisk(&mi->gendisk);
/* Delete the major info from dasd_major_info. */ /* Delete the major info from dasd_major_info. */
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
list_del(&mi->list); list_del(&mi->list);
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
/* Clear block device pointers. */ /* Clear block device pointers. */
major = mi->gendisk.major; major = mi->major;
blk_dev[major].queue = NULL; blk_dev[major].queue = NULL;
blk_clear(major); blk_clear(major);
...@@ -166,9 +168,6 @@ dasd_unregister_major(struct major_info * mi) ...@@ -166,9 +168,6 @@ dasd_unregister_major(struct major_info * mi)
major, rc); major, rc);
/* Free memory. */ /* Free memory. */
kfree(mi->gendisk.part);
kfree(mi->gendisk.flags);
kfree(mi->gendisk.de_arr);
kfree(mi); kfree(mi);
} }
...@@ -189,19 +188,19 @@ dasd_gendisk_new_major(void) ...@@ -189,19 +188,19 @@ dasd_gendisk_new_major(void)
/* /*
* Return pointer to gendisk structure by kdev. * Return pointer to gendisk structure by kdev.
*/ */
struct gendisk * static struct gendisk *dasd_gendisk_by_dev(kdev_t dev)
dasd_gendisk_from_major(int major)
{ {
struct list_head *l; struct list_head *l;
struct major_info *mi; struct major_info *mi;
struct gendisk *gdp; struct gendisk *gdp;
int major = major(dev);
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
gdp = NULL; gdp = NULL;
list_for_each(l, &dasd_major_info) { list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list); mi = list_entry(l, struct major_info, list);
if (mi->gendisk.major == major) { if (mi->major == major) {
gdp = &mi->gendisk; gdp = &mi->disks[minor(dev) >> DASD_PARTN_BITS];
break; break;
} }
} }
...@@ -224,7 +223,7 @@ dasd_gendisk_from_devindex(int devindex) ...@@ -224,7 +223,7 @@ dasd_gendisk_from_devindex(int devindex)
list_for_each(l, &dasd_major_info) { list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list); mi = list_entry(l, struct major_info, list);
if (devindex < DASD_PER_MAJOR) { if (devindex < DASD_PER_MAJOR) {
gdp = &mi->gendisk; gdp = &mi->disks[devindex];
break; break;
} }
devindex -= DASD_PER_MAJOR; devindex -= DASD_PER_MAJOR;
...@@ -247,7 +246,7 @@ int dasd_gendisk_major_index(int major) ...@@ -247,7 +246,7 @@ int dasd_gendisk_major_index(int major)
devindex = 0; devindex = 0;
list_for_each(l, &dasd_major_info) { list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list); mi = list_entry(l, struct major_info, list);
if (mi->gendisk.major == major) { if (mi->major == major) {
rc = devindex; rc = devindex;
break; break;
} }
...@@ -257,62 +256,19 @@ int dasd_gendisk_major_index(int major) ...@@ -257,62 +256,19 @@ int dasd_gendisk_major_index(int major)
return rc; return rc;
} }
/*
* This one is needed for naming 18000+ possible dasd devices.
* dasda - dasdz : 26 devices
* dasdaa - dasdzz : 676 devices, added up = 702
* dasdaaa - dasdzzz : 17576 devices, added up = 18278
* This function is called from the partition detection code (see disk_name)
* via the genhd_dasd_name hook. As mentioned in partition/check.c this
* is ugly...
*/
int
dasd_device_name(char *str, int index, int partition, struct gendisk *hd)
{
struct list_head *l;
int len, found;
/* Check if this is on of our gendisk structures. */
found = 0;
spin_lock(&dasd_major_lock);
list_for_each(l, &dasd_major_info) {
struct major_info *mi;
mi = list_entry(l, struct major_info, list);
if (&mi->gendisk == hd) {
found = 1;
break;
}
index += DASD_PER_MAJOR;
}
spin_unlock(&dasd_major_lock);
if (!found)
/* Not one of our structures. Can't be a dasd. */
return -EINVAL;
len = sprintf(str, "dasd");
if (index > 25) {
if (index > 701)
len += sprintf(str + len, "%c",
'a' + (((index - 702) / 676) % 26));
len += sprintf(str + len, "%c",
'a' + (((index - 26) / 26) % 26));
}
len += sprintf(str + len, "%c", 'a' + (index % 26));
if (partition > DASD_PARTN_MASK)
return -EINVAL;
if (partition)
len += sprintf(str + len, "%d", partition);
return 0;
}
/* /*
* Register disk to genhd. This will trigger a partition detection. * Register disk to genhd. This will trigger a partition detection.
*/ */
void void
dasd_setup_partitions(dasd_device_t * device) dasd_setup_partitions(dasd_device_t * device)
{ {
grok_partitions(device->kdev, device->blocks << device->s2b_shift); struct gendisk *disk = dasd_gendisk_by_dev(device->kdev);
if (disk == NULL)
return;
add_gendisk(disk);
register_disk(disk, mk_kdev(disk->major, disk->first_minor),
1<<disk->minor_shift, disk->fops,
device->blocks << device->s2b_shift);
} }
/* /*
...@@ -322,11 +278,10 @@ dasd_setup_partitions(dasd_device_t * device) ...@@ -322,11 +278,10 @@ dasd_setup_partitions(dasd_device_t * device)
void void
dasd_destroy_partitions(dasd_device_t * device) dasd_destroy_partitions(dasd_device_t * device)
{ {
struct gendisk *gdp; struct gendisk *disk = dasd_gendisk_by_dev(device->kdev);
int minor, i; int minor, i;
gdp = dasd_gendisk_from_major(major(device->kdev)); if (disk == NULL)
if (gdp == NULL)
return; return;
wipe_partitions(device->kdev); wipe_partitions(device->kdev);
...@@ -336,13 +291,10 @@ dasd_destroy_partitions(dasd_device_t * device) ...@@ -336,13 +291,10 @@ dasd_destroy_partitions(dasd_device_t * device)
* but the 1 as third parameter makes it do an unregister... * but the 1 as third parameter makes it do an unregister...
* FIXME: there must be a better way to get rid of the devfs entries * FIXME: there must be a better way to get rid of the devfs entries
*/ */
devfs_register_partitions(gdp, minor(device->kdev), 1); devfs_register_partitions(disk, minor(device->kdev), 1);
del_gendisk(disk);
} }
extern int (*genhd_dasd_name)(char *, int, int, struct gendisk *);
extern int (*genhd_dasd_ioctl) (struct inode *inp, struct file *filp,
unsigned int no, unsigned long data);
int int
dasd_gendisk_init(void) dasd_gendisk_init(void)
{ {
...@@ -350,25 +302,17 @@ dasd_gendisk_init(void) ...@@ -350,25 +302,17 @@ dasd_gendisk_init(void)
/* Register to static dasd major 94 */ /* Register to static dasd major 94 */
rc = dasd_register_major(DASD_MAJOR); rc = dasd_register_major(DASD_MAJOR);
if (rc != 0) { if (rc != 0)
MESSAGE(KERN_WARNING, MESSAGE(KERN_WARNING,
"Couldn't register successfully to " "Couldn't register successfully to "
"major no %d", DASD_MAJOR); "major no %d", DASD_MAJOR);
return rc; return rc;
}
genhd_dasd_name = dasd_device_name;
genhd_dasd_ioctl = dasd_ioctl;
return 0;
} }
void void
dasd_gendisk_exit(void) dasd_gendisk_exit(void)
{ {
struct list_head *l, *n; struct list_head *l, *n;
genhd_dasd_ioctl = NULL;
genhd_dasd_name = NULL;
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
list_for_each_safe(l, n, &dasd_major_info) list_for_each_safe(l, n, &dasd_major_info)
dasd_unregister_major(list_entry(l, struct major_info, list)); dasd_unregister_major(list_entry(l, struct major_info, list));
......
...@@ -480,9 +480,7 @@ int dasd_gendisk_init(void); ...@@ -480,9 +480,7 @@ int dasd_gendisk_init(void);
void dasd_gendisk_exit(void); void dasd_gendisk_exit(void);
int dasd_gendisk_new_major(void); int dasd_gendisk_new_major(void);
int dasd_gendisk_major_index(int); int dasd_gendisk_major_index(int);
struct gendisk *dasd_gendisk_from_major(int);
struct gendisk *dasd_gendisk_from_devindex(int); struct gendisk *dasd_gendisk_from_devindex(int);
int dasd_device_name(char *, int, int, struct gendisk *);
void dasd_setup_partitions(dasd_device_t *); void dasd_setup_partitions(dasd_device_t *);
void dasd_destroy_partitions(dasd_device_t *); void dasd_destroy_partitions(dasd_device_t *);
......
...@@ -173,12 +173,7 @@ dasd_devices_print(dasd_devmap_t *devmap, char *str) ...@@ -173,12 +173,7 @@ dasd_devices_print(dasd_devmap_t *devmap, char *str)
minor = devmap->devindex % DASD_PER_MAJOR; minor = devmap->devindex % DASD_PER_MAJOR;
len += sprintf(str + len, " at (%3d:%3d)", gdp->major, minor); len += sprintf(str + len, " at (%3d:%3d)", gdp->major, minor);
/* Print device name. */ /* Print device name. */
if (device == NULL) { len += sprintf(str + len, " is %-7s", gdp->major_name);
dasd_device_name(buffer, minor, 0, gdp);
substr = buffer;
} else
substr = device->name;
len += sprintf(str + len, " is %-7s", substr);
/* Print devices features. */ /* Print devices features. */
substr = (devmap->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; substr = (devmap->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
len += sprintf(str + len, "%4s: ", substr); len += sprintf(str + len, "%4s: ", substr);
......
...@@ -79,22 +79,7 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = ...@@ -79,22 +79,7 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
#endif #endif
NULL NULL
}; };
/*
* This is ucking fugly but its probably the best thing for 2.4.x
* 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
/* /*
* disk_name() is used by partition check code and the md driver. * disk_name() is used by partition check code and the md driver.
* It formats the devicename of the indicated disk into * It formats the devicename of the indicated disk into
...@@ -119,11 +104,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) ...@@ -119,11 +104,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
return buf + pos; return buf + pos;
} }
#ifdef CONFIG_ARCH_S390
if (genhd_dasd_name
&& genhd_dasd_name (buf, unit, part, hd) == 0)
return buf;
#endif
/* /*
* Yes, I know, ... in cases is gccism and not a pretty one. * Yes, I know, ... in cases is gccism and not a pretty one.
* However, the first variant will eventually consume _all_ cases * However, the first variant will eventually consume _all_ cases
...@@ -138,7 +118,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) ...@@ -138,7 +118,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
maj = s; maj = s;
break; break;
case I2O_MAJOR: case I2O_MAJOR:
case DASD_MAJOR:
sprintf(s, "%s%c", hd->major_name, unit + 'a'); sprintf(s, "%s%c", hd->major_name, unit + 'a');
maj = s; maj = s;
} }
......
...@@ -52,39 +52,6 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) { ...@@ -52,39 +52,6 @@ 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
...@@ -106,8 +73,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) ...@@ -106,8 +73,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL) if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL)
goto out_novlab; goto out_novlab;
if (ibm_ioctl_unopened(bdev, BIODASDINFO, (unsigned long)info) != 0 || if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
ibm_ioctl_unopened(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
goto out_noioctl; goto out_noioctl;
if ((blocksize = bdev_hardsect_size(bdev)) <= 0) if ((blocksize = bdev_hardsect_size(bdev)) <= 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