The kobject embedded into the request_queue is used for the queue directory in sysfs, but that is a child of the gendisks directory and is intimately tied to it. Move this kobject to the gendisk and use a refcount_t in the request_queue for the actual request_queue refcounting that is completely unrelated to the device model.
Unified · Split
| @@ -59,12 +59,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_split); · 58 unmodified lines | |||
| 59 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug); | 59 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug); |
| 60 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert); | 60 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert); |
| 61 | 61 | ||
| 62 | DEFINE_IDA(blk_queue_ida); | 62 | static DEFINE_IDA(blk_queue_ida); |
| 63 | 63 | ||
| 64 | /* | 64 | /* |
| 65 | * For queue allocation | 65 | * For queue allocation |
| 66 | */ | 66 | */ |
| 67 | struct kmem_cache *blk_requestq_cachep; | 67 | static struct kmem_cache *blk_requestq_cachep; |
| 68 | 68 | ||
| 69 | /* | 69 | /* |
| 70 | * Controlling structure to kblockd | 70 | * Controlling structure to kblockd |
| @@ -252,19 +252,46 @@ void blk_clear_pm_only(struct request_queue *q) · 181 unmodified lines | |||
| 252 | } | 252 | } |
| 253 | EXPORT_SYMBOL_GPL(blk_clear_pm_only); | 253 | EXPORT_SYMBOL_GPL(blk_clear_pm_only); |
| 254 | 254 | ||
| 255 | static void blk_free_queue_rcu(struct rcu_head *rcu_head) | ||
| 256 | { | ||
| 257 | kmem_cache_free(blk_requestq_cachep, | ||
| 258 | container_of(rcu_head, struct request_queue, rcu_head)); | ||
| 259 | } | ||
| 260 | |||
| 261 | static void blk_free_queue(struct request_queue *q) | ||
| 262 | { | ||
| 263 | might_sleep(); | ||
| 264 | |||
| 265 | percpu_ref_exit(&q->q_usage_counter); | ||
| 266 | |||
| 267 | if (q->poll_stat) | ||
| 268 | blk_stat_remove_callback(q, q->poll_cb); | ||
| 269 | blk_stat_free_callback(q->poll_cb); | ||
| 270 | |||
| 271 | blk_free_queue_stats(q->stats); | ||
| 272 | kfree(q->poll_stat); | ||
| 273 | |||
| 274 | if (queue_is_mq(q)) | ||
| 275 | blk_mq_release(q); | ||
| 276 | |||
| 277 | ida_free(&blk_queue_ida, q->id); | ||
| 278 | call_rcu(&q->rcu_head, blk_free_queue_rcu); | ||
| 279 | } | ||
| 280 | |||
| 255 | /** | 281 | /** |
| 256 | * blk_put_queue - decrement the request_queue refcount | 282 | * blk_put_queue - decrement the request_queue refcount |
| 257 | * @q: the request_queue structure to decrement the refcount for | 283 | * @q: the request_queue structure to decrement the refcount for |
| 258 | * | 284 | * |
| 259 | * Decrements the refcount of the request_queue kobject. When this reaches 0 | 285 | * Decrements the refcount of the request_queue and free it when the refcount |
| 260 | * we'll have blk_release_queue() called. | 286 | * reaches 0. |
| 261 | * | 287 | * |
| 262 | * Context: Any context, but the last reference must not be dropped from | 288 | * Context: Any context, but the last reference must not be dropped from |
| 263 | * atomic context. | 289 | * atomic context. |
| 264 | */ | 290 | */ |
| 265 | void blk_put_queue(struct request_queue *q) | 291 | void blk_put_queue(struct request_queue *q) |
| 266 | { | 292 | { |
| 267 | kobject_put(&q->kobj); | 293 | if (refcount_dec_and_test(&q->refs)) |
| 294 | blk_free_queue(q); | ||
| 268 | } | 295 | } |
| 269 | EXPORT_SYMBOL(blk_put_queue); | 296 | EXPORT_SYMBOL(blk_put_queue); |
| 270 | 297 | ||
| @@ -399,8 +426,7 @@ struct request_queue *blk_alloc_queue(int node_id) · 128 unmodified lines | |||
| 399 | INIT_WORK(&q->timeout_work, blk_timeout_work); | 426 | INIT_WORK(&q->timeout_work, blk_timeout_work); |
| 400 | INIT_LIST_HEAD(&q->icq_list); | 427 | INIT_LIST_HEAD(&q->icq_list); |
| 401 | 428 | ||
| 402 | kobject_init(&q->kobj, &blk_queue_ktype); | 429 | refcount_set(&q->refs, 1); |
| 403 | |||
| 404 | mutex_init(&q->debugfs_mutex); | 430 | mutex_init(&q->debugfs_mutex); |
| 405 | mutex_init(&q->sysfs_lock); | 431 | mutex_init(&q->sysfs_lock); |
| 406 | mutex_init(&q->sysfs_dir_lock); | 432 | mutex_init(&q->sysfs_dir_lock); |
| @@ -445,7 +471,7 @@ bool blk_get_queue(struct request_queue *q) · 38 unmodified lines | |||
| 445 | { | 471 | { |
| 446 | if (unlikely(blk_queue_dying(q))) | 472 | if (unlikely(blk_queue_dying(q))) |
| 447 | return false; | 473 | return false; |
| 448 | kobject_get(&q->kobj); | 474 | refcount_inc(&q->refs); |
| 449 | return true; | 475 | return true; |
| 450 | } | 476 | } |
| 451 | EXPORT_SYMBOL(blk_get_queue); | 477 | EXPORT_SYMBOL(blk_get_queue); |
| @@ -140,8 +140,8 @@ int blk_crypto_sysfs_register(struct gendisk *disk) · 139 unmodified lines | |||
| 140 | return -ENOMEM; | 140 | return -ENOMEM; |
| 141 | obj->profile = q->crypto_profile; | 141 | obj->profile = q->crypto_profile; |
| 142 | 142 | ||
| 143 | err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, &q->kobj, | 143 | err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, |
| 144 | "crypto"); | 144 | &disk->queue_kobj, "crypto"); |
| 145 | if (err) { | 145 | if (err) { |
| 146 | kobject_put(&obj->kobj); | 146 | kobject_put(&obj->kobj); |
| 147 | return err; | 147 | return err; |
| @@ -123,7 +123,8 @@ int disk_register_independent_access_ranges(struct gendisk *disk) · 122 unmodified lines | |||
| 123 | */ | 123 | */ |
| 124 | WARN_ON(iars->sysfs_registered); | 124 | WARN_ON(iars->sysfs_registered); |
| 125 | ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype, | 125 | ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype, |
| 126 | &q->kobj, "%s", "independent_access_ranges"); | 126 | &disk->queue_kobj, "%s", |
| 127 | "independent_access_ranges"); | ||
| 127 | if (ret) { | 128 | if (ret) { |
| 128 | disk->ia_ranges = NULL; | 129 | disk->ia_ranges = NULL; |
| 129 | kobject_put(&iars->kobj); | 130 | kobject_put(&iars->kobj); |
| @@ -683,8 +683,8 @@ static struct attribute *queue_attrs[] = { · 682 unmodified lines | |||
| 683 | static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr, | 683 | static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr, |
| 684 | int n) | 684 | int n) |
| 685 | { | 685 | { |
| 686 | struct request_queue *q = | 686 | struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); |
| 687 | container_of(kobj, struct request_queue, kobj); | 687 | struct request_queue *q = disk->queue; |
| 688 | 688 | ||
| 689 | if (attr == &queue_io_timeout_entry.attr && | 689 | if (attr == &queue_io_timeout_entry.attr && |
| 690 | (!q->mq_ops || !q->mq_ops->timeout)) | 690 | (!q->mq_ops || !q->mq_ops->timeout)) |
| @@ -710,8 +710,8 @@ static ssize_t · 19 unmodified lines | |||
| 710 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | 710 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) |
| 711 | { | 711 | { |
| 712 | struct queue_sysfs_entry *entry = to_queue(attr); | 712 | struct queue_sysfs_entry *entry = to_queue(attr); |
| 713 | struct request_queue *q = | 713 | struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); |
| 714 | container_of(kobj, struct request_queue, kobj); | 714 | struct request_queue *q = disk->queue; |
| 715 | ssize_t res; | 715 | ssize_t res; |
| 716 | 716 | ||
| 717 | if (!entry->show) | 717 | if (!entry->show) |
| @@ -727,63 +727,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr, · 9 unmodified lines | |||
| 727 | const char *page, size_t length) | 727 | const char *page, size_t length) |
| 728 | { | 728 | { |
| 729 | struct queue_sysfs_entry *entry = to_queue(attr); | 729 | struct queue_sysfs_entry *entry = to_queue(attr); |
| 730 | struct request_queue *q; | 730 | struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); |
| 731 | struct request_queue *q = disk->queue; | ||
| 731 | ssize_t res; | 732 | ssize_t res; |
| 732 | 733 | ||
| 733 | if (!entry->store) | 734 | if (!entry->store) |
| 734 | return -EIO; | 735 | return -EIO; |
| 735 | 736 | ||
| 736 | q = container_of(kobj, struct request_queue, kobj); | ||
| 737 | mutex_lock(&q->sysfs_lock); | 737 | mutex_lock(&q->sysfs_lock); |
| 738 | res = entry->store(q, page, length); | 738 | res = entry->store(q, page, length); |
| 739 | mutex_unlock(&q->sysfs_lock); | 739 | mutex_unlock(&q->sysfs_lock); |
| 740 | return res; | 740 | return res; |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | static void blk_free_queue_rcu(struct rcu_head *rcu_head) | ||
| 744 | { | ||
| 745 | kmem_cache_free(blk_requestq_cachep, | ||
| 746 | container_of(rcu_head, struct request_queue, rcu_head)); | ||
| 747 | } | ||
| 748 | |||
| 749 | /** | ||
| 750 | * blk_release_queue - releases all allocated resources of the request_queue | ||
| 751 | * @kobj: pointer to a kobject, whose container is a request_queue | ||
| 752 | * | ||
| 753 | * This function releases all allocated resources of the request queue. | ||
| 754 | * | ||
| 755 | * The struct request_queue refcount is incremented with blk_get_queue() and | ||
| 756 | * decremented with blk_put_queue(). Once the refcount reaches 0 this function | ||
| 757 | * is called. | ||
| 758 | * | ||
| 759 | * Drivers exist which depend on the release of the request_queue to be | ||
| 760 | * synchronous, it should not be deferred. | ||
| 761 | * | ||
| 762 | * Context: can sleep | ||
| 763 | */ | ||
| 764 | static void blk_release_queue(struct kobject *kobj) | ||
| 765 | { | ||
| 766 | struct request_queue *q = | ||
| 767 | container_of(kobj, struct request_queue, kobj); | ||
| 768 | |||
| 769 | might_sleep(); | ||
| 770 | |||
| 771 | percpu_ref_exit(&q->q_usage_counter); | ||
| 772 | |||
| 773 | if (q->poll_stat) | ||
| 774 | blk_stat_remove_callback(q, q->poll_cb); | ||
| 775 | blk_stat_free_callback(q->poll_cb); | ||
| 776 | |||
| 777 | blk_free_queue_stats(q->stats); | ||
| 778 | kfree(q->poll_stat); | ||
| 779 | |||
| 780 | if (queue_is_mq(q)) | ||
| 781 | blk_mq_release(q); | ||
| 782 | |||
| 783 | ida_free(&blk_queue_ida, q->id); | ||
| 784 | call_rcu(&q->rcu_head, blk_free_queue_rcu); | ||
| 785 | } | ||
| 786 | |||
| 787 | static const struct sysfs_ops queue_sysfs_ops = { | 743 | static const struct sysfs_ops queue_sysfs_ops = { |
| 788 | .show = queue_attr_show, | 744 | .show = queue_attr_show, |
| 789 | .store = queue_attr_store, | 745 | .store = queue_attr_store, |
| @@ -794,10 +750,15 @@ static const struct attribute_group *blk_queue_attr_groups[] = { · 4 unmodified lines | |||
| 794 | NULL | 750 | NULL |
| 795 | }; | 751 | }; |
| 796 | 752 | ||
| 797 | struct kobj_type blk_queue_ktype = { | 753 | static void blk_queue_release(struct kobject *kobj) |
| 754 | { | ||
| 755 | /* nothing to do here, all data is associated with the parent gendisk */ | ||
| 756 | } | ||
| 757 | |||
| 758 | static struct kobj_type blk_queue_ktype = { | ||
| 798 | .default_groups = blk_queue_attr_groups, | 759 | .default_groups = blk_queue_attr_groups, |
| 799 | .sysfs_ops = &queue_sysfs_ops, | 760 | .sysfs_ops = &queue_sysfs_ops, |
| 800 | .release = blk_release_queue, | 761 | .release = blk_queue_release, |
| 801 | }; | 762 | }; |
| 802 | 763 | ||
| 803 | static void blk_debugfs_remove(struct gendisk *disk) | 764 | static void blk_debugfs_remove(struct gendisk *disk) |
| @@ -823,20 +784,20 @@ int blk_register_queue(struct gendisk *disk) · 19 unmodified lines | |||
| 823 | int ret; | 784 | int ret; |
| 824 | 785 | ||
| 825 | mutex_lock(&q->sysfs_dir_lock); | 786 | mutex_lock(&q->sysfs_dir_lock); |
| 826 | ret = kobject_add(&q->kobj, &disk_to_dev(disk)->kobj, "queue"); | 787 | kobject_init(&disk->queue_kobj, &blk_queue_ktype); |
| 788 | ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue"); | ||
| 827 | if (ret < 0) | 789 | if (ret < 0) |
| 828 | goto out_unlock_dir; | 790 | goto out_put_queue_kobj; |
| 829 | 791 | ||
| 830 | if (queue_is_mq(q)) { | 792 | if (queue_is_mq(q)) { |
| 831 | ret = blk_mq_sysfs_register(disk); | 793 | ret = blk_mq_sysfs_register(disk); |
| 832 | if (ret) | 794 | if (ret) |
| 833 | goto out_del_queue_kobj; | 795 | goto out_put_queue_kobj; |
| 834 | } | 796 | } |
| 835 | mutex_lock(&q->sysfs_lock); | 797 | mutex_lock(&q->sysfs_lock); |
| 836 | 798 | ||
| 837 | mutex_lock(&q->debugfs_mutex); | 799 | mutex_lock(&q->debugfs_mutex); |
| 838 | q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent), | 800 | q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root); |
| 839 | blk_debugfs_root); | ||
| 840 | if (queue_is_mq(q)) | 801 | if (queue_is_mq(q)) |
| 841 | blk_mq_debugfs_register(q); | 802 | blk_mq_debugfs_register(q); |
| 842 | mutex_unlock(&q->debugfs_mutex); | 803 | mutex_unlock(&q->debugfs_mutex); |
| @@ -860,7 +821,7 @@ int blk_register_queue(struct gendisk *disk) · 17 unmodified lines | |||
| 860 | blk_throtl_register(disk); | 821 | blk_throtl_register(disk); |
| 861 | 822 | ||
| 862 | /* Now everything is ready and send out KOBJ_ADD uevent */ | 823 | /* Now everything is ready and send out KOBJ_ADD uevent */ |
| 863 | kobject_uevent(&q->kobj, KOBJ_ADD); | 824 | kobject_uevent(&disk->queue_kobj, KOBJ_ADD); |
| 864 | if (q->elevator) | 825 | if (q->elevator) |
| 865 | kobject_uevent(&q->elevator->kobj, KOBJ_ADD); | 826 | kobject_uevent(&q->elevator->kobj, KOBJ_ADD); |
| 866 | mutex_unlock(&q->sysfs_lock); | 827 | mutex_unlock(&q->sysfs_lock); |
| @@ -889,9 +850,8 @@ out_unregister_ia_ranges: · 22 unmodified lines | |||
| 889 | out_debugfs_remove: | 850 | out_debugfs_remove: |
| 890 | blk_debugfs_remove(disk); | 851 | blk_debugfs_remove(disk); |
| 891 | mutex_unlock(&q->sysfs_lock); | 852 | mutex_unlock(&q->sysfs_lock); |
| 892 | out_del_queue_kobj: | 853 | out_put_queue_kobj: |
| 893 | kobject_del(&q->kobj); | 854 | kobject_put(&disk->queue_kobj); |
| 894 | out_unlock_dir: | ||
| 895 | mutex_unlock(&q->sysfs_dir_lock); | 855 | mutex_unlock(&q->sysfs_dir_lock); |
| 896 | return ret; | 856 | return ret; |
| 897 | } | 857 | } |
| @@ -938,8 +898,8 @@ void blk_unregister_queue(struct gendisk *disk) · 40 unmodified lines | |||
| 938 | mutex_unlock(&q->sysfs_lock); | 898 | mutex_unlock(&q->sysfs_lock); |
| 939 | 899 | ||
| 940 | /* Now that we've deleted all child objects, we can delete the queue. */ | 900 | /* Now that we've deleted all child objects, we can delete the queue. */ |
| 941 | kobject_uevent(&q->kobj, KOBJ_REMOVE); | 901 | kobject_uevent(&disk->queue_kobj, KOBJ_REMOVE); |
| 942 | kobject_del(&q->kobj); | 902 | kobject_del(&disk->queue_kobj); |
| 943 | mutex_unlock(&q->sysfs_dir_lock); | 903 | mutex_unlock(&q->sysfs_dir_lock); |
| 944 | 904 | ||
| 945 | blk_debugfs_remove(disk); | 905 | blk_debugfs_remove(disk); |
| @@ -26,10 +26,6 @@ struct blk_flush_queue { · 25 unmodified lines | |||
| 26 | spinlock_t mq_flush_lock; | 26 | spinlock_t mq_flush_lock; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | extern struct kmem_cache *blk_requestq_cachep; | ||
| 30 | extern struct kobj_type blk_queue_ktype; | ||
| 31 | extern struct ida blk_queue_ida; | ||
| 32 | |||
| 33 | bool is_flush_rq(struct request *req); | 29 | bool is_flush_rq(struct request *req); |
| 34 | 30 | ||
| 35 | struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size, | 31 | struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size, |
| @@ -175,8 +175,10 @@ static void bsg_device_release(struct device *dev) · 174 unmodified lines | |||
| 175 | 175 | ||
| 176 | void bsg_unregister_queue(struct bsg_device *bd) | 176 | void bsg_unregister_queue(struct bsg_device *bd) |
| 177 | { | 177 | { |
| 178 | if (bd->queue->kobj.sd) | 178 | struct gendisk *disk = bd->queue->disk; |
| 179 | sysfs_remove_link(&bd->queue->kobj, "bsg"); | 179 | |
| 180 | if (disk && disk->queue_kobj.sd) | ||
| 181 | sysfs_remove_link(&disk->queue_kobj, "bsg"); | ||
| 180 | cdev_device_del(&bd->cdev, &bd->device); | 182 | cdev_device_del(&bd->cdev, &bd->device); |
| 181 | put_device(&bd->device); | 183 | put_device(&bd->device); |
| 182 | } | 184 | } |
| @@ -216,8 +218,9 @@ struct bsg_device *bsg_register_queue(struct request_queue *q, · 33 unmodified lines | |||
| 216 | if (ret) | 218 | if (ret) |
| 217 | goto out_put_device; | 219 | goto out_put_device; |
| 218 | 220 | ||
| 219 | if (q->kobj.sd) { | 221 | if (q->disk && q->disk->queue_kobj.sd) { |
| 220 | ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg"); | 222 | ret = sysfs_create_link(&q->disk->queue_kobj, &bd->device.kobj, |
| 223 | "bsg"); | ||
| 221 | if (ret) | 224 | if (ret) |
| 222 | goto out_device_del; | 225 | goto out_device_del; |
| 223 | } | 226 | } |
| @@ -467,7 +467,7 @@ int elv_register_queue(struct request_queue *q, bool uevent) · 466 unmodified lines | |||
| 467 | 467 | ||
| 468 | lockdep_assert_held(&q->sysfs_lock); | 468 | lockdep_assert_held(&q->sysfs_lock); |
| 469 | 469 | ||
| 470 | error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); | 470 | error = kobject_add(&e->kobj, &q->disk->queue_kobj, "iosched"); |
| 471 | if (!error) { | 471 | if (!error) { |
| 472 | struct elv_fs_entry *attr = e->type->elevator_attrs; | 472 | struct elv_fs_entry *attr = e->type->elevator_attrs; |
| 473 | if (attr) { | 473 | if (attr) { |
| @@ -155,6 +155,7 @@ struct gendisk { · 154 unmodified lines | |||
| 155 | unsigned open_partitions; /* number of open partitions */ | 155 | unsigned open_partitions; /* number of open partitions */ |
| 156 | 156 | ||
| 157 | struct backing_dev_info *bdi; | 157 | struct backing_dev_info *bdi; |
| 158 | struct kobject queue_kobj; /* the queue/ directory */ | ||
| 158 | struct kobject *slave_dir; | 159 | struct kobject *slave_dir; |
| 159 | #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED | 160 | #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED |
| 160 | struct list_head slave_bdevs; | 161 | struct list_head slave_bdevs; |
| @@ -430,10 +431,7 @@ struct request_queue { · 269 unmodified lines | |||
| 430 | 431 | ||
| 431 | struct gendisk *disk; | 432 | struct gendisk *disk; |
| 432 | 433 | ||
| 433 | /* | 434 | refcount_t refs; |
| 434 | * queue kobject | ||
| 435 | */ | ||
| 436 | struct kobject kobj; | ||
| 437 | 435 | ||
| 438 | /* | 436 | /* |
| 439 | * mq queue kobject | 437 | * mq queue kobject |