diff options
Diffstat (limited to 'block/ll_rw_blk.c')
-rw-r--r-- | block/ll_rw_blk.c | 105 |
1 files changed, 72 insertions, 33 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 0ef2971a9e82..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); |
@@ -1854,8 +1874,10 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) | |||
1854 | return NULL; | 1874 | return NULL; |
1855 | 1875 | ||
1856 | q->node = node_id; | 1876 | q->node = node_id; |
1857 | if (blk_init_free_list(q)) | 1877 | if (blk_init_free_list(q)) { |
1858 | goto out_init; | 1878 | kmem_cache_free(requestq_cachep, q); |
1879 | return NULL; | ||
1880 | } | ||
1859 | 1881 | ||
1860 | /* | 1882 | /* |
1861 | * if caller didn't supply a lock, they get per-queue locking with | 1883 | * if caller didn't supply a lock, they get per-queue locking with |
@@ -1891,9 +1913,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) | |||
1891 | return q; | 1913 | return q; |
1892 | } | 1914 | } |
1893 | 1915 | ||
1894 | blk_cleanup_queue(q); | 1916 | blk_put_queue(q); |
1895 | out_init: | ||
1896 | kmem_cache_free(requestq_cachep, q); | ||
1897 | return NULL; | 1917 | return NULL; |
1898 | } | 1918 | } |
1899 | EXPORT_SYMBOL(blk_init_queue_node); | 1919 | EXPORT_SYMBOL(blk_init_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 | ||
@@ -3477,10 +3497,12 @@ void put_io_context(struct io_context *ioc) | |||
3477 | BUG_ON(atomic_read(&ioc->refcount) == 0); | 3497 | BUG_ON(atomic_read(&ioc->refcount) == 0); |
3478 | 3498 | ||
3479 | if (atomic_dec_and_test(&ioc->refcount)) { | 3499 | if (atomic_dec_and_test(&ioc->refcount)) { |
3500 | rcu_read_lock(); | ||
3480 | if (ioc->aic && ioc->aic->dtor) | 3501 | if (ioc->aic && ioc->aic->dtor) |
3481 | ioc->aic->dtor(ioc->aic); | 3502 | ioc->aic->dtor(ioc->aic); |
3482 | if (ioc->cic && ioc->cic->dtor) | 3503 | if (ioc->cic && ioc->cic->dtor) |
3483 | ioc->cic->dtor(ioc->cic); | 3504 | ioc->cic->dtor(ioc->cic); |
3505 | rcu_read_unlock(); | ||
3484 | 3506 | ||
3485 | kmem_cache_free(iocontext_cachep, ioc); | 3507 | kmem_cache_free(iocontext_cachep, ioc); |
3486 | } | 3508 | } |
@@ -3614,10 +3636,13 @@ static ssize_t | |||
3614 | queue_requests_store(struct request_queue *q, const char *page, size_t count) | 3636 | queue_requests_store(struct request_queue *q, const char *page, size_t count) |
3615 | { | 3637 | { |
3616 | struct request_list *rl = &q->rq; | 3638 | struct request_list *rl = &q->rq; |
3639 | unsigned long nr; | ||
3640 | int ret = queue_var_store(&nr, page, count); | ||
3641 | if (nr < BLKDEV_MIN_RQ) | ||
3642 | nr = BLKDEV_MIN_RQ; | ||
3617 | 3643 | ||
3618 | int ret = queue_var_store(&q->nr_requests, page, count); | 3644 | spin_lock_irq(q->queue_lock); |
3619 | if (q->nr_requests < BLKDEV_MIN_RQ) | 3645 | q->nr_requests = nr; |
3620 | q->nr_requests = BLKDEV_MIN_RQ; | ||
3621 | blk_queue_congestion_threshold(q); | 3646 | blk_queue_congestion_threshold(q); |
3622 | 3647 | ||
3623 | if (rl->count[READ] >= queue_congestion_on_threshold(q)) | 3648 | if (rl->count[READ] >= queue_congestion_on_threshold(q)) |
@@ -3643,6 +3668,7 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count) | |||
3643 | blk_clear_queue_full(q, WRITE); | 3668 | blk_clear_queue_full(q, WRITE); |
3644 | wake_up(&rl->wait[WRITE]); | 3669 | wake_up(&rl->wait[WRITE]); |
3645 | } | 3670 | } |
3671 | spin_unlock_irq(q->queue_lock); | ||
3646 | return ret; | 3672 | return ret; |
3647 | } | 3673 | } |
3648 | 3674 | ||
@@ -3758,13 +3784,19 @@ static ssize_t | |||
3758 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | 3784 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) |
3759 | { | 3785 | { |
3760 | struct queue_sysfs_entry *entry = to_queue(attr); | 3786 | struct queue_sysfs_entry *entry = to_queue(attr); |
3761 | struct request_queue *q; | 3787 | request_queue_t *q = container_of(kobj, struct request_queue, kobj); |
3788 | ssize_t res; | ||
3762 | 3789 | ||
3763 | q = container_of(kobj, struct request_queue, kobj); | ||
3764 | if (!entry->show) | 3790 | if (!entry->show) |
3765 | return -EIO; | 3791 | return -EIO; |
3766 | 3792 | mutex_lock(&q->sysfs_lock); | |
3767 | 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; | ||
3768 | } | 3800 | } |
3769 | 3801 | ||
3770 | static ssize_t | 3802 | static ssize_t |
@@ -3772,13 +3804,20 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr, | |||
3772 | const char *page, size_t length) | 3804 | const char *page, size_t length) |
3773 | { | 3805 | { |
3774 | struct queue_sysfs_entry *entry = to_queue(attr); | 3806 | struct queue_sysfs_entry *entry = to_queue(attr); |
3775 | struct request_queue *q; | 3807 | request_queue_t *q = container_of(kobj, struct request_queue, kobj); |
3808 | |||
3809 | ssize_t res; | ||
3776 | 3810 | ||
3777 | q = container_of(kobj, struct request_queue, kobj); | ||
3778 | if (!entry->store) | 3811 | if (!entry->store) |
3779 | return -EIO; | 3812 | return -EIO; |
3780 | 3813 | mutex_lock(&q->sysfs_lock); | |
3781 | 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; | ||
3782 | } | 3821 | } |
3783 | 3822 | ||
3784 | static struct sysfs_ops queue_sysfs_ops = { | 3823 | static struct sysfs_ops queue_sysfs_ops = { |
@@ -3789,6 +3828,7 @@ static struct sysfs_ops queue_sysfs_ops = { | |||
3789 | static struct kobj_type queue_ktype = { | 3828 | static struct kobj_type queue_ktype = { |
3790 | .sysfs_ops = &queue_sysfs_ops, | 3829 | .sysfs_ops = &queue_sysfs_ops, |
3791 | .default_attrs = default_attrs, | 3830 | .default_attrs = default_attrs, |
3831 | .release = blk_release_queue, | ||
3792 | }; | 3832 | }; |
3793 | 3833 | ||
3794 | int blk_register_queue(struct gendisk *disk) | 3834 | int blk_register_queue(struct gendisk *disk) |
@@ -3801,19 +3841,17 @@ int blk_register_queue(struct gendisk *disk) | |||
3801 | return -ENXIO; | 3841 | return -ENXIO; |
3802 | 3842 | ||
3803 | q->kobj.parent = kobject_get(&disk->kobj); | 3843 | q->kobj.parent = kobject_get(&disk->kobj); |
3804 | if (!q->kobj.parent) | ||
3805 | return -EBUSY; | ||
3806 | 3844 | ||
3807 | snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); | 3845 | ret = kobject_add(&q->kobj); |
3808 | q->kobj.ktype = &queue_ktype; | ||
3809 | |||
3810 | ret = kobject_register(&q->kobj); | ||
3811 | if (ret < 0) | 3846 | if (ret < 0) |
3812 | return ret; | 3847 | return ret; |
3813 | 3848 | ||
3849 | kobject_uevent(&q->kobj, KOBJ_ADD); | ||
3850 | |||
3814 | ret = elv_register_queue(q); | 3851 | ret = elv_register_queue(q); |
3815 | if (ret) { | 3852 | if (ret) { |
3816 | kobject_unregister(&q->kobj); | 3853 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
3854 | kobject_del(&q->kobj); | ||
3817 | return ret; | 3855 | return ret; |
3818 | } | 3856 | } |
3819 | 3857 | ||
@@ -3827,7 +3865,8 @@ void blk_unregister_queue(struct gendisk *disk) | |||
3827 | if (q && q->request_fn) { | 3865 | if (q && q->request_fn) { |
3828 | elv_unregister_queue(q); | 3866 | elv_unregister_queue(q); |
3829 | 3867 | ||
3830 | kobject_unregister(&q->kobj); | 3868 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
3869 | kobject_del(&q->kobj); | ||
3831 | kobject_put(&disk->kobj); | 3870 | kobject_put(&disk->kobj); |
3832 | } | 3871 | } |
3833 | } | 3872 | } |