aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-14 16:32:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-14 16:32:07 -0500
commit6ab82196492a0b6968a654a06aae923b28afef0d (patch)
tree8affe1097bba194fe677d5399f47693dc0363dd8
parent6f7f7caab259026234277b659485d22c1dcb1ab4 (diff)
parent49731baa41df404c2c3f44555869ab387363af43 (diff)
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block: block: restore multiple bd_link_disk_holder() support block cfq: compensate preempted queue even if it has no slice assigned block cfq: make queue preempt work for queues from different workload
-rw-r--r--block/cfq-iosched.c28
-rw-r--r--drivers/md/dm-table.c1
-rw-r--r--drivers/md/md.c1
-rw-r--r--fs/block_dev.c93
-rw-r--r--include/linux/fs.h8
5 files changed, 108 insertions, 23 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 8427697c5437..501ffdf0399c 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -598,8 +598,8 @@ cfq_group_slice(struct cfq_data *cfqd, struct cfq_group *cfqg)
598 return cfq_target_latency * cfqg->weight / st->total_weight; 598 return cfq_target_latency * cfqg->weight / st->total_weight;
599} 599}
600 600
601static inline void 601static inline unsigned
602cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) 602cfq_scaled_group_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
603{ 603{
604 unsigned slice = cfq_prio_to_slice(cfqd, cfqq); 604 unsigned slice = cfq_prio_to_slice(cfqd, cfqq);
605 if (cfqd->cfq_latency) { 605 if (cfqd->cfq_latency) {
@@ -625,6 +625,14 @@ cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
625 low_slice); 625 low_slice);
626 } 626 }
627 } 627 }
628 return slice;
629}
630
631static inline void
632cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
633{
634 unsigned slice = cfq_scaled_group_slice(cfqd, cfqq);
635
628 cfqq->slice_start = jiffies; 636 cfqq->slice_start = jiffies;
629 cfqq->slice_end = jiffies + slice; 637 cfqq->slice_end = jiffies + slice;
630 cfqq->allocated_slice = slice; 638 cfqq->allocated_slice = slice;
@@ -1661,8 +1669,11 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1661 /* 1669 /*
1662 * store what was left of this slice, if the queue idled/timed out 1670 * store what was left of this slice, if the queue idled/timed out
1663 */ 1671 */
1664 if (timed_out && !cfq_cfqq_slice_new(cfqq)) { 1672 if (timed_out) {
1665 cfqq->slice_resid = cfqq->slice_end - jiffies; 1673 if (cfq_cfqq_slice_new(cfqq))
1674 cfqq->slice_resid = cfq_scaled_group_slice(cfqd, cfqq);
1675 else
1676 cfqq->slice_resid = cfqq->slice_end - jiffies;
1666 cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid); 1677 cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid);
1667 } 1678 }
1668 1679
@@ -3284,10 +3295,19 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
3284 */ 3295 */
3285static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) 3296static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
3286{ 3297{
3298 struct cfq_queue *old_cfqq = cfqd->active_queue;
3299
3287 cfq_log_cfqq(cfqd, cfqq, "preempt"); 3300 cfq_log_cfqq(cfqd, cfqq, "preempt");
3288 cfq_slice_expired(cfqd, 1); 3301 cfq_slice_expired(cfqd, 1);
3289 3302
3290 /* 3303 /*
3304 * workload type is changed, don't save slice, otherwise preempt
3305 * doesn't happen
3306 */
3307 if (cfqq_type(old_cfqq) != cfqq_type(cfqq))
3308 cfqq->cfqg->saved_workload_slice = 0;
3309
3310 /*
3291 * Put the new queue at the front of the of the current list, 3311 * Put the new queue at the front of the of the current list,
3292 * so we know that it will be selected next. 3312 * so we know that it will be selected next.
3293 */ 3313 */
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index dffa0ac7c4f0..38e4eb1bb965 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -350,6 +350,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
350 if (!d->dm_dev.bdev) 350 if (!d->dm_dev.bdev)
351 return; 351 return;
352 352
353 bd_unlink_disk_holder(d->dm_dev.bdev, dm_disk(md));
353 blkdev_put(d->dm_dev.bdev, d->dm_dev.mode | FMODE_EXCL); 354 blkdev_put(d->dm_dev.bdev, d->dm_dev.mode | FMODE_EXCL);
354 d->dm_dev.bdev = NULL; 355 d->dm_dev.bdev = NULL;
355} 356}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index cf8594c5ea21..b76cfc89e1b5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1912,6 +1912,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
1912 MD_BUG(); 1912 MD_BUG();
1913 return; 1913 return;
1914 } 1914 }
1915 bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
1915 list_del_rcu(&rdev->same_set); 1916 list_del_rcu(&rdev->same_set);
1916 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); 1917 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
1917 rdev->mddev = NULL; 1918 rdev->mddev = NULL;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fe3f59c14a02..333a7bb4cb9c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -432,6 +432,9 @@ static void init_once(void *foo)
432 mutex_init(&bdev->bd_mutex); 432 mutex_init(&bdev->bd_mutex);
433 INIT_LIST_HEAD(&bdev->bd_inodes); 433 INIT_LIST_HEAD(&bdev->bd_inodes);
434 INIT_LIST_HEAD(&bdev->bd_list); 434 INIT_LIST_HEAD(&bdev->bd_list);
435#ifdef CONFIG_SYSFS
436 INIT_LIST_HEAD(&bdev->bd_holder_disks);
437#endif
435 inode_init_once(&ei->vfs_inode); 438 inode_init_once(&ei->vfs_inode);
436 /* Initialize mutex for freeze. */ 439 /* Initialize mutex for freeze. */
437 mutex_init(&bdev->bd_fsfreeze_mutex); 440 mutex_init(&bdev->bd_fsfreeze_mutex);
@@ -779,6 +782,23 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
779} 782}
780 783
781#ifdef CONFIG_SYSFS 784#ifdef CONFIG_SYSFS
785struct bd_holder_disk {
786 struct list_head list;
787 struct gendisk *disk;
788 int refcnt;
789};
790
791static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
792 struct gendisk *disk)
793{
794 struct bd_holder_disk *holder;
795
796 list_for_each_entry(holder, &bdev->bd_holder_disks, list)
797 if (holder->disk == disk)
798 return holder;
799 return NULL;
800}
801
782static int add_symlink(struct kobject *from, struct kobject *to) 802static int add_symlink(struct kobject *from, struct kobject *to)
783{ 803{
784 return sysfs_create_link(from, to, kobject_name(to)); 804 return sysfs_create_link(from, to, kobject_name(to));
@@ -794,6 +814,8 @@ static void del_symlink(struct kobject *from, struct kobject *to)
794 * @bdev: the claimed slave bdev 814 * @bdev: the claimed slave bdev
795 * @disk: the holding disk 815 * @disk: the holding disk
796 * 816 *
817 * DON'T USE THIS UNLESS YOU'RE ALREADY USING IT.
818 *
797 * This functions creates the following sysfs symlinks. 819 * This functions creates the following sysfs symlinks.
798 * 820 *
799 * - from "slaves" directory of the holder @disk to the claimed @bdev 821 * - from "slaves" directory of the holder @disk to the claimed @bdev
@@ -817,47 +839,83 @@ static void del_symlink(struct kobject *from, struct kobject *to)
817 */ 839 */
818int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk) 840int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
819{ 841{
842 struct bd_holder_disk *holder;
820 int ret = 0; 843 int ret = 0;
821 844
822 mutex_lock(&bdev->bd_mutex); 845 mutex_lock(&bdev->bd_mutex);
823 846
824 WARN_ON_ONCE(!bdev->bd_holder || bdev->bd_holder_disk); 847 WARN_ON_ONCE(!bdev->bd_holder);
825 848
826 /* FIXME: remove the following once add_disk() handles errors */ 849 /* FIXME: remove the following once add_disk() handles errors */
827 if (WARN_ON(!disk->slave_dir || !bdev->bd_part->holder_dir)) 850 if (WARN_ON(!disk->slave_dir || !bdev->bd_part->holder_dir))
828 goto out_unlock; 851 goto out_unlock;
829 852
830 ret = add_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj); 853 holder = bd_find_holder_disk(bdev, disk);
831 if (ret) 854 if (holder) {
855 holder->refcnt++;
832 goto out_unlock; 856 goto out_unlock;
857 }
833 858
834 ret = add_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj); 859 holder = kzalloc(sizeof(*holder), GFP_KERNEL);
835 if (ret) { 860 if (!holder) {
836 del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj); 861 ret = -ENOMEM;
837 goto out_unlock; 862 goto out_unlock;
838 } 863 }
839 864
840 bdev->bd_holder_disk = disk; 865 INIT_LIST_HEAD(&holder->list);
866 holder->disk = disk;
867 holder->refcnt = 1;
868
869 ret = add_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
870 if (ret)
871 goto out_free;
872
873 ret = add_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj);
874 if (ret)
875 goto out_del;
876
877 list_add(&holder->list, &bdev->bd_holder_disks);
878 goto out_unlock;
879
880out_del:
881 del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
882out_free:
883 kfree(holder);
841out_unlock: 884out_unlock:
842 mutex_unlock(&bdev->bd_mutex); 885 mutex_unlock(&bdev->bd_mutex);
843 return ret; 886 return ret;
844} 887}
845EXPORT_SYMBOL_GPL(bd_link_disk_holder); 888EXPORT_SYMBOL_GPL(bd_link_disk_holder);
846 889
847static void bd_unlink_disk_holder(struct block_device *bdev) 890/**
891 * bd_unlink_disk_holder - destroy symlinks created by bd_link_disk_holder()
892 * @bdev: the calimed slave bdev
893 * @disk: the holding disk
894 *
895 * DON'T USE THIS UNLESS YOU'RE ALREADY USING IT.
896 *
897 * CONTEXT:
898 * Might sleep.
899 */
900void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
848{ 901{
849 struct gendisk *disk = bdev->bd_holder_disk; 902 struct bd_holder_disk *holder;
850 903
851 bdev->bd_holder_disk = NULL; 904 mutex_lock(&bdev->bd_mutex);
852 if (!disk)
853 return;
854 905
855 del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj); 906 holder = bd_find_holder_disk(bdev, disk);
856 del_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj); 907
908 if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
909 del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
910 del_symlink(bdev->bd_part->holder_dir,
911 &disk_to_dev(disk)->kobj);
912 list_del_init(&holder->list);
913 kfree(holder);
914 }
915
916 mutex_unlock(&bdev->bd_mutex);
857} 917}
858#else 918EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
859static inline void bd_unlink_disk_holder(struct block_device *bdev)
860{ }
861#endif 919#endif
862 920
863/** 921/**
@@ -1380,7 +1438,6 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
1380 * unblock evpoll if it was a write holder. 1438 * unblock evpoll if it was a write holder.
1381 */ 1439 */
1382 if (bdev_free) { 1440 if (bdev_free) {
1383 bd_unlink_disk_holder(bdev);
1384 if (bdev->bd_write_holder) { 1441 if (bdev->bd_write_holder) {
1385 disk_unblock_events(bdev->bd_disk); 1442 disk_unblock_events(bdev->bd_disk);
1386 bdev->bd_write_holder = false; 1443 bdev->bd_write_holder = false;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ed6ee473cc8a..08824e0ef381 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -666,7 +666,7 @@ struct block_device {
666 int bd_holders; 666 int bd_holders;
667 bool bd_write_holder; 667 bool bd_write_holder;
668#ifdef CONFIG_SYSFS 668#ifdef CONFIG_SYSFS
669 struct gendisk * bd_holder_disk; /* for sysfs slave linkng */ 669 struct list_head bd_holder_disks;
670#endif 670#endif
671 struct block_device * bd_contains; 671 struct block_device * bd_contains;
672 unsigned bd_block_size; 672 unsigned bd_block_size;
@@ -2057,12 +2057,18 @@ extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode,
2057extern int blkdev_put(struct block_device *bdev, fmode_t mode); 2057extern int blkdev_put(struct block_device *bdev, fmode_t mode);
2058#ifdef CONFIG_SYSFS 2058#ifdef CONFIG_SYSFS
2059extern int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk); 2059extern int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk);
2060extern void bd_unlink_disk_holder(struct block_device *bdev,
2061 struct gendisk *disk);
2060#else 2062#else
2061static inline int bd_link_disk_holder(struct block_device *bdev, 2063static inline int bd_link_disk_holder(struct block_device *bdev,
2062 struct gendisk *disk) 2064 struct gendisk *disk)
2063{ 2065{
2064 return 0; 2066 return 0;
2065} 2067}
2068static inline void bd_unlink_disk_holder(struct block_device *bdev,
2069 struct gendisk *disk)
2070{
2071}
2066#endif 2072#endif
2067#endif 2073#endif
2068 2074