Skip to content

Commit 6d00d0c

Browse files
author
Ming Lei
committed
block: fix queue freeze vs limits lock order in sysfs store methods
JIRA: https://issues.redhat.com/browse/RHEL-71345 Upstream Status: for-6.4/block commit c99f66e Author: Christoph Hellwig <hch@lst.de> Date: Fri Jan 10 06:47:14 2025 +0100 block: fix queue freeze vs limits lock order in sysfs store methods queue_attr_store() always freezes a device queue before calling the attribute store operation. For attributes that control queue limits, the store operation will also lock the queue limits with a call to queue_limits_start_update(). However, some drivers (e.g. SCSI sd) may need to issue commands to a device to obtain limit values from the hardware with the queue limits locked. This creates a potential ABBA deadlock situation if a user attempts to modify a limit (thus freezing the device queue) while the device driver starts a revalidation of the device queue limits. Avoid such deadlock by not freezing the queue before calling the ->store_limit() method in struct queue_sysfs_entry and instead use the queue_limits_commit_update_frozen helper to freeze the queue after taking the limits lock. This also removes taking the sysfs lock for the store_limit method as it doesn't protect anything here, but creates even more nesting. Hopefully it will go away from the actual sysfs methods entirely soon. (commit log adapted from a similar patch from Damien Le Moal) Fixes: ff956a3 ("block: use queue_limits_commit_update in queue_discard_max_store") Fixes: 0327ca9 ("block: use queue_limits_commit_update in queue_max_sectors_store") Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Nilay Shroff <nilay@linux.ibm.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Link: https://lore.kernel.org/r/20250110054726.1499538-7-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Ming Lei <ming.lei@redhat.com>
1 parent 4396943 commit 6d00d0c

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

block/blk-sysfs.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -681,22 +681,24 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
681681
if (entry->load_module)
682682
entry->load_module(disk, page, length);
683683

684-
mutex_lock(&q->sysfs_lock);
685-
blk_mq_freeze_queue(q);
686684
if (entry->store_limit) {
687685
struct queue_limits lim = queue_limits_start_update(q);
688686

689687
res = entry->store_limit(disk, page, length, &lim);
690688
if (res < 0) {
691689
queue_limits_cancel_update(q);
692-
} else {
693-
res = queue_limits_commit_update(q, &lim);
694-
if (!res)
695-
res = length;
690+
return res;
696691
}
697-
} else {
698-
res = entry->store(disk, page, length);
692+
693+
res = queue_limits_commit_update_frozen(q, &lim);
694+
if (res)
695+
return res;
696+
return length;
699697
}
698+
699+
mutex_lock(&q->sysfs_lock);
700+
blk_mq_freeze_queue(q);
701+
res = entry->store(disk, page, length);
700702
blk_mq_unfreeze_queue(q);
701703
mutex_unlock(&q->sysfs_lock);
702704
return res;

0 commit comments

Comments
 (0)