Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

block: use trylock to avoid lockdep circular dependency in sysfs

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: 626ff4f8ebcb ("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>

authored by

Ming Lei and committed by
Jens Axboe
ce8ee858 d90c470b

+18 -2
+7 -1
block/blk-sysfs.c
··· 78 78 /* 79 79 * Serialize updating nr_requests with concurrent queue_requests_store() 80 80 * 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) 81 86 */ 82 - down_write(&set->update_nr_hwq_lock); 87 + if (!down_write_trylock(&set->update_nr_hwq_lock)) 88 + return -EBUSY; 83 89 84 90 if (nr == q->nr_requests) 85 91 goto unlock;
+11 -1
block/elevator.c
··· 807 807 elv_iosched_load_module(ctx.name); 808 808 ctx.type = elevator_find_get(ctx.name); 809 809 810 - down_read(&set->update_nr_hwq_lock); 810 + /* 811 + * Use trylock to avoid circular lock dependency with kernfs active 812 + * reference during concurrent disk deletion: 813 + * update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del) 814 + * kn->active -> update_nr_hwq_lock (via this sysfs write path) 815 + */ 816 + if (!down_read_trylock(&set->update_nr_hwq_lock)) { 817 + ret = -EBUSY; 818 + goto out; 819 + } 811 820 if (!blk_queue_no_elv_switch(q)) { 812 821 ret = elevator_change(q, &ctx); 813 822 if (!ret) ··· 826 817 } 827 818 up_read(&set->update_nr_hwq_lock); 828 819 820 + out: 829 821 if (ctx.type) 830 822 elevator_put(ctx.type); 831 823 return ret;