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 | 59 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug); |
| 60 | 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 | 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 | 70 | * Controlling structure to kblockd |
| @@ -252,19 +252,46 @@ void blk_clear_pm_only(struct request_queue *q) · 181 unmodified lines | ||
| 252 | 252 | } |
| 253 | 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 | 282 | * blk_put_queue - decrement the request_queue refcount |
| 257 | 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 | |
| 260 | − * we'll have blk_release_queue() called. | |
| 285 | + * Decrements the refcount of the request_queue and free it when the refcount | |
| 286 | + * reaches 0. | |
| 261 | 287 | * |
| 262 | 288 | * Context: Any context, but the last reference must not be dropped from |
| 263 | 289 | * atomic context. |
| 264 | 290 | */ |
| 265 | 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 | 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 | 426 | INIT_WORK(&q->timeout_work, blk_timeout_work); |
| 400 | 427 | INIT_LIST_HEAD(&q->icq_list); |
| 401 | 428 | |
| 402 | − kobject_init(&q->kobj, &blk_queue_ktype); | |
| 403 | − | |
| 429 | + refcount_set(&q->refs, 1); | |
| 404 | 430 | mutex_init(&q->debugfs_mutex); |
| 405 | 431 | mutex_init(&q->sysfs_lock); |
| 406 | 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 | 472 | if (unlikely(blk_queue_dying(q))) |
| 447 | 473 | return false; |
| 448 | − kobject_get(&q->kobj); | |
| 474 | + refcount_inc(&q->refs); | |
| 449 | 475 | return true; |
| 450 | 476 | } |
| 451 | 477 | EXPORT_SYMBOL(blk_get_queue); |
| @@ -140,8 +140,8 @@ int blk_crypto_sysfs_register(struct gendisk *disk) · 139 unmodified lines | ||
| 140 | 140 | return -ENOMEM; |
| 141 | 141 | obj->profile = q->crypto_profile; |
| 142 | 142 | |
| 143 | − err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, &q->kobj, | |
| 144 | − "crypto"); | |
| 143 | + err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, | |
| 144 | + &disk->queue_kobj, "crypto"); | |
| 145 | 145 | if (err) { |
| 146 | 146 | kobject_put(&obj->kobj); |
| 147 | 147 | return err; |
| @@ -123,7 +123,8 @@ int disk_register_independent_access_ranges(struct gendisk *disk) · 122 unmodified lines | ||
| 123 | 123 | */ |
| 124 | 124 | WARN_ON(iars->sysfs_registered); |
| 125 | 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 | 128 | if (ret) { |
| 128 | 129 | disk->ia_ranges = NULL; |
| 129 | 130 | kobject_put(&iars->kobj); |
| @@ -683,8 +683,8 @@ static struct attribute *queue_attrs[] = { · 682 unmodified lines | ||
| 683 | 683 | static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr, |
| 684 | 684 | int n) |
| 685 | 685 | { |
| 686 | − struct request_queue *q = | |
| 687 | − container_of(kobj, struct request_queue, kobj); | |
| 686 | + struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); | |
| 687 | + struct request_queue *q = disk->queue; | |
| 688 | 688 | |
| 689 | 689 | if (attr == &queue_io_timeout_entry.attr && |
| 690 | 690 | (!q->mq_ops || !q->mq_ops->timeout)) |
| @@ -710,8 +710,8 @@ static ssize_t · 19 unmodified lines | ||
| 710 | 710 | queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) |
| 711 | 711 | { |
| 712 | 712 | struct queue_sysfs_entry *entry = to_queue(attr); |
| 713 | − struct request_queue *q = | |
| 714 | − container_of(kobj, struct request_queue, kobj); | |
| 713 | + struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); | |
| 714 | + struct request_queue *q = disk->queue; | |
| 715 | 715 | ssize_t res; |
| 716 | 716 | |
| 717 | 717 | if (!entry->show) |
| @@ -727,63 +727,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr, · 9 unmodified lines | ||
| 727 | 727 | const char *page, size_t length) |
| 728 | 728 | { |
| 729 | 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 | 732 | ssize_t res; |
| 732 | 733 | |
| 733 | 734 | if (!entry->store) |
| 734 | 735 | return -EIO; |
| 735 | 736 | |
| 736 | − q = container_of(kobj, struct request_queue, kobj); | |
| 737 | 737 | mutex_lock(&q->sysfs_lock); |
| 738 | 738 | res = entry->store(q, page, length); |
| 739 | 739 | mutex_unlock(&q->sysfs_lock); |
| 740 | 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 | 743 | static const struct sysfs_ops queue_sysfs_ops = { |
| 788 | 744 | .show = queue_attr_show, |
| 789 | 745 | .store = queue_attr_store, |
| @@ -794,10 +750,15 @@ static const struct attribute_group *blk_queue_attr_groups[] = { · 4 unmodified lines | ||
| 794 | 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 | 759 | .default_groups = blk_queue_attr_groups, |
| 799 | 760 | .sysfs_ops = &queue_sysfs_ops, |
| 800 | − .release = blk_release_queue, | |
| 761 | + .release = blk_queue_release, | |
| 801 | 762 | }; |
| 802 | 763 | |
| 803 | 764 | static void blk_debugfs_remove(struct gendisk *disk) |
| @@ -823,20 +784,20 @@ int blk_register_queue(struct gendisk *disk) · 19 unmodified lines | ||
| 823 | 784 | int ret; |
| 824 | 785 | |
| 825 | 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 | 789 | if (ret < 0) |
| 828 | − goto out_unlock_dir; | |
| 790 | + goto out_put_queue_kobj; | |
| 829 | 791 | |
| 830 | 792 | if (queue_is_mq(q)) { |
| 831 | 793 | ret = blk_mq_sysfs_register(disk); |
| 832 | 794 | if (ret) |
| 833 | − goto out_del_queue_kobj; | |
| 795 | + goto out_put_queue_kobj; | |
| 834 | 796 | } |
| 835 | 797 | mutex_lock(&q->sysfs_lock); |
| 836 | 798 | |
| 837 | 799 | mutex_lock(&q->debugfs_mutex); |
| 838 | − q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent), | |
| 839 | − blk_debugfs_root); | |
| 800 | + q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root); | |
| 840 | 801 | if (queue_is_mq(q)) |
| 841 | 802 | blk_mq_debugfs_register(q); |
| 842 | 803 | mutex_unlock(&q->debugfs_mutex); |
| @@ -860,7 +821,7 @@ int blk_register_queue(struct gendisk *disk) · 17 unmodified lines | ||
| 860 | 821 | blk_throtl_register(disk); |
| 861 | 822 | |
| 862 | 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 | 825 | if (q->elevator) |
| 865 | 826 | kobject_uevent(&q->elevator->kobj, KOBJ_ADD); |
| 866 | 827 | mutex_unlock(&q->sysfs_lock); |
| @@ -889,9 +850,8 @@ out_unregister_ia_ranges: · 22 unmodified lines | ||
| 889 | 850 | out_debugfs_remove: |
| 890 | 851 | blk_debugfs_remove(disk); |
| 891 | 852 | mutex_unlock(&q->sysfs_lock); |
| 892 | −out_del_queue_kobj: | |
| 893 | − kobject_del(&q->kobj); | |
| 894 | −out_unlock_dir: | |
| 853 | +out_put_queue_kobj: | |
| 854 | + kobject_put(&disk->queue_kobj); | |
| 895 | 855 | mutex_unlock(&q->sysfs_dir_lock); |
| 896 | 856 | return ret; |
| 897 | 857 | } |
| @@ -938,8 +898,8 @@ void blk_unregister_queue(struct gendisk *disk) · 40 unmodified lines | ||
| 938 | 898 | mutex_unlock(&q->sysfs_lock); |
| 939 | 899 | |
| 940 | 900 | /* Now that we've deleted all child objects, we can delete the queue. */ |
| 941 | − kobject_uevent(&q->kobj, KOBJ_REMOVE); | |
| 942 | − kobject_del(&q->kobj); | |
| 901 | + kobject_uevent(&disk->queue_kobj, KOBJ_REMOVE); | |
| 902 | + kobject_del(&disk->queue_kobj); | |
| 943 | 903 | mutex_unlock(&q->sysfs_dir_lock); |
| 944 | 904 | |
| 945 | 905 | blk_debugfs_remove(disk); |
| @@ -26,10 +26,6 @@ struct blk_flush_queue { · 25 unmodified lines | ||
| 26 | 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 | 29 | bool is_flush_rq(struct request *req); |
| 34 | 30 | |
| 35 | 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 | 176 | void bsg_unregister_queue(struct bsg_device *bd) |
| 177 | 177 | { |
| 178 | − if (bd->queue->kobj.sd) | |
| 179 | − sysfs_remove_link(&bd->queue->kobj, "bsg"); | |
| 178 | + struct gendisk *disk = bd->queue->disk; | |
| 179 | + | |
| 180 | + if (disk && disk->queue_kobj.sd) | |
| 181 | + sysfs_remove_link(&disk->queue_kobj, "bsg"); | |
| 180 | 182 | cdev_device_del(&bd->cdev, &bd->device); |
| 181 | 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 | 218 | if (ret) |
| 217 | 219 | goto out_put_device; |
| 218 | 220 | |
| 219 | − if (q->kobj.sd) { | |
| 220 | − ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg"); | |
| 221 | + if (q->disk && q->disk->queue_kobj.sd) { | |
| 222 | + ret = sysfs_create_link(&q->disk->queue_kobj, &bd->device.kobj, | |
| 223 | + "bsg"); | |
| 221 | 224 | if (ret) |
| 222 | 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 | 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 | 471 | if (!error) { |
| 472 | 472 | struct elv_fs_entry *attr = e->type->elevator_attrs; |
| 473 | 473 | if (attr) { |
| @@ -155,6 +155,7 @@ struct gendisk { · 154 unmodified lines | ||
| 155 | 155 | unsigned open_partitions; /* number of open partitions */ |
| 156 | 156 | |
| 157 | 157 | struct backing_dev_info *bdi; |
| 158 | + struct kobject queue_kobj; /* the queue/ directory */ | |
| 158 | 159 | struct kobject *slave_dir; |
| 159 | 160 | #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED |
| 160 | 161 | struct list_head slave_bdevs; |
| @@ -430,10 +431,7 @@ struct request_queue { · 269 unmodified lines | ||
| 430 | 431 | |
| 431 | 432 | struct gendisk *disk; |
| 432 | 433 | |
| 433 | − /* | |
| 434 | − * queue kobject | |
| 435 | − */ | |
| 436 | − struct kobject kobj; | |
| 434 | + refcount_t refs; | |
| 437 | 435 | |
| 438 | 436 | /* |
| 439 | 437 | * mq queue kobject |