]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: core: Drop using the host_lock to protect async_scan race condition
authorChaohai Chen <wdhh6@aliyun.com>
Thu, 5 Mar 2026 02:51:24 +0000 (10:51 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 7 Mar 2026 15:58:33 +0000 (10:58 -0500)
Previously, host_lock was used to prevent bit-set conflicts in async_scan,
but this approach introduced naked reads in some code paths.

Convert async_scan from a bitfield to a bool type to eliminate bit-level
conflicts entirely. Use __guarded_by(&scan_mutex) to indicate that the
async_scan variable is protected by scan_mutex.

Signed-off-by: Chaohai Chen <wdhh6@aliyun.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20260305025125.3649517-1-wdhh6@aliyun.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_scan.c
include/scsi/scsi_host.h

index 60c06fa4ec326d36b39924107068b0f83ef4055a..efcaf85ff69941a2ed2672d6483c36603971d05b 100644 (file)
@@ -1943,7 +1943,6 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
 static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 {
        struct async_scan_data *data = NULL;
-       unsigned long flags;
 
        if (strncmp(scsi_scan_type, "sync", 4) == 0)
                return NULL;
@@ -1962,9 +1961,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                goto err;
        init_completion(&data->prev_finished);
 
-       spin_lock_irqsave(shost->host_lock, flags);
-       shost->async_scan = 1;
-       spin_unlock_irqrestore(shost->host_lock, flags);
+       shost->async_scan = true;
        mutex_unlock(&shost->scan_mutex);
 
        spin_lock(&async_scan_lock);
@@ -1992,7 +1989,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 static void scsi_finish_async_scan(struct async_scan_data *data)
 {
        struct Scsi_Host *shost;
-       unsigned long flags;
 
        if (!data)
                return;
@@ -2012,9 +2008,7 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
 
        scsi_sysfs_add_devices(shost);
 
-       spin_lock_irqsave(shost->host_lock, flags);
-       shost->async_scan = 0;
-       spin_unlock_irqrestore(shost->host_lock, flags);
+       shost->async_scan = false;
 
        mutex_unlock(&shost->scan_mutex);
 
index f6e12565a81de30871bed446b8454588109f57c4..7e2011830ba4bd48fe8a7df3c88285d6da6d0a71 100644 (file)
@@ -660,6 +660,10 @@ struct Scsi_Host {
         */
        unsigned nr_hw_queues;
        unsigned nr_maps;
+
+       /* Asynchronous scan in progress */
+       bool async_scan __guarded_by(&scan_mutex);
+
        unsigned active_mode:2;
 
        /*
@@ -678,9 +682,6 @@ struct Scsi_Host {
        /* Task mgmt function in progress */
        unsigned tmf_in_progress:1;
 
-       /* Asynchronous scan in progress */
-       unsigned async_scan:1;
-
        /* Don't resume host in EH */
        unsigned eh_noresume:1;