Skip to content

Commit 2bd8522

Browse files
Christoph Hellwigaxboe
authored andcommitted
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. Signed-off-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 4060299 commit 2bd8522

File tree

8 files changed

+71
-87
lines changed

8 files changed

+71
-87
lines changed

block/blk-core.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_split);
5959
EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
6060
EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert);
6161

62-
DEFINE_IDA(blk_queue_ida);
62+
static DEFINE_IDA(blk_queue_ida);
6363

6464
/*
6565
* For queue allocation
6666
*/
67-
struct kmem_cache *blk_requestq_cachep;
67+
static struct kmem_cache *blk_requestq_cachep;
6868

6969
/*
7070
* Controlling structure to kblockd
@@ -252,19 +252,46 @@ void blk_clear_pm_only(struct request_queue *q)
252252
}
253253
EXPORT_SYMBOL_GPL(blk_clear_pm_only);
254254

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+
255281
/**
256282
* blk_put_queue - decrement the request_queue refcount
257283
* @q: the request_queue structure to decrement the refcount for
258284
*
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.
261287
*
262288
* Context: Any context, but the last reference must not be dropped from
263289
* atomic context.
264290
*/
265291
void blk_put_queue(struct request_queue *q)
266292
{
267-
kobject_put(&q->kobj);
293+
if (refcount_dec_and_test(&q->refs))
294+
blk_free_queue(q);
268295
}
269296
EXPORT_SYMBOL(blk_put_queue);
270297

@@ -399,8 +426,7 @@ struct request_queue *blk_alloc_queue(int node_id)
399426
INIT_WORK(&q->timeout_work, blk_timeout_work);
400427
INIT_LIST_HEAD(&q->icq_list);
401428

402-
kobject_init(&q->kobj, &blk_queue_ktype);
403-
429+
refcount_set(&q->refs, 1);
404430
mutex_init(&q->debugfs_mutex);
405431
mutex_init(&q->sysfs_lock);
406432
mutex_init(&q->sysfs_dir_lock);
@@ -445,7 +471,7 @@ bool blk_get_queue(struct request_queue *q)
445471
{
446472
if (unlikely(blk_queue_dying(q)))
447473
return false;
448-
kobject_get(&q->kobj);
474+
refcount_inc(&q->refs);
449475
return true;
450476
}
451477
EXPORT_SYMBOL(blk_get_queue);

