Skip to content

Commit 8700ed8

Browse files
Ming LeiSasha Levin
authored andcommitted
block: use trylock to avoid lockdep circular dependency in sysfs
[ Upstream commit ce8ee85 ] Use trylock instead of blocking lock acquisition for update_nr_hwq_lock in queue_requests_store() and elv_iosched_store() to avoid circular lock dependency with kernfs active reference during concurrent disk deletion: update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del) kn->active -> update_nr_hwq_lock (via sysfs write path) Return -EBUSY when the lock is not immediately available. Reported-and-tested-by: Yi Zhang <yi.zhang@redhat.com> Closes: https://lore.kernel.org/linux-block/CAHj4cs-em-4acsHabMdT=jJhXkCzjnprD-aQH1OgrZo4nTnmMw@mail.gmail.com/ Fixes: 626ff4f ("blk-mq: convert to serialize updating nr_requests with update_nr_hwq_lock") Signed-off-by: Ming Lei <ming.lei@redhat.com> Tested-by: Yi Zhang <yi.zhang@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent c52f641 commit 8700ed8

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

block/blk-sysfs.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,14 @@ queue_requests_store(struct gendisk *disk, const char *page, size_t count)
7878
/*
7979
* Serialize updating nr_requests with concurrent queue_requests_store()
8080
* and switching elevator.
81+
*
82+
* Use trylock to avoid circular lock dependency with kernfs active
83+
* reference during concurrent disk deletion:
84+
* update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
85+
* kn->active -> update_nr_hwq_lock (via this sysfs write path)
8186
*/
82-
down_write(&set->update_nr_hwq_lock);
87+
if (!down_write_trylock(&set->update_nr_hwq_lock))
88+
return -EBUSY;
8389

8490
if (nr == q->nr_requests)
8591
goto unlock;

block/elevator.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,16 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
806806
elv_iosched_load_module(ctx.name);
807807
ctx.type = elevator_find_get(ctx.name);
808808

809-
down_read(&set->update_nr_hwq_lock);
809+
/*
810+
* Use trylock to avoid circular lock dependency with kernfs active
811+
* reference during concurrent disk deletion:
812+
* update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
813+
* kn->active -> update_nr_hwq_lock (via this sysfs write path)
814+
*/
815+
if (!down_read_trylock(&set->update_nr_hwq_lock)) {
816+
ret = -EBUSY;
817+
goto out;
818+
}
810819
if (!blk_queue_no_elv_switch(q)) {
811820
ret = elevator_change(q, &ctx);
812821
if (!ret)
@@ -816,6 +825,7 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
816825
}
817826
up_read(&set->update_nr_hwq_lock);
818827

828+
out:
819829
if (ctx.type)
820830
elevator_put(ctx.type);
821831
return ret;

0 commit comments

Comments
 (0)