Commit 897c924e authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[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.
parent 06f55b09
...@@ -107,7 +107,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) ...@@ -107,7 +107,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p)
/* all seems OK */ /* all seems OK */
g->part[p->pno].start_sect = pstart; g->part[p->pno].start_sect = pstart;
g->part[p->pno].nr_sects = plength; g->part[p->pno].nr_sects = plength;
devfs_register_partitions (g, 0); update_partition(g, p->pno);
return 0; return 0;
} }
...@@ -156,7 +156,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) ...@@ -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].start_sect = 0;
g->part[p->pno].nr_sects = 0; g->part[p->pno].nr_sects = 0;
devfs_register_partitions (g, 0); update_partition(g, p->pno);
bd_release(bdevp); bd_release(bdevp);
bdput(bdevp); bdput(bdevp);
......
...@@ -67,22 +67,11 @@ add_gendisk(struct gendisk *gp) ...@@ -67,22 +67,11 @@ add_gendisk(struct gendisk *gp)
} }
EXPORT_SYMBOL(add_gendisk); EXPORT_SYMBOL(add_gendisk);
EXPORT_SYMBOL(del_gendisk);
void unlink_gendisk(struct gendisk *disk)
/**
* 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)
{ {
struct gendisk **p; struct gendisk **p;
driverfs_remove_partitions(disk);
wipe_partitions(disk);
write_lock(&gendisk_lock); write_lock(&gendisk_lock);
for (p = &gendisk_head; *p; p = &((*p)->next)) for (p = &gendisk_head; *p; p = &((*p)->next))
if (*p == disk) if (*p == disk)
...@@ -90,12 +79,8 @@ del_gendisk(struct gendisk *disk) ...@@ -90,12 +79,8 @@ del_gendisk(struct gendisk *disk)
if (*p) if (*p)
*p = (*p)->next; *p = (*p)->next;
write_unlock(&gendisk_lock); write_unlock(&gendisk_lock);
devfs_register_partitions(disk, 1);
} }
EXPORT_SYMBOL(del_gendisk);
/** /**
* get_gendisk - get partitioning information for a given device * get_gendisk - get partitioning information for a given device
* @dev: device to get partitioning information for * @dev: device to get partitioning information for
......
...@@ -527,22 +527,13 @@ int check_disk_change(struct block_device *bdev) ...@@ -527,22 +527,13 @@ int check_disk_change(struct block_device *bdev)
int full_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) if (bdev->bd_contains != bdev)
BUG(); BUG();
down(&bdev->bd_sem); down(&bdev->bd_sem);
res = check_disk_change(bdev); if (check_disk_change(bdev)) {
if (bdev->bd_invalidated && !bdev->bd_part_count) { rescan_partitions(get_gendisk(to_kdev_t(bdev->bd_dev)), bdev);
struct gendisk *disk = get_gendisk(to_kdev_t(bdev->bd_dev)); res = 1;
int p;
bdev->bd_invalidated = 0;
for (p = 1; p < 1<<disk->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); up(&bdev->bd_sem);
return res; return res;
...@@ -654,17 +645,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * ...@@ -654,17 +645,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
inode->i_data.backing_dev_info = bdi; inode->i_data.backing_dev_info = bdi;
bdev->bd_inode->i_data.backing_dev_info = bdi; bdev->bd_inode->i_data.backing_dev_info = bdi;
} }
if (bdev->bd_invalidated && !bdev->bd_part_count) { if (bdev->bd_invalidated)
int p; rescan_partitions(g, bdev);
bdev->bd_invalidated = 0;
for (p = 1; p < 1<<g->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 { } else {
down(&bdev->bd_contains->bd_sem); down(&bdev->bd_contains->bd_sem);
bdev->bd_contains->bd_part_count++; bdev->bd_contains->bd_part_count++;
...@@ -799,7 +781,7 @@ static int blkdev_reread_part(struct block_device *bdev) ...@@ -799,7 +781,7 @@ static int blkdev_reread_part(struct block_device *bdev)
{ {
kdev_t dev = to_kdev_t(bdev->bd_dev); kdev_t dev = to_kdev_t(bdev->bd_dev);
struct gendisk *disk = get_gendisk(dev); struct gendisk *disk = get_gendisk(dev);
int p, res; int res = 0;
if (!disk || !disk->minor_shift || bdev != bdev->bd_contains) if (!disk || !disk->minor_shift || bdev != bdev->bd_contains)
return -EINVAL; return -EINVAL;
...@@ -807,21 +789,7 @@ static int blkdev_reread_part(struct block_device *bdev) ...@@ -807,21 +789,7 @@ static int blkdev_reread_part(struct block_device *bdev)
return -EACCES; return -EACCES;
if (down_trylock(&bdev->bd_sem)) if (down_trylock(&bdev->bd_sem))
return -EBUSY; return -EBUSY;
if (bdev->bd_part_count) { res = rescan_partitions(disk, bdev);
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);
}
up(&bdev->bd_sem); up(&bdev->bd_sem);
return res; return res;
} }
......
...@@ -149,29 +149,29 @@ static void driverfs_create_partitions(struct gendisk *hd) ...@@ -149,29 +149,29 @@ static void driverfs_create_partitions(struct gendisk *hd)
sprintf(dev->name, "%sdisc", name); sprintf(dev->name, "%sdisc", name);
sprintf(dev->bus_id, "%sdisc", bus_id); sprintf(dev->bus_id, "%sdisc", bus_id);
for (part=1; part < max_p; part++) { 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) if (!p[part].nr_sects)
continue; continue;
dev = &p[part].hd_driverfs_dev;
dev->driver_data = dev->driver_data =
(void *)(long)__mkdev(hd->major, hd->first_minor+part); (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++) { for (part=0; part < max_p; part++) {
dev = &p[part].hd_driverfs_dev; dev = &p[part].hd_driverfs_dev;
if (!dev->driver_data)
continue;
dev->parent = parent; dev->parent = parent;
if (parent) if (parent)
dev->bus = parent->bus; dev->bus = parent->bus;
if (!dev->driver_data)
continue;
device_register(dev); device_register(dev);
device_create_file(dev, &dev_attr_type); device_create_file(dev, &dev_attr_type);
device_create_file(dev, &dev_attr_kdev); 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<<hd->minor_shift; int max_p = 1<<hd->minor_shift;
struct hd_struct *p; struct hd_struct *p;
...@@ -188,10 +188,7 @@ void driverfs_remove_partitions(struct gendisk *hd) ...@@ -188,10 +188,7 @@ void driverfs_remove_partitions(struct gendisk *hd)
} }
} }
/* static void check_partition(struct gendisk *hd, struct block_device *bdev)
* DON'T EXPORT
*/
void check_partition(struct gendisk *hd, struct block_device *bdev)
{ {
devfs_handle_t de = NULL; devfs_handle_t de = NULL;
dev_t dev = bdev->bd_dev; dev_t dev = bdev->bd_dev;
...@@ -226,7 +223,7 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) ...@@ -226,7 +223,7 @@ void check_partition(struct gendisk *hd, struct block_device *bdev)
if (res < 0) { if (res < 0) {
if (warn_no_part) if (warn_no_part)
printk(" unable to read partition table\n"); printk(" unable to read partition table\n");
goto out; return;
} }
p = hd->part; p = hd->part;
for (j = 1; j < state->limit; j++) { for (j = 1; j < state->limit; j++) {
...@@ -238,18 +235,14 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) ...@@ -238,18 +235,14 @@ void check_partition(struct gendisk *hd, struct block_device *bdev)
md_autodetect_dev(dev+j); md_autodetect_dev(dev+j);
#endif #endif
} }
goto out; return;
} }
printk(" unknown partition table\n"); 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) static void devfs_register_partition(struct gendisk *dev, int part)
{ {
#ifdef CONFIG_DEVFS_FS
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; struct hd_struct *p = dev->part;
...@@ -262,26 +255,29 @@ static void devfs_register_partition(struct gendisk *dev, int part) ...@@ -262,26 +255,29 @@ static void devfs_register_partition(struct gendisk *dev, int part)
return; return;
if (dev->flags & GENHD_FL_REMOVABLE) if (dev->flags & GENHD_FL_REMOVABLE)
devfs_flags |= DEVFS_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, p[part].de = devfs_register (dir, devname, devfs_flags,
dev->major, dev->first_minor + part, dev->major, dev->first_minor + part,
S_IFBLK | S_IRUSR | S_IWUSR, S_IFBLK | S_IRUSR | S_IWUSR,
dev->fops, NULL); dev->fops, NULL);
#endif
} }
#ifdef CONFIG_DEVFS_FS
static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; 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; int pos = 0;
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;
int part, max_p = 1<<dev->minor_shift;
struct hd_struct *p = dev->part; struct hd_struct *p = dev->part;
if (p[0].de)
return;
if (dev->flags & GENHD_FL_REMOVABLE) if (dev->flags & GENHD_FL_REMOVABLE)
devfs_flags |= DEVFS_FL_REMOVABLE; devfs_flags |= DEVFS_FL_REMOVABLE;
if (dev->flags & GENHD_FL_DEVFS) { if (dev->flags & GENHD_FL_DEVFS) {
...@@ -304,38 +300,28 @@ static void devfs_register_disc(struct gendisk *dev) ...@@ -304,38 +300,28 @@ static void devfs_register_disc(struct gendisk *dev)
sprintf(symlink, "disc%d", dev->number); sprintf(symlink, "disc%d", dev->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);
p[0].de = devfs_register (dir, "disc", devfs_flags, p->de = devfs_register(dir, "disc", devfs_flags,
dev->major, dev->first_minor, dev->major, dev->first_minor,
S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); 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)) if (!(dev->flags & GENHD_FL_DEVFS))
devfs_auto_unregister (slave, dir); 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 #ifdef CONFIG_DEVFS_FS
int part, max_p; int part;
struct hd_struct *p = dev->part; for (part = 1<<dev->minor_shift; part--; ) {
devfs_unregister(dev->part[part].de);
if (!unregister) dev->part[part].de = NULL;
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);
} }
#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) ...@@ -348,20 +334,20 @@ void devfs_register_partitions (struct gendisk *dev, int unregister)
* done * 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_operations *ops, long size)
{ {
struct block_device *bdev; struct block_device *bdev;
struct hd_struct *p; struct hd_struct *p;
if (!g) if (!disk)
return; return;
p = g->part; p = disk->part;
p[0].nr_sects = size; p[0].nr_sects = size;
/* No minors to use for partitions */ /* No minors to use for partitions */
if (!g->minor_shift) if (!disk->minor_shift)
return; return;
/* No such device (e.g., media were just removed) */ /* No such device (e.g., media were just removed) */
...@@ -371,10 +357,66 @@ void register_disk(struct gendisk *g, kdev_t dev, unsigned minors, ...@@ -371,10 +357,66 @@ void register_disk(struct gendisk *g, kdev_t dev, unsigned minors,
bdev = bdget(kdev_t_to_nr(dev)); bdev = bdget(kdev_t_to_nr(dev));
if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0) if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
return; return;
check_partition(g, bdev); check_partition(disk, bdev);
driverfs_create_partitions(disk);
devfs_create_partitions(disk);
blkdev_put(bdev, BDEV_RAW); 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<<disk->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<<disk->minor_shift); p++)
update_partition(disk, p);
return res;
}
unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p) unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
{ {
struct address_space *mapping = bdev->bd_inode->i_mapping; struct address_space *mapping = bdev->bd_inode->i_mapping;
...@@ -398,7 +440,7 @@ unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Secto ...@@ -398,7 +440,7 @@ unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Secto
return NULL; return NULL;
} }
int wipe_partitions(struct gendisk *disk) static int wipe_partitions(struct gendisk *disk)
{ {
int max_p = 1 << disk->minor_shift; int max_p = 1 << disk->minor_shift;
int p; int p;
...@@ -419,3 +461,11 @@ int wipe_partitions(struct gendisk *disk) ...@@ -419,3 +461,11 @@ int wipe_partitions(struct gendisk *disk)
} }
return 0; return 0;
} }
void del_gendisk(struct gendisk *disk)
{
driverfs_remove_partitions(disk);
wipe_partitions(disk);
unlink_gendisk(disk);
devfs_remove_partitions(disk);
}
...@@ -281,9 +281,7 @@ struct sec_size { ...@@ -281,9 +281,7 @@ struct sec_size {
extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct sec_size * blk_sec[MAX_BLKDEV];
extern struct blk_dev_struct blk_dev[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 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 void generic_make_request(struct bio *bio);
extern inline request_queue_t *bdev_get_queue(struct block_device *bdev); extern inline request_queue_t *bdev_get_queue(struct block_device *bdev);
extern void blk_put_request(struct request *); extern void blk_put_request(struct request *);
......
...@@ -89,6 +89,7 @@ struct gendisk { ...@@ -89,6 +89,7 @@ struct gendisk {
/* drivers/block/genhd.c */ /* drivers/block/genhd.c */
extern void add_gendisk(struct gendisk *gp); extern void add_gendisk(struct gendisk *gp);
extern void del_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); extern struct gendisk *get_gendisk(kdev_t dev);
static inline unsigned long get_start_sect(struct block_device *bdev) static inline unsigned long get_start_sect(struct block_device *bdev)
{ {
...@@ -244,8 +245,8 @@ struct unixware_disklabel { ...@@ -244,8 +245,8 @@ struct unixware_disklabel {
char *disk_name (struct gendisk *hd, int part, char *buf); char *disk_name (struct gendisk *hd, int part, char *buf);
extern void devfs_register_partitions (struct gendisk *dev, int unregister); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void driverfs_remove_partitions (struct gendisk *hd); extern void update_partition(struct gendisk *disk, int part);
static inline unsigned int disk_index (kdev_t dev) static inline unsigned int disk_index (kdev_t dev)
{ {
......
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