block/blk-crypto-sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ int blk_crypto_sysfs_register(struct gendisk *disk)
140140
return -ENOMEM;
141141
obj->profile = q->crypto_profile;
142142

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");
145145
if (err) {
146146
kobject_put(&obj->kobj);
147147
return err;

block/blk-ia-ranges.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ int disk_register_independent_access_ranges(struct gendisk *disk)
123123
*/
124124
WARN_ON(iars->sysfs_registered);
125125
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");
127128
if (ret) {
128129
disk->ia_ranges = NULL;
129130
kobject_put(&iars->kobj);

block/blk-sysfs.c

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -683,8 +683,8 @@ static struct attribute *queue_attrs[] = {
683683
static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr,
684684
int n)
685685
{
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;
688688

689689
if (attr == &queue_io_timeout_entry.attr &&
690690
(!q->mq_ops || !q->mq_ops->timeout))
@@ -710,8 +710,8 @@ static ssize_t
710710
queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
711711
{
712712
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;
715715
ssize_t res;
716716

717717
if (!entry->show)
@@ -727,63 +727,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
727727
const char *page, size_t length)
728728
{
729729
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;
731732
ssize_t res;
732733

733734
if (!entry->store)
734735
return -EIO;
735736

736-
q = container_of(kobj, struct request_queue, kobj);
737737
mutex_lock(&q->sysfs_lock);
738738
res = entry->store(q, page, length);
739739
mutex_unlock(&q->sysfs_lock);
740740
return res;
741741
}
742742

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-
787743
static const struct sysfs_ops queue_sysfs_ops = {
788744
.show = queue_attr_show,
789745
.store = queue_attr_store,
@@ -794,10 +750,15 @@ static const struct attribute_group *blk_queue_attr_groups[] = {
794750
NULL
795751
};
796752

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 = {
798759
.default_groups = blk_queue_attr_groups,
799760
.sysfs_ops = &queue_sysfs_ops,
800-
.release = blk_release_queue,
761+
.release = blk_queue_release,
801762
};
802763

803764
static void blk_debugfs_remove(struct gendisk *disk)
@@ -823,20 +784,20 @@ int blk_register_queue(struct gendisk *disk)
823784
int ret;
824785

825786
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");
827789
if (ret < 0)
828-
goto out_unlock_dir;
790+
goto out_put_queue_kobj;
829791

830792
if (queue_is_mq(q)) {
831793
ret = blk_mq_sysfs_register(disk);
832794
if (ret)
833-
goto out_del_queue_kobj;
795+
goto out_put_queue_kobj;
834796
}
835797
mutex_lock(&q->sysfs_lock);
836798

837799
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);
840801
if (queue_is_mq(q))
841802
blk_mq_debugfs_register(q);
842803
mutex_unlock(&q->debugfs_mutex);
@@ -860,7 +821,7 @@ int blk_register_queue(struct gendisk *disk)
860821
blk_throtl_register(disk);
861822

862823
/* 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);
864825
if (q->elevator)
865826
kobject_uevent(&q->elevator->kobj, KOBJ_ADD);
866827
mutex_unlock(&q->sysfs_lock);
@@ -889,9 +850,8 @@ int blk_register_queue(struct gendisk *disk)
889850
out_debugfs_remove:
890851
blk_debugfs_remove(disk);
891852
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);
895855
mutex_unlock(&q->sysfs_dir_lock);
896856
return ret;
897857
}
@@ -938,8 +898,8 @@ void blk_unregister_queue(struct gendisk *disk)
938898
mutex_unlock(&q->sysfs_lock);
939899

940900
/* 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);
943903
mutex_unlock(&q->sysfs_dir_lock);
944904

945905
blk_debugfs_remove(disk);

block/blk.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ struct blk_flush_queue {
2626
spinlock_t mq_flush_lock;
2727
};
2828

29-
extern struct kmem_cache *blk_requestq_cachep;
30-
extern struct kobj_type blk_queue_ktype;
31-
extern struct ida blk_queue_ida;
32-
3329
bool is_flush_rq(struct request *req);
3430

3531
struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,

block/bsg.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ static void bsg_device_release(struct device *dev)
175175

176176
void bsg_unregister_queue(struct bsg_device *bd)
177177
{
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");
180182
cdev_device_del(&bd->cdev, &bd->device);
181183
put_device(&bd->device);
182184
}
@@ -216,8 +218,9 @@ struct bsg_device *bsg_register_queue(struct request_queue *q,
216218
if (ret)
217219
goto out_put_device;
218220

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");
221224
if (ret)
222225
goto out_device_del;
223226
}

block/elevator.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ int elv_register_queue(struct request_queue *q, bool uevent)
467467

468468
lockdep_assert_held(&q->sysfs_lock);
469469

470-
error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
470+
error = kobject_add(&e->kobj, &q->disk->queue_kobj, "iosched");
471471
if (!error) {
472472
struct elv_fs_entry *attr = e->type->elevator_attrs;
473473
if (attr) {

include/linux/blkdev.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct gendisk {
155155
unsigned open_partitions; /* number of open partitions */
156156

157157
struct backing_dev_info *bdi;
158+
struct kobject queue_kobj; /* the queue/ directory */
158159
struct kobject *slave_dir;
159160
#ifdef CONFIG_BLOCK_HOLDER_DEPRECATED
160161
struct list_head slave_bdevs;
@@ -430,10 +431,7 @@ struct request_queue {
430431

431432
struct gendisk *disk;
432433

433-
/*
434-
* queue kobject
435-
*/
436-
struct kobject kobj;
434+
refcount_t refs;
437435

438436
/*
439437
* mq queue kobject

0 commit comments

Comments
 (0)