Skip to content

Commit ffed586

Browse files
kawasakimartinkpetersen
authored andcommitted
scsi: sd: Move sd_read_cpr() out of the q->limits_lock region
Commit 804e498 ("sd: convert to the atomic queue limits API") introduced pairs of function calls to queue_limits_start_update() and queue_limits_commit_update(). These two functions lock and unlock q->limits_lock. In sd_revalidate_disk(), sd_read_cpr() is called after queue_limits_start_update() call and before queue_limits_commit_update() call. sd_read_cpr() locks q->sysfs_dir_lock and &q->sysfs_lock. Then new lock dependencies were created between q->limits_lock, q->sysfs_dir_lock and q->sysfs_lock, as follows: sd_revalidate_disk queue_limits_start_update mutex_lock(&q->limits_lock) sd_read_cpr disk_set_independent_access_ranges mutex_lock(&q->sysfs_dir_lock) mutex_lock(&q->sysfs_lock) mutex_unlock(&q->sysfs_lock) mutex_unlock(&q->sysfs_dir_lock) queue_limits_commit_update mutex_unlock(&q->limits_lock) However, the three locks already had reversed dependencies in other places. Then the new dependencies triggered the lockdep WARN "possible circular locking dependency detected" [1]. This WARN was observed by running the blktests test case srp/002. To avoid the WARN, move the sd_read_cpr() call in sd_revalidate_disk() after the queue_limits_commit_update() call. In other words, move the sd_read_cpr() call out of the q->limits_lock region. [1] https://lore.kernel.org/linux-scsi/vlmv53ni3ltwxplig5qnw4xsl2h6ccxijfbqzekx76vxoim5a5@dekv7q3es3tx/ Fixes: 804e498 ("sd: convert to the atomic queue limits API") Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Link: https://lore.kernel.org/r/20240801054234.540532-1-shinichiro.kawasaki@wdc.com Tested-by: Luca Coelho <luciano.coelho@intel.com> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent ab9fd06 commit ffed586

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

drivers/scsi/sd.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3753,7 +3753,6 @@ static int sd_revalidate_disk(struct gendisk *disk)
37533753
sd_read_block_limits_ext(sdkp);
37543754
sd_read_block_characteristics(sdkp, &lim);
37553755
sd_zbc_read_zones(sdkp, &lim, buffer);
3756-
sd_read_cpr(sdkp);
37573756
}
37583757

37593758
sd_print_capacity(sdkp, old_capacity);
@@ -3808,6 +3807,14 @@ static int sd_revalidate_disk(struct gendisk *disk)
38083807
if (err)
38093808
return err;
38103809

3810+
/*
3811+
* Query concurrent positioning ranges after
3812+
* queue_limits_commit_update() unlocked q->limits_lock to avoid
3813+
* deadlock with q->sysfs_dir_lock and q->sysfs_lock.
3814+
*/
3815+
if (sdkp->media_present && scsi_device_supports_vpd(sdp))
3816+
sd_read_cpr(sdkp);
3817+
38113818
/*
38123819
* For a zoned drive, revalidating the zones can be done only once
38133820
* the gendisk capacity is set. So if this fails, set back the gendisk

0 commit comments

Comments
 (0)