Commit d7536161 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] split "gendisk" to be per-disk, part 1

now that gendisks don't have shared stuff (we used to set blk_size[]
from ->sizes) we can start splitting them into per-disk ones.

Step 1:
  we introduce a new field - ->first_minor (to be merged with ->major
  into dev_t of entire disk once all gendisks are split).  All arrays
  are assumed to start at that minor (i.e.  gd->part[minor] got replaced
  with gd->part[minor - gd->first_minor], etc.).  get_gendisk() is
  taught to pick the right gendisk if there are several with the same
  major.
parent 143fe0af
...@@ -86,7 +86,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) ...@@ -86,7 +86,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p)
g = get_gendisk(dev); g = get_gendisk(dev);
if (!g) if (!g)
return -ENXIO; return -ENXIO;
part = g->part + minor(dev); part = g->part + minor(dev) - g->first_minor;
/* existing drive? */ /* existing drive? */
...@@ -135,7 +135,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) ...@@ -135,7 +135,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p)
g = get_gendisk(dev); g = get_gendisk(dev);
if (!g) if (!g)
return -ENXIO; return -ENXIO;
part = g->part + minor(dev); part = g->part + minor(dev) - g->first_minor;
if (bdev != bdev->bd_contains) if (bdev != bdev->bd_contains)
return -EINVAL; return -EINVAL;
......
...@@ -104,15 +104,22 @@ struct gendisk * ...@@ -104,15 +104,22 @@ struct gendisk *
get_gendisk(kdev_t dev) get_gendisk(kdev_t dev)
{ {
struct gendisk *gp = NULL; struct gendisk *gp = NULL;
int maj = major(dev); int major = major(dev);
int minor = minor(dev);
read_lock(&gendisk_lock); read_lock(&gendisk_lock);
for (gp = gendisk_head; gp; gp = gp->next) for (gp = gendisk_head; gp; gp = gp->next) {
if (gp->major == maj) if (gp->major != major)
break; continue;
if (gp->first_minor > minor)
continue;
if (gp->first_minor + (1<<gp->minor_shift) <= minor)
continue;
read_unlock(&gendisk_lock); read_unlock(&gendisk_lock);
return gp; return gp;
}
read_unlock(&gendisk_lock);
return NULL;
} }
EXPORT_SYMBOL(get_gendisk); EXPORT_SYMBOL(get_gendisk);
...@@ -158,8 +165,9 @@ static int show_partition(struct seq_file *part, void *v) ...@@ -158,8 +165,9 @@ static int show_partition(struct seq_file *part, void *v)
if ((n & minormask) && sgp->part[n].nr_sects == 0) if ((n & minormask) && sgp->part[n].nr_sects == 0)
continue; continue;
seq_printf(part, "%4d %4d %10ld %s\n", seq_printf(part, "%4d %4d %10ld %s\n",
sgp->major, n, sgp->part[n].nr_sects << 1, sgp->major, n + sgp->first_minor,
disk_name(sgp, n, buf)); sgp->part[n].nr_sects << 1,
disk_name(sgp, n + sgp->first_minor, buf));
} }
return 0; return 0;
......
...@@ -599,9 +599,10 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * ...@@ -599,9 +599,10 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
bdev->bd_offset = 0; bdev->bd_offset = 0;
if (g) { if (g) {
bdev->bd_inode->i_size = struct hd_struct *p;
(loff_t) g->part[minor(dev)].nr_sects << 9; p = g->part + minor(dev) - g->first_minor;
bdev->bd_offset = g->part[minor(dev)].start_sect; bdev->bd_inode->i_size = (loff_t) p->nr_sects << 9;
bdev->bd_offset = p->start_sect;
} else if (blk_size[major(dev)]) } else if (blk_size[major(dev)])
bdev->bd_inode->i_size = bdev->bd_inode->i_size =
(loff_t) blk_size[major(dev)][minor(dev)] << 10; (loff_t) blk_size[major(dev)][minor(dev)] << 10;
......
...@@ -107,11 +107,13 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) ...@@ -107,11 +107,13 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
const char *maj = hd->major_name; const char *maj = hd->major_name;
unsigned int unit = (minor >> hd->minor_shift); unsigned int unit = (minor >> hd->minor_shift);
unsigned int part = (minor & ((1 << hd->minor_shift) -1 )); unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
struct hd_struct *p = hd->part + minor - hd->first_minor;
if ((unit < hd->nr_real) && hd->part[minor].de) { if ((((minor - hd->first_minor) >> hd->minor_shift) < hd->nr_real) &&
p->de) {
int pos; int pos;
pos = devfs_generate_path (hd->part[minor].de, buf, 64); pos = devfs_generate_path(p->de, buf, 64);
if (pos >= 0) if (pos >= 0)
return buf + pos; return buf + pos;
} }
...@@ -230,13 +232,13 @@ static struct driver_file_entry partition_device_type_file = { ...@@ -230,13 +232,13 @@ static struct driver_file_entry partition_device_type_file = {
void driverfs_create_partitions(struct gendisk *hd, int minor) void driverfs_create_partitions(struct gendisk *hd, int minor)
{ {
int pos = -1; int pos = -1;
int devnum = minor >> hd->minor_shift; int devnum = (minor - hd->first_minor) >> hd->minor_shift;
char dirname[256]; char dirname[256];
struct device *parent = 0; struct device *parent = 0;
int max_p; int max_p;
int part; int part;
devfs_handle_t dir = 0; devfs_handle_t dir = 0;
struct hd_struct *p = hd->part + minor; struct hd_struct *p = hd->part + minor - hd->first_minor;
/* get parent driverfs device structure */ /* get parent driverfs device structure */
if (hd->driverfs_dev_arr) if (hd->driverfs_dev_arr)
...@@ -308,7 +310,7 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor) ...@@ -308,7 +310,7 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
int max_p; int max_p;
int part; int part;
struct device * current_driverfs_dev; struct device * current_driverfs_dev;
struct hd_struct *p = hd->part + minor; struct hd_struct *p = hd->part + minor - hd->first_minor;
max_p=(1 << hd->minor_shift); max_p=(1 << hd->minor_shift);
...@@ -335,31 +337,17 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor) ...@@ -335,31 +337,17 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
static void check_partition(struct gendisk *hd, kdev_t dev) static void check_partition(struct gendisk *hd, kdev_t dev)
{ {
devfs_handle_t de = NULL; devfs_handle_t de = NULL;
unsigned long first_sector;
struct block_device *bdev; struct block_device *bdev;
char buf[64]; char buf[64];
struct parsed_partitions *state; struct parsed_partitions *state;
int i; int i;
first_sector = hd->part[minor(dev)].start_sect;
/*
* This is a kludge to allow the partition check to be
* skipped for specific drives (e.g. IDE CD-ROM drives)
*/
if ((int)first_sector == -1) {
hd->part[minor(dev)].start_sect = 0;
return;
}
if (first_sector != 0)
BUG();
state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL); state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
if (!state) if (!state)
return; return;
if (hd->de_arr) if (hd->de_arr)
de = hd->de_arr[minor(dev) >> hd->minor_shift]; de = hd->de_arr[(minor(dev)-hd->first_minor)>>hd->minor_shift];
i = devfs_generate_path (de, buf, sizeof buf); i = devfs_generate_path (de, buf, sizeof buf);
if (i >= 0) { if (i >= 0) {
printk(KERN_INFO " /dev/%s:", buf + i); printk(KERN_INFO " /dev/%s:", buf + i);
...@@ -377,6 +365,7 @@ static void check_partition(struct gendisk *hd, kdev_t dev) ...@@ -377,6 +365,7 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
state->limit = 1<<hd->minor_shift; state->limit = 1<<hd->minor_shift;
for (i = 0; check_part[i]; i++) { for (i = 0; check_part[i]; i++) {
int res, j; int res, j;
struct hd_struct *p;
memset(&state->parts, 0, sizeof(state->parts)); memset(&state->parts, 0, sizeof(state->parts));
res = check_part[i](state, bdev); res = check_part[i](state, bdev);
if (!res) if (!res)
...@@ -386,11 +375,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev) ...@@ -386,11 +375,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
printk(" unable to read partition table\n"); printk(" unable to read partition table\n");
goto setup_devfs; goto setup_devfs;
} }
p = hd->part + minor(dev) - hd->first_minor;
for (j = 1; j < state->limit; j++) { for (j = 1; j < state->limit; j++) {
hd->part[j + minor(dev)].start_sect = p[j].start_sect = state->parts[j].from;
state->parts[j].from; p[j].nr_sects = state->parts[j].size;
hd->part[j + minor(dev)].nr_sects =
state->parts[j].size;
#if CONFIG_BLK_DEV_MD #if CONFIG_BLK_DEV_MD
if (!state->parts[j].flags) if (!state->parts[j].flags)
continue; continue;
...@@ -411,19 +399,21 @@ static void check_partition(struct gendisk *hd, kdev_t dev) ...@@ -411,19 +399,21 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
static void devfs_register_partition (struct gendisk *dev, int minor, int part) static void devfs_register_partition (struct gendisk *dev, int minor, int part)
{ {
int devnum = minor >> dev->minor_shift; int devnum = (minor - dev->first_minor) >> dev->minor_shift;
devfs_handle_t dir; devfs_handle_t dir;
unsigned int devfs_flags = DEVFS_FL_DEFAULT; unsigned int devfs_flags = DEVFS_FL_DEFAULT;
struct hd_struct *p = dev->part + minor - dev->first_minor;
char devname[16]; char devname[16];
if (dev->part[minor + part].de) return; if (p[part].de)
dir = devfs_get_parent (dev->part[minor].de); return;
if (!dir) return; dir = devfs_get_parent(p[0].de);
if (!dir)
return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE; devfs_flags |= DEVFS_FL_REMOVABLE;
sprintf (devname, "part%d", part); sprintf (devname, "part%d", part);
dev->part[minor + part].de = p[part].de = devfs_register (dir, devname, devfs_flags,
devfs_register (dir, devname, devfs_flags,
dev->major, minor + part, dev->major, minor + part,
S_IFBLK | S_IRUSR | S_IWUSR, S_IFBLK | S_IRUSR | S_IWUSR,
dev->fops, NULL); dev->fops, NULL);
...@@ -434,38 +424,40 @@ static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; ...@@ -434,38 +424,40 @@ static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
static void devfs_register_disc (struct gendisk *dev, int minor) static void devfs_register_disc (struct gendisk *dev, int minor)
{ {
int pos = 0; int pos = 0;
int devnum = minor >> dev->minor_shift; int devnum = (minor - dev->first_minor) >> dev->minor_shift;
devfs_handle_t dir, slave; devfs_handle_t dir, slave;
unsigned int devfs_flags = DEVFS_FL_DEFAULT; unsigned int devfs_flags = DEVFS_FL_DEFAULT;
char dirname[64], symlink[16]; char dirname[64], symlink[16];
static devfs_handle_t devfs_handle; static devfs_handle_t devfs_handle;
struct hd_struct *p = dev->part + minor - dev->first_minor;
if (dev->part[minor].de) return; if (p[0].de)
return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE; devfs_flags |= DEVFS_FL_REMOVABLE;
if (dev->de_arr) { if (dev->de_arr) {
dir = dev->de_arr[devnum]; dir = dev->de_arr[devnum];
if (!dir) /* Aware driver wants to block disc management */ if (!dir) /* Aware driver wants to block disc management */
return; return;
pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3); pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3);
if (pos < 0) return; if (pos < 0)
strncpy (dirname + pos, "../", 3); return;
} strncpy(dirname + pos, "../", 3);
else { } else {
/* Unaware driver: construct "real" directory */ /* Unaware driver: construct "real" directory */
sprintf (dirname, "../%s/disc%d", dev->major_name, devnum); sprintf(dirname, "../%s/disc%d", dev->major_name,
dir = devfs_mk_dir (NULL, dirname + 3, NULL); (dev->first_minor >> dev->minor_shift) + devnum);
dir = devfs_mk_dir(NULL, dirname + 3, NULL);
} }
if (!devfs_handle) if (!devfs_handle)
devfs_handle = devfs_mk_dir (NULL, "discs", NULL); devfs_handle = devfs_mk_dir(NULL, "discs", NULL);
dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace); p[0].number = devfs_alloc_unique_number (&disc_numspace);
sprintf (symlink, "disc%d", dev->part[minor].number); sprintf(symlink, "disc%d", p[0].number);
devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
dirname + pos, &slave, NULL); dirname + pos, &slave, NULL);
dev->part[minor].de = p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor,
devfs_register (dir, "disc", devfs_flags, dev->major, minor,
S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
devfs_auto_unregister (dev->part[minor].de, slave); devfs_auto_unregister(p[0].de, slave);
if (!dev->de_arr) if (!dev->de_arr)
devfs_auto_unregister (slave, dir); devfs_auto_unregister (slave, dir);
} }
...@@ -475,23 +467,23 @@ void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) ...@@ -475,23 +467,23 @@ void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
{ {
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
int part, max_p; int part, max_p;
struct hd_struct *p = dev->part + minor - dev->first_minor;
if (!unregister) if (!unregister)
devfs_register_disc (dev, minor); devfs_register_disc (dev, minor);
max_p = (1 << dev->minor_shift); max_p = (1 << dev->minor_shift);
for (part = 1; part < max_p; part++) { for (part = 1; part < max_p; part++) {
if ( unregister || (dev->part[part + minor].nr_sects < 1) ) { if ( unregister || (p[part].nr_sects < 1) ) {
devfs_unregister (dev->part[part + minor].de); devfs_unregister(p[part].de);
dev->part[part + minor].de = NULL; dev->part[p].de = NULL;
continue; continue;
} }
devfs_register_partition (dev, minor, part); devfs_register_partition (dev, minor, part);
} }
if (unregister) { if (unregister) {
devfs_unregister (dev->part[minor].de); devfs_unregister(p[0].de);
dev->part[minor].de = NULL; p[0].de = NULL;
devfs_dealloc_unique_number (&disc_numspace, devfs_dealloc_unique_number(&disc_numspace, p[0].number);
dev->part[minor].number);
} }
#endif /* CONFIG_DEVFS_FS */ #endif /* CONFIG_DEVFS_FS */
} }
...@@ -516,8 +508,9 @@ void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors, ...@@ -516,8 +508,9 @@ void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
void grok_partitions(kdev_t dev, long size) void grok_partitions(kdev_t dev, long size)
{ {
int i, minors, first_minor, end_minor; int minors, first_minor, end_minor;
struct gendisk *g = get_gendisk(dev); struct gendisk *g = get_gendisk(dev);
struct hd_struct *p;
if (!g) if (!g)
return; return;
...@@ -531,7 +524,8 @@ void grok_partitions(kdev_t dev, long size) ...@@ -531,7 +524,8 @@ void grok_partitions(kdev_t dev, long size)
} }
end_minor = first_minor + minors; end_minor = first_minor + minors;
g->part[first_minor].nr_sects = size; p = g->part + first_minor - g->first_minor;
p[0].nr_sects = size;
/* No minors to use for partitions */ /* No minors to use for partitions */
if (minors == 1) if (minors == 1)
...@@ -572,6 +566,7 @@ int wipe_partitions(kdev_t dev) ...@@ -572,6 +566,7 @@ int wipe_partitions(kdev_t dev)
struct gendisk *g; struct gendisk *g;
kdev_t devp; kdev_t devp;
int p, major, minor, minor0, max_p, res; int p, major, minor, minor0, max_p, res;
struct hd_struct *part;
g = get_gendisk(dev); g = get_gendisk(dev);
if (g == NULL) if (g == NULL)
...@@ -584,19 +579,20 @@ int wipe_partitions(kdev_t dev) ...@@ -584,19 +579,20 @@ int wipe_partitions(kdev_t dev)
if (minor0 != minor) /* for now only whole-disk reread */ if (minor0 != minor) /* for now only whole-disk reread */
return -EINVAL; /* %%% later.. */ return -EINVAL; /* %%% later.. */
part = g->part + minor - g->first_minor;
/* invalidate stuff */ /* invalidate stuff */
for (p = max_p - 1; p >= 0; p--) { for (p = max_p - 1; p >= 0; p--) {
minor = minor0 + p; minor = minor0 + p;
devp = mk_kdev(major,minor); devp = mk_kdev(major,minor);
#if 0 /* %%% superfluous? */ #if 0 /* %%% superfluous? */
if (g->part[minor].nr_sects == 0) if (part[p].nr_sects == 0)
continue; continue;
#endif #endif
res = invalidate_device(devp, 1); res = invalidate_device(devp, 1);
if (res) if (res)
return res; return res;
g->part[minor].start_sect = 0; part[p].start_sect = 0;
g->part[minor].nr_sects = 0; part[p].nr_sects = 0;
} }
return 0; return 0;
} }
...@@ -70,6 +70,7 @@ struct hd_struct { ...@@ -70,6 +70,7 @@ struct hd_struct {
struct gendisk { struct gendisk {
int major; /* major number of driver */ int major; /* major number of driver */
int first_minor;
const char *major_name; /* name of major driver */ const char *major_name; /* name of major driver */
int minor_shift; /* number of times minor is shifted to int minor_shift; /* number of times minor is shifted to
get real minor */ get real minor */
......
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