History

block: untangle request_queue refcounting from sysfs

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.

Christoph Hellwig committed 4 years ago

Commit 2bd85221 parent 40602998 files · +71 −87Browse files

Unified · Split

8 files
  1. block/blk-core.c +34 −8
  2. block/blk-crypto-sysfs.c +2 −2
  3. block/blk-ia-ranges.c +2 −1
  4. block/blk-sysfs.c +23 −63
  5. block/blk.h +0 −4
  6. block/bsg.c +7 −4
  7. block/elevator.c +1 −1
  8. include/linux/blkdev.h +2 −4
block/blk-core.c+34−8
@@ -59,12 +59,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_split); · 58 unmodified lines
59EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);59EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
60EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert);60EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert);
61 61
62DEFINE_IDA(blk_queue_ida);62static DEFINE_IDA(blk_queue_ida);
63 63
64/*64/*
65 * For queue allocation65 * For queue allocation
66 */66 */
67struct kmem_cache *blk_requestq_cachep;67static struct kmem_cache *blk_requestq_cachep;
68 68
69/*69/*
70 * Controlling structure to kblockd70 * Controlling structure to kblockd
@@ -252,19 +252,46 @@ void blk_clear_pm_only(struct request_queue *q) · 181 unmodified lines
252}252}
253EXPORT_SYMBOL_GPL(blk_clear_pm_only);253EXPORT_SYMBOL_GPL(blk_clear_pm_only);
254 254
255static 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
261static 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 refcount282 * blk_put_queue - decrement the request_queue refcount
257 * @q: the request_queue structure to decrement the refcount for283 * @q: the request_queue structure to decrement the refcount for
258 *284 *
259 * Decrements the refcount of the request_queue kobject. When this reaches 0285 * 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 from288 * Context: Any context, but the last reference must not be dropped from
263 * atomic context.289 * atomic context.
264 */290 */
265void blk_put_queue(struct request_queue *q)291void 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}
269EXPORT_SYMBOL(blk_put_queue);296EXPORT_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}
451EXPORT_SYMBOL(blk_get_queue);477EXPORT_SYMBOL(blk_get_queue);
block/blk-crypto-sysfs.c+2−2
@@ -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;
block/blk-ia-ranges.c+2−1
@@ -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);
block/blk-sysfs.c+23−63
@@ -683,8 +683,8 @@ static struct attribute *queue_attrs[] = { · 682 unmodified lines
683static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr,683static 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
710queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)710queue_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
743static 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 */
764static 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
787static const struct sysfs_ops queue_sysfs_ops = {743static 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 NULL750 NULL
795};751};
796 752
797struct kobj_type blk_queue_ktype = {753static void blk_queue_release(struct kobject *kobj)
754{
755 /* nothing to do here, all data is associated with the parent gendisk */
756}
757
758static 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
803static void blk_debugfs_remove(struct gendisk *disk)764static 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
889out_debugfs_remove:850out_debugfs_remove:
890 blk_debugfs_remove(disk);851 blk_debugfs_remove(disk);
891 mutex_unlock(&q->sysfs_lock);852 mutex_unlock(&q->sysfs_lock);
892out_del_queue_kobj:853out_put_queue_kobj:
893 kobject_del(&q->kobj);854 kobject_put(&disk->queue_kobj);
894out_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);
block/blk.h+0−4
@@ -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
29extern struct kmem_cache *blk_requestq_cachep;
30extern struct kobj_type blk_queue_ktype;
31extern struct ida blk_queue_ida;
32
33bool is_flush_rq(struct request *req);29bool is_flush_rq(struct request *req);
34 30
35struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,31struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
block/bsg.c+7−4
@@ -175,8 +175,10 @@ static void bsg_device_release(struct device *dev) · 174 unmodified lines
175 175
176void bsg_unregister_queue(struct bsg_device *bd)176void 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 }
block/elevator.c+1−1
@@ -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) {
include/linux/blkdev.h+2−4
@@ -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_DEPRECATED160#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 kobject437 * mq queue kobject