block: Fix potential deadlock in blk_ia_range_sysfs_show()
authorDamien Le Moal <damien.lemoal@opensource.wdc.com>
Fri, 3 Jun 2022 02:19:05 +0000 (11:19 +0900)
committerJens Axboe <axboe@kernel.dk>
Fri, 3 Jun 2022 05:02:37 +0000 (23:02 -0600)
When being read, a sysfs attribute is already protected against removal
with the kobject node active reference counter. As a result, in
blk_ia_range_sysfs_show(), there is no need to take the queue sysfs
lock when reading the value of a range attribute. Using the queue sysfs
lock in this function creates a potential deadlock situation with the
disk removal, something that a lockdep signals with a splat when the
device is removed:

[  760.703551]  Possible unsafe locking scenario:
[  760.703551]
[  760.703554]        CPU0                    CPU1
[  760.703556]        ----                    ----
[  760.703558]   lock(&q->sysfs_lock);
[  760.703565]                                lock(kn->active#385);
[  760.703573]                                lock(&q->sysfs_lock);
[  760.703579]   lock(kn->active#385);
[  760.703587]
[  760.703587]  *** DEADLOCK ***

Solve this by removing the mutex_lock()/mutex_unlock() calls from
blk_ia_range_sysfs_show().

Fixes: a2247f19ee1c ("block: Add independent access ranges support")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Link: https://lore.kernel.org/r/20220603021905.1441419-1-damien.lemoal@opensource.wdc.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-ia-ranges.c

index 18c68d8..56ed48d 100644 (file)
@@ -54,13 +54,8 @@ static ssize_t blk_ia_range_sysfs_show(struct kobject *kobj,
                container_of(attr, struct blk_ia_range_sysfs_entry, attr);
        struct blk_independent_access_range *iar =
                container_of(kobj, struct blk_independent_access_range, kobj);
-       ssize_t ret;
 
-       mutex_lock(&iar->queue->sysfs_lock);
-       ret = entry->show(iar, buf);
-       mutex_unlock(&iar->queue->sysfs_lock);
-
-       return ret;
+       return entry->show(iar, buf);
 }
 
 static const struct sysfs_ops blk_ia_range_sysfs_ops = {