diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:34:37 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:34:37 -0500 |
commit | 483f4afc421435b7cfe5e88f74eea0b73a476d75 (patch) | |
tree | 9a3bbcf8ae83c5edb9ab1f9e98333d6f5673211b | |
parent | 1312f40e11c57edb5c3250f1b782cef8e3efea82 (diff) |
[PATCH] fix sysfs interaction and lifetime rules handling for queues
-rw-r--r-- | block/ll_rw_blk.c | 83 | ||||
-rw-r--r-- | include/linux/blkdev.h | 6 |
2 files changed, 61 insertions, 28 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 6dc769182052..6c793b196aa9 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
@@ -1740,16 +1740,11 @@ EXPORT_SYMBOL(blk_run_queue); | |||
1740 | * Hopefully the low level driver will have finished any | 1740 | * Hopefully the low level driver will have finished any |
1741 | * outstanding requests first... | 1741 | * outstanding requests first... |
1742 | **/ | 1742 | **/ |
1743 | void blk_cleanup_queue(request_queue_t * q) | 1743 | static void blk_release_queue(struct kobject *kobj) |
1744 | { | 1744 | { |
1745 | request_queue_t *q = container_of(kobj, struct request_queue, kobj); | ||
1745 | struct request_list *rl = &q->rq; | 1746 | struct request_list *rl = &q->rq; |
1746 | 1747 | ||
1747 | if (!atomic_dec_and_test(&q->refcnt)) | ||
1748 | return; | ||
1749 | |||
1750 | if (q->elevator) | ||
1751 | elevator_exit(q->elevator); | ||
1752 | |||
1753 | blk_sync_queue(q); | 1748 | blk_sync_queue(q); |
1754 | 1749 | ||
1755 | if (rl->rq_pool) | 1750 | if (rl->rq_pool) |
@@ -1761,6 +1756,24 @@ void blk_cleanup_queue(request_queue_t * q) | |||
1761 | kmem_cache_free(requestq_cachep, q); | 1756 | kmem_cache_free(requestq_cachep, q); |
1762 | } | 1757 | } |
1763 | 1758 | ||
1759 | void blk_put_queue(request_queue_t *q) | ||
1760 | { | ||
1761 | kobject_put(&q->kobj); | ||
1762 | } | ||
1763 | EXPORT_SYMBOL(blk_put_queue); | ||
1764 | |||
1765 | void blk_cleanup_queue(request_queue_t * q) | ||
1766 | { | ||
1767 | mutex_lock(&q->sysfs_lock); | ||
1768 | set_bit(QUEUE_FLAG_DEAD, &q->queue_flags); | ||
1769 | mutex_unlock(&q->sysfs_lock); | ||
1770 | |||
1771 | if (q->elevator) | ||
1772 | elevator_exit(q->elevator); | ||
1773 | |||
1774 | blk_put_queue(q); | ||
1775 | } | ||
1776 | |||
1764 | EXPORT_SYMBOL(blk_cleanup_queue); | 1777 | EXPORT_SYMBOL(blk_cleanup_queue); |
1765 | 1778 | ||
1766 | static int blk_init_free_list(request_queue_t *q) | 1779 | static int blk_init_free_list(request_queue_t *q) |
@@ -1788,6 +1801,8 @@ request_queue_t *blk_alloc_queue(gfp_t gfp_mask) | |||
1788 | } | 1801 | } |
1789 | EXPORT_SYMBOL(blk_alloc_queue); | 1802 | EXPORT_SYMBOL(blk_alloc_queue); |
1790 | 1803 | ||
1804 | static struct kobj_type queue_ktype; | ||
1805 | |||
1791 | request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | 1806 | request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) |
1792 | { | 1807 | { |
1793 | request_queue_t *q; | 1808 | request_queue_t *q; |
@@ -1798,11 +1813,16 @@ request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | |||
1798 | 1813 | ||
1799 | memset(q, 0, sizeof(*q)); | 1814 | memset(q, 0, sizeof(*q)); |
1800 | init_timer(&q->unplug_timer); | 1815 | init_timer(&q->unplug_timer); |
1801 | atomic_set(&q->refcnt, 1); | 1816 | |
1817 | snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); | ||
1818 | q->kobj.ktype = &queue_ktype; | ||
1819 | kobject_init(&q->kobj); | ||
1802 | 1820 | ||
1803 | q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug; | 1821 | q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug; |
1804 | q->backing_dev_info.unplug_io_data = q; | 1822 | q->backing_dev_info.unplug_io_data = q; |
1805 | 1823 | ||
1824 | mutex_init(&q->sysfs_lock); | ||
1825 | |||
1806 | return q; | 1826 | return q; |
1807 | } | 1827 | } |
1808 | EXPORT_SYMBOL(blk_alloc_queue_node); | 1828 | EXPORT_SYMBOL(blk_alloc_queue_node); |
@@ -1901,7 +1921,7 @@ EXPORT_SYMBOL(blk_init_queue_node); | |||
1901 | int blk_get_queue(request_queue_t *q) | 1921 | int blk_get_queue(request_queue_t *q) |
1902 | { | 1922 | { |
1903 | if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { | 1923 | if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { |
1904 | atomic_inc(&q->refcnt); | 1924 | kobject_get(&q->kobj); |
1905 | return 0; | 1925 | return 0; |
1906 | } | 1926 | } |
1907 | 1927 | ||
@@ -3764,13 +3784,19 @@ static ssize_t | |||
3764 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | 3784 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) |
3765 | { | 3785 | { |
3766 | struct queue_sysfs_entry *entry = to_queue(attr); | 3786 | struct queue_sysfs_entry *entry = to_queue(attr); |
3767 | struct request_queue *q; | 3787 | request_queue_t *q = container_of(kobj, struct request_queue, kobj); |
3788 | ssize_t res; | ||
3768 | 3789 | ||
3769 | q = container_of(kobj, struct request_queue, kobj); | ||
3770 | if (!entry->show) | 3790 | if (!entry->show) |
3771 | return -EIO; | 3791 | return -EIO; |
3772 | 3792 | mutex_lock(&q->sysfs_lock); | |
3773 | return entry->show(q, page); | 3793 | if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) { |
3794 | mutex_unlock(&q->sysfs_lock); | ||
3795 | return -ENOENT; | ||
3796 | } | ||
3797 | res = entry->show(q, page); | ||
3798 | mutex_unlock(&q->sysfs_lock); | ||
3799 | return res; | ||
3774 | } | 3800 | } |
3775 | 3801 | ||
3776 | static ssize_t | 3802 | static ssize_t |
@@ -3778,13 +3804,20 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr, | |||
3778 | const char *page, size_t length) | 3804 | const char *page, size_t length) |
3779 | { | 3805 | { |
3780 | struct queue_sysfs_entry *entry = to_queue(attr); | 3806 | struct queue_sysfs_entry *entry = to_queue(attr); |
3781 | struct request_queue *q; | 3807 | request_queue_t *q = container_of(kobj, struct request_queue, kobj); |
3808 | |||
3809 | ssize_t res; | ||
3782 | 3810 | ||
3783 | q = container_of(kobj, struct request_queue, kobj); | ||
3784 | if (!entry->store) | 3811 | if (!entry->store) |
3785 | return -EIO; | 3812 | return -EIO; |
3786 | 3813 | mutex_lock(&q->sysfs_lock); | |
3787 | return entry->store(q, page, length); | 3814 | if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) { |
3815 | mutex_unlock(&q->sysfs_lock); | ||
3816 | return -ENOENT; | ||
3817 | } | ||
3818 | res = entry->store(q, page, length); | ||
3819 | mutex_unlock(&q->sysfs_lock); | ||
3820 | return res; | ||
3788 | } | 3821 | } |
3789 | 3822 | ||
3790 | static struct sysfs_ops queue_sysfs_ops = { | 3823 | static struct sysfs_ops queue_sysfs_ops = { |
@@ -3795,6 +3828,7 @@ static struct sysfs_ops queue_sysfs_ops = { | |||
3795 | static struct kobj_type queue_ktype = { | 3828 | static struct kobj_type queue_ktype = { |
3796 | .sysfs_ops = &queue_sysfs_ops, | 3829 | .sysfs_ops = &queue_sysfs_ops, |
3797 | .default_attrs = default_attrs, | 3830 | .default_attrs = default_attrs, |
3831 | .release = blk_release_queue, | ||
3798 | }; | 3832 | }; |
3799 | 3833 | ||
3800 | int blk_register_queue(struct gendisk *disk) | 3834 | int blk_register_queue(struct gendisk *disk) |
@@ -3807,19 +3841,17 @@ int blk_register_queue(struct gendisk *disk) | |||
3807 | return -ENXIO; | 3841 | return -ENXIO; |
3808 | 3842 | ||
3809 | q->kobj.parent = kobject_get(&disk->kobj); | 3843 | q->kobj.parent = kobject_get(&disk->kobj); |
3810 | if (!q->kobj.parent) | ||
3811 | return -EBUSY; | ||
3812 | 3844 | ||
3813 | snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); | 3845 | ret = kobject_add(&q->kobj); |
3814 | q->kobj.ktype = &queue_ktype; | ||
3815 | |||
3816 | ret = kobject_register(&q->kobj); | ||
3817 | if (ret < 0) | 3846 | if (ret < 0) |
3818 | return ret; | 3847 | return ret; |
3819 | 3848 | ||
3849 | kobject_uevent(&q->kobj, KOBJ_ADD); | ||
3850 | |||
3820 | ret = elv_register_queue(q); | 3851 | ret = elv_register_queue(q); |
3821 | if (ret) { | 3852 | if (ret) { |
3822 | kobject_unregister(&q->kobj); | 3853 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
3854 | kobject_del(&q->kobj); | ||
3823 | return ret; | 3855 | return ret; |
3824 | } | 3856 | } |
3825 | 3857 | ||
@@ -3833,7 +3865,8 @@ void blk_unregister_queue(struct gendisk *disk) | |||
3833 | if (q && q->request_fn) { | 3865 | if (q && q->request_fn) { |
3834 | elv_unregister_queue(q); | 3866 | elv_unregister_queue(q); |
3835 | 3867 | ||
3836 | kobject_unregister(&q->kobj); | 3868 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
3869 | kobject_del(&q->kobj); | ||
3837 | kobject_put(&disk->kobj); | 3870 | kobject_put(&disk->kobj); |
3838 | } | 3871 | } |
3839 | } | 3872 | } |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 80518f703538..56bb6a4e15f3 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -406,8 +406,6 @@ struct request_queue | |||
406 | 406 | ||
407 | struct blk_queue_tag *queue_tags; | 407 | struct blk_queue_tag *queue_tags; |
408 | 408 | ||
409 | atomic_t refcnt; | ||
410 | |||
411 | unsigned int nr_sorted; | 409 | unsigned int nr_sorted; |
412 | unsigned int in_flight; | 410 | unsigned int in_flight; |
413 | 411 | ||
@@ -426,6 +424,8 @@ struct request_queue | |||
426 | struct request pre_flush_rq, bar_rq, post_flush_rq; | 424 | struct request pre_flush_rq, bar_rq, post_flush_rq; |
427 | struct request *orig_bar_rq; | 425 | struct request *orig_bar_rq; |
428 | unsigned int bi_size; | 426 | unsigned int bi_size; |
427 | |||
428 | struct mutex sysfs_lock; | ||
429 | }; | 429 | }; |
430 | 430 | ||
431 | #define RQ_INACTIVE (-1) | 431 | #define RQ_INACTIVE (-1) |
@@ -727,7 +727,7 @@ extern long nr_blockdev_pages(void); | |||
727 | int blk_get_queue(request_queue_t *); | 727 | int blk_get_queue(request_queue_t *); |
728 | request_queue_t *blk_alloc_queue(gfp_t); | 728 | request_queue_t *blk_alloc_queue(gfp_t); |
729 | request_queue_t *blk_alloc_queue_node(gfp_t, int); | 729 | request_queue_t *blk_alloc_queue_node(gfp_t, int); |
730 | #define blk_put_queue(q) blk_cleanup_queue((q)) | 730 | extern void blk_put_queue(request_queue_t *); |
731 | 731 | ||
732 | /* | 732 | /* |
733 | * tag stuff | 733 | * tag stuff |