block: unify disk/part handling and improve ext devt
Subsystems (8)
PATCH 1/1 block: unify disk/part handling and improve ext devt
Hello, again.
This is the first take of unify-disk-part-handling patchset.
The block code represented a disk with struct genhd and a partition with struct hd_struct. The whole disk (a.k.a partition 0) has a lot in common with other partitions but genhd and hd_struct had their own versions for the same things. This led to good number of duplicate similar code paths and branches to deal with them separately. Also, the partition array disk->part[] is indexed by partno - 1 which gets quite confusing at times.
This patchset introduces partition 0 and unifies handling of the whole disk and other partitions and, on top of those changes, improves ext devt handling such that increasing the number of allowed partitions can be done without much overhead and the disk device itself can be allocated an extended devt.
This patchset contains the following 13 patches.
0001-block-implement-and-use-disk-part-_to_dev.patch 0002-block-introduce-partition-0.patch 0003-block-move-capacity-from-disk-to-part0.patch 0004-block-move-__dev-from-disk-to-part0.patch 0005-block-unify-sysfs-size-node-handling.patch 0006-block-move-policy-from-disk-to-part0.patch 0007-block-move-holder_dir-from-disk-to-part0.patch 0008-block-always-set-bdev-bd_part.patch 0009-block-kill-GENHD_FL_FAIL-and-use-part0-make_it_fai.patch 0010-block-move-stats-from-disk-to-part0.patch 0011-block-make-partition-array-dynamic.patch 0012-block-replace-ext_minors-with-GENHD_FL_EXT_DEVT.patch 0013-block-allow-disk-to-have-extended-device-number.patch
0001-0002: preps and introduces part0
0003-0009: moves what's common from disk to part0 and unifies code
paths
0010 : simplifies stats handling
0011 : make partition array dynamic
0012 : ext_minors restriction isn't necessary anymore. simplify
ext devt interface
0013 : allow disk (part0) to have extended devt
After this patchset, partition number is only limited by the number of entries in struct parsed_partitions which is used by actual partition scan code. The limit is currently 256 but it can be increased by changing MAX_PART.
A block driver now can simply set GENHD_FL_EXT_DEVT and skip specifying disk->minors to tell block layer to use extended devt for the disk and its partitions. There's no need to allocate fixed regions and worry about the device number availability.
If CONFIG_DEBUG_BLOCK_EXT_DEVT is turned on, sd and ide-disk use ext devt for everything.
This patchset is on top of
v2.6.26 (bce7f793daec3e65ec5c5705d2457b81fe7b5725)
+ [1] RCU-implement-rcu_read_[un]lock_preempt
+ [2] block-fix-block_class-iteration-locking
+ [3] block-allow-deleting-zero-lenght-partition
+ [4] block-update-add_partition-error-handling
+ [5] sd-update-index-allocation-and-use-ida
+ [6] block-extended-devt patchset, take #2
and available in the following git tree.
http://git.kernel.org/?p=linux/kernel/git/tj/misc.git;a=shortlog;h=block-unify-disk-part
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git block-unify-disk-part
Even with the added feature and comments, this patchset reduces code by 40 lines. ;-)
block/blk-core.c | 84 +++------ block/blk-merge.c | 8 block/blk-sysfs.c | 4 block/genhd.c | 402 ++++++++++++++++++++++----------------------- block/ioctl.c | 4 drivers/block/aoe/aoeblk.c | 6 drivers/block/aoe/aoecmd.c | 12 - drivers/block/aoe/aoedev.c | 2 drivers/block/nbd.c | 4 drivers/ide/ide-cd.c | 2 drivers/ide/ide-disk.c | 16 - drivers/ide/ide-probe.c | 2 drivers/md/dm-ioctl.c | 2 drivers/md/dm.c | 19 +- drivers/md/linear.c | 4 drivers/md/md.c | 15 - drivers/md/multipath.c | 4 drivers/md/raid0.c | 4 drivers/md/raid1.c | 4 drivers/md/raid10.c | 4 drivers/md/raid5.c | 4 drivers/scsi/sd.c | 83 ++++++--- fs/block_dev.c | 79 +++----- fs/partitions/check.c | 160 +++++++++-------- fs/partitions/check.h | 4 include/linux/genhd.h | 238 +++++++++++--------------- 26 files changed, 565 insertions(+), 605 deletions(-)
--
tejun
[1] http://article.gmane.org/gmane.linux.kernel/706149
[2] http://article.gmane.org/gmane.linux.kernel/706152
[3] http://article.gmane.org/gmane.linux.kernel/706153
[4] http://article.gmane.org/gmane.linux.kernel/706154
[5] http://article.gmane.org/gmane.linux.scsi/43109
[6] http://thread.gmane.org/gmane.linux.kernel/706175
PATCH 1/13 block: implement and use {disk|part}_to_dev()
Implement and use {disk|part}_to_dev() and use them to access generic device instead of directly dereferencing {disk|part}->dev. To make sure no user is left behind, rename generic devices fields to __dev.
This is in preparation of unifying partition 0 handling with other partitions.
--- block/blk-sysfs.c | 4 +- block/genhd.c | 32 +++++++++--------- drivers/block/aoe/aoeblk.c | 4 +- drivers/block/nbd.c | 4 +- drivers/ide/ide-probe.c | 2 +- drivers/md/dm.c | 4 +- drivers/md/md.c | 10 +++--- fs/block_dev.c | 4 +- fs/partitions/check.c | 75 +++++++++++++++++++++++--------------------- include/linux/genhd.h | 20 ++++++----- 10 files changed, 82 insertions(+), 77 deletions(-)
block/blk-sysfs.c +2 -2
@@ -310,7 +310,7 @@ int blk_register_queue(struct gendisk *disk)if (!q->request_fn)return 0 ; - ret =kobject_add (&q->kobj,kobject_get (&disk->dev.kobj), + ret =kobject_add (&q->kobj,kobject_get (&disk_to_dev (disk)->kobj),"%s" ,"queue" );if (ret <0 )return ret;
@@ -339,6 +339,6 @@ void blk_unregister_queue(struct gendisk *disk)kobject_uevent (&q->kobj,KOBJ_REMOVE );kobject_del (&q->kobj); -kobject_put (&disk->dev.kobj); +kobject_put (&disk_to_dev (disk)->kobj); } }
block/genhd.c +16 -16
@@ -59,7 +59,7 @@ struct hd_struct *disk_get_part(struct gendisk *disk, int partno)rcu_read_lock (); part =rcu_dereference (disk->__part[partno -1 ]);if (part) -get_device (&part->dev); +get_device (part_to_dev (part));rcu_read_unlock ();return part;
@@ -130,7 +130,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)if (!(piter->flags &DISK_PITER_INCL_EMPTY ) && !part->nr_sects)continue ; -get_device (&part->dev); +get_device (part_to_dev (part)); piter->part = part; piter->idx++;break ;
@@ -434,7 +434,7 @@ static struct kobject *exact_match(dev_t devt, int *partno, void *data) {struct gendisk *p = data; -return &p->dev.kobj; +return &disk_to_dev (p)->kobj; }static int exact_lock (dev_t devt,void *data)
@@ -458,7 +458,7 @@ void add_disk(struct gendisk *disk)struct backing_dev_info *bdi; disk->flags |=GENHD_FL_UP ; - disk->dev.devt =MKDEV (disk->major, disk->first_minor); +disk_to_dev (disk)->devt =MKDEV (disk->major, disk->first_minor);blk_register_region (disk_devt (disk), disk->minors,NULL , exact_match, exact_lock, disk);register_disk (disk);
@@ -466,7 +466,7 @@ void add_disk(struct gendisk *disk) bdi = &disk->queue->backing_dev_info;bdi_register_dev (bdi,disk_devt (disk)); -sysfs_create_link (&disk->dev.kobj, &bdi->dev->kobj,"bdi" ); +sysfs_create_link (&disk_to_dev (disk)->kobj, &bdi->dev->kobj,"bdi" ); }EXPORT_SYMBOL (add_disk);
@@ -474,7 +474,7 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */void unlink_gendisk (struct gendisk *disk) { -sysfs_remove_link (&disk->dev.kobj,"bdi" ); +sysfs_remove_link (&disk_to_dev (disk)->kobj,"bdi" );bdi_unregister (&disk->queue->backing_dev_info);blk_unregister_queue (disk);blk_unregister_region (disk_devt (disk), disk->minors);
@@ -623,7 +623,7 @@ static void *part_next(struct seq_file *seqf, void *v, loff_t *pos)struct gendisk *gp = v;struct device *dev; ++*pos; -list_for_each_entry (dev, &gp->dev.node, node) { +list_for_each_entry (dev, &disk_to_dev (gp)->node, node) {if (&dev->node == &block_class.devices)return NULL ;if (dev->type == &disk_type)
@@ -644,7 +644,7 @@ static int show_partition(struct seq_file *seqf, void *v)struct hd_struct *part;char buf[BDEVNAME_SIZE ]; -if (&sgp->dev.node == block_class.devices.next) +if (&disk_to_dev (sgp)->node == block_class.devices.next)seq_puts (seqf,"major minor #blocks name\n\n" );/* Don't show non-partitionable removeable devices or empty devices */
@@ -881,7 +881,7 @@ static void *diskstats_next(struct seq_file *seqf, void *v, loff_t *pos)struct device *dev; ++*pos; -list_for_each_entry (dev, &gp->dev.node, node) { +list_for_each_entry (dev, &disk_to_dev (gp)->node, node) {if (&dev->node == &block_class.devices)return NULL ;if (dev->type == &disk_type)
@@ -903,7 +903,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)char buf[BDEVNAME_SIZE ];/* -if (&gp->dev.kobj.entry == block_class.devices.next) +if (&disk_to_dev(gp)->kobj.entry == block_class.devices.next) seq_puts(seqf, "major minor name" " rio rmerge rsect ruse wio wmerge " "wsect wuse running use aveq"
@@ -971,7 +971,7 @@ static void media_change_notify_thread(struct work_struct *work)* set enviroment vars to indicate which event this is for * so that user space will know to go check the media status. */ -kobject_uevent_env (&gd->dev.kobj,KOBJ_CHANGE , envp); +kobject_uevent_env (&disk_to_dev (gd)->kobj,KOBJ_CHANGE , envp);put_device (gd->driverfs_dev); }
@@ -1063,9 +1063,9 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->minors = minors; disk->ext_minors = ext_minors;rand_initialize_disk (disk); - disk->dev.class = &block_class; - disk->dev.type = &disk_type; -device_initialize (&disk->dev); +disk_to_dev (disk)->class = &block_class; +disk_to_dev (disk)->type = &disk_type; +device_initialize (disk_to_dev (disk));INIT_WORK (&disk->async_notify, media_change_notify_thread); }
@@ -1087,7 +1087,7 @@ struct kobject *get_disk(struct gendisk *disk) owner = disk->fops->owner;if (owner && !try_module_get (owner))return NULL ; - kobj =kobject_get (&disk->dev.kobj); + kobj =kobject_get (&disk_to_dev (disk)->kobj);if (kobj ==NULL ) {module_put (owner);return NULL ;
@@ -1101,7 +1101,7 @@ EXPORT_SYMBOL(get_disk);void put_disk (struct gendisk *disk) {if (disk) -kobject_put (&disk->dev.kobj); +kobject_put (&disk_to_dev (disk)->kobj); }EXPORT_SYMBOL (put_disk);
drivers/block/aoe/aoeblk.c +2 -2
@@ -109,12 +109,12 @@ static const struct attribute_group attr_group = {static int aoedisk_add_sysfs (struct aoedev *d) { -return sysfs_create_group (&d->gd->dev.kobj, &attr_group); +return sysfs_create_group (&disk_to_dev (d->gd)->kobj, &attr_group); }void aoedisk_rm_sysfs (struct aoedev *d) { -sysfs_remove_group (&d->gd->dev.kobj, &attr_group); +sysfs_remove_group (&disk_to_dev (d->gd)->kobj, &attr_group); } static int
drivers/block/nbd.c +2 -2
@@ -403,7 +403,7 @@ static int nbd_do_it(struct nbd_device *lo)BUG_ON (lo->magic !=LO_MAGIC ); lo->pid = current->pid; - ret =sysfs_create_file (&lo->disk->dev.kobj, &pid_attr.attr); + ret =sysfs_create_file (&disk_to_dev (lo->disk)->kobj, &pid_attr.attr);if (ret) {printk (KERN_ERR "nbd: sysfs_create_file failed!" );return ret;
@@ -412,7 +412,7 @@ static int nbd_do_it(struct nbd_device *lo)while ((req =nbd_read_stat (lo)) !=NULL )nbd_end_request (req); -sysfs_remove_file (&lo->disk->dev.kobj, &pid_attr.attr); +sysfs_remove_file (&disk_to_dev (lo->disk)->kobj, &pid_attr.attr);return 0 ; }
drivers/ide/ide-probe.c +1 -1
@@ -1133,7 +1133,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data) {struct gendisk *p = data; *part &= (1 <<PARTN_BITS ) -1 ; -return &p->dev.kobj; +return &disk_to_dev (p)->kobj; }static int exact_lock (dev_t dev,void *data)
drivers/md/dm.c +2 -2
@@ -1136,7 +1136,7 @@ static void event_callback(void *context)list_splice_init (&md->uevent_list, &uevents);spin_unlock_irqrestore (&md->uevent_lock, flags); -dm_send_uevents (&uevents, &md->disk->dev.kobj); +dm_send_uevents (&uevents, &disk_to_dev (md->disk)->kobj);atomic_inc (&md->event_nr);wake_up (&md->eventq);
@@ -1593,7 +1593,7 @@ out:*---------------------------------------------------------------*/ void dm_kobject_uevent (struct mapped_device *md) { -kobject_uevent (&md->disk->dev.kobj,KOBJ_CHANGE ); +kobject_uevent (&disk_to_dev (md->disk)->kobj,KOBJ_CHANGE ); }uint32_t dm_next_uevent_seq (struct mapped_device *md)
drivers/md/md.c +5 -5
@@ -1416,9 +1416,9 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) goto fail;if (rdev->bdev->bd_part) - ko = &rdev->bdev->bd_part->dev.kobj; + ko = &part_to_dev (rdev->bdev->bd_part)->kobj;else - ko = &rdev->bdev->bd_disk->dev.kobj; + ko = &disk_to_dev (rdev->bdev->bd_disk)->kobj;if ((err =sysfs_create_link (&rdev->kobj, ko,"block" ))) {kobject_del (&rdev->kobj); goto fail;
@@ -3327,8 +3327,8 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)add_disk (disk); mddev->gendisk = disk;mutex_unlock (&disks_mutex); - error =kobject_init_and_add (&mddev->kobj, &md_ktype, &disk->dev.kobj, -"%s" ,"md" ); + error =kobject_init_and_add (&mddev->kobj, &md_ktype, + &disk_to_dev (disk)->kobj,"%s" ,"md" );if (error)printk (KERN_WARNING "md: cannot register %s/md - name in use\n" , disk->disk_name);
@@ -3608,7 +3608,7 @@ static int do_md_run(mddev_t * mddev) mddev->changed =1 ;md_new_event (mddev); -kobject_uevent (&mddev->gendisk->dev.kobj,KOBJ_CHANGE ); +kobject_uevent (&disk_to_dev (mddev->gendisk)->kobj,KOBJ_CHANGE );return 0 ; }
fs/block_dev.c +2 -2
@@ -543,9 +543,9 @@ EXPORT_SYMBOL(bd_release);static struct kobject *bdev_get_kobj (struct block_device *bdev) {if (bdev->bd_contains != bdev) -return kobject_get (&bdev->bd_part->dev.kobj); +return kobject_get (&part_to_dev (bdev->bd_part)->kobj);else -return kobject_get (&bdev->bd_disk->dev.kobj); +return kobject_get (&disk_to_dev (bdev->bd_disk)->kobj); }static struct kobject *bdev_get_holder (struct block_device *bdev)
fs/partitions/check.c +39 -36
179 lines not on this page · raw message
include/linux/genhd.h +11 -9
@@ -15,9 +15,11 @@#ifdef CONFIG_BLOCK -#define kobj_to_dev (k) container_of(k, struct device, kobj) -#define dev_to_disk (device) container_of(device, struct gendisk, dev) -#define dev_to_part (device) container_of(device, struct hd_struct, dev) +#define kobj_to_dev (k) container_of((k), struct device, kobj) +#define dev_to_disk (device) container_of((device), struct gendisk, __dev) +#define dev_to_part (device) container_of((device), struct hd_struct, __dev) +#define disk_to_dev (disk) (&((disk)->__dev)) +#define part_to_dev (part) (&((part)->__dev))extern struct device_type part_type;extern struct kobject *block_depr;
@@ -88,7 +90,7 @@ struct disk_stats {struct hd_struct {sector_t start_sect;sector_t nr_sects; -struct device dev; +struct device __dev;struct kobject *holder_dir;int policy, partno;#ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -140,7 +142,7 @@ struct gendisk {int flags;struct device *driverfs_dev;// FIXME: remove -struct device dev; +struct device __dev;struct kobject *holder_dir;struct kobject *slave_dir;
@@ -161,7 +163,7 @@ struct gendisk {static inline struct gendisk *part_to_disk (struct hd_struct *part) {if (likely (part)) -return dev_to_disk ((part)->dev.parent); +return dev_to_disk (part_to_dev (part)->parent);return NULL ; }
@@ -172,12 +174,12 @@ static inline int disk_max_parts(struct gendisk *disk)static inline dev_t disk_devt (struct gendisk *disk) { -return disk->dev.devt; +return disk_to_dev (disk)->devt; }static inline dev_t part_devt (struct hd_struct *part) { -return part->dev.devt; +return part_to_dev (part)->devt; }extern struct hd_struct *disk_get_part (struct gendisk *disk,int partno);
@@ -185,7 +187,7 @@ extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno);static inline void disk_put_part (struct hd_struct *part) {if (likely (part)) -put_device (&part->dev); +put_device (part_to_dev (part)); }/*
Signature · 1 line
1.5.4.5
PATCH 2/13 block: introduce partition 0
In reply to Tejun Heogenhd and partition code handled disk and partitions separately. All information about the whole disk was in struct genhd and partitions in struct hd_struct. However, the whole disk (part0) and other partitions have a lot in common and the data structures end up having good number of common fields and separate code paths doing the same thing. Also, the partition array was indexed by partno - 1 which gets pretty confusing at times.
This patch introduces partition 0 and makes the partition array indexed by partno. Following patches will unify the handling of disk and parts piece-by-piece.
This patch also implements disk_partitionable() which tests whether a disk is partitionable. With coming dynamic partition array change, the most common usage of disk_max_parts() will be testing whether a disk is partitionable and the number of max partitions will become much less important.
--- block/genhd.c | 40 +++++++++++++++++++++++----------------- block/ioctl.c | 4 ++-- fs/block_dev.c | 2 +- fs/partitions/check.c | 12 ++++++------ include/linux/genhd.h | 11 +++++++++-- 5 files changed, 41 insertions(+), 28 deletions(-)
block/genhd.c +23 -17
@@ -54,10 +54,10 @@ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) {struct hd_struct *part; -if (unlikely (partno <1 || partno >disk_max_parts (disk))) +if (unlikely (partno <0 || partno >=disk_max_parts (disk)))return NULL ;rcu_read_lock (); - part =rcu_dereference (disk->__part[partno -1 ]); + part =rcu_dereference (disk->__part[partno]);if (part)get_device (part_to_dev (part));rcu_read_unlock ();
@@ -85,8 +85,10 @@ void disk_part_iter_start(struct disk_part_iter *piter, struct gendisk *disk,if (flags &DISK_PITER_REVERSE ) piter->idx =disk_max_parts (piter->disk) -1 ; -else +else if (flags &DISK_PITER_INCL_PART0 ) piter->idx =0 ; +else + piter->idx =1 ; piter->flags = flags; }
@@ -114,7 +116,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)/* determine iteration parameters */ if (piter->flags &DISK_PITER_REVERSE ) { inc =-1 ; - end =-1 ; +if (piter->flags &DISK_PITER_INCL_PART0 ) + end =-1 ; +else + end =0 ; }else { inc =1 ; end =disk_max_parts (piter->disk);
@@ -177,7 +182,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) {int i; -for (i =0 ; i <disk_max_parts (disk); i++) { +for (i =1 ; i <disk_max_parts (disk); i++) {struct hd_struct *part =rcu_dereference (disk->__part[i]); if (part && part->start_sect <= sector &&
@@ -648,7 +653,7 @@ static int show_partition(struct seq_file *seqf, void *v)seq_puts (seqf,"major minor #blocks name\n\n" );/* Don't show non-partitionable removeable devices or empty devices */ -if (!get_capacity (sgp) || (!disk_max_parts (sgp) && +if (!get_capacity (sgp) || (!disk_partitionable (sgp) && (sgp->flags &GENHD_FL_REMOVABLE )))return 0 ;if (sgp->flags &GENHD_FL_SUPPRESS_PARTITION_INFO )
@@ -718,7 +723,7 @@ static ssize_t disk_ext_range_show(struct device *dev, {struct gendisk *disk =dev_to_disk (dev); -return sprintf (buf,"%d\n" ,disk_max_parts (disk) +1 ); +return sprintf (buf,"%d\n" ,disk_max_parts (disk)); } static ssize_t disk_removable_show(struct device *dev,
@@ -997,7 +1002,7 @@ dev_t blk_lookup_devt(const char *name, int partno)continue ;if (strcmp (dev->bus_id, name))continue ; -if (partno <0 || partno >disk_max_parts (disk)) +if (partno <0 || partno >=disk_max_parts (disk))continue ;if (partno ==0 )
@@ -1045,21 +1050,22 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) GFP_KERNEL | __GFP_ZERO, node_id);if (disk) {int tot_minors = minors + ext_minors; +int size = tot_minors *sizeof (struct hd_struct *);if (!init_disk_stats (disk)) {kfree (disk);return NULL ; } -if (tot_minors >1 ) { -int size = (tot_minors -1 ) *sizeof (struct hd_struct *); - disk->__part =kmalloc_node (size, -GFP_KERNEL | __GFP_ZERO, node_id); -if (!disk->__part) { -free_disk_stats (disk); -kfree (disk); -return NULL ; - } + + disk->__part =kmalloc_node (size,GFP_KERNEL | __GFP_ZERO, + node_id); +if (!disk->__part) { +free_disk_stats (disk); +kfree (disk); +return NULL ; } + disk->__part[0 ] = &disk->part0; + disk->minors = minors; disk->ext_minors = ext_minors;rand_initialize_disk (disk);
block/ioctl.c +2 -2
@@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __userif (bdev != bdev->bd_contains)return -EINVAL ; partno = p.pno; -if (partno <=0 || partno >disk_max_parts (disk)) +if (partno <=0 || partno >=disk_max_parts (disk))return -EINVAL ;switch (a.op) {case BLKPG_ADD_PARTITION :
@@ -104,7 +104,7 @@ static int blkdev_reread_part(struct block_device *bdev)struct gendisk *disk = bdev->bd_disk;int res; -if (!disk_max_parts (disk) || bdev != bdev->bd_contains) +if (!disk_partitionable (disk) || bdev != bdev->bd_contains)return -EINVAL ;if (!capable (CAP_SYS_ADMIN ))return -EACCES ;
fs/block_dev.c +1 -1
@@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev)if (bdops->revalidate_disk) bdops->revalidate_disk (bdev->bd_disk); -if (disk_max_parts (bdev->bd_disk)) +if (disk_partitionable (bdev->bd_disk)) bdev->bd_invalidated =1 ;return 1 ; }
fs/partitions/check.c +6 -6
@@ -173,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev)if (isdigit (state->name[strlen (state->name)-1 ]))sprintf (state->name,"p" ); - state->limit =disk_max_parts (hd) +1 ; + state->limit =disk_max_parts (hd); i = res = err =0 ;while (!res && check_part[i]) {memset (&state->parts,0 ,sizeof (state->parts));
@@ -338,12 +338,12 @@ void delete_partition(struct gendisk *disk, int partno) {struct hd_struct *part; - part = disk->__part[partno-1 ]; + part = disk->__part[partno];if (!part)return ;blk_free_devt (part_devt (part)); -rcu_assign_pointer (disk->__part[partno-1 ],NULL ); +rcu_assign_pointer (disk->__part[partno],NULL );kobject_put (part->holder_dir);device_del (part_to_dev (part));
@@ -368,7 +368,7 @@ int add_partition(struct gendisk *disk, int partno,const char *dname;int err; -if (disk->__part[partno -1 ]) { +if (disk->__part[partno]) { err = -EBUSY ; goto fail; }
@@ -403,7 +403,7 @@ int add_partition(struct gendisk *disk, int partno, pdev->devt = devt;INIT_RCU_HEAD (&p->rcu_head); -rcu_assign_pointer (disk->__part[partno-1 ], p); +rcu_assign_pointer (disk->__part[partno], p);/* delay uevent until 'holders' subdir is created */ pdev->uevent_suppress =1 ;
@@ -466,7 +466,7 @@ void register_disk(struct gendisk *disk)disk_sysfs_add_subdirs (disk);/* No minors to use for partitions */ -if (!disk_max_parts (disk)) +if (!disk_partitionable (disk)) goto exit;/* No such device (e.g., media were just removed) */
include/linux/genhd.h +9 -2
@@ -128,12 +128,13 @@ struct gendisk {char disk_name[32 ];/* name of major driver */ -/* Array of pointers to partitions indexed by partno - 1. +/* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other * non-critical accesses use RCU. Always access through * helpers. */ struct hd_struct **__part; +struct hd_struct part0;struct block_device_operations *fops;struct request_queue *queue;
@@ -169,7 +170,12 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part)static inline int disk_max_parts (struct gendisk *disk) { -return disk->minors + disk->ext_minors -1 ; +return disk->minors + disk->ext_minors; +} + +static inline bool disk_partitionable (struct gendisk *disk) +{ +return disk_max_parts (disk) >1 ; }static inline dev_t disk_devt (struct gendisk *disk)
@@ -195,6 +201,7 @@ static inline void disk_put_part(struct hd_struct *part)*/ #define DISK_PITER_REVERSE (1 << 0)/* iterate in the reverse direction */ #define DISK_PITER_INCL_EMPTY (1 << 1)/* include 0-sized parts */ +#define DISK_PITER_INCL_PART0 (1 << 2)/* include partition 0 */ struct disk_part_iter {struct gendisk *disk;
Signature · 1 line
1.5.4.5
PATCH 3/13 block: move capacity from disk to part0
In reply to Tejun HeoMove disk->capacity to part0->nr_sects and convert all users who directly accessed the field to use {get|set}_capacity(). This is done early to allow the __dev field to be moved.
--- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoecmd.c | 4 ++-- drivers/block/aoe/aoedev.c | 2 +- fs/partitions/check.c | 2 +- include/linux/genhd.h | 5 ++--- 5 files changed, 7 insertions(+), 8 deletions(-)
drivers/block/aoe/aoeblk.c +1 -1
@@ -276,7 +276,7 @@ aoeblk_gdalloc(void *vp) gd->first_minor = d->sysminor *AOE_PARTITIONS ; gd->fops = &aoe_bdops; gd->private_data = d; - gd->capacity = d->ssize; +set_capacity (gd, d->ssize);snprintf (gd->disk_name,sizeof gd->disk_name,"etherd/e%ld.%d" , d->aoemajor, d->aoeminor);
drivers/block/aoe/aoecmd.c +2 -2
@@ -645,7 +645,7 @@ aoecmd_sleepwork(struct work_struct *work)unsigned long flags;u64 ssize; - ssize = d->gd->capacity; + ssize =get_capacity (d->gd); bd =bdget_disk (d->gd,0 );if (bd) {
@@ -707,7 +707,7 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)if (d->flags & (DEVFL_GDALLOC |DEVFL_NEWSIZE ))return ;if (d->gd !=NULL ) { - d->gd->capacity = ssize; +set_capacity (d->gd, ssize); d->flags |=DEVFL_NEWSIZE ; }else d->flags |=DEVFL_GDALLOC ;
drivers/block/aoe/aoedev.c +1 -1
@@ -91,7 +91,7 @@ aoedev_downdev(struct aoedev *d) }if (d->gd) - d->gd->capacity =0 ; +set_capacity (d->gd,0 ); d->flags &= ~DEVFL_UP ; }
fs/partitions/check.c +1 -1
@@ -582,7 +582,7 @@ void del_gendisk(struct gendisk *disk)delete_partition (disk, part->partno); }invalidate_partition (disk,0 ); - disk->capacity =0 ; +set_capacity (disk,0 ); disk->flags &= ~GENHD_FL_UP ;unlink_gendisk (disk);disk_stat_set_all (disk,0 );
include/linux/genhd.h +2 -3
@@ -139,7 +139,6 @@ struct gendisk {struct block_device_operations *fops;struct request_queue *queue;void *private_data; -sector_t capacity;int flags;struct device *driverfs_dev;// FIXME: remove
@@ -397,11 +396,11 @@ static inline sector_t get_start_sect(struct block_device *bdev) }static inline sector_t get_capacity (struct gendisk *disk) { -return disk->capacity; +return disk->part0.nr_sects; }static inline void set_capacity (struct gendisk *disk,sector_t size) { - disk->capacity = size; + disk->part0.nr_sects = size; }#ifdef CONFIG_SOLARIS_X86_PARTITION
Signature · 1 line
1.5.4.5
PATCH 4/13 block: move __dev from disk to part0
In reply to Tejun HeoMove disk->__dev to part0->__dev. This simplifies bdget_disk() and lookup_devt() and allows common sysfs attributes to be unified. part_to_disk() is updated to handle part0 -> disk.
--- block/genhd.c | 40 ++++++++++++---------------------------- include/linux/genhd.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 33 deletions(-)
block/genhd.c +12 -28
@@ -532,22 +532,15 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)*/ extern struct block_device *bdget_disk (struct gendisk *disk,int partno) { -dev_t devt =MKDEV (0 ,0 ); +struct hd_struct *part; +struct block_device *bdev =NULL ; -if (partno ==0 ) - devt =disk_devt (disk); -else { -struct hd_struct *part; + part =disk_get_part (disk, partno); +if (part && part->nr_sects) + bdev =bdget (part_devt (part)); +disk_put_part (part); - part =disk_get_part (disk, partno); -if (part && part->nr_sects) - devt =part_devt (part); -disk_put_part (part); - } - -if (likely (devt !=MKDEV (0 ,0 ))) -return bdget (devt); -return NULL ; +return bdev; }EXPORT_SYMBOL (bdget_disk);
@@ -997,29 +990,20 @@ dev_t blk_lookup_devt(const char *name, int partno)down (&block_class.sem);list_for_each_entry (dev, &block_class.devices, node) {struct gendisk *disk =dev_to_disk (dev); +struct hd_struct *part;if (dev->type != &disk_type)continue ;if (strcmp (dev->bus_id, name))continue ; -if (partno <0 || partno >=disk_max_parts (disk)) -continue ; - -if (partno ==0 ) - devt =disk_devt (disk); -else { -struct hd_struct *part; - - part =disk_get_part (disk, partno); -if (!part || !part->nr_sects) { -disk_put_part (part); -continue ; - } + part =disk_get_part (disk, partno); +if (part && part->nr_sects) { devt =part_devt (part);disk_put_part (part); +break ; } -break ; +disk_put_part (part); }up (&block_class.sem);
include/linux/genhd.h +8 -5
@@ -16,9 +16,9 @@#ifdef CONFIG_BLOCK #define kobj_to_dev (k) container_of((k), struct device, kobj) -#define dev_to_disk (device) container_of((device), struct gendisk, __dev) +#define dev_to_disk (device) container_of((device), struct gendisk, part0.__dev)#define dev_to_part (device) container_of((device), struct hd_struct, __dev) -#define disk_to_dev (disk) (&((disk)->__dev)) +#define disk_to_dev (disk) (&(disk)->part0.__dev)#define part_to_dev (part) (&((part)->__dev))extern struct device_type part_type;
@@ -142,7 +142,6 @@ struct gendisk {int flags;struct device *driverfs_dev;// FIXME: remove -struct device __dev;struct kobject *holder_dir;struct kobject *slave_dir;
@@ -162,8 +161,12 @@ struct gendisk {static inline struct gendisk *part_to_disk (struct hd_struct *part) { -if (likely (part)) -return dev_to_disk (part_to_dev (part)->parent); +if (likely (part)) { +if (part->partno) +return dev_to_disk (part_to_dev (part)->parent); +else +return dev_to_disk (part_to_dev (part)); + }return NULL ; }
Signature · 1 line
1.5.4.5
PATCH 4/13 block: move __dev from disk to part0
In reply to Tejun HeoMove disk->__dev to part0->__dev. This simplifies bdget_disk() and lookup_devt() and allows common sysfs attributes to be unified. part_to_disk() is updated to handle part0 -> disk.
--- block/genhd.c | 40 ++++++++++++---------------------------- include/linux/genhd.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 33 deletions(-)
block/genhd.c +12 -28
@@ -532,22 +532,15 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)*/ extern struct block_device *bdget_disk (struct gendisk *disk,int partno) { -dev_t devt =MKDEV (0 ,0 ); +struct hd_struct *part; +struct block_device *bdev =NULL ; -if (partno ==0 ) - devt =disk_devt (disk); -else { -struct hd_struct *part; + part =disk_get_part (disk, partno); +if (part && part->nr_sects) + bdev =bdget (part_devt (part)); +disk_put_part (part); - part =disk_get_part (disk, partno); -if (part && part->nr_sects) - devt =part_devt (part); -disk_put_part (part); - } - -if (likely (devt !=MKDEV (0 ,0 ))) -return bdget (devt); -return NULL ; +return bdev; }EXPORT_SYMBOL (bdget_disk);
@@ -997,29 +990,20 @@ dev_t blk_lookup_devt(const char *name, int partno)down (&block_class.sem);list_for_each_entry (dev, &block_class.devices, node) {struct gendisk *disk =dev_to_disk (dev); +struct hd_struct *part;if (dev->type != &disk_type)continue ;if (strcmp (dev->bus_id, name))continue ; -if (partno <0 || partno >=disk_max_parts (disk)) -continue ; - -if (partno ==0 ) - devt =disk_devt (disk); -else { -struct hd_struct *part; - - part =disk_get_part (disk, partno); -if (!part || !part->nr_sects) { -disk_put_part (part); -continue ; - } + part =disk_get_part (disk, partno); +if (part && part->nr_sects) { devt =part_devt (part);disk_put_part (part); +break ; } -break ; +disk_put_part (part); }up (&block_class.sem);
include/linux/genhd.h +8 -5
@@ -16,9 +16,9 @@#ifdef CONFIG_BLOCK #define kobj_to_dev (k) container_of((k), struct device, kobj) -#define dev_to_disk (device) container_of((device), struct gendisk, __dev) +#define dev_to_disk (device) container_of((device), struct gendisk, part0.__dev)#define dev_to_part (device) container_of((device), struct hd_struct, __dev) -#define disk_to_dev (disk) (&((disk)->__dev)) +#define disk_to_dev (disk) (&(disk)->part0.__dev)#define part_to_dev (part) (&((part)->__dev))extern struct device_type part_type;
@@ -142,7 +142,6 @@ struct gendisk {int flags;struct device *driverfs_dev;// FIXME: remove -struct device __dev;struct kobject *holder_dir;struct kobject *slave_dir;
@@ -162,8 +161,12 @@ struct gendisk {static inline struct gendisk *part_to_disk (struct hd_struct *part) { -if (likely (part)) -return dev_to_disk (part_to_dev (part)->parent); +if (likely (part)) { +if (part->partno) +return dev_to_disk (part_to_dev (part)->parent); +else +return dev_to_disk (part_to_dev (part)); + }return NULL ; }
Signature · 1 line
1.5.4.5
PATCH 5/13 block: unify sysfs size node handling
In reply to Tejun HeoNow that capacity and __dev are moved to part0, part0 and others can share the same method.
--- block/genhd.c | 10 +--------- fs/partitions/check.c | 4 ++-- include/linux/genhd.h | 3 +++ 3 files changed, 6 insertions(+), 11 deletions(-)
block/genhd.c +1 -9
@@ -728,14 +728,6 @@ static ssize_t disk_removable_show(struct device *dev, (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); } -static ssize_t disk_size_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -struct gendisk *disk =dev_to_disk (dev); - -return sprintf (buf,"%llu\n" , (unsigned long long )get_capacity (disk)); -} -static ssize_t disk_capability_show (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -801,7 +793,7 @@ static ssize_t disk_fail_store(struct device *dev, static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); -static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);#ifdef CONFIG_FAIL_MAKE_REQUEST
fs/partitions/check.c +2 -2
@@ -208,8 +208,8 @@ static ssize_t part_start_show(struct device *dev,return sprintf (buf,"%llu\n" ,(unsigned long long )p->start_sect); } -static ssize_t part_size_show (struct device *dev, -struct device_attribute *attr,char *buf) +ssize_t part_size_show (struct device *dev, +struct device_attribute *attr,char *buf) {struct hd_struct *p =dev_to_part (dev);return sprintf (buf,"%llu\n" ,(unsigned long long )p->nr_sects);
include/linux/genhd.h +3 -0
@@ -577,6 +577,9 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data);extern void blk_unregister_region (dev_t devt,unsigned long range); +extern ssize_t part_size_show (struct device *dev, +struct device_attribute *attr,char *buf); +#else /* CONFIG_BLOCK */ static inline void printk_all_partitions (void ) { }
Signature · 1 line
1.5.4.5
PATCH 5/13 block: unify sysfs size node handling
In reply to Tejun HeoNow that capacity and __dev are moved to part0, part0 and others can share the same method.
--- block/genhd.c | 10 +--------- fs/partitions/check.c | 4 ++-- include/linux/genhd.h | 3 +++ 3 files changed, 6 insertions(+), 11 deletions(-)
block/genhd.c +1 -9
@@ -728,14 +728,6 @@ static ssize_t disk_removable_show(struct device *dev, (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); } -static ssize_t disk_size_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -struct gendisk *disk =dev_to_disk (dev); - -return sprintf (buf,"%llu\n" , (unsigned long long )get_capacity (disk)); -} -static ssize_t disk_capability_show (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -801,7 +793,7 @@ static ssize_t disk_fail_store(struct device *dev, static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); -static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);#ifdef CONFIG_FAIL_MAKE_REQUEST
fs/partitions/check.c +2 -2
@@ -208,8 +208,8 @@ static ssize_t part_start_show(struct device *dev,return sprintf (buf,"%llu\n" ,(unsigned long long )p->start_sect); } -static ssize_t part_size_show (struct device *dev, -struct device_attribute *attr,char *buf) +ssize_t part_size_show (struct device *dev, +struct device_attribute *attr,char *buf) {struct hd_struct *p =dev_to_part (dev);return sprintf (buf,"%llu\n" ,(unsigned long long )p->nr_sects);
include/linux/genhd.h +3 -0
@@ -577,6 +577,9 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data);extern void blk_unregister_region (dev_t devt,unsigned long range); +extern ssize_t part_size_show (struct device *dev, +struct device_attribute *attr,char *buf); +#else /* CONFIG_BLOCK */ static inline void printk_all_partitions (void ) { }
Signature · 1 line
1.5.4.5
PATCH 6/13 block: move policy from disk to part0
In reply to Tejun HeoMove disk->policy to part0->policy. Implement and use get_disk_ro().
--- block/genhd.c | 14 ++++---------- drivers/ide/ide-cd.c | 2 +- drivers/md/dm-ioctl.c | 2 +- fs/partitions/check.c | 2 +- include/linux/genhd.h | 6 +++++- 5 files changed, 12 insertions(+), 14 deletions(-)
block/genhd.c +4 -10
@@ -1090,10 +1090,7 @@ EXPORT_SYMBOL(put_disk);void set_device_ro (struct block_device *bdev,int flag) { -if (bdev->bd_contains != bdev) - bdev->bd_part->policy = flag; -else - bdev->bd_disk->policy = flag; + bdev->bd_part->policy = flag; }EXPORT_SYMBOL (set_device_ro);
@@ -1103,8 +1100,8 @@ void set_disk_ro(struct gendisk *disk, int flag)struct disk_part_iter piter;struct hd_struct *part; - disk->policy = flag; -disk_part_iter_start (&piter, disk,DISK_PITER_INCL_EMPTY ); +disk_part_iter_start (&piter, disk, +DISK_PITER_INCL_EMPTY |DISK_PITER_INCL_PART0 );while ((part =disk_part_iter_next (&piter))) part->policy = flag;disk_part_iter_stop (&piter);
@@ -1116,10 +1113,7 @@ int bdev_read_only(struct block_device *bdev) {if (!bdev)return 0 ; -else if (bdev->bd_contains != bdev) -return bdev->bd_part->policy; -else -return bdev->bd_disk->policy; +return bdev->bd_part->policy; }EXPORT_SYMBOL (bdev_read_only);
drivers/ide/ide-cd.c +1 -1
@@ -1126,7 +1126,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)if (write) {/* disk has become write protected */ -if (cd->disk->policy) { +if (get_disk_ro (cd->disk)) {cdrom_end_request (drive,0 );return ide_stopped; }
drivers/md/dm-ioctl.c +1 -1
@@ -548,7 +548,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)*/ param->open_count =dm_open_count (md); -if (disk->policy) +if (get_disk_ro (disk)) param->flags |=DM_READONLY_FLAG ; param->event_nr =dm_get_event_nr (md);
fs/partitions/check.c +1 -1
@@ -384,7 +384,7 @@ int add_partition(struct gendisk *disk, int partno, p->start_sect = start; p->nr_sects = len; p->partno = partno; - p->policy = disk->policy; + p->policy =get_disk_ro (disk); dname =dev_name (ddev);if (isdigit (dname[strlen (dname) -1 ]))
include/linux/genhd.h +5 -1
@@ -146,7 +146,6 @@ struct gendisk {struct kobject *slave_dir;struct timer_rand_state *random; -int policy;atomic_t sync_io;/* RAID */ unsigned long stamp;
@@ -389,6 +388,11 @@ extern struct block_device *bdget_disk(struct gendisk *disk, int partno);extern void set_device_ro (struct block_device *bdev,int flag);extern void set_disk_ro (struct gendisk *disk,int flag); +static inline int get_disk_ro (struct gendisk *disk) +{ +return disk->part0.policy; +} +/* drivers/char/random.c */ extern void add_disk_randomness (struct gendisk *disk);extern void rand_initialize_disk (struct gendisk *disk);
Signature · 1 line
1.5.4.5
PATCH 7/13 block: move holder_dir from disk to part0
In reply to Tejun HeoMove disk->holder_dir to part0->holder_dir. Kill now mostly superflous bdev_get_holder().
--- fs/block_dev.c | 10 +--------- fs/partitions/check.c | 20 +++++++------------- include/linux/genhd.h | 1 - 3 files changed, 8 insertions(+), 23 deletions(-)
fs/block_dev.c +1 -9
@@ -548,14 +548,6 @@ static struct kobject *bdev_get_kobj(struct block_device *bdev)return kobject_get (&disk_to_dev (bdev->bd_disk)->kobj); } -static struct kobject *bdev_get_holder (struct block_device *bdev) -{ -if (bdev->bd_contains != bdev) -return kobject_get (bdev->bd_part->holder_dir); -else -return kobject_get (bdev->bd_disk->holder_dir); -} -static int add_symlink (struct kobject *from,struct kobject *to) {if (!from || !to)
@@ -608,7 +600,7 @@ static int bd_holder_grab_dirs(struct block_device *bdev,if (!bo->sdev) goto fail_put_hdev; - bo->hdir =bdev_get_holder (bdev); + bo->hdir =kobject_get (bdev->bd_part->holder_dir);if (!bo->hdir) goto fail_put_sdev;
fs/partitions/check.c +7 -13
@@ -304,23 +304,17 @@ struct device_type part_type = { .release = part_release, }; -static inline void partition_sysfs_add_subdir (struct hd_struct *p) +static inline void partition_sysfs_add_subdir (struct hd_struct *part) { -struct kobject *k; - - k =kobject_get (&part_to_dev (p)->kobj); - p->holder_dir =kobject_create_and_add ("holders" , k); -kobject_put (k); + part->holder_dir =kobject_create_and_add ("holders" , + &part_to_dev (part)->kobj); }static inline void disk_sysfs_add_subdirs (struct gendisk *disk) { -struct kobject *k; - - k =kobject_get (&disk_to_dev (disk)->kobj); - disk->holder_dir =kobject_create_and_add ("holders" , k); - disk->slave_dir =kobject_create_and_add ("slaves" , k); -kobject_put (k); +partition_sysfs_add_subdir (&disk->part0); + disk->slave_dir =kobject_create_and_add ("slaves" , + &disk_to_dev (disk)->kobj); }static void delete_partition_rcu_cb (struct rcu_head *head)
@@ -588,7 +582,7 @@ void del_gendisk(struct gendisk *disk)disk_stat_set_all (disk,0 ); disk->stamp =0 ; -kobject_put (disk->holder_dir); +kobject_put (disk->part0.holder_dir);kobject_put (disk->slave_dir); disk->driverfs_dev =NULL ;#ifndef CONFIG_SYSFS_DEPRECATED
include/linux/genhd.h +0 -1
@@ -142,7 +142,6 @@ struct gendisk {int flags;struct device *driverfs_dev;// FIXME: remove -struct kobject *holder_dir;struct kobject *slave_dir;struct timer_rand_state *random;
Signature · 1 line
1.5.4.5
PATCH 7/13 block: move holder_dir from disk to part0
In reply to Tejun HeoMove disk->holder_dir to part0->holder_dir. Kill now mostly superflous bdev_get_holder().
--- fs/block_dev.c | 10 +--------- fs/partitions/check.c | 20 +++++++------------- include/linux/genhd.h | 1 - 3 files changed, 8 insertions(+), 23 deletions(-)
fs/block_dev.c +1 -9
@@ -548,14 +548,6 @@ static struct kobject *bdev_get_kobj(struct block_device *bdev)return kobject_get (&disk_to_dev (bdev->bd_disk)->kobj); } -static struct kobject *bdev_get_holder (struct block_device *bdev) -{ -if (bdev->bd_contains != bdev) -return kobject_get (bdev->bd_part->holder_dir); -else -return kobject_get (bdev->bd_disk->holder_dir); -} -static int add_symlink (struct kobject *from,struct kobject *to) {if (!from || !to)
@@ -608,7 +600,7 @@ static int bd_holder_grab_dirs(struct block_device *bdev,if (!bo->sdev) goto fail_put_hdev; - bo->hdir =bdev_get_holder (bdev); + bo->hdir =kobject_get (bdev->bd_part->holder_dir);if (!bo->hdir) goto fail_put_sdev;
fs/partitions/check.c +7 -13
@@ -304,23 +304,17 @@ struct device_type part_type = { .release = part_release, }; -static inline void partition_sysfs_add_subdir (struct hd_struct *p) +static inline void partition_sysfs_add_subdir (struct hd_struct *part) { -struct kobject *k; - - k =kobject_get (&part_to_dev (p)->kobj); - p->holder_dir =kobject_create_and_add ("holders" , k); -kobject_put (k); + part->holder_dir =kobject_create_and_add ("holders" , + &part_to_dev (part)->kobj); }static inline void disk_sysfs_add_subdirs (struct gendisk *disk) { -struct kobject *k; - - k =kobject_get (&disk_to_dev (disk)->kobj); - disk->holder_dir =kobject_create_and_add ("holders" , k); - disk->slave_dir =kobject_create_and_add ("slaves" , k); -kobject_put (k); +partition_sysfs_add_subdir (&disk->part0); + disk->slave_dir =kobject_create_and_add ("slaves" , + &disk_to_dev (disk)->kobj); }static void delete_partition_rcu_cb (struct rcu_head *head)
@@ -588,7 +582,7 @@ void del_gendisk(struct gendisk *disk)disk_stat_set_all (disk,0 ); disk->stamp =0 ; -kobject_put (disk->holder_dir); +kobject_put (disk->part0.holder_dir);kobject_put (disk->slave_dir); disk->driverfs_dev =NULL ;#ifndef CONFIG_SYSFS_DEPRECATED
include/linux/genhd.h +0 -1
@@ -142,7 +142,6 @@ struct gendisk {int flags;struct device *driverfs_dev;// FIXME: remove -struct kobject *holder_dir;struct kobject *slave_dir;struct timer_rand_state *random;
Signature · 1 line
1.5.4.5
PATCH 8/13 block: always set bdev->bd_part
In reply to Tejun HeoTill now, bdev->bd_part is set only if the bdev was for parts other than part0. This patch makes bdev->bd_part always set so that code paths don't have to differenciate common handling.
--- block/blk-core.c | 2 +- drivers/md/md.c | 5 +--- fs/block_dev.c | 67 ++++++++++++++++++++++-------------------------- fs/partitions/check.c | 7 +---- include/linux/genhd.h | 2 +- 5 files changed, 35 insertions(+), 48 deletions(-)
block/blk-core.c +1 -1
@@ -1263,7 +1263,7 @@ __setup("fail_make_request=", setup_fail_make_request);static int should_fail_request (struct bio *bio) {if ((bio->bi_bdev->bd_disk->flags &GENHD_FL_FAIL ) || - (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail)) + bio->bi_bdev->bd_part->make_it_fail)return should_fail (&fail_make_request, bio->bi_size);return 0 ;
drivers/md/md.c +1 -4
@@ -1415,10 +1415,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)if ((err =kobject_add (&rdev->kobj, &mddev->kobj,"dev-%s" , b))) goto fail; -if (rdev->bdev->bd_part) - ko = &part_to_dev (rdev->bdev->bd_part)->kobj; -else - ko = &disk_to_dev (rdev->bdev->bd_disk)->kobj; + ko = &part_to_dev (rdev->bdev->bd_part)->kobj;if ((err =sysfs_create_link (&rdev->kobj, ko,"block" ))) {kobject_del (&rdev->kobj); goto fail;
fs/block_dev.c +31 -36
146 lines not on this page · raw message
fs/partitions/check.c +1 -6
@@ -134,12 +134,7 @@ char *disk_name(struct gendisk *hd, int partno, char *buf)const char *bdevname (struct block_device *bdev,char *buf) { -int partno =0 ; - -if (bdev->bd_part) - partno = bdev->bd_part->partno; - -return disk_name (bdev->bd_disk, partno, buf); +return disk_name (bdev->bd_disk, bdev->bd_part->partno, buf); }EXPORT_SYMBOL (bdevname);
include/linux/genhd.h +1 -1
@@ -398,7 +398,7 @@ extern void rand_initialize_disk(struct gendisk *disk);static inline sector_t get_start_sect (struct block_device *bdev) { -return bdev->bd_contains == bdev ?0 : bdev->bd_part->start_sect; +return bdev->bd_part->start_sect; }static inline sector_t get_capacity (struct gendisk *disk) {
Signature · 1 line
1.5.4.5
PATCH 9/13 block: kill GENHD_FL_FAIL and use part0->make_it_fail
In reply to Tejun HeoGENHD_FL_FAIL for disk is what make_it_fail is for parts. Kill it and use part0->make_it_fail. Sysfs node handling is unified too.
--- block/blk-core.c | 5 +++-- block/genhd.c | 30 +----------------------------- fs/partitions/check.c | 10 +++++----- include/linux/genhd.h | 9 +++++++-- 4 files changed, 16 insertions(+), 38 deletions(-)
block/blk-core.c +3 -2
@@ -1262,8 +1262,9 @@ __setup("fail_make_request=", setup_fail_make_request);static int should_fail_request (struct bio *bio) { -if ((bio->bi_bdev->bd_disk->flags &GENHD_FL_FAIL ) || - bio->bi_bdev->bd_part->make_it_fail) +struct hd_struct *part = bio->bi_bdev->bd_part; + +if (part_to_disk (part)->part0.make_it_fail || part->make_it_fail)return should_fail (&fail_make_request, bio->bi_size);return 0 ;
block/genhd.c +1 -29
@@ -762,34 +762,6 @@ static ssize_t disk_stat_show(struct device *dev, jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); } -#ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t disk_fail_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -struct gendisk *disk =dev_to_disk (dev); - -return sprintf (buf,"%d\n" , disk->flags &GENHD_FL_FAIL ?1 :0 ); -} - -static ssize_t disk_fail_store (struct device *dev, -struct device_attribute *attr, -const char *buf,size_t count) -{ -struct gendisk *disk =dev_to_disk (dev); -int i; - -if (count >0 &&sscanf (buf,"%d" , &i) >0 ) { -if (i ==0 ) - disk->flags &= ~GENHD_FL_FAIL ; -else - disk->flags |=GENHD_FL_FAIL ; - } - -return count; -} - -#endif - static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
@@ -798,7 +770,7 @@ static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);#ifdef CONFIG_FAIL_MAKE_REQUEST static struct device_attribute dev_attr_fail = -__ATTR (make-it-fail,S_IRUGO |S_IWUSR , disk_fail_show, disk_fail_store); +__ATTR (make-it-fail,S_IRUGO |S_IWUSR , part_fail_show, part_fail_store);#endif static struct attribute *disk_attrs[] = {
fs/partitions/check.c +5 -5
@@ -237,17 +237,17 @@ static ssize_t part_stat_show(struct device *dev, }#ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t part_fail_show (struct device *dev, -struct device_attribute *attr,char *buf) +ssize_t part_fail_show (struct device *dev, +struct device_attribute *attr,char *buf) {struct hd_struct *p =dev_to_part (dev);return sprintf (buf,"%d\n" , p->make_it_fail); } -static ssize_t part_fail_store (struct device *dev, -struct device_attribute *attr, -const char *buf,size_t count) +ssize_t part_fail_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) {struct hd_struct *p =dev_to_part (dev);int i;
include/linux/genhd.h +7 -2
@@ -112,8 +112,6 @@ struct hd_struct {#define GENHD_FL_CD 8#define GENHD_FL_UP 16#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 -#define GENHD_FL_FAIL 64 -struct gendisk {/* major, first_minor, minors and ext_minors are input
@@ -582,6 +580,13 @@ extern void blk_unregister_region(dev_t devt, unsigned long range);extern ssize_t part_size_show (struct device *dev,struct device_attribute *attr,char *buf); +#ifdef CONFIG_FAIL_MAKE_REQUEST +extern ssize_t part_fail_show (struct device *dev, +struct device_attribute *attr,char *buf); +extern ssize_t part_fail_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count); +#endif /* CONFIG_FAIL_MAKE_REQUEST */ #else /* CONFIG_BLOCK */
Signature · 1 line
1.5.4.5
PATCH 10/13 block: move stats from disk to part0
In reply to Tejun HeoMove stats related fields - stamp, in_flight, dkstats - from disk to part0 and unify stat handling such that...
* part_stat_*() now updates part0 together if the specified partition is not part0. ie. part_stat_*() are now essentially all_stat_*().
* {disk|all}_stat_*() are gone.
* part_round_stats() is updated similary. It handles part0 stats automatically and disk_round_stats() is killed.
* part_{inc|dec}_in_fligh() is implemented which automatically updates part0 stats for parts other than part0.
* disk_map_sector_rcu() is updated to return part0 if no part matches. Combined with the above changes, this makes NULL special case handling in callers unnecessary.
* Separate stats show code paths for disk are collapsed into part stats show code paths.
--- block/blk-core.c | 79 ++++++++---------------- block/blk-merge.c | 8 +-- block/genhd.c | 90 ++++++-------------------- drivers/block/aoe/aoecmd.c | 8 +- drivers/md/dm.c | 15 +++-- drivers/md/linear.c | 4 +- drivers/md/md.c | 4 +- drivers/md/multipath.c | 4 +- drivers/md/raid0.c | 4 +- drivers/md/raid1.c | 4 +- drivers/md/raid10.c | 4 +- drivers/md/raid5.c | 4 +- fs/partitions/check.c | 8 +- include/linux/genhd.h | 150 ++++++++++++------------------------------- 14 files changed, 121 insertions(+), 265 deletions(-)
block/blk-core.c +26 -53
@@ -64,14 +64,10 @@ static void drive_stat_acct(struct request *rq, int new_io) part =disk_map_sector_rcu (rq->rq_disk, rq->sector);if (!new_io) -all_stat_inc (rq->rq_disk, part, merges[rw], rq->sector); +part_stat_inc (part, merges[rw]);else { -disk_round_stats (rq->rq_disk); - rq->rq_disk->in_flight++; -if (part) { -part_round_stats (part); - part->in_flight++; - } +part_round_stats (part); +part_inc_in_flight (part); }rcu_read_unlock_preempt ();
@@ -966,8 +962,21 @@ static inline void add_request(struct request_queue *q, struct request *req)__elv_add_request (q, req,ELEVATOR_INSERT_SORT ,0 ); } +static void part_round_stats_single (struct hd_struct *part,unsigned long now) +{ +if (now == part->stamp) +return ; + +if (part->in_flight) { +__part_stat_add (part, time_in_queue, + part->in_flight * (now - part->stamp)); +__part_stat_add (part, io_ticks, (now - part->stamp)); + } + part->stamp = now; +} +/** -* disk_round_stats() - Round off the performance stats on a struct +* part_round_stats() - Round off the performance stats on a struct * disk_stats. * * The average IO queue length and utilisation statistics are maintained
@@ -984,45 +993,15 @@ static inline void add_request(struct request_queue *q, struct request *req)* CONTEXT: * Preemption disabled. */ -void disk_round_stats (struct gendisk *disk) -{ -unsigned long now = jiffies; - -if (now == disk->stamp) -return ; - -if (disk->in_flight) { -disk_stat_add (disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); -disk_stat_add (disk, io_ticks, (now - disk->stamp)); - } - disk->stamp = now; -} -EXPORT_SYMBOL_GPL (disk_round_stats); - -/** -* part_round_stats() - Round off the performance stats on a struct -* disk_stats. -* -* Please see disk_round_stats() for more information. -* -* CONTEXT: -* Preemption disabled. -*/ void part_round_stats (struct hd_struct *part) {unsigned long now = jiffies; -if (now == part->stamp) -return ; - -if (part->in_flight) { -part_stat_add (part, time_in_queue, - part->in_flight * (now - part->stamp)); -part_stat_add (part, io_ticks, (now - part->stamp)); - } - part->stamp = now; +if (part->partno) +part_round_stats_single (&part_to_disk (part)->part0, now); +part_round_stats_single (part, now); } +EXPORT_SYMBOL_GPL (part_round_stats);/* * queue lock must be held
@@ -1557,8 +1536,7 @@ static int __end_that_request_first(struct request *req, int error,rcu_read_lock_preempt (); part =disk_map_sector_rcu (req->rq_disk, req->sector); -all_stat_add (req->rq_disk, part, sectors[rw], - nr_bytes >>9 , req->sector); +part_stat_add (part, sectors[rw], nr_bytes >>9 );rcu_read_unlock_preempt (); }
@@ -1748,15 +1726,10 @@ static void end_that_request_last(struct request *req, int error)rcu_read_lock_preempt (); part =disk_map_sector_rcu (disk, req->sector); - -all_stat_inc (disk, part, ios[rw], req->sector); -all_stat_add (disk, part, ticks[rw], duration, req->sector); -disk_round_stats (disk); - disk->in_flight--; -if (part) { -part_round_stats (part); - part->in_flight--; - } +part_stat_inc (part, ios[rw]); +part_stat_add (part, ticks[rw], duration); +part_round_stats (part); +part_dec_in_flight (part);rcu_read_unlock_preempt (); }
block/blk-merge.c +2 -6
@@ -472,12 +472,8 @@ static int attempt_merge(struct request_queue *q, struct request *req,rcu_read_lock_preempt (); part =disk_map_sector_rcu (req->rq_disk, req->sector); -disk_round_stats (req->rq_disk); - req->rq_disk->in_flight--; -if (part) { -part_round_stats (part); - part->in_flight--; - } +part_round_stats (part); +part_dec_in_flight (part);rcu_read_unlock_preempt (); }
block/genhd.c +21 -69
154 lines not on this page · raw message
drivers/block/aoe/aoecmd.c +4 -4
@@ -760,10 +760,10 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sectorrcu_read_lock_preempt (); part =disk_map_sector_rcu (disk, sector); -all_stat_inc (disk, part, ios[rw], sector); -all_stat_add (disk, part, ticks[rw], duration, sector); -all_stat_add (disk, part, sectors[rw], n_sect, sector); -all_stat_add (disk, part, io_ticks, duration, sector); +part_stat_inc (part, ios[rw]); +part_stat_add (part, ticks[rw], duration); +part_stat_add (part, sectors[rw], n_sect); +part_stat_add (part, io_ticks, duration);rcu_read_unlock_preempt (); }
drivers/md/dm.c +8 -7
@@ -381,9 +381,9 @@ static void start_io_acct(struct dm_io *io) io->start_time = jiffies;preempt_disable (); -disk_round_stats (dm_disk (md)); +part_round_stats (&dm_disk (md)->part0);preempt_enable (); -dm_disk (md)->in_flight =atomic_inc_return (&md->pending); +dm_disk (md)->part0.in_flight =atomic_inc_return (&md->pending); }static int end_io_acct (struct dm_io *io)
@@ -395,11 +395,12 @@ static int end_io_acct(struct dm_io *io)int rw =bio_data_dir (bio);preempt_disable (); -disk_round_stats (dm_disk (md)); -disk_stat_add (dm_disk (md), ticks[rw], duration); +part_round_stats (&dm_disk (md)->part0); +part_stat_add (&dm_disk (md)->part0, ticks[rw], duration);preempt_enable (); -dm_disk (md)->in_flight = pending =atomic_dec_return (&md->pending); +dm_disk (md)->part0.in_flight = pending = +atomic_dec_return (&md->pending);return !pending; }
@@ -851,8 +852,8 @@ static int dm_request(struct request_queue *q, struct bio *bio)down_read (&md->io_lock);preempt_disable (); -disk_stat_inc (dm_disk (md), ios[rw]); -disk_stat_add (dm_disk (md), sectors[rw],bio_sectors (bio)); +part_stat_inc (&dm_disk (md)->part0, ios[rw]); +part_stat_add (&dm_disk (md)->part0, sectors[rw],bio_sectors (bio));preempt_enable ();/*
drivers/md/linear.c +2 -2
@@ -323,8 +323,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) }preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); tmp_dev =which_dev (mddev, bio->bi_sector);
drivers/md/md.c +2 -2
@@ -5395,8 +5395,8 @@ static int is_mddev_idle(mddev_t *mddev) idle =1 ;rdev_for_each (rdev, tmp, mddev) {struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events =disk_stat_read (disk, sectors[0 ]) + -disk_stat_read (disk, sectors[1 ]) - + curr_events =part_stat_read (&disk->part0, sectors[0 ]) + +part_stat_read (&disk->part0, sectors[1 ]) -atomic_read (&disk->sync_io);/* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and
drivers/md/multipath.c +2 -2
@@ -159,8 +159,8 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->mddev = mddev;preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); mp_bh->path =multipath_map (conf);
drivers/md/raid0.c +2 -2
@@ -404,8 +404,8 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) }preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); chunk_size = mddev->chunk_size >>10 ;
drivers/md/raid1.c +2 -2
@@ -805,8 +805,8 @@ static int make_request(struct request_queue *q, struct bio * bio) bitmap = mddev->bitmap;preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable ();/*
drivers/md/raid10.c +2 -2
@@ -839,8 +839,8 @@ static int make_request(struct request_queue *q, struct bio * bio)wait_barrier (conf);preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); r10_bio =mempool_alloc (conf->r10bio_pool,GFP_NOIO );
drivers/md/raid5.c +2 -2
@@ -3581,8 +3581,8 @@ static int make_request(struct request_queue *q, struct bio * bi)md_write_start (mddev, bi);preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bi)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bi));preempt_enable (); if (rw == READ &&
fs/partitions/check.c +4 -4
@@ -210,8 +210,8 @@ ssize_t part_size_show(struct device *dev,return sprintf (buf,"%llu\n" ,(unsigned long long )p->nr_sects); } -static ssize_t part_stat_show (struct device *dev, -struct device_attribute *attr,char *buf) +ssize_t part_stat_show (struct device *dev, +struct device_attribute *attr,char *buf) {struct hd_struct *p =dev_to_part (dev);
@@ -574,8 +574,8 @@ void del_gendisk(struct gendisk *disk)set_capacity (disk,0 ); disk->flags &= ~GENHD_FL_UP ;unlink_gendisk (disk); -disk_stat_set_all (disk,0 ); - disk->stamp =0 ; +part_stat_set_all (&disk->part0,0 ); + disk->part0.stamp =0 ;kobject_put (disk->part0.holder_dir);kobject_put (disk->slave_dir);
include/linux/genhd.h +42 -108
213 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 10/13 block: move stats from disk to part0
In reply to Tejun HeoMove stats related fields - stamp, in_flight, dkstats - from disk to part0 and unify stat handling such that...
* part_stat_*() now updates part0 together if the specified partition is not part0. ie. part_stat_*() are now essentially all_stat_*().
* {disk|all}_stat_*() are gone.
* part_round_stats() is updated similary. It handles part0 stats automatically and disk_round_stats() is killed.
* part_{inc|dec}_in_fligh() is implemented which automatically updates part0 stats for parts other than part0.
* disk_map_sector_rcu() is updated to return part0 if no part matches. Combined with the above changes, this makes NULL special case handling in callers unnecessary.
* Separate stats show code paths for disk are collapsed into part stats show code paths.
--- block/blk-core.c | 79 ++++++++---------------- block/blk-merge.c | 8 +-- block/genhd.c | 90 ++++++-------------------- drivers/block/aoe/aoecmd.c | 8 +- drivers/md/dm.c | 15 +++-- drivers/md/linear.c | 4 +- drivers/md/md.c | 4 +- drivers/md/multipath.c | 4 +- drivers/md/raid0.c | 4 +- drivers/md/raid1.c | 4 +- drivers/md/raid10.c | 4 +- drivers/md/raid5.c | 4 +- fs/partitions/check.c | 8 +- include/linux/genhd.h | 150 ++++++++++++------------------------------- 14 files changed, 121 insertions(+), 265 deletions(-)
block/blk-core.c +26 -53
@@ -64,14 +64,10 @@ static void drive_stat_acct(struct request *rq, int new_io) part =disk_map_sector_rcu (rq->rq_disk, rq->sector);if (!new_io) -all_stat_inc (rq->rq_disk, part, merges[rw], rq->sector); +part_stat_inc (part, merges[rw]);else { -disk_round_stats (rq->rq_disk); - rq->rq_disk->in_flight++; -if (part) { -part_round_stats (part); - part->in_flight++; - } +part_round_stats (part); +part_inc_in_flight (part); }rcu_read_unlock_preempt ();
@@ -966,8 +962,21 @@ static inline void add_request(struct request_queue *q, struct request *req)__elv_add_request (q, req,ELEVATOR_INSERT_SORT ,0 ); } +static void part_round_stats_single (struct hd_struct *part,unsigned long now) +{ +if (now == part->stamp) +return ; + +if (part->in_flight) { +__part_stat_add (part, time_in_queue, + part->in_flight * (now - part->stamp)); +__part_stat_add (part, io_ticks, (now - part->stamp)); + } + part->stamp = now; +} +/** -* disk_round_stats() - Round off the performance stats on a struct +* part_round_stats() - Round off the performance stats on a struct * disk_stats. * * The average IO queue length and utilisation statistics are maintained
@@ -984,45 +993,15 @@ static inline void add_request(struct request_queue *q, struct request *req)* CONTEXT: * Preemption disabled. */ -void disk_round_stats (struct gendisk *disk) -{ -unsigned long now = jiffies; - -if (now == disk->stamp) -return ; - -if (disk->in_flight) { -disk_stat_add (disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); -disk_stat_add (disk, io_ticks, (now - disk->stamp)); - } - disk->stamp = now; -} -EXPORT_SYMBOL_GPL (disk_round_stats); - -/** -* part_round_stats() - Round off the performance stats on a struct -* disk_stats. -* -* Please see disk_round_stats() for more information. -* -* CONTEXT: -* Preemption disabled. -*/ void part_round_stats (struct hd_struct *part) {unsigned long now = jiffies; -if (now == part->stamp) -return ; - -if (part->in_flight) { -part_stat_add (part, time_in_queue, - part->in_flight * (now - part->stamp)); -part_stat_add (part, io_ticks, (now - part->stamp)); - } - part->stamp = now; +if (part->partno) +part_round_stats_single (&part_to_disk (part)->part0, now); +part_round_stats_single (part, now); } +EXPORT_SYMBOL_GPL (part_round_stats);/* * queue lock must be held
@@ -1557,8 +1536,7 @@ static int __end_that_request_first(struct request *req, int error,rcu_read_lock_preempt (); part =disk_map_sector_rcu (req->rq_disk, req->sector); -all_stat_add (req->rq_disk, part, sectors[rw], - nr_bytes >>9 , req->sector); +part_stat_add (part, sectors[rw], nr_bytes >>9 );rcu_read_unlock_preempt (); }
@@ -1748,15 +1726,10 @@ static void end_that_request_last(struct request *req, int error)rcu_read_lock_preempt (); part =disk_map_sector_rcu (disk, req->sector); - -all_stat_inc (disk, part, ios[rw], req->sector); -all_stat_add (disk, part, ticks[rw], duration, req->sector); -disk_round_stats (disk); - disk->in_flight--; -if (part) { -part_round_stats (part); - part->in_flight--; - } +part_stat_inc (part, ios[rw]); +part_stat_add (part, ticks[rw], duration); +part_round_stats (part); +part_dec_in_flight (part);rcu_read_unlock_preempt (); }
block/blk-merge.c +2 -6
@@ -472,12 +472,8 @@ static int attempt_merge(struct request_queue *q, struct request *req,rcu_read_lock_preempt (); part =disk_map_sector_rcu (req->rq_disk, req->sector); -disk_round_stats (req->rq_disk); - req->rq_disk->in_flight--; -if (part) { -part_round_stats (part); - part->in_flight--; - } +part_round_stats (part); +part_dec_in_flight (part);rcu_read_unlock_preempt (); }
block/genhd.c +21 -69
154 lines not on this page · raw message
drivers/block/aoe/aoecmd.c +4 -4
@@ -760,10 +760,10 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sectorrcu_read_lock_preempt (); part =disk_map_sector_rcu (disk, sector); -all_stat_inc (disk, part, ios[rw], sector); -all_stat_add (disk, part, ticks[rw], duration, sector); -all_stat_add (disk, part, sectors[rw], n_sect, sector); -all_stat_add (disk, part, io_ticks, duration, sector); +part_stat_inc (part, ios[rw]); +part_stat_add (part, ticks[rw], duration); +part_stat_add (part, sectors[rw], n_sect); +part_stat_add (part, io_ticks, duration);rcu_read_unlock_preempt (); }
drivers/md/dm.c +8 -7
@@ -381,9 +381,9 @@ static void start_io_acct(struct dm_io *io) io->start_time = jiffies;preempt_disable (); -disk_round_stats (dm_disk (md)); +part_round_stats (&dm_disk (md)->part0);preempt_enable (); -dm_disk (md)->in_flight =atomic_inc_return (&md->pending); +dm_disk (md)->part0.in_flight =atomic_inc_return (&md->pending); }static int end_io_acct (struct dm_io *io)
@@ -395,11 +395,12 @@ static int end_io_acct(struct dm_io *io)int rw =bio_data_dir (bio);preempt_disable (); -disk_round_stats (dm_disk (md)); -disk_stat_add (dm_disk (md), ticks[rw], duration); +part_round_stats (&dm_disk (md)->part0); +part_stat_add (&dm_disk (md)->part0, ticks[rw], duration);preempt_enable (); -dm_disk (md)->in_flight = pending =atomic_dec_return (&md->pending); +dm_disk (md)->part0.in_flight = pending = +atomic_dec_return (&md->pending);return !pending; }
@@ -851,8 +852,8 @@ static int dm_request(struct request_queue *q, struct bio *bio)down_read (&md->io_lock);preempt_disable (); -disk_stat_inc (dm_disk (md), ios[rw]); -disk_stat_add (dm_disk (md), sectors[rw],bio_sectors (bio)); +part_stat_inc (&dm_disk (md)->part0, ios[rw]); +part_stat_add (&dm_disk (md)->part0, sectors[rw],bio_sectors (bio));preempt_enable ();/*
drivers/md/linear.c +2 -2
@@ -323,8 +323,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) }preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); tmp_dev =which_dev (mddev, bio->bi_sector);
drivers/md/md.c +2 -2
@@ -5395,8 +5395,8 @@ static int is_mddev_idle(mddev_t *mddev) idle =1 ;rdev_for_each (rdev, tmp, mddev) {struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events =disk_stat_read (disk, sectors[0 ]) + -disk_stat_read (disk, sectors[1 ]) - + curr_events =part_stat_read (&disk->part0, sectors[0 ]) + +part_stat_read (&disk->part0, sectors[1 ]) -atomic_read (&disk->sync_io);/* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and
drivers/md/multipath.c +2 -2
@@ -159,8 +159,8 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->mddev = mddev;preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); mp_bh->path =multipath_map (conf);
drivers/md/raid0.c +2 -2
@@ -404,8 +404,8 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) }preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); chunk_size = mddev->chunk_size >>10 ;
drivers/md/raid1.c +2 -2
@@ -805,8 +805,8 @@ static int make_request(struct request_queue *q, struct bio * bio) bitmap = mddev->bitmap;preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable ();/*
drivers/md/raid10.c +2 -2
@@ -839,8 +839,8 @@ static int make_request(struct request_queue *q, struct bio * bio)wait_barrier (conf);preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bio)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bio));preempt_enable (); r10_bio =mempool_alloc (conf->r10bio_pool,GFP_NOIO );
drivers/md/raid5.c +2 -2
@@ -3581,8 +3581,8 @@ static int make_request(struct request_queue *q, struct bio * bi)md_write_start (mddev, bi);preempt_disable (); -disk_stat_inc (mddev->gendisk, ios[rw]); -disk_stat_add (mddev->gendisk, sectors[rw],bio_sectors (bi)); +part_stat_inc (&mddev->gendisk->part0, ios[rw]); +part_stat_add (&mddev->gendisk->part0, sectors[rw],bio_sectors (bi));preempt_enable (); if (rw == READ &&
fs/partitions/check.c +4 -4
@@ -210,8 +210,8 @@ ssize_t part_size_show(struct device *dev,return sprintf (buf,"%llu\n" ,(unsigned long long )p->nr_sects); } -static ssize_t part_stat_show (struct device *dev, -struct device_attribute *attr,char *buf) +ssize_t part_stat_show (struct device *dev, +struct device_attribute *attr,char *buf) {struct hd_struct *p =dev_to_part (dev);
@@ -574,8 +574,8 @@ void del_gendisk(struct gendisk *disk)set_capacity (disk,0 ); disk->flags &= ~GENHD_FL_UP ;unlink_gendisk (disk); -disk_stat_set_all (disk,0 ); - disk->stamp =0 ; +part_stat_set_all (&disk->part0,0 ); + disk->part0.stamp =0 ;kobject_put (disk->part0.holder_dir);kobject_put (disk->slave_dir);
include/linux/genhd.h +42 -108
213 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 11/13 block: make partition array dynamic
In reply to Tejun Heodisk->__part used to be statically allocated to the maximum possible number of partitions. This patch makes partition array allocation dynamic. The added overhead is minimal as only real change is one memory dereference changed to RCU one. This saves both a bit of memory and cpu cycles iterating through unoccupied slots and makes increasing partition limit easier.
--- block/genhd.c | 129 +++++++++++++++++++++++++++++++++++++++++-------- block/ioctl.c | 2 +- fs/partitions/check.c | 31 ++++++++++-- include/linux/genhd.h | 11 ++++- 4 files changed, 146 insertions(+), 27 deletions(-)
block/genhd.c +109 -20
@@ -52,14 +52,21 @@ static struct device_type disk_type;*/ struct hd_struct *disk_get_part (struct gendisk *disk,int partno) { -struct hd_struct *part; +struct hd_struct *part =NULL ; +struct disk_part_tbl *ptbl; -if (unlikely (partno <0 || partno >=disk_max_parts (disk))) +if (unlikely (partno <0 ))return NULL ; +rcu_read_lock (); - part =rcu_dereference (disk->__part[partno]); -if (part) -get_device (part_to_dev (part)); + + ptbl =rcu_dereference (disk->part_tbl); +if (likely (partno < ptbl->len)) { + part =rcu_dereference (ptbl->part[partno]); +if (part) +get_device (part_to_dev (part)); + } +rcu_read_unlock ();return part;
@@ -80,17 +87,24 @@ EXPORT_SYMBOL_GPL(disk_get_part);void disk_part_iter_start (struct disk_part_iter *piter,struct gendisk *disk,unsigned int flags) { +struct disk_part_tbl *ptbl; + +rcu_read_lock (); + ptbl =rcu_dereference (disk->part_tbl); + piter->disk = disk; piter->part =NULL ;if (flags &DISK_PITER_REVERSE ) - piter->idx =disk_max_parts (piter->disk) -1 ; + piter->idx = ptbl->len -1 ;else if (flags &DISK_PITER_INCL_PART0 ) piter->idx =0 ;else piter->idx =1 ; piter->flags = flags; + +rcu_read_unlock (); }EXPORT_SYMBOL_GPL (disk_part_iter_start);
@@ -105,13 +119,16 @@ EXPORT_SYMBOL_GPL(disk_part_iter_start);*/ struct hd_struct *disk_part_iter_next (struct disk_part_iter *piter) { +struct disk_part_tbl *ptbl;int inc, end;/* put the last partition */ disk_put_part (piter->part); piter->part =NULL ; +/* get part_tbl */ rcu_read_lock (); + ptbl =rcu_dereference (piter->disk->part_tbl);/* determine iteration parameters */ if (piter->flags &DISK_PITER_REVERSE ) {
@@ -122,14 +139,14 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) end =0 ; }else { inc =1 ; - end =disk_max_parts (piter->disk); + end = ptbl->len; }/* iterate to the next partition */ for (; piter->idx != end; piter->idx += inc) {struct hd_struct *part; - part =rcu_dereference (piter->disk->__part[piter->idx]); + part =rcu_dereference (ptbl->part[piter->idx]);if (!part)continue ;if (!(piter->flags &DISK_PITER_INCL_EMPTY ) && !part->nr_sects)
@@ -180,10 +197,13 @@ EXPORT_SYMBOL_GPL(disk_part_iter_stop);*/ struct hd_struct *disk_map_sector_rcu (struct gendisk *disk,sector_t sector) { +struct disk_part_tbl *ptbl;int i; -for (i =1 ; i <disk_max_parts (disk); i++) { -struct hd_struct *part =rcu_dereference (disk->__part[i]); + ptbl =rcu_dereference (disk->part_tbl); + +for (i =1 ; i < ptbl->len; i++) { +struct hd_struct *part =rcu_dereference (ptbl->part[i]);if (part && part->start_sect <= sector && sector < part->start_sect + part->nr_sects)
@@ -763,12 +783,86 @@ static struct attribute_group *disk_attr_groups[] = {NULL }; +static void disk_free_ptbl_rcu_cb (struct rcu_head *head) +{ +struct disk_part_tbl *ptbl = + container_of(head, struct disk_part_tbl, rcu_head); + +kfree (ptbl); +} + +/** +* disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way +* @disk: disk to replace part_tbl for +* @new_ptbl: new part_tbl to install +* +* Replace disk->part_tbl with @new_ptbl in RCU-safe way. The +* original ptbl is freed using RCU callback. +* +* LOCKING: +* Matching bd_mutx locked. +*/ +static void disk_replace_part_tbl (struct gendisk *disk, +struct disk_part_tbl *new_ptbl) +{ +struct disk_part_tbl *old_ptbl = disk->part_tbl; + +rcu_assign_pointer (disk->part_tbl, new_ptbl); +if (old_ptbl) +call_rcu (&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); +} + +/** +* disk_expand_part_tbl - expand disk->part_tbl +* @disk: disk to expand part_tbl for +* @partno: expand such that this partno can fit in +* +* Expand disk->part_tbl such that @partno can fit in. disk->part_tbl +* uses RCU to allow unlocked dereferencing for stats and other stuff. +* +* LOCKING: +* Matching bd_mutex locked, might sleep. +* +* RETURNS: +* 0 on success, -errno on failure. +*/ +int disk_expand_part_tbl (struct gendisk *disk,int partno) +{ +struct disk_part_tbl *old_ptbl = disk->part_tbl; +struct disk_part_tbl *new_ptbl; +int len = old_ptbl ? old_ptbl->len :0 ; +int target = partno +1 ; +size_t size; +int i; + +/* disk_max_parts() is zero during initialization, ignore if so */ +if (disk_max_parts (disk) && target >disk_max_parts (disk)) +return -EINVAL ; + +if (target <= len) +return 0 ; + + size =sizeof (*new_ptbl) + target *sizeof (new_ptbl->part[0 ]); + new_ptbl =kzalloc_node (size,GFP_KERNEL , disk->node_id); +if (!new_ptbl) +return -ENOMEM ; + +INIT_RCU_HEAD (&new_ptbl->rcu_head); + new_ptbl->len = target; + +for (i =0 ; i < len; i++) +rcu_assign_pointer (new_ptbl->part[i], old_ptbl->part[i]); + +disk_replace_part_tbl (disk, new_ptbl); +return 0 ; +} +static void disk_release (struct device *dev) {struct gendisk *disk =dev_to_disk (dev);kfree (disk->random); -kfree (disk->__part); +disk_replace_part_tbl (disk,NULL );free_part_stats (&disk->part0);kfree (disk); }
@@ -949,22 +1043,16 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk =kmalloc_node (sizeof (struct gendisk ),GFP_KERNEL | __GFP_ZERO, node_id);if (disk) { -int tot_minors = minors + ext_minors; -int size = tot_minors *sizeof (struct hd_struct *); -if (!init_part_stats (&disk->part0)) {kfree (disk);return NULL ; } - - disk->__part =kmalloc_node (size,GFP_KERNEL | __GFP_ZERO, - node_id); -if (!disk->__part) { -free_part_stats (&disk->part0); +if (disk_expand_part_tbl (disk,0 )) { +free_part_stats (&disk->part0);kfree (disk);return NULL ; } - disk->__part[0 ] = &disk->part0; + disk->part_tbl->part[0 ] = &disk->part0; disk->minors = minors; disk->ext_minors = ext_minors;
@@ -974,6 +1062,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id)device_initialize (disk_to_dev (disk));INIT_WORK (&disk->async_notify, media_change_notify_thread); + disk->node_id = node_id; }return disk; }
block/ioctl.c +1 -1
@@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __userif (bdev != bdev->bd_contains)return -EINVAL ; partno = p.pno; -if (partno <=0 || partno >=disk_max_parts (disk)) +if (partno <=0 )return -EINVAL ;switch (a.op) {case BLKPG_ADD_PARTITION :
fs/partitions/check.c +26 -5
@@ -325,14 +325,18 @@ static void delete_partition_rcu_cb(struct rcu_head *head)void delete_partition (struct gendisk *disk,int partno) { +struct disk_part_tbl *ptbl = disk->part_tbl;struct hd_struct *part; - part = disk->__part[partno]; +if (partno >= ptbl->len) +return ; + + part = ptbl->part[partno];if (!part)return ;blk_free_devt (part_devt (part)); -rcu_assign_pointer (disk->__part[partno],NULL ); +rcu_assign_pointer (ptbl->part[partno],NULL );kobject_put (part->holder_dir);device_del (part_to_dev (part));
@@ -354,10 +358,16 @@ int add_partition(struct gendisk *disk, int partno,dev_t devt =MKDEV (0 ,0 );struct device *ddev =disk_to_dev (disk);struct device *pdev; +struct disk_part_tbl *ptbl;const char *dname;int err; -if (disk->__part[partno]) { + err =disk_expand_part_tbl (disk, partno); +if (err) +return err; + ptbl = disk->part_tbl; + +if (ptbl->part[partno]) { err = -EBUSY ; goto fail; }
@@ -392,7 +402,7 @@ int add_partition(struct gendisk *disk, int partno, pdev->devt = devt;INIT_RCU_HEAD (&p->rcu_head); -rcu_assign_pointer (disk->__part[partno], p); +rcu_assign_pointer (ptbl->part[partno], p);/* delay uevent until 'holders' subdir is created */ pdev->uevent_suppress =1 ;
@@ -489,7 +499,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)struct disk_part_iter piter;struct hd_struct *part;struct parsed_partitions *state; -int p, res; +int p, highest, res;if (bdev->bd_part_count)return -EBUSY ;
@@ -513,6 +523,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)/* tell userspace that the media / partition table may have changed */ kobject_uevent (&disk_to_dev (disk)->kobj,KOBJ_CHANGE ); +/* Detect the highest partition number and preallocate +* disk->part_tbl. This is an optimization and not strictly +* necessary. +*/ +for (p =1 , highest =0 ; p < state->limit; p++) +if (state->parts[p].size) + highest = p; + +disk_expand_part_tbl (disk, highest); + +/* add partitions */ for (p =1 ; p < state->limit; p++) {sector_t size = state->parts[p].size;sector_t from = state->parts[p].from;
include/linux/genhd.h +10 -1
@@ -113,6 +113,12 @@ struct hd_struct {#define GENHD_FL_UP 16#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +struct disk_part_tbl { +struct rcu_head rcu_head; +int len; +struct hd_struct *part[]; +}; +struct gendisk {/* major, first_minor, minors and ext_minors are input * parameters only, don't use directly. Use disk_devt() and
@@ -131,7 +137,7 @@ struct gendisk {* non-critical accesses use RCU. Always access through * helpers. */ -struct hd_struct **__part; +struct disk_part_tbl *part_tbl;struct hd_struct part0;struct block_device_operations *fops;
@@ -146,6 +152,8 @@ struct gendisk {atomic_t sync_io;/* RAID */ struct work_struct async_notify; + +int node_id; };static inline struct gendisk *part_to_disk (struct hd_struct *part)
@@ -491,6 +499,7 @@ extern void blk_free_devt(dev_t devt);extern dev_t blk_lookup_devt (const char *name,int partno);extern char *disk_name (struct gendisk *hd,int partno,char *buf); +extern int disk_expand_part_tbl (struct gendisk *disk,int target);extern int rescan_partitions (struct gendisk *disk,struct block_device *bdev);extern int add_partition (struct gendisk *,int ,sector_t ,sector_t ,int );extern void delete_partition (struct gendisk *,int );
Signature · 1 line
1.5.4.5
PATCH 11/13 block: make partition array dynamic
In reply to Tejun Heodisk->__part used to be statically allocated to the maximum possible number of partitions. This patch makes partition array allocation dynamic. The added overhead is minimal as only real change is one memory dereference changed to RCU one. This saves both a bit of memory and cpu cycles iterating through unoccupied slots and makes increasing partition limit easier.
--- block/genhd.c | 129 +++++++++++++++++++++++++++++++++++++++++-------- block/ioctl.c | 2 +- fs/partitions/check.c | 31 ++++++++++-- include/linux/genhd.h | 11 ++++- 4 files changed, 146 insertions(+), 27 deletions(-)
block/genhd.c +109 -20
@@ -52,14 +52,21 @@ static struct device_type disk_type;*/ struct hd_struct *disk_get_part (struct gendisk *disk,int partno) { -struct hd_struct *part; +struct hd_struct *part =NULL ; +struct disk_part_tbl *ptbl; -if (unlikely (partno <0 || partno >=disk_max_parts (disk))) +if (unlikely (partno <0 ))return NULL ; +rcu_read_lock (); - part =rcu_dereference (disk->__part[partno]); -if (part) -get_device (part_to_dev (part)); + + ptbl =rcu_dereference (disk->part_tbl); +if (likely (partno < ptbl->len)) { + part =rcu_dereference (ptbl->part[partno]); +if (part) +get_device (part_to_dev (part)); + } +rcu_read_unlock ();return part;
@@ -80,17 +87,24 @@ EXPORT_SYMBOL_GPL(disk_get_part);void disk_part_iter_start (struct disk_part_iter *piter,struct gendisk *disk,unsigned int flags) { +struct disk_part_tbl *ptbl; + +rcu_read_lock (); + ptbl =rcu_dereference (disk->part_tbl); + piter->disk = disk; piter->part =NULL ;if (flags &DISK_PITER_REVERSE ) - piter->idx =disk_max_parts (piter->disk) -1 ; + piter->idx = ptbl->len -1 ;else if (flags &DISK_PITER_INCL_PART0 ) piter->idx =0 ;else piter->idx =1 ; piter->flags = flags; + +rcu_read_unlock (); }EXPORT_SYMBOL_GPL (disk_part_iter_start);
@@ -105,13 +119,16 @@ EXPORT_SYMBOL_GPL(disk_part_iter_start);*/ struct hd_struct *disk_part_iter_next (struct disk_part_iter *piter) { +struct disk_part_tbl *ptbl;int inc, end;/* put the last partition */ disk_put_part (piter->part); piter->part =NULL ; +/* get part_tbl */ rcu_read_lock (); + ptbl =rcu_dereference (piter->disk->part_tbl);/* determine iteration parameters */ if (piter->flags &DISK_PITER_REVERSE ) {
@@ -122,14 +139,14 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) end =0 ; }else { inc =1 ; - end =disk_max_parts (piter->disk); + end = ptbl->len; }/* iterate to the next partition */ for (; piter->idx != end; piter->idx += inc) {struct hd_struct *part; - part =rcu_dereference (piter->disk->__part[piter->idx]); + part =rcu_dereference (ptbl->part[piter->idx]);if (!part)continue ;if (!(piter->flags &DISK_PITER_INCL_EMPTY ) && !part->nr_sects)
@@ -180,10 +197,13 @@ EXPORT_SYMBOL_GPL(disk_part_iter_stop);*/ struct hd_struct *disk_map_sector_rcu (struct gendisk *disk,sector_t sector) { +struct disk_part_tbl *ptbl;int i; -for (i =1 ; i <disk_max_parts (disk); i++) { -struct hd_struct *part =rcu_dereference (disk->__part[i]); + ptbl =rcu_dereference (disk->part_tbl); + +for (i =1 ; i < ptbl->len; i++) { +struct hd_struct *part =rcu_dereference (ptbl->part[i]);if (part && part->start_sect <= sector && sector < part->start_sect + part->nr_sects)
@@ -763,12 +783,86 @@ static struct attribute_group *disk_attr_groups[] = {NULL }; +static void disk_free_ptbl_rcu_cb (struct rcu_head *head) +{ +struct disk_part_tbl *ptbl = + container_of(head, struct disk_part_tbl, rcu_head); + +kfree (ptbl); +} + +/** +* disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way +* @disk: disk to replace part_tbl for +* @new_ptbl: new part_tbl to install +* +* Replace disk->part_tbl with @new_ptbl in RCU-safe way. The +* original ptbl is freed using RCU callback. +* +* LOCKING: +* Matching bd_mutx locked. +*/ +static void disk_replace_part_tbl (struct gendisk *disk, +struct disk_part_tbl *new_ptbl) +{ +struct disk_part_tbl *old_ptbl = disk->part_tbl; + +rcu_assign_pointer (disk->part_tbl, new_ptbl); +if (old_ptbl) +call_rcu (&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); +} + +/** +* disk_expand_part_tbl - expand disk->part_tbl +* @disk: disk to expand part_tbl for +* @partno: expand such that this partno can fit in +* +* Expand disk->part_tbl such that @partno can fit in. disk->part_tbl +* uses RCU to allow unlocked dereferencing for stats and other stuff. +* +* LOCKING: +* Matching bd_mutex locked, might sleep. +* +* RETURNS: +* 0 on success, -errno on failure. +*/ +int disk_expand_part_tbl (struct gendisk *disk,int partno) +{ +struct disk_part_tbl *old_ptbl = disk->part_tbl; +struct disk_part_tbl *new_ptbl; +int len = old_ptbl ? old_ptbl->len :0 ; +int target = partno +1 ; +size_t size; +int i; + +/* disk_max_parts() is zero during initialization, ignore if so */ +if (disk_max_parts (disk) && target >disk_max_parts (disk)) +return -EINVAL ; + +if (target <= len) +return 0 ; + + size =sizeof (*new_ptbl) + target *sizeof (new_ptbl->part[0 ]); + new_ptbl =kzalloc_node (size,GFP_KERNEL , disk->node_id); +if (!new_ptbl) +return -ENOMEM ; + +INIT_RCU_HEAD (&new_ptbl->rcu_head); + new_ptbl->len = target; + +for (i =0 ; i < len; i++) +rcu_assign_pointer (new_ptbl->part[i], old_ptbl->part[i]); + +disk_replace_part_tbl (disk, new_ptbl); +return 0 ; +} +static void disk_release (struct device *dev) {struct gendisk *disk =dev_to_disk (dev);kfree (disk->random); -kfree (disk->__part); +disk_replace_part_tbl (disk,NULL );free_part_stats (&disk->part0);kfree (disk); }
@@ -949,22 +1043,16 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk =kmalloc_node (sizeof (struct gendisk ),GFP_KERNEL | __GFP_ZERO, node_id);if (disk) { -int tot_minors = minors + ext_minors; -int size = tot_minors *sizeof (struct hd_struct *); -if (!init_part_stats (&disk->part0)) {kfree (disk);return NULL ; } - - disk->__part =kmalloc_node (size,GFP_KERNEL | __GFP_ZERO, - node_id); -if (!disk->__part) { -free_part_stats (&disk->part0); +if (disk_expand_part_tbl (disk,0 )) { +free_part_stats (&disk->part0);kfree (disk);return NULL ; } - disk->__part[0 ] = &disk->part0; + disk->part_tbl->part[0 ] = &disk->part0; disk->minors = minors; disk->ext_minors = ext_minors;
@@ -974,6 +1062,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id)device_initialize (disk_to_dev (disk));INIT_WORK (&disk->async_notify, media_change_notify_thread); + disk->node_id = node_id; }return disk; }
block/ioctl.c +1 -1
@@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __userif (bdev != bdev->bd_contains)return -EINVAL ; partno = p.pno; -if (partno <=0 || partno >=disk_max_parts (disk)) +if (partno <=0 )return -EINVAL ;switch (a.op) {case BLKPG_ADD_PARTITION :
fs/partitions/check.c +26 -5
@@ -325,14 +325,18 @@ static void delete_partition_rcu_cb(struct rcu_head *head)void delete_partition (struct gendisk *disk,int partno) { +struct disk_part_tbl *ptbl = disk->part_tbl;struct hd_struct *part; - part = disk->__part[partno]; +if (partno >= ptbl->len) +return ; + + part = ptbl->part[partno];if (!part)return ;blk_free_devt (part_devt (part)); -rcu_assign_pointer (disk->__part[partno],NULL ); +rcu_assign_pointer (ptbl->part[partno],NULL );kobject_put (part->holder_dir);device_del (part_to_dev (part));
@@ -354,10 +358,16 @@ int add_partition(struct gendisk *disk, int partno,dev_t devt =MKDEV (0 ,0 );struct device *ddev =disk_to_dev (disk);struct device *pdev; +struct disk_part_tbl *ptbl;const char *dname;int err; -if (disk->__part[partno]) { + err =disk_expand_part_tbl (disk, partno); +if (err) +return err; + ptbl = disk->part_tbl; + +if (ptbl->part[partno]) { err = -EBUSY ; goto fail; }
@@ -392,7 +402,7 @@ int add_partition(struct gendisk *disk, int partno, pdev->devt = devt;INIT_RCU_HEAD (&p->rcu_head); -rcu_assign_pointer (disk->__part[partno], p); +rcu_assign_pointer (ptbl->part[partno], p);/* delay uevent until 'holders' subdir is created */ pdev->uevent_suppress =1 ;
@@ -489,7 +499,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)struct disk_part_iter piter;struct hd_struct *part;struct parsed_partitions *state; -int p, res; +int p, highest, res;if (bdev->bd_part_count)return -EBUSY ;
@@ -513,6 +523,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)/* tell userspace that the media / partition table may have changed */ kobject_uevent (&disk_to_dev (disk)->kobj,KOBJ_CHANGE ); +/* Detect the highest partition number and preallocate +* disk->part_tbl. This is an optimization and not strictly +* necessary. +*/ +for (p =1 , highest =0 ; p < state->limit; p++) +if (state->parts[p].size) + highest = p; + +disk_expand_part_tbl (disk, highest); + +/* add partitions */ for (p =1 ; p < state->limit; p++) {sector_t size = state->parts[p].size;sector_t from = state->parts[p].from;
include/linux/genhd.h +10 -1
@@ -113,6 +113,12 @@ struct hd_struct {#define GENHD_FL_UP 16#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +struct disk_part_tbl { +struct rcu_head rcu_head; +int len; +struct hd_struct *part[]; +}; +struct gendisk {/* major, first_minor, minors and ext_minors are input * parameters only, don't use directly. Use disk_devt() and
@@ -131,7 +137,7 @@ struct gendisk {* non-critical accesses use RCU. Always access through * helpers. */ -struct hd_struct **__part; +struct disk_part_tbl *part_tbl;struct hd_struct part0;struct block_device_operations *fops;
@@ -146,6 +152,8 @@ struct gendisk {atomic_t sync_io;/* RAID */ struct work_struct async_notify; + +int node_id; };static inline struct gendisk *part_to_disk (struct hd_struct *part)
@@ -491,6 +499,7 @@ extern void blk_free_devt(dev_t devt);extern dev_t blk_lookup_devt (const char *name,int partno);extern char *disk_name (struct gendisk *hd,int partno,char *buf); +extern int disk_expand_part_tbl (struct gendisk *disk,int target);extern int rescan_partitions (struct gendisk *disk,struct block_device *bdev);extern int add_partition (struct gendisk *,int ,sector_t ,sector_t ,int );extern void delete_partition (struct gendisk *,int );
Signature · 1 line
1.5.4.5
PATCH 12/13 block: replace @ext_minors with GENHD_FL_EXT_DEVT
In reply to Tejun HeoWith previous changes, it's meaningless to limit the number of partitions. Replace @ext_minors with GENHD_FL_EXT_DEVT such that setting the flag allows the disk to have maximum number of allowed partitions (only limited by the number of entries in parsed_partitions as determined by MAX_PART constant).
This kills not-too-pretty alloc_disk_ext[_node]() functions and makes @minors parameter to alloc_disk[_node]() unnecessary. The parameter is left alone to avoid disturbing the users.
--- block/genhd.c | 16 +--------------- drivers/ide/ide-disk.c | 14 +++++--------- drivers/scsi/sd.c | 9 ++------- fs/partitions/check.h | 4 +--- include/linux/genhd.h | 16 ++++++++-------- 5 files changed, 17 insertions(+), 42 deletions(-)
block/genhd.c +1 -15
@@ -1025,19 +1025,10 @@ struct gendisk *alloc_disk(int minors) {return alloc_disk_node (minors,-1 ); } +EXPORT_SYMBOL (alloc_disk);struct gendisk *alloc_disk_node (int minors,int node_id) { -return alloc_disk_ext_node (minors,0 , node_id); -} - -struct gendisk *alloc_disk_ext (int minors,int ext_minors) -{ -return alloc_disk_ext_node (minors, ext_minors,-1 ); -} - -struct gendisk *alloc_disk_ext_node (int minors,int ext_minors,int node_id) -{struct gendisk *disk; disk = kmalloc_node(sizeof(struct gendisk),
@@ -1055,7 +1046,6 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->part_tbl->part[0 ] = &disk->part0; disk->minors = minors; - disk->ext_minors = ext_minors;rand_initialize_disk (disk);disk_to_dev (disk)->class = &block_class;disk_to_dev (disk)->type = &disk_type;
@@ -1066,11 +1056,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) }return disk; } - -EXPORT_SYMBOL (alloc_disk);EXPORT_SYMBOL (alloc_disk_node); -EXPORT_SYMBOL (alloc_disk_ext); -EXPORT_SYMBOL (alloc_disk_ext_node);struct kobject *get_disk (struct gendisk *disk) {
drivers/ide/ide-disk.c +5 -9
@@ -41,16 +41,12 @@#include <asm/io.h> #include <asm/div64.h> -#define IDE_DISK_PARTS (1 << PARTN_BITS) -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT ) -#define IDE_DISK_MINORS IDE_DISK_PARTS +#define IDE_DISK_MINORS (1 << PARTN_BITS)#else #define IDE_DISK_MINORS 1#endif -#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) -struct ide_disk_obj {ide_drive_t *drive;ide_driver_t *driver;
@@ -1168,8 +1164,7 @@ static int ide_disk_probe(ide_drive_t *drive)if (!idkp) goto failed; - g =alloc_disk_ext_node (IDE_DISK_MINORS ,IDE_DISK_EXT_MINORS , -hwif_to_node (drive->hwif)); + g =alloc_disk_node (IDE_DISK_MINORS ,hwif_to_node (drive->hwif));if (!g) goto out_free_idkp;
@@ -1196,9 +1191,10 @@ static int ide_disk_probe(ide_drive_t *drive) drive->attach =1 ; g->minors =IDE_DISK_MINORS ; - g->ext_minors =IDE_DISK_EXT_MINORS ; g->driverfs_dev = &drive->gendev; - g->flags = drive->removable ?GENHD_FL_REMOVABLE :0 ; + g->flags |=GENHD_FL_EXT_DEVT ; +if (drive->removable) + g->flags |=GENHD_FL_REMOVABLE ;set_capacity (g,idedisk_capacity (drive)); g->fops = &idedisk_ops;add_disk (g);
drivers/scsi/sd.c +2 -7
@@ -86,16 +86,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);MODULE_ALIAS_SCSI_DEVICE (TYPE_MOD );MODULE_ALIAS_SCSI_DEVICE (TYPE_RBC ); -#define SD_PARTS 64 -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT )#define SD_MINORS 16#else #define SD_MINORS 1#endif -#define SD_EXT_MINORS (SD_PARTS - SD_MINORS) -static int sd_revalidate_disk (struct gendisk *);static int sd_probe (struct device *);static int sd_remove (struct device *);
@@ -1651,7 +1647,7 @@ static int sd_probe(struct device *dev)if (!sdkp) goto out; - gd =alloc_disk_ext (SD_MINORS ,SD_EXT_MINORS ); + gd =alloc_disk (SD_MINORS );if (!gd) goto out_free;
@@ -1696,7 +1692,6 @@ static int sd_probe(struct device *dev) gd->major =sd_major ((index &0xf0 ) >>4 ); gd->first_minor = ((index &0xf ) <<4 ) | (index &0xfff00 ); gd->minors =SD_MINORS ; - gd->ext_minors =SD_EXT_MINORS ; gd->fops = &sd_fops;if (index <26 ) {
@@ -1720,7 +1715,7 @@ static int sd_probe(struct device *dev)blk_queue_prep_rq (sdp->request_queue, sd_prep_fn); gd->driverfs_dev = &sdp->sdev_gendev; - gd->flags =GENHD_FL_DRIVERFS ; + gd->flags =GENHD_FL_EXT_DEVT |GENHD_FL_DRIVERFS ;if (sdp->removable) gd->flags |=GENHD_FL_REMOVABLE ;
fs/partitions/check.h +1 -3
@@ -5,15 +5,13 @@* add_gd_partition adds a partitions details to the devices partition * description. */ -enum {MAX_PART =256 }; -struct parsed_partitions {char name[BDEVNAME_SIZE ];struct {sector_t from;sector_t size;int flags; - } parts[MAX_PART ]; + } parts[DISK_MAX_PARTS ];int next;int limit; };
include/linux/genhd.h +8 -8
@@ -58,6 +58,8 @@ enum { UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ }; +#define DISK_MAX_PARTS 256 +#include <linux/major.h> #include <linux/device.h> #include <linux/smp.h>
@@ -112,6 +114,7 @@ struct hd_struct {#define GENHD_FL_CD 8#define GENHD_FL_UP 16#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +#define GENHD_FL_EXT_DEVT 64/* allow extended devt */ struct disk_part_tbl {struct rcu_head rcu_head;
@@ -120,15 +123,13 @@ struct disk_part_tbl { };struct gendisk { -/* major, first_minor, minors and ext_minors are input -* parameters only, don't use directly. Use disk_devt() and -* disk_max_parts(). +/* major, first_minor and minors are input parameters only, +* don't use directly. Use disk_devt() and disk_max_parts(). */ int major;/* major number of driver */ int first_minor;int minors;/* maximum number of minors, =1 for * disks that can't be partitioned. */ -int ext_minors;/* number of extended dynamic minors */ char disk_name[32 ];/* name of major driver */
@@ -169,7 +170,9 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part)static inline int disk_max_parts (struct gendisk *disk) { -return disk->minors + disk->ext_minors; +if (disk->flags &GENHD_FL_EXT_DEVT ) +return DISK_MAX_PARTS ; +return disk->minors; }static inline bool disk_partitionable (struct gendisk *disk)
@@ -507,9 +510,6 @@ extern void printk_all_partitions(void);extern struct gendisk *alloc_disk_node (int minors,int node_id);extern struct gendisk *alloc_disk (int minors); -extern struct gendisk *alloc_disk_ext_node (int minors,int ext_minrs, -int node_id); -extern struct gendisk *alloc_disk_ext (int minors,int ext_minors);extern struct kobject *get_disk (struct gendisk *disk);extern void put_disk (struct gendisk *disk); extern void blk_register_region(dev_t devt, unsigned long range,
Signature · 1 line
1.5.4.5
PATCH 12/13 block: replace @ext_minors with GENHD_FL_EXT_DEVT
In reply to Tejun HeoWith previous changes, it's meaningless to limit the number of partitions. Replace @ext_minors with GENHD_FL_EXT_DEVT such that setting the flag allows the disk to have maximum number of allowed partitions (only limited by the number of entries in parsed_partitions as determined by MAX_PART constant).
This kills not-too-pretty alloc_disk_ext[_node]() functions and makes @minors parameter to alloc_disk[_node]() unnecessary. The parameter is left alone to avoid disturbing the users.
--- block/genhd.c | 16 +--------------- drivers/ide/ide-disk.c | 14 +++++--------- drivers/scsi/sd.c | 9 ++------- fs/partitions/check.h | 4 +--- include/linux/genhd.h | 16 ++++++++-------- 5 files changed, 17 insertions(+), 42 deletions(-)
block/genhd.c +1 -15
@@ -1025,19 +1025,10 @@ struct gendisk *alloc_disk(int minors) {return alloc_disk_node (minors,-1 ); } +EXPORT_SYMBOL (alloc_disk);struct gendisk *alloc_disk_node (int minors,int node_id) { -return alloc_disk_ext_node (minors,0 , node_id); -} - -struct gendisk *alloc_disk_ext (int minors,int ext_minors) -{ -return alloc_disk_ext_node (minors, ext_minors,-1 ); -} - -struct gendisk *alloc_disk_ext_node (int minors,int ext_minors,int node_id) -{struct gendisk *disk; disk = kmalloc_node(sizeof(struct gendisk),
@@ -1055,7 +1046,6 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->part_tbl->part[0 ] = &disk->part0; disk->minors = minors; - disk->ext_minors = ext_minors;rand_initialize_disk (disk);disk_to_dev (disk)->class = &block_class;disk_to_dev (disk)->type = &disk_type;
@@ -1066,11 +1056,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) }return disk; } - -EXPORT_SYMBOL (alloc_disk);EXPORT_SYMBOL (alloc_disk_node); -EXPORT_SYMBOL (alloc_disk_ext); -EXPORT_SYMBOL (alloc_disk_ext_node);struct kobject *get_disk (struct gendisk *disk) {
drivers/ide/ide-disk.c +5 -9
@@ -41,16 +41,12 @@#include <asm/io.h> #include <asm/div64.h> -#define IDE_DISK_PARTS (1 << PARTN_BITS) -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT ) -#define IDE_DISK_MINORS IDE_DISK_PARTS +#define IDE_DISK_MINORS (1 << PARTN_BITS)#else #define IDE_DISK_MINORS 1#endif -#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) -struct ide_disk_obj {ide_drive_t *drive;ide_driver_t *driver;
@@ -1168,8 +1164,7 @@ static int ide_disk_probe(ide_drive_t *drive)if (!idkp) goto failed; - g =alloc_disk_ext_node (IDE_DISK_MINORS ,IDE_DISK_EXT_MINORS , -hwif_to_node (drive->hwif)); + g =alloc_disk_node (IDE_DISK_MINORS ,hwif_to_node (drive->hwif));if (!g) goto out_free_idkp;
@@ -1196,9 +1191,10 @@ static int ide_disk_probe(ide_drive_t *drive) drive->attach =1 ; g->minors =IDE_DISK_MINORS ; - g->ext_minors =IDE_DISK_EXT_MINORS ; g->driverfs_dev = &drive->gendev; - g->flags = drive->removable ?GENHD_FL_REMOVABLE :0 ; + g->flags |=GENHD_FL_EXT_DEVT ; +if (drive->removable) + g->flags |=GENHD_FL_REMOVABLE ;set_capacity (g,idedisk_capacity (drive)); g->fops = &idedisk_ops;add_disk (g);
drivers/scsi/sd.c +2 -7
@@ -86,16 +86,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);MODULE_ALIAS_SCSI_DEVICE (TYPE_MOD );MODULE_ALIAS_SCSI_DEVICE (TYPE_RBC ); -#define SD_PARTS 64 -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT )#define SD_MINORS 16#else #define SD_MINORS 1#endif -#define SD_EXT_MINORS (SD_PARTS - SD_MINORS) -static int sd_revalidate_disk (struct gendisk *);static int sd_probe (struct device *);static int sd_remove (struct device *);
@@ -1651,7 +1647,7 @@ static int sd_probe(struct device *dev)if (!sdkp) goto out; - gd =alloc_disk_ext (SD_MINORS ,SD_EXT_MINORS ); + gd =alloc_disk (SD_MINORS );if (!gd) goto out_free;
@@ -1696,7 +1692,6 @@ static int sd_probe(struct device *dev) gd->major =sd_major ((index &0xf0 ) >>4 ); gd->first_minor = ((index &0xf ) <<4 ) | (index &0xfff00 ); gd->minors =SD_MINORS ; - gd->ext_minors =SD_EXT_MINORS ; gd->fops = &sd_fops;if (index <26 ) {
@@ -1720,7 +1715,7 @@ static int sd_probe(struct device *dev)blk_queue_prep_rq (sdp->request_queue, sd_prep_fn); gd->driverfs_dev = &sdp->sdev_gendev; - gd->flags =GENHD_FL_DRIVERFS ; + gd->flags =GENHD_FL_EXT_DEVT |GENHD_FL_DRIVERFS ;if (sdp->removable) gd->flags |=GENHD_FL_REMOVABLE ;
fs/partitions/check.h +1 -3
@@ -5,15 +5,13 @@* add_gd_partition adds a partitions details to the devices partition * description. */ -enum {MAX_PART =256 }; -struct parsed_partitions {char name[BDEVNAME_SIZE ];struct {sector_t from;sector_t size;int flags; - } parts[MAX_PART ]; + } parts[DISK_MAX_PARTS ];int next;int limit; };
include/linux/genhd.h +8 -8
@@ -58,6 +58,8 @@ enum { UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ }; +#define DISK_MAX_PARTS 256 +#include <linux/major.h> #include <linux/device.h> #include <linux/smp.h>
@@ -112,6 +114,7 @@ struct hd_struct {#define GENHD_FL_CD 8#define GENHD_FL_UP 16#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +#define GENHD_FL_EXT_DEVT 64/* allow extended devt */ struct disk_part_tbl {struct rcu_head rcu_head;
@@ -120,15 +123,13 @@ struct disk_part_tbl { };struct gendisk { -/* major, first_minor, minors and ext_minors are input -* parameters only, don't use directly. Use disk_devt() and -* disk_max_parts(). +/* major, first_minor and minors are input parameters only, +* don't use directly. Use disk_devt() and disk_max_parts(). */ int major;/* major number of driver */ int first_minor;int minors;/* maximum number of minors, =1 for * disks that can't be partitioned. */ -int ext_minors;/* number of extended dynamic minors */ char disk_name[32 ];/* name of major driver */
@@ -169,7 +170,9 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part)static inline int disk_max_parts (struct gendisk *disk) { -return disk->minors + disk->ext_minors; +if (disk->flags &GENHD_FL_EXT_DEVT ) +return DISK_MAX_PARTS ; +return disk->minors; }static inline bool disk_partitionable (struct gendisk *disk)
@@ -507,9 +510,6 @@ extern void printk_all_partitions(void);extern struct gendisk *alloc_disk_node (int minors,int node_id);extern struct gendisk *alloc_disk (int minors); -extern struct gendisk *alloc_disk_ext_node (int minors,int ext_minrs, -int node_id); -extern struct gendisk *alloc_disk_ext (int minors,int ext_minors);extern struct kobject *get_disk (struct gendisk *disk);extern void put_disk (struct gendisk *disk); extern void blk_register_region(dev_t devt, unsigned long range,
Signature · 1 line
1.5.4.5
PATCH 13/13 block: allow disk to have extended device number
In reply to Tejun HeoNow that disk and partition handlings are mostly unified, it's easy to allow disk to have extended device number. This patch makes add_disk() use extended device number if disk->minors is zero. Both sd and ide-disk are updated to use this.
* sd_format_disk_name() is implemented which can generically determine the drive name. This removes disk number restriction stemming from limited device names.
* If sd index goes over SD_MAX_DISKS (which can be increased now BTW), sd simply doesn't initialize minors letting block layer choose extended device number.
* If CONFIG_DEBUG_EXT_DEVT is set, both sd and ide-disk always set minors to 0 and use extended device numbers.
--- block/genhd.c | 29 ++++++++++++++++++- drivers/ide/ide-disk.c | 2 +- drivers/scsi/sd.c | 74 +++++++++++++++++++++++++++++++++++------------- fs/partitions/check.c | 1 + include/linux/genhd.h | 3 +- 5 files changed, 86 insertions(+), 23 deletions(-)
block/genhd.c +28 -1
@@ -477,13 +477,40 @@ static int exact_lock(dev_t devt, void *data)* * This function registers the partitioning information in @disk * with the kernel. +* +* FIXME: error handling */ void add_disk (struct gendisk *disk) {struct backing_dev_info *bdi; +dev_t devt; +int rc; + +/* minors == 0 indicates to use ext devt from part0 and should +* be accompanied with EXT_DEVT flag. Make sure all +* parameters make sense. +*/ +WARN_ON (disk->minors && !(disk->major || disk->first_minor)); +WARN_ON (!disk->minors && !(disk->flags &GENHD_FL_EXT_DEVT )); disk->flags |=GENHD_FL_UP ; -disk_to_dev (disk)->devt =MKDEV (disk->major, disk->first_minor); + +if (disk->minors) + devt =MKDEV (disk->major, disk->first_minor); +else { + rc =blk_alloc_devt (&disk->part0, &devt); +if (rc) +return ; + +/* ->major and ->first_minor aren't supposed to be +* referenced from here on, but set them just in case. +*/ + disk->major =MAJOR (devt); + disk->first_minor =MINOR (devt); + } + +disk_to_dev (disk)->devt = devt; +blk_register_region (disk_devt (disk), disk->minors,NULL , exact_match, exact_lock, disk);register_disk (disk);
drivers/ide/ide-disk.c +1 -1
@@ -44,7 +44,7 @@#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT )#define IDE_DISK_MINORS (1 << PARTN_BITS)#else -#define IDE_DISK_MINORS 1 +#define IDE_DISK_MINORS 0#endif struct ide_disk_obj {
drivers/scsi/sd.c +54 -20
99 lines not on this page · raw message
fs/partitions/check.c +1 -0
@@ -592,6 +592,7 @@ void del_gendisk(struct gendisk *disk)delete_partition (disk, part->partno); }invalidate_partition (disk,0 ); +blk_free_devt (disk_to_dev (disk)->devt);set_capacity (disk,0 ); disk->flags &= ~GENHD_FL_UP ;unlink_gendisk (disk);
include/linux/genhd.h +2 -1
@@ -59,6 +59,7 @@ enum { };#define DISK_MAX_PARTS 256 +#define DISK_NAME_LEN 32#include <linux/major.h> #include <linux/device.h>
@@ -131,7 +132,7 @@ struct gendisk {int minors;/* maximum number of minors, =1 for * disks that can't be partitioned. */ -char disk_name[32 ];/* name of major driver */ +char disk_name[DISK_NAME_LEN ];/* name of major driver */ /* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other
Signature · 1 line
1.5.4.5
PATCH 13/13 block: allow disk to have extended device number
In reply to Tejun HeoNow that disk and partition handlings are mostly unified, it's easy to allow disk to have extended device number. This patch makes add_disk() use extended device number if disk->minors is zero. Both sd and ide-disk are updated to use this.
* sd_format_disk_name() is implemented which can generically determine the drive name. This removes disk number restriction stemming from limited device names.
* If sd index goes over SD_MAX_DISKS (which can be increased now BTW), sd simply doesn't initialize minors letting block layer choose extended device number.
* If CONFIG_DEBUG_EXT_DEVT is set, both sd and ide-disk always set minors to 0 and use extended device numbers.
--- block/genhd.c | 29 ++++++++++++++++++- drivers/ide/ide-disk.c | 2 +- drivers/scsi/sd.c | 74 +++++++++++++++++++++++++++++++++++------------- fs/partitions/check.c | 1 + include/linux/genhd.h | 3 +- 5 files changed, 86 insertions(+), 23 deletions(-)
block/genhd.c +28 -1
@@ -477,13 +477,40 @@ static int exact_lock(dev_t devt, void *data)* * This function registers the partitioning information in @disk * with the kernel. +* +* FIXME: error handling */ void add_disk (struct gendisk *disk) {struct backing_dev_info *bdi; +dev_t devt; +int rc; + +/* minors == 0 indicates to use ext devt from part0 and should +* be accompanied with EXT_DEVT flag. Make sure all +* parameters make sense. +*/ +WARN_ON (disk->minors && !(disk->major || disk->first_minor)); +WARN_ON (!disk->minors && !(disk->flags &GENHD_FL_EXT_DEVT )); disk->flags |=GENHD_FL_UP ; -disk_to_dev (disk)->devt =MKDEV (disk->major, disk->first_minor); + +if (disk->minors) + devt =MKDEV (disk->major, disk->first_minor); +else { + rc =blk_alloc_devt (&disk->part0, &devt); +if (rc) +return ; + +/* ->major and ->first_minor aren't supposed to be +* referenced from here on, but set them just in case. +*/ + disk->major =MAJOR (devt); + disk->first_minor =MINOR (devt); + } + +disk_to_dev (disk)->devt = devt; +blk_register_region (disk_devt (disk), disk->minors,NULL , exact_match, exact_lock, disk);register_disk (disk);
drivers/ide/ide-disk.c +1 -1
@@ -44,7 +44,7 @@#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT )#define IDE_DISK_MINORS (1 << PARTN_BITS)#else -#define IDE_DISK_MINORS 1 +#define IDE_DISK_MINORS 0#endif struct ide_disk_obj {
drivers/scsi/sd.c +54 -20
99 lines not on this page · raw message
fs/partitions/check.c +1 -0
@@ -592,6 +592,7 @@ void del_gendisk(struct gendisk *disk)delete_partition (disk, part->partno); }invalidate_partition (disk,0 ); +blk_free_devt (disk_to_dev (disk)->devt);set_capacity (disk,0 ); disk->flags &= ~GENHD_FL_UP ;unlink_gendisk (disk);
include/linux/genhd.h +2 -1
@@ -59,6 +59,7 @@ enum { };#define DISK_MAX_PARTS 256 +#define DISK_NAME_LEN 32#include <linux/major.h> #include <linux/device.h>
@@ -131,7 +132,7 @@ struct gendisk {int minors;/* maximum number of minors, =1 for * disks that can't be partitioned. */ -char disk_name[32 ];/* name of major driver */ +char disk_name[DISK_NAME_LEN ];/* name of major driver */ /* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other
Signature · 1 line
1.5.4.5