linux/block
Yu Kuai 56ac639d6f blk-cgroup: fix possible deadlock while configuring policy
[ Upstream commit 5d726c4dbe ]

Following deadlock can be triggered easily by lockdep:

WARNING: possible circular locking dependency detected
6.17.0-rc3-00124-ga12c2658ced0 #1665 Not tainted
------------------------------------------------------
check/1334 is trying to acquire lock:
ff1100011d9d0678 (&q->sysfs_lock){+.+.}-{4:4}, at: blk_unregister_queue+0x53/0x180

but task is already holding lock:
ff1100011d9d00e0 (&q->q_usage_counter(queue)#3){++++}-{0:0}, at: del_gendisk+0xba/0x110

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #2 (&q->q_usage_counter(queue)#3){++++}-{0:0}:
       blk_queue_enter+0x40b/0x470
       blkg_conf_prep+0x7b/0x3c0
       tg_set_limit+0x10a/0x3e0
       cgroup_file_write+0xc6/0x420
       kernfs_fop_write_iter+0x189/0x280
       vfs_write+0x256/0x490
       ksys_write+0x83/0x190
       __x64_sys_write+0x21/0x30
       x64_sys_call+0x4608/0x4630
       do_syscall_64+0xdb/0x6b0
       entry_SYSCALL_64_after_hwframe+0x76/0x7e

-> #1 (&q->rq_qos_mutex){+.+.}-{4:4}:
       __mutex_lock+0xd8/0xf50
       mutex_lock_nested+0x2b/0x40
       wbt_init+0x17e/0x280
       wbt_enable_default+0xe9/0x140
       blk_register_queue+0x1da/0x2e0
       __add_disk+0x38c/0x5d0
       add_disk_fwnode+0x89/0x250
       device_add_disk+0x18/0x30
       virtblk_probe+0x13a3/0x1800
       virtio_dev_probe+0x389/0x610
       really_probe+0x136/0x620
       __driver_probe_device+0xb3/0x230
       driver_probe_device+0x2f/0xe0
       __driver_attach+0x158/0x250
       bus_for_each_dev+0xa9/0x130
       driver_attach+0x26/0x40
       bus_add_driver+0x178/0x3d0
       driver_register+0x7d/0x1c0
       __register_virtio_driver+0x2c/0x60
       virtio_blk_init+0x6f/0xe0
       do_one_initcall+0x94/0x540
       kernel_init_freeable+0x56a/0x7b0
       kernel_init+0x2b/0x270
       ret_from_fork+0x268/0x4c0
       ret_from_fork_asm+0x1a/0x30

-> #0 (&q->sysfs_lock){+.+.}-{4:4}:
       __lock_acquire+0x1835/0x2940
       lock_acquire+0xf9/0x450
       __mutex_lock+0xd8/0xf50
       mutex_lock_nested+0x2b/0x40
       blk_unregister_queue+0x53/0x180
       __del_gendisk+0x226/0x690
       del_gendisk+0xba/0x110
       sd_remove+0x49/0xb0 [sd_mod]
       device_remove+0x87/0xb0
       device_release_driver_internal+0x11e/0x230
       device_release_driver+0x1a/0x30
       bus_remove_device+0x14d/0x220
       device_del+0x1e1/0x5a0
       __scsi_remove_device+0x1ff/0x2f0
       scsi_remove_device+0x37/0x60
       sdev_store_delete+0x77/0x100
       dev_attr_store+0x1f/0x40
       sysfs_kf_write+0x65/0x90
       kernfs_fop_write_iter+0x189/0x280
       vfs_write+0x256/0x490
       ksys_write+0x83/0x190
       __x64_sys_write+0x21/0x30
       x64_sys_call+0x4608/0x4630
       do_syscall_64+0xdb/0x6b0
       entry_SYSCALL_64_after_hwframe+0x76/0x7e

other info that might help us debug this:

Chain exists of:
  &q->sysfs_lock --> &q->rq_qos_mutex --> &q->q_usage_counter(queue)#3

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&q->q_usage_counter(queue)#3);
                               lock(&q->rq_qos_mutex);
                               lock(&q->q_usage_counter(queue)#3);
  lock(&q->sysfs_lock);

Root cause is that queue_usage_counter is grabbed with rq_qos_mutex
held in blkg_conf_prep(), while queue should be freezed before
rq_qos_mutex from other context.

The blk_queue_enter() from blkg_conf_prep() is used to protect against
policy deactivation, which is already protected with blkcg_mutex, hence
convert blk_queue_enter() to blkcg_mutex to fix this problem. Meanwhile,
consider that blkcg_mutex is held after queue is freezed from policy
deactivation, also convert blkg_alloc() to use GFP_NOIO.

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2025-11-13 15:34:07 -05:00
..
partitions block: fix conversion of GPT partition name to 7-bit 2025-03-13 13:01:58 +01:00
badblocks.c badblocks: Fix a nonsense WARN_ON() which checks whether a u64 variable < 0 2025-05-29 11:02:24 +02:00
bdev.c block: fix race between set_blocksize and read paths 2025-05-29 11:02:01 +02:00
bfq-cgroup.c Revert "block, bfq: merge bfq_release_process_ref() into bfq_put_cooperator()" 2024-12-05 14:02:54 +01:00
bfq-iosched.c lib/sbitmap: convert shallow_depth from one word to the whole sbitmap 2025-08-20 18:30:49 +02:00
bfq-iosched.h lib/sbitmap: convert shallow_depth from one word to the whole sbitmap 2025-08-20 18:30:49 +02:00
bfq-wf2q.c block, bfq: inject I/O to underutilized actuators 2023-01-29 15:18:33 -07:00
bio-integrity.c block: integrity: Do not call set_page_dirty_lock() 2025-04-25 10:47:50 +02:00
bio.c block: fix adding folio to bio 2025-06-10 07:12:59 -04:00
blk-cgroup-fc-appid.c block: Replace all non-returning strlcpy with strscpy 2023-06-01 09:13:31 -06:00
blk-cgroup-rwstat.c blk-cgroup: use group allocation/free of per-cpu counters API 2024-04-03 09:10:17 -06:00
blk-cgroup-rwstat.h block: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
blk-cgroup.c blk-cgroup: fix possible deadlock while configuring policy 2025-11-13 15:34:07 -05:00
blk-cgroup.h blk-cgroup: Remove unused declaration blkg_path() 2024-08-16 15:07:27 -06:00
blk-core.c block: add a rq_list type 2025-04-25 10:48:06 +02:00
blk-crypto-fallback.c blk-crypto: fix missing blktrace bio split events 2025-10-19 16:33:48 +02:00
blk-crypto-internal.h blk-crypto: remove blk_crypto_insert_cloned_request() 2023-03-16 09:35:09 -06:00
blk-crypto-profile.c blk-crypto: use dynamic lock class for blk_crypto_profile::lock 2023-07-05 16:36:12 -06:00
blk-crypto-sysfs.c block: make kobj_type structures constant 2023-02-09 09:38:16 -07:00
blk-crypto.c blk-crypto: make blk_crypto_evict_key() more robust 2023-03-16 09:35:09 -06:00
blk-flush.c for-6.11/block-20240710 2024-07-15 14:20:22 -07:00
blk-ia-ranges.c block: make kobj_type structures constant 2023-02-09 09:38:16 -07:00
blk-integrity.c block: add a queue_limits_commit_update_frozen helper 2025-09-09 18:58:24 +02:00
blk-ioc.c blk-ioc: fix recursive spin_lock/unlock_irq() in ioc_clear_queue() 2023-06-07 07:51:00 -06:00
blk-iocost.c blk-iocost: Avoid using clamp() on inuse in __propagate_weights() 2024-12-19 18:13:22 +01:00
blk-iolatency.c block: add blk_time_get_ns() and blk_time_get() helpers 2024-02-05 10:07:22 -07:00
blk-ioprio.c blk-ioprio: remove per-disk structure 2024-07-28 16:47:51 -06:00
blk-ioprio.h blk-ioprio: remove per-disk structure 2024-07-28 16:47:51 -06:00
blk-lib.c block: fix detection of unsupported WRITE SAME in blkdev_issue_write_zeroes 2024-08-28 08:49:25 -06:00
blk-map.c block: fix queue limits checks in blk_rq_map_user_bvec for real 2024-10-28 12:35:05 -06:00
blk-merge.c block: use plug request list tail for one-shot backmerge attempt 2025-06-27 11:11:19 +01:00
blk-mq-cpumap.c blk-mq: create correct map for fallback case 2025-05-09 09:50:48 +02:00
blk-mq-debugfs.c block: Catch possible entries missing from rqf_name[] 2024-07-19 09:32:49 -06:00
blk-mq-debugfs.h block: Replace zone_wlock debugfs entry with zone_wplugs entry 2024-04-17 08:44:03 -06:00
blk-mq-pci.c blk-mq: include <linux/blk-mq.h> in block/blk-mq.h 2023-04-13 06:52:29 -06:00
blk-mq-sched.c blk-mq: Remove the hctx 'run' debugfs attribute 2024-01-17 14:16:34 -07:00
blk-mq-sched.h blk-mq: make sure elevator callbacks aren't called for passthrough request 2023-05-18 19:42:54 -06:00
blk-mq-sysfs.c blk-mq: check kobject state_in_sysfs before deleting in blk_mq_unregister_hctx 2025-10-15 11:59:57 +02:00
blk-mq-tag.c block: Fix lockdep warning in blk_mq_mark_tag_wait 2024-08-15 19:25:03 -06:00
blk-mq-virtio.c blk-mq: include <linux/blk-mq.h> in block/blk-mq.h 2023-04-13 06:52:29 -06:00
blk-mq.c block: Introduce bio_needs_zone_write_plugging() 2025-08-20 18:30:51 +02:00
blk-mq.h block: add a rq_list type 2025-04-25 10:48:06 +02:00
blk-pm.c block: Remove blk_set_runtime_active() 2023-11-20 10:22:40 -07:00
blk-pm.h block: Remove unused blk_pm_*() function definitions 2021-02-22 06:33:48 -07:00
blk-rq-qos.c blk-rq-qos: fix crash on rq_qos_wait vs. rq_qos_wake_function race 2024-10-16 07:20:14 -06:00
blk-rq-qos.h block: skip QUEUE_FLAG_STATS and rq-qos for passthrough io 2023-12-01 18:29:18 -07:00
blk-settings.c block: use int to store blk_stack_limits() return value 2025-10-15 11:59:58 +02:00
blk-stat.c blk-throttle: remove CONFIG_BLK_DEV_THROTTLING_LOW 2024-05-09 09:44:55 -06:00
blk-stat.h block: delete redundant function declaration 2024-05-27 13:58:06 -06:00
blk-sysfs.c block: fix kobject leak in blk_unregister_queue 2025-07-24 08:56:30 +02:00
blk-throttle.c blk-throttle: don't take carryover for prioritized processing of metadata 2025-05-29 11:02:29 +02:00
blk-throttle.h blk-throttle: remove last_low_overflow_time 2024-09-10 16:31:41 -06:00
blk-timeout.c block: blk-timeout: delete duplicated word 2020-07-31 16:29:47 -06:00
blk-wbt.c blk-wbt: don't throttle swap writes in direct reclaim 2024-07-01 06:51:53 -06:00
blk-wbt.h blk-wbt: remove the separate write cache tracking 2023-12-26 09:28:10 -07:00
blk-zoned.c block: add a queue_limits_commit_update_frozen helper 2025-09-09 18:58:24 +02:00
blk.h block: only update request sector if needed 2025-05-29 11:03:12 +02:00
bounce.c block: mark bounce buffering as incompatible with integrity 2025-05-29 11:02:32 +02:00
bsg-lib.c scsi: bsg: Pass dev to blk_mq_alloc_queue() 2024-05-30 20:22:15 -04:00
bsg.c SCSI misc on 20230629 2023-06-30 11:57:07 -07:00
disk-events.c block: move bdev_mark_dead out of disk_check_media_change 2023-10-28 13:29:23 +02:00
early-lookup.c wrapper for access to ->bd_partno 2024-05-02 17:48:09 -04:00
elevator.c block: use q->elevator with ->elevator_lock held in elv_iosched_show() 2025-06-19 15:32:32 +02:00
elevator.h block: Prevent deadlocks when switching elevators 2024-09-10 13:43:42 -06:00
fops.c block: fix race between set_blocksize and read paths 2025-05-29 11:02:01 +02:00
genhd.c block: retry call probe after request_module in blk_request_module 2025-02-08 09:56:51 +01:00
holder.c block: fix deadlock between bd_link_disk_holder and partition scan 2024-02-23 07:44:19 -07:00
ioctl.c block: fix race between set_blocksize and read paths 2025-05-29 11:02:01 +02:00
ioprio.c block: move __get_task_ioprio() into header file 2024-01-08 12:27:39 -07:00
Kconfig block: remove the blk_integrity_profile structure 2024-06-14 10:20:06 -06:00
Kconfig.iosched block: Default to use cgroup support for BFQ 2023-01-30 09:42:42 -07:00
kyber-iosched.c lib/sbitmap: convert shallow_depth from one word to the whole sbitmap 2025-08-20 18:30:49 +02:00
Makefile block: remove the blk_integrity_profile structure 2024-06-14 10:20:06 -06:00
mq-deadline.c lib/sbitmap: convert shallow_depth from one word to the whole sbitmap 2025-08-20 18:30:49 +02:00
opal_proto.h block: sed-opal: handle empty atoms when parsing response 2024-02-16 15:52:45 -07:00
sed-opal.c block: sed-opal: avoid possible wrong address reference in read_sed_opal_key() 2024-06-12 10:53:20 -06:00
t10-pi.c move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00