Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@math.psu.edu>2002-07-31 23:31:15 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-07-31 23:31:15 -0700
commitd7536161a456543c86286e4f4f2928eef4297fdb (patch)
tree43edb651a07bab23cc2faefcf43de521d2798227
parent143fe0af17a2a5b229e67d91cf32687a72b4f3d7 (diff)
[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.
-rw-r--r--drivers/block/blkpg.c4
-rw-r--r--drivers/block/genhd.c24
-rw-r--r--fs/block_dev.c7
-rw-r--r--fs/partitions/check.c118
-rw-r--r--include/linux/genhd.h1
5 files changed, 80 insertions, 74 deletions
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
index f38dfe33c8d9..15e028f28074 100644
--- a/drivers/block/blkpg.c
+++ b/drivers/block/blkpg.c
@@ -86,7 +86,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p)
g = get_gendisk(dev);
if (!g)
return -ENXIO;
- part = g->part + minor(dev);
+ part = g->part + minor(dev) - g->first_minor;
/* existing drive? */
@@ -135,7 +135,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p)
g = get_gendisk(dev);
if (!g)
return -ENXIO;
- part = g->part + minor(dev);
+ part = g->part + minor(dev) - g->first_minor;
if (bdev != bdev->bd_contains)
return -EINVAL;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 313b2eea6189..0917d42da972 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -104,15 +104,22 @@ struct gendisk *
get_gendisk(kdev_t dev)
{
struct gendisk *gp = NULL;
- int maj = major(dev);
+ int major = major(dev);
+ int minor = minor(dev);
read_lock(&gendisk_lock);
- for (gp = gendisk_head; gp; gp = gp->next)
- if (gp->major == maj)
- break;
+ for (gp = gendisk_head; gp; gp = gp->next) {
+ if (gp->major != major)
+ continue;
+ if (gp->first_minor > minor)
+ continue;
+ if (gp->first_minor + (1<<gp->minor_shift) <= minor)
+ continue;
+ read_unlock(&gendisk_lock);
+ return gp;
+ }
read_unlock(&gendisk_lock);
-
- return gp;
+ return NULL;
}
EXPORT_SYMBOL(get_gendisk);
@@ -158,8 +165,9 @@ static int show_partition(struct seq_file *part, void *v)
if ((n & minormask) && sgp->part[n].nr_sects == 0)
continue;
seq_printf(part, "%4d %4d %10ld %s\n",
- sgp->major, n, sgp->part[n].nr_sects << 1,
- disk_name(sgp, n, buf));
+ sgp->major, n + sgp->first_minor,
+ sgp->part[n].nr_sects << 1,
+ disk_name(sgp, n + sgp->first_minor, buf));
}
return 0;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 62c973eeb278..5723ad522ee5 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -599,9 +599,10 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
bdev->bd_offset = 0;
if (g) {
- bdev->bd_inode->i_size =
- (loff_t) g->part[minor(dev)].nr_sects << 9;
- bdev->bd_offset = g->part[minor(dev)].start_sect;
+ struct hd_struct *p;
+ p = g->part + minor(dev) - g->first_minor;
+ bdev->bd_inode->i_size = (loff_t) p->nr_sects << 9;
+ bdev->bd_offset = p->start_sect;
} else if (blk_size[major(dev)])
bdev->bd_inode->i_size =
(loff_t) blk_size[major(dev)][minor(dev)] << 10;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 273b85b91732..8b61260253cf 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -107,11 +107,13 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
const char *maj = hd->major_name;
unsigned int unit = (minor >> hd->minor_shift);
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;
- pos = devfs_generate_path (hd->part[minor].de, buf, 64);
+ pos = devfs_generate_path(p->de, buf, 64);
if (pos >= 0)
return buf + pos;
}
@@ -230,13 +232,13 @@ static struct driver_file_entry partition_device_type_file = {
void driverfs_create_partitions(struct gendisk *hd, int minor)
{
int pos = -1;
- int devnum = minor >> hd->minor_shift;
+ int devnum = (minor - hd->first_minor) >> hd->minor_shift;
char dirname[256];
struct device *parent = 0;
int max_p;
int part;
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 */
if (hd->driverfs_dev_arr)
@@ -308,7 +310,7 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
int max_p;
int part;
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);
@@ -335,31 +337,17 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
static void check_partition(struct gendisk *hd, kdev_t dev)
{
devfs_handle_t de = NULL;
- unsigned long first_sector;
struct block_device *bdev;
char buf[64];
struct parsed_partitions *state;
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);
if (!state)
return;
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);
if (i >= 0) {
printk(KERN_INFO " /dev/%s:", buf + i);
@@ -377,6 +365,7 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
state->limit = 1<<hd->minor_shift;
for (i = 0; check_part[i]; i++) {
int res, j;
+ struct hd_struct *p;
memset(&state->parts, 0, sizeof(state->parts));
res = check_part[i](state, bdev);
if (!res)
@@ -385,12 +374,11 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
if (warn_no_part)
printk(" unable to read partition table\n");
goto setup_devfs;
- }
+ }
+ p = hd->part + minor(dev) - hd->first_minor;
for (j = 1; j < state->limit; j++) {
- hd->part[j + minor(dev)].start_sect =
- state->parts[j].from;
- hd->part[j + minor(dev)].nr_sects =
- state->parts[j].size;
+ p[j].start_sect = state->parts[j].from;
+ p[j].nr_sects = state->parts[j].size;
#if CONFIG_BLK_DEV_MD
if (!state->parts[j].flags)
continue;
@@ -411,22 +399,24 @@ out:
#ifdef CONFIG_DEVFS_FS
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;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
+ struct hd_struct *p = dev->part + minor - dev->first_minor;
char devname[16];
- if (dev->part[minor + part].de) return;
- dir = devfs_get_parent (dev->part[minor].de);
- if (!dir) return;
+ if (p[part].de)
+ return;
+ dir = devfs_get_parent(p[0].de);
+ if (!dir)
+ return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE;
sprintf (devname, "part%d", part);
- dev->part[minor + part].de =
- devfs_register (dir, devname, devfs_flags,
- dev->major, minor + part,
- S_IFBLK | S_IRUSR | S_IWUSR,
- dev->fops, NULL);
+ p[part].de = devfs_register (dir, devname, devfs_flags,
+ dev->major, minor + part,
+ S_IFBLK | S_IRUSR | S_IWUSR,
+ dev->fops, NULL);
}
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)
{
int pos = 0;
- int devnum = minor >> dev->minor_shift;
+ int devnum = (minor - dev->first_minor) >> dev->minor_shift;
devfs_handle_t dir, slave;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
char dirname[64], symlink[16];
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) )
devfs_flags |= DEVFS_FL_REMOVABLE;
if (dev->de_arr) {
dir = dev->de_arr[devnum];
if (!dir) /* Aware driver wants to block disc management */
return;
- pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
- if (pos < 0) return;
- strncpy (dirname + pos, "../", 3);
- }
- else {
+ pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3);
+ if (pos < 0)
+ return;
+ strncpy(dirname + pos, "../", 3);
+ } else {
/* Unaware driver: construct "real" directory */
- sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
- dir = devfs_mk_dir (NULL, dirname + 3, NULL);
+ sprintf(dirname, "../%s/disc%d", dev->major_name,
+ (dev->first_minor >> dev->minor_shift) + devnum);
+ dir = devfs_mk_dir(NULL, dirname + 3, NULL);
}
if (!devfs_handle)
- devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
- dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
- sprintf (symlink, "disc%d", dev->part[minor].number);
+ devfs_handle = devfs_mk_dir(NULL, "discs", NULL);
+ p[0].number = devfs_alloc_unique_number (&disc_numspace);
+ sprintf(symlink, "disc%d", p[0].number);
devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
dirname + pos, &slave, NULL);
- dev->part[minor].de =
- devfs_register (dir, "disc", devfs_flags, dev->major, minor,
+ p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor,
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)
devfs_auto_unregister (slave, dir);
}
@@ -475,23 +467,23 @@ void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
{
#ifdef CONFIG_DEVFS_FS
int part, max_p;
+ struct hd_struct *p = dev->part + minor - dev->first_minor;
if (!unregister)
devfs_register_disc (dev, minor);
max_p = (1 << dev->minor_shift);
for (part = 1; part < max_p; part++) {
- if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
- devfs_unregister (dev->part[part + minor].de);
- dev->part[part + minor].de = NULL;
+ if ( unregister || (p[part].nr_sects < 1) ) {
+ devfs_unregister(p[part].de);
+ dev->part[p].de = NULL;
continue;
}
devfs_register_partition (dev, minor, part);
}
if (unregister) {
- devfs_unregister (dev->part[minor].de);
- dev->part[minor].de = NULL;
- devfs_dealloc_unique_number (&disc_numspace,
- dev->part[minor].number);
+ devfs_unregister(p[0].de);
+ p[0].de = NULL;
+ devfs_dealloc_unique_number(&disc_numspace, p[0].number);
}
#endif /* CONFIG_DEVFS_FS */
}
@@ -516,8 +508,9 @@ void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
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 hd_struct *p;
if (!g)
return;
@@ -531,7 +524,8 @@ void grok_partitions(kdev_t dev, long size)
}
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 */
if (minors == 1)
@@ -572,6 +566,7 @@ int wipe_partitions(kdev_t dev)
struct gendisk *g;
kdev_t devp;
int p, major, minor, minor0, max_p, res;
+ struct hd_struct *part;
g = get_gendisk(dev);
if (g == NULL)
@@ -584,19 +579,20 @@ int wipe_partitions(kdev_t dev)
if (minor0 != minor) /* for now only whole-disk reread */
return -EINVAL; /* %%% later.. */
+ part = g->part + minor - g->first_minor;
/* invalidate stuff */
for (p = max_p - 1; p >= 0; p--) {
minor = minor0 + p;
devp = mk_kdev(major,minor);
#if 0 /* %%% superfluous? */
- if (g->part[minor].nr_sects == 0)
+ if (part[p].nr_sects == 0)
continue;
#endif
res = invalidate_device(devp, 1);
if (res)
return res;
- g->part[minor].start_sect = 0;
- g->part[minor].nr_sects = 0;
+ part[p].start_sect = 0;
+ part[p].nr_sects = 0;
}
return 0;
}
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index f8ce7a12c7dd..fd9f5a8d7c06 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -70,6 +70,7 @@ struct hd_struct {
struct gendisk {
int major; /* major number of driver */
+ int first_minor;
const char *major_name; /* name of major driver */
int minor_shift; /* number of times minor is shifted to
get real minor */