From b315226781b180732abb0aa4ead6322b8c7827c6 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 7 Sep 2002 03:03:26 -0700 Subject: [PATCH] (1/25) Unexporting helper functions wipe_partitions() and driverfs_register_partitions(..., 1) (i.e. unregistering them) pulled into del_gendisk() and removed from callers. grok_partitions() merged with register_disk(). devfs_register_partitions(), grok_partitions() and wipe_partitions() not exported anymore. --- include/linux/blkdev.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9f1ac6d07fe8..e0fd1bbd5520 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -281,7 +281,6 @@ struct sec_size { extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern void grok_partitions(kdev_t dev, long size); extern int wipe_partitions(kdev_t dev); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); extern void check_partition(struct gendisk *disk, struct block_device *bdev); -- cgit v1.2.3 From 36bd834b4b5c9e59afc45f863075b4687077ebab Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 7 Sep 2002 03:03:36 -0700 Subject: [PATCH] (3/25) Removing useless minor arguments driverfs_remove_partitions(), devfs_register_partitions(), driverfs_create_partitions(), devfs_register_partition(), devfs_register_disc(), had lost 'minor' argument - it's always disk->first_minor these days. disk_name() takes partition number instead of minor now. Callers of wipe_partitions() in fs/block_dev.c expanded. Remaining caller passes gendisk instead of kdev_t now. --- drivers/block/blkpg.c | 25 +++++------- drivers/block/genhd.c | 6 +-- drivers/md/md.c | 2 +- drivers/scsi/sd.c | 4 +- fs/block_dev.c | 42 ++++++++++++-------- fs/partitions/check.c | 102 +++++++++++++++++++------------------------------ include/linux/blkdev.h | 2 +- include/linux/genhd.h | 7 ++-- 8 files changed, 85 insertions(+), 105 deletions(-) (limited to 'include/linux/blkdev.h') diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c index 1d13a84a9919..106df6b4644c 100644 --- a/drivers/block/blkpg.c +++ b/drivers/block/blkpg.c @@ -71,7 +71,6 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) long pstart, plength; int i; kdev_t dev = to_kdev_t(bdev->bd_dev); - struct hd_struct *part; /* convert bytes to sectors, check for fit in a hd_struct */ ppstart = (p->start >> 9); @@ -86,7 +85,6 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev) - g->first_minor; /* existing drive? */ @@ -97,19 +95,19 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) return -EINVAL; /* partition number in use? */ - if (part[p->pno].nr_sects != 0) + if (g->part[p->pno].nr_sects != 0) return -EBUSY; /* overlap? */ for (i = 1; i < (1<minor_shift); i++) - if (!(pstart+plength <= part[i].start_sect || - pstart >= part[i].start_sect + part[i].nr_sects)) + if (!(pstart+plength <= g->part[i].start_sect || + pstart >= g->part[i].start_sect + g->part[i].nr_sects)) return -EBUSY; /* all seems OK */ - part[p->pno].start_sect = pstart; - part[p->pno].nr_sects = plength; - devfs_register_partitions (g, minor(dev), 0); + g->part[p->pno].start_sect = pstart; + g->part[p->pno].nr_sects = plength; + devfs_register_partitions (g, 0); return 0; } @@ -128,22 +126,19 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *g; struct block_device *bdevp; - struct hd_struct *part; int holder; /* find the drive major */ g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev) - g->first_minor; - if (bdev != bdev->bd_contains) return -EINVAL; if (p->pno <= 0 || p->pno >= (1 << g->minor_shift)) return -EINVAL; /* existing drive and partition? */ - if (part[p->pno].nr_sects == 0) + if (g->part[p->pno].nr_sects == 0) return -ENXIO; /* partition in use? Incomplete check for now. */ @@ -159,9 +154,9 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - part[p->pno].start_sect = 0; - part[p->pno].nr_sects = 0; - devfs_register_partitions (g, minor(dev), 0); + g->part[p->pno].start_sect = 0; + g->part[p->pno].nr_sects = 0; + devfs_register_partitions (g, 0); bd_release(bdevp); bdput(bdevp); diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index f30b605b71d3..782017d52905 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -81,7 +81,7 @@ del_gendisk(struct gendisk *disk) { struct gendisk **p; - wipe_partitions(mk_kdev(disk->major, disk->first_minor)); + wipe_partitions(disk); write_lock(&gendisk_lock); for (p = &gendisk_head; *p; p = &((*p)->next)) if (*p == disk) @@ -89,7 +89,7 @@ del_gendisk(struct gendisk *disk) if (*p) *p = (*p)->next; write_unlock(&gendisk_lock); - devfs_register_partitions(disk, disk->first_minor, 1); + devfs_register_partitions(disk, 1); } EXPORT_SYMBOL(del_gendisk); @@ -168,7 +168,7 @@ static int show_partition(struct seq_file *part, void *v) seq_printf(part, "%4d %4d %10ld %s\n", sgp->major, n + sgp->first_minor, sgp->part[n].nr_sects >> 1 , - disk_name(sgp, n + sgp->first_minor, buf)); + disk_name(sgp, n, buf)); } return 0; diff --git a/drivers/md/md.c b/drivers/md/md.c index 04dc32ea7ce2..e50bfe391c01 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -276,7 +276,7 @@ char * partition_name(kdev_t dev) hd = get_gendisk (dev); dname->name = NULL; if (hd) - dname->name = disk_name (hd, minor(dev), dname->namebuf); + dname->name = disk_name(hd, minor(dev)-hd->first_minor, dname->namebuf); if (!dname->name) { sprintf (dname->namebuf, "[dev %s]", kdevname(dev)); dname->name = dname->namebuf; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ddff04c6d4b2..b8cdd54caaae 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -126,8 +126,6 @@ static void sd_rw_intr(Scsi_Cmnd * SCpnt); static Scsi_Disk * sd_get_sdisk(int index); -extern void driverfs_remove_partitions(struct gendisk *hd, int minor); - #if defined(CONFIG_PPC32) /** * sd_find_target - find kdev_t of first scsi disk that matches @@ -1424,7 +1422,7 @@ static void sd_detach(Scsi_Device * sdp) if (sdkp->has_been_registered) { sdkp->has_been_registered = 0; dev = MKDEV_SD(dsk_nr); - driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev)); + driverfs_remove_partitions(sd_disks[dsk_nr]); del_gendisk(sd_disks[dsk_nr]); } sdp->attached--; diff --git a/fs/block_dev.c b/fs/block_dev.c index a7bd20a9dd48..637c6f0f387d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -528,16 +528,21 @@ int check_disk_change(struct block_device *bdev) int full_check_disk_change(struct block_device *bdev) { int res; + if (bdev->bd_contains != bdev) + BUG(); down(&bdev->bd_sem); res = check_disk_change(bdev); if (bdev->bd_invalidated && !bdev->bd_part_count) { - struct gendisk *g = get_gendisk(to_kdev_t(bdev->bd_dev)); - struct hd_struct *part; - part = g->part + MINOR(bdev->bd_dev) - g->first_minor; + struct gendisk *disk = get_gendisk(to_kdev_t(bdev->bd_dev)); + int p; bdev->bd_invalidated = 0; - wipe_partitions(to_kdev_t(bdev->bd_dev)); - if (part[0].nr_sects) - check_partition(g, bdev); + for (p = 1; p < 1<minor_shift; p++) { + disk->part[p].start_sect = 0; + disk->part[p].nr_sects = 0; + } + res = invalidate_device(to_kdev_t(bdev->bd_dev), 1); + if (disk->part[0].nr_sects) + check_partition(disk, bdev); } up(&bdev->bd_sem); return res; @@ -650,11 +655,14 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * bdev->bd_inode->i_data.backing_dev_info = bdi; } if (bdev->bd_invalidated && !bdev->bd_part_count) { - struct hd_struct *part; - part = g->part + minor(dev) - g->first_minor; + int p; bdev->bd_invalidated = 0; - wipe_partitions(dev); - if (part[0].nr_sects) + for (p = 1; p < 1<minor_shift; p++) { + g->part[p].start_sect = 0; + g->part[p].nr_sects = 0; + } + invalidate_device(dev, 1); + if (g->part[0].nr_sects) check_partition(g, bdev); } } else { @@ -791,12 +799,10 @@ static int blkdev_reread_part(struct block_device *bdev) { kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *disk = get_gendisk(dev); - struct hd_struct *part; - int res; + int p, res; - if (!disk || !disk->minor_shift) + if (!disk || !disk->minor_shift || bdev != bdev->bd_contains) return -EINVAL; - part = disk->part + minor(dev) - disk->first_minor; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (down_trylock(&bdev->bd_sem)) @@ -805,11 +811,15 @@ static int blkdev_reread_part(struct block_device *bdev) up(&bdev->bd_sem); return -EBUSY; } - res = wipe_partitions(dev); + for (p = 1; p < 1 << disk->minor_shift; p++) { + disk->part[p].start_sect = 0; + disk->part[p].nr_sects = 0; + } + res = invalidate_device(dev, 1); if (!res) { if (bdev->bd_op->revalidate) bdev->bd_op->revalidate(dev); - if (part[0].nr_sects) + if (disk->part[0].nr_sects) check_partition(disk, bdev); } up(&bdev->bd_sem); diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 6b79a6f10f2c..6dd2bb455c27 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -87,28 +87,21 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = * a pointer to that same buffer (for convenience). */ -char *disk_name (struct gendisk *hd, int minor, char *buf) +char *disk_name (struct gendisk *hd, int part, char *buf) { - unsigned int part = minor - hd->first_minor; - struct hd_struct *p = hd->part + part; - char s[40]; - const char *maj; - - if (part < 1<minor_shift && p->de) { + if (part < 1<minor_shift && hd->part[part].de) { int pos; - pos = devfs_generate_path(p->de, buf, 64); + pos = devfs_generate_path(hd->part[part].de, buf, 64); if (pos >= 0) return buf + pos; } - - maj = hd->major_name; if (!part) - sprintf(buf, "%s", maj); - else if (isdigit(maj[strlen(maj)-1])) - sprintf(buf, "%sp%d", maj, part); + sprintf(buf, "%s", hd->major_name); + else if (isdigit(hd->major_name[strlen(hd->major_name)-1])) + sprintf(buf, "%sp%d", hd->major_name, part); else - sprintf(buf, "%s%d", maj, part); + sprintf(buf, "%s%d", hd->major_name, part); return buf; } @@ -129,7 +122,7 @@ static ssize_t partition_device_type_read(struct device *driverfs_dev, } static DEVICE_ATTR(type,S_IRUGO,partition_device_type_read,NULL); -void driverfs_create_partitions(struct gendisk *hd, int minor) +static void driverfs_create_partitions(struct gendisk *hd) { int pos = -1; char dirname[256]; @@ -137,7 +130,7 @@ void driverfs_create_partitions(struct gendisk *hd, int minor) int max_p; int part; devfs_handle_t dir = 0; - struct hd_struct *p = hd->part + minor - hd->first_minor; + struct hd_struct *p = hd->part; /* get parent driverfs device structure */ if (hd->driverfs_dev_arr) @@ -154,7 +147,7 @@ void driverfs_create_partitions(struct gendisk *hd, int minor) } if (pos < 0) { - disk_name(hd, minor, dirname); + disk_name(hd, 0, dirname); pos = 0; } @@ -168,7 +161,7 @@ void driverfs_create_partitions(struct gendisk *hd, int minor) current_driverfs_dev->parent = parent; /* handle disc case */ current_driverfs_dev->driver_data = - (void *)(long)__mkdev(hd->major, minor+part); + (void *)(long)__mkdev(hd->major, hd->first_minor+part); if (part == 0) { if (parent) { sprintf(current_driverfs_dev->name, @@ -204,12 +197,12 @@ void driverfs_create_partitions(struct gendisk *hd, int minor) } } -void driverfs_remove_partitions(struct gendisk *hd, int minor) +void driverfs_remove_partitions(struct gendisk *hd) { int max_p; int part; struct device * current_driverfs_dev; - struct hd_struct *p = hd->part + minor - hd->first_minor; + struct hd_struct *p = hd->part; max_p=(1 << hd->minor_shift); @@ -225,10 +218,8 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor) } } current_driverfs_dev = &p->hd_driverfs_dev; - device_remove_file(current_driverfs_dev, - &dev_attr_type); - device_remove_file(current_driverfs_dev, - &dev_attr_kdev); + device_remove_file(current_driverfs_dev, &dev_attr_type); + device_remove_file(current_driverfs_dev, &dev_attr_kdev); put_device(current_driverfs_dev); return; } @@ -256,7 +247,7 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) sprintf(state->name, "p"); } else { unsigned n = hd->major; - disk_name(hd, minor(dev), state->name); + disk_name(hd, 0, state->name); printk(KERN_INFO " %s:", state->name); if (n - COMPAQ_SMART2_MAJOR <= 7 || n - COMPAQ_CISS_MAJOR <= 7) sprintf(state->name, "p"); @@ -274,7 +265,7 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) printk(" unable to read partition table\n"); goto out; } - p = hd->part + minor(dev) - hd->first_minor; + p = hd->part; for (j = 1; j < state->limit; j++) { p[j].start_sect = state->parts[j].from; p[j].nr_sects = state->parts[j].size; @@ -289,16 +280,16 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) printk(" unknown partition table\n"); out: - driverfs_create_partitions(hd, minor(dev)); - devfs_register_partitions (hd, minor(dev), 0); + driverfs_create_partitions(hd); + devfs_register_partitions(hd, 0); } #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 part) { devfs_handle_t dir; unsigned int devfs_flags = DEVFS_FL_DEFAULT; - struct hd_struct *p = dev->part + minor - dev->first_minor; + struct hd_struct *p = dev->part; char devname[16]; if (p[part].de) @@ -310,21 +301,21 @@ static void devfs_register_partition (struct gendisk *dev, int minor, int part) devfs_flags |= DEVFS_FL_REMOVABLE; sprintf (devname, "part%d", part); p[part].de = devfs_register (dir, devname, devfs_flags, - dev->major, minor + part, + dev->major, dev->first_minor + part, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); } 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 pos = 0; 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; + struct hd_struct *p = dev->part; if (p[0].de) return; @@ -350,7 +341,8 @@ static void devfs_register_disc (struct gendisk *dev, int minor) sprintf(symlink, "disc%d", p[0].number); devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, dirname + pos, &slave, NULL); - p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor, + p[0].de = devfs_register (dir, "disc", devfs_flags, + dev->major, dev->first_minor, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); devfs_auto_unregister(p[0].de, slave); if (!dev->de_arr) @@ -358,14 +350,14 @@ static void devfs_register_disc (struct gendisk *dev, int minor) } #endif /* CONFIG_DEVFS_FS */ -void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) +void devfs_register_partitions (struct gendisk *dev, int unregister) { #ifdef CONFIG_DEVFS_FS int part, max_p; - struct hd_struct *p = dev->part + minor - dev->first_minor; + struct hd_struct *p = dev->part; if (!unregister) - devfs_register_disc (dev, minor); + devfs_register_disc(dev); max_p = (1 << dev->minor_shift); for (part = 1; part < max_p; part++) { if ( unregister || (p[part].nr_sects < 1) ) { @@ -373,7 +365,7 @@ void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) p[part].de = NULL; continue; } - devfs_register_partition (dev, minor, part); + devfs_register_partition(dev, part); } if (unregister) { devfs_unregister(p[0].de); @@ -402,7 +394,7 @@ void register_disk(struct gendisk *g, kdev_t dev, unsigned minors, if (!g) return; - p = g->part + minor(dev) - g->first_minor; + p = g->part; p[0].nr_sects = size; /* No minors to use for partitions */ @@ -443,38 +435,24 @@ fail: return NULL; } -int wipe_partitions(kdev_t dev) +int wipe_partitions(struct gendisk *disk) { - 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) - return -EINVAL; - - max_p = 1 << g->minor_shift; - major = major(dev); - minor = minor(dev); - minor0 = minor & ~(max_p - 1); - if (minor0 != minor) /* for now only whole-disk reread */ - return -EINVAL; /* %%% later.. */ - - part = g->part + minor - g->first_minor; + int max_p = 1 << disk->minor_shift; + int p; + /* invalidate stuff */ for (p = max_p - 1; p >= 0; p--) { - minor = minor0 + p; - devp = mk_kdev(major,minor); + kdev_t devp = mk_kdev(disk->major,disk->first_minor + p); + int res; #if 0 /* %%% superfluous? */ - if (part[p].nr_sects == 0) + if (disk->part[p].nr_sects == 0) continue; #endif res = invalidate_device(devp, 1); if (res) return res; - part[p].start_sect = 0; - part[p].nr_sects = 0; + disk->part[p].start_sect = 0; + disk->part[p].nr_sects = 0; } return 0; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e0fd1bbd5520..77fec95ff4b4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -281,7 +281,7 @@ struct sec_size { extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern int wipe_partitions(kdev_t dev); +extern int wipe_partitions(struct gendisk *disk); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); extern void check_partition(struct gendisk *disk, struct block_device *bdev); extern void generic_make_request(struct bio *bio); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 304ebe48ec24..dcff86342667 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -240,11 +240,10 @@ struct unixware_disklabel { #ifdef __KERNEL__ -char *disk_name (struct gendisk *hd, int minor, char *buf); +char *disk_name (struct gendisk *hd, int part, char *buf); -extern void devfs_register_partitions (struct gendisk *dev, int minor, - int unregister); -extern void driverfs_remove_partitions (struct gendisk *hd, int minor); +extern void devfs_register_partitions (struct gendisk *dev, int unregister); +extern void driverfs_remove_partitions (struct gendisk *hd); static inline unsigned int disk_index (kdev_t dev) { -- cgit v1.2.3 From 897c924ed245812b0fafc96da5b2eb0232697e00 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 7 Sep 2002 03:04:02 -0700 Subject: [PATCH] (9/25) update_partition() new helper - update_partition(disk, partition_number); does the right thing wrt devfs and driverfs (un)registration of partition entries. BLKPG ioctls fixed - now they call that beast rather than calling only devfs side. New helper - rescan_partitions(disk, bdev); does all work with wiping/rereading/etc. and fs/block_dev.c now uses it instead of check_partition(). The latter became static. --- drivers/block/blkpg.c | 4 +- drivers/block/genhd.c | 19 +------ fs/block_dev.c | 48 +++------------- fs/partitions/check.c | 150 ++++++++++++++++++++++++++++++++----------------- include/linux/blkdev.h | 2 - include/linux/genhd.h | 5 +- 6 files changed, 115 insertions(+), 113 deletions(-) (limited to 'include/linux/blkdev.h') diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c index 106df6b4644c..9fbfaafbea25 100644 --- a/drivers/block/blkpg.c +++ b/drivers/block/blkpg.c @@ -107,7 +107,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) /* all seems OK */ g->part[p->pno].start_sect = pstart; g->part[p->pno].nr_sects = plength; - devfs_register_partitions (g, 0); + update_partition(g, p->pno); return 0; } @@ -156,7 +156,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) g->part[p->pno].start_sect = 0; g->part[p->pno].nr_sects = 0; - devfs_register_partitions (g, 0); + update_partition(g, p->pno); bd_release(bdevp); bdput(bdevp); diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index d9e3c2052b21..589ae73d7366 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -67,22 +67,11 @@ out: } EXPORT_SYMBOL(add_gendisk); +EXPORT_SYMBOL(del_gendisk); - -/** - * del_gendisk - remove partitioning information from kernel list - * @gp: per-device partitioning information - * - * This function unregisters the partitioning information in @gp - * with the kernel. - */ -void -del_gendisk(struct gendisk *disk) +void unlink_gendisk(struct gendisk *disk) { struct gendisk **p; - - driverfs_remove_partitions(disk); - wipe_partitions(disk); write_lock(&gendisk_lock); for (p = &gendisk_head; *p; p = &((*p)->next)) if (*p == disk) @@ -90,12 +79,8 @@ del_gendisk(struct gendisk *disk) if (*p) *p = (*p)->next; write_unlock(&gendisk_lock); - devfs_register_partitions(disk, 1); } -EXPORT_SYMBOL(del_gendisk); - - /** * get_gendisk - get partitioning information for a given device * @dev: device to get partitioning information for diff --git a/fs/block_dev.c b/fs/block_dev.c index 637c6f0f387d..30e46a931b2f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -527,22 +527,13 @@ int check_disk_change(struct block_device *bdev) int full_check_disk_change(struct block_device *bdev) { - int res; + int res = 0; if (bdev->bd_contains != bdev) BUG(); down(&bdev->bd_sem); - res = check_disk_change(bdev); - if (bdev->bd_invalidated && !bdev->bd_part_count) { - struct gendisk *disk = get_gendisk(to_kdev_t(bdev->bd_dev)); - int p; - bdev->bd_invalidated = 0; - for (p = 1; p < 1<minor_shift; p++) { - disk->part[p].start_sect = 0; - disk->part[p].nr_sects = 0; - } - res = invalidate_device(to_kdev_t(bdev->bd_dev), 1); - if (disk->part[0].nr_sects) - check_partition(disk, bdev); + if (check_disk_change(bdev)) { + rescan_partitions(get_gendisk(to_kdev_t(bdev->bd_dev)), bdev); + res = 1; } up(&bdev->bd_sem); return res; @@ -654,17 +645,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * inode->i_data.backing_dev_info = bdi; bdev->bd_inode->i_data.backing_dev_info = bdi; } - if (bdev->bd_invalidated && !bdev->bd_part_count) { - int p; - bdev->bd_invalidated = 0; - for (p = 1; p < 1<minor_shift; p++) { - g->part[p].start_sect = 0; - g->part[p].nr_sects = 0; - } - invalidate_device(dev, 1); - if (g->part[0].nr_sects) - check_partition(g, bdev); - } + if (bdev->bd_invalidated) + rescan_partitions(g, bdev); } else { down(&bdev->bd_contains->bd_sem); bdev->bd_contains->bd_part_count++; @@ -799,7 +781,7 @@ static int blkdev_reread_part(struct block_device *bdev) { kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *disk = get_gendisk(dev); - int p, res; + int res = 0; if (!disk || !disk->minor_shift || bdev != bdev->bd_contains) return -EINVAL; @@ -807,21 +789,7 @@ static int blkdev_reread_part(struct block_device *bdev) return -EACCES; if (down_trylock(&bdev->bd_sem)) return -EBUSY; - if (bdev->bd_part_count) { - up(&bdev->bd_sem); - return -EBUSY; - } - for (p = 1; p < 1 << disk->minor_shift; p++) { - disk->part[p].start_sect = 0; - disk->part[p].nr_sects = 0; - } - res = invalidate_device(dev, 1); - if (!res) { - if (bdev->bd_op->revalidate) - bdev->bd_op->revalidate(dev); - if (disk->part[0].nr_sects) - check_partition(disk, bdev); - } + res = rescan_partitions(disk, bdev); up(&bdev->bd_sem); return res; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 0401913788df..8927d25ef60d 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -149,29 +149,29 @@ static void driverfs_create_partitions(struct gendisk *hd) sprintf(dev->name, "%sdisc", name); sprintf(dev->bus_id, "%sdisc", bus_id); for (part=1; part < max_p; part++) { + dev = &p[part].hd_driverfs_dev; + sprintf(dev->name, "%spart%d", name, part); + sprintf(dev->bus_id, "%s:p%d", bus_id, part); if (!p[part].nr_sects) continue; - dev = &p[part].hd_driverfs_dev; dev->driver_data = (void *)(long)__mkdev(hd->major, hd->first_minor+part); - sprintf(dev->name, "%spart%d", name, part); - sprintf(dev->bus_id, "%s:p%d", bus_id, part); } for (part=0; part < max_p; part++) { dev = &p[part].hd_driverfs_dev; - if (!dev->driver_data) - continue; dev->parent = parent; if (parent) dev->bus = parent->bus; + if (!dev->driver_data) + continue; device_register(dev); device_create_file(dev, &dev_attr_type); device_create_file(dev, &dev_attr_kdev); } } -void driverfs_remove_partitions(struct gendisk *hd) +static void driverfs_remove_partitions(struct gendisk *hd) { int max_p = 1<minor_shift; struct hd_struct *p; @@ -188,10 +188,7 @@ void driverfs_remove_partitions(struct gendisk *hd) } } -/* - * DON'T EXPORT - */ -void check_partition(struct gendisk *hd, struct block_device *bdev) +static void check_partition(struct gendisk *hd, struct block_device *bdev) { devfs_handle_t de = NULL; dev_t dev = bdev->bd_dev; @@ -226,7 +223,7 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) if (res < 0) { if (warn_no_part) printk(" unable to read partition table\n"); - goto out; + return; } p = hd->part; for (j = 1; j < state->limit; j++) { @@ -238,18 +235,14 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) md_autodetect_dev(dev+j); #endif } - goto out; + return; } - printk(" unknown partition table\n"); -out: - driverfs_create_partitions(hd); - devfs_register_partitions(hd, 0); } -#ifdef CONFIG_DEVFS_FS static void devfs_register_partition(struct gendisk *dev, int part) { +#ifdef CONFIG_DEVFS_FS devfs_handle_t dir; unsigned int devfs_flags = DEVFS_FL_DEFAULT; struct hd_struct *p = dev->part; @@ -262,26 +255,29 @@ static void devfs_register_partition(struct gendisk *dev, int part) return; if (dev->flags & GENHD_FL_REMOVABLE) devfs_flags |= DEVFS_FL_REMOVABLE; - sprintf (devname, "part%d", part); + sprintf(devname, "part%d", part); p[part].de = devfs_register (dir, devname, devfs_flags, dev->major, dev->first_minor + part, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); +#endif } +#ifdef CONFIG_DEVFS_FS static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; +#endif -static void devfs_register_disc(struct gendisk *dev) +static void devfs_create_partitions(struct gendisk *dev) { +#ifdef CONFIG_DEVFS_FS int pos = 0; devfs_handle_t dir, slave; unsigned int devfs_flags = DEVFS_FL_DEFAULT; char dirname[64], symlink[16]; static devfs_handle_t devfs_handle; + int part, max_p = 1<minor_shift; struct hd_struct *p = dev->part; - if (p[0].de) - return; if (dev->flags & GENHD_FL_REMOVABLE) devfs_flags |= DEVFS_FL_REMOVABLE; if (dev->flags & GENHD_FL_DEVFS) { @@ -304,38 +300,28 @@ static void devfs_register_disc(struct gendisk *dev) sprintf(symlink, "disc%d", dev->number); devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, dirname + pos, &slave, NULL); - p[0].de = devfs_register (dir, "disc", devfs_flags, + p->de = devfs_register(dir, "disc", devfs_flags, dev->major, dev->first_minor, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); - devfs_auto_unregister(p[0].de, slave); + devfs_auto_unregister(p->de, slave); if (!(dev->flags & GENHD_FL_DEVFS)) devfs_auto_unregister (slave, dir); + for (part = 1, p++; part < max_p; part++, p++) + if (p->nr_sects) + devfs_register_partition(dev, part); +#endif } -#endif /* CONFIG_DEVFS_FS */ -void devfs_register_partitions (struct gendisk *dev, int unregister) +static void devfs_remove_partitions(struct gendisk *dev) { #ifdef CONFIG_DEVFS_FS - int part, max_p; - struct hd_struct *p = dev->part; - - if (!unregister) - devfs_register_disc(dev); - max_p = (1 << dev->minor_shift); - for (part = 1; part < max_p; part++) { - if ( unregister || (p[part].nr_sects < 1) ) { - devfs_unregister(p[part].de); - p[part].de = NULL; - continue; - } - devfs_register_partition(dev, part); - } - if (unregister) { - devfs_unregister(p[0].de); - p[0].de = NULL; - devfs_dealloc_unique_number(&disc_numspace, dev->number); + int part; + for (part = 1<minor_shift; part--; ) { + devfs_unregister(dev->part[part].de); + dev->part[part].de = NULL; } -#endif /* CONFIG_DEVFS_FS */ + devfs_dealloc_unique_number(&disc_numspace, dev->number); +#endif } /* @@ -348,20 +334,20 @@ void devfs_register_partitions (struct gendisk *dev, int unregister) * done */ -void register_disk(struct gendisk *g, kdev_t dev, unsigned minors, +void register_disk(struct gendisk *disk, kdev_t dev, unsigned minors, struct block_device_operations *ops, long size) { struct block_device *bdev; struct hd_struct *p; - if (!g) + if (!disk) return; - p = g->part; + p = disk->part; p[0].nr_sects = size; /* No minors to use for partitions */ - if (!g->minor_shift) + if (!disk->minor_shift) return; /* No such device (e.g., media were just removed) */ @@ -371,10 +357,66 @@ void register_disk(struct gendisk *g, kdev_t dev, unsigned minors, bdev = bdget(kdev_t_to_nr(dev)); if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0) return; - check_partition(g, bdev); + check_partition(disk, bdev); + driverfs_create_partitions(disk); + devfs_create_partitions(disk); blkdev_put(bdev, BDEV_RAW); } +void update_partition(struct gendisk *disk, int part) +{ + struct hd_struct *p = disk->part + part; + struct device *dev = &p->hd_driverfs_dev; + + if (!p->nr_sects) { + if (p->de) { + devfs_unregister(p->de); + p->de = NULL; + } + if (dev->driver_data) { + device_remove_file(dev, &dev_attr_type); + device_remove_file(dev, &dev_attr_kdev); + put_device(dev); + dev->driver_data = NULL; + } + return; + } + if (!p->de) + devfs_register_partition(disk, part); + if (dev->driver_data || !(disk->flags & GENHD_FL_DRIVERFS)) + return; + dev->driver_data = + (void *)(long)__mkdev(disk->major, disk->first_minor+part); + device_register(dev); + device_create_file(dev, &dev_attr_type); + device_create_file(dev, &dev_attr_kdev); +} + +int rescan_partitions(struct gendisk *disk, struct block_device *bdev) +{ + kdev_t dev = to_kdev_t(bdev->bd_dev); + int p, res; + if (!bdev->bd_invalidated) + return 0; + if (bdev->bd_part_count) + return -EBUSY; + res = invalidate_device(dev, 1); + if (res) + return res; + bdev->bd_invalidated = 0; + for (p = 1; p < (1<minor_shift); p++) { + disk->part[p].start_sect = 0; + disk->part[p].nr_sects = 0; + } + if (bdev->bd_op->revalidate) + bdev->bd_op->revalidate(dev); + if (disk->part[0].nr_sects) + check_partition(disk, bdev); + for (p = 1; p < (1<minor_shift); p++) + update_partition(disk, p); + return res; +} + unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p) { struct address_space *mapping = bdev->bd_inode->i_mapping; @@ -398,7 +440,7 @@ fail: return NULL; } -int wipe_partitions(struct gendisk *disk) +static int wipe_partitions(struct gendisk *disk) { int max_p = 1 << disk->minor_shift; int p; @@ -419,3 +461,11 @@ int wipe_partitions(struct gendisk *disk) } return 0; } + +void del_gendisk(struct gendisk *disk) +{ + driverfs_remove_partitions(disk); + wipe_partitions(disk); + unlink_gendisk(disk); + devfs_remove_partitions(disk); +} diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 77fec95ff4b4..a11b6181c76f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -281,9 +281,7 @@ struct sec_size { extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern int wipe_partitions(struct gendisk *disk); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); -extern void check_partition(struct gendisk *disk, struct block_device *bdev); extern void generic_make_request(struct bio *bio); extern inline request_queue_t *bdev_get_queue(struct block_device *bdev); extern void blk_put_request(struct request *); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index ee2d41d8bd4d..6474393eff5e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -89,6 +89,7 @@ struct gendisk { /* drivers/block/genhd.c */ extern void add_gendisk(struct gendisk *gp); extern void del_gendisk(struct gendisk *gp); +extern void unlink_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(kdev_t dev); static inline unsigned long get_start_sect(struct block_device *bdev) { @@ -244,8 +245,8 @@ struct unixware_disklabel { char *disk_name (struct gendisk *hd, int part, char *buf); -extern void devfs_register_partitions (struct gendisk *dev, int unregister); -extern void driverfs_remove_partitions (struct gendisk *hd); +extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); +extern void update_partition(struct gendisk *disk, int part); static inline unsigned int disk_index (kdev_t dev) { -- cgit v1.2.3