From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from 013.lax.mailroute.net (013.lax.mailroute.net [199.89.1.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A11263537FF for ; Thu, 30 Apr 2026 18:26:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=199.89.1.16 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777573567; cv=none; b=TbrYzrbxwN+7mWiNNr7fhkhYAZpxRXrJmgYOImND89aR2oFU0I/FRgzyEHcDqS0Ti3oO7IGrc3/hWJWwx4iOZn28C6bMdFJNKnASoe8ApKBd4pERrSapu7PugUFXBmvuY0nvjbRcf4Ba6Hwu4kZSWPLkI+LzSdgUpev0Jcr6TR8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777573567; c=relaxed/simple; bh=9rWhgHR7Qh7Xk1kCaLWP5kSAx8gRiD6qeUptlhxcPzY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tg8AaZIx9wbPJ38lBPbY2CE2nHU8VBfLBEzoE0J68lghsEv7Z++++Z5ux0SJQ4iQIQ18Skb4+Nu6chVWrcOaonGhxw89h+a5S0MLZP4XE7XAAcIh8EIugOH+Ar5JyB4DBQgHVPzBvFepW7/EoaCONAIKWdbgNujm04502/yxv9U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=acm.org; spf=pass smtp.mailfrom=acm.org; dkim=pass (2048-bit key) header.d=acm.org header.i=@acm.org header.b=lLedW6Tm; arc=none smtp.client-ip=199.89.1.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=acm.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=acm.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=acm.org header.i=@acm.org header.b="lLedW6Tm" Received: from localhost (localhost [127.0.0.1]) by 013.lax.mailroute.net (Postfix) with ESMTP id 4g62g131t6zlfvpH; Thu, 30 Apr 2026 18:26:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=acm.org; h= content-transfer-encoding:mime-version:references:in-reply-to :x-mailer:message-id:date:date:subject:subject:from:from :received:received; s=mr01; t=1777573543; x=1780165544; bh=WPg0O TGqjAzdF/jKdIDRSIFfK8r+0nwHvzP1/99eBcw=; b=lLedW6Tmmpm23u4J2h6g/ uikv7bKHhyB2UNGIome8Ekm3Zsp5fUeQKhe7tNt5d7s4GP4I+AHWdfVwJhIE7jNm 3pDtes6o/LfOVEQNXSW3pxKLSOYoe3++a1oMjWYTIX3HOCxkHm/PVbolNYFfElYk X8jbdt8meVqdoQhCnDwDN+1lcnFkb65ipXaeBtHeLhR/Caq3C0neduO2CjfylHXy jGSGPfaY+fCDM2ybZptglJv8dyiSpxJhyxY53yQoVZtFVfyjx6li7BSBhtUF7WOO JecDoiJTDDAGjAGF3Md5SzB9QbFQCH+KVx0uC3xVtRZCPzzTdufhnP3eZEDfPVsL w== X-Virus-Scanned: by MailRoute Received: from 013.lax.mailroute.net ([127.0.0.1]) by localhost (013.lax [127.0.0.1]) (mroute_mailscanner, port 10029) with LMTP id BpClUXJfwBr0; Thu, 30 Apr 2026 18:25:43 +0000 (UTC) Received: from bvanassche.mtv.corp.google.com (unknown [104.135.180.219]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: bvanassche@acm.org) by 013.lax.mailroute.net (Postfix) with ESMTPSA id 4g62fW1KGgzlh1Rp; Thu, 30 Apr 2026 18:25:38 +0000 (UTC) From: Bart Van Assche To: "Martin K . Petersen" Cc: linux-scsi@vger.kernel.org, Marco Elver , Bart Van Assche , Jianzhou Zhao , "James E.J. Bottomley" , Kashyap Desai , Sumit Saxena , Shivasharan S , Chandrakanth patil , Sathya Prakash , Sreekanth Reddy , Suganath Prabu Subramani , Ranjan Kumar , Nilesh Javali , Manish Rangankar , GR-QLogic-Storage-Upstream@marvell.com Subject: [PATCH v2 56/56] scsi: core: Protect host state changes with the host lock Date: Thu, 30 Apr 2026 11:20:26 -0700 Message-ID: <20260430182130.1978347-57-bvanassche@acm.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260430182130.1978347-1-bvanassche@acm.org> References: <20260430182130.1978347-1-bvanassche@acm.org> Precedence: bulk X-Mailing-List: linux-scsi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Some but not all SCSI host state changes are protected with the SCSI host lock. Annotate the SCSI host state with __guarded_by(&host_lock), protect all SCSI host state changes with the SCSI host lock and use READ_ONCE() for all SCSI host state reads. This patch prevents that KCSAN complains about data races when accessing the SCSI host state. Reported-by: Jianzhou Zhao Closes: https://lore.kernel.org/all/36d59d0e.6db0.19cdbeee01b.Coremail.lu= ckd0g@163.com/ Signed-off-by: Bart Van Assche --- drivers/scsi/hosts.c | 13 ++++++++----- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +- drivers/scsi/qla4xxx/ql4_os.c | 6 ++---- drivers/scsi/scsi_lib.c | 3 +-- drivers/scsi/scsi_sysfs.c | 7 ++++--- include/scsi/scsi_host.h | 23 ++++++++++++++++------- 7 files changed, 33 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index e047747d4ecf..7482ae7777c8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -278,7 +278,8 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, s= truct device *dev, if (error) goto out_disable_runtime_pm; =20 - scsi_host_set_state(shost, SHOST_RUNNING); + scoped_guard(spinlock_irq, shost->host_lock) + scsi_host_set_state(shost, SHOST_RUNNING); get_device(shost->shost_gendev.parent); =20 device_enable_async_suspend(&shost->shost_dev); @@ -352,6 +353,7 @@ EXPORT_SYMBOL(scsi_add_host_with_dma); static void scsi_host_dev_release(struct device *dev) { struct Scsi_Host *shost =3D dev_to_shost(dev); + enum scsi_host_state host_state =3D scsi_get_host_state(shost); struct device *parent =3D dev->parent; =20 /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ @@ -364,7 +366,7 @@ static void scsi_host_dev_release(struct device *dev) if (shost->work_q) destroy_workqueue(shost->work_q); =20 - if (shost->shost_state =3D=3D SHOST_CREATED) { + if (host_state =3D=3D SHOST_CREATED) { /* * Free the shost_dev device name and remove the proc host dir * here if scsi_host_{alloc,put}() have been called but neither @@ -380,7 +382,7 @@ static void scsi_host_dev_release(struct device *dev) =20 ida_free(&host_index_ida, shost->host_no); =20 - if (shost->shost_state !=3D SHOST_CREATED) + if (host_state !=3D SHOST_CREATED) put_device(parent); kfree(shost); } @@ -414,7 +416,8 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_h= ost_template *sht, int priv =20 shost->host_lock =3D &shost->default_lock; spin_lock_init(shost->host_lock); - shost->shost_state =3D SHOST_CREATED; + scoped_guard(spinlock_init, shost->host_lock) + shost->shost_state =3D SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); INIT_LIST_HEAD(&shost->__targets); INIT_LIST_HEAD(&shost->eh_abort_list); @@ -600,7 +603,7 @@ EXPORT_SYMBOL(scsi_host_lookup); **/ struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) { - if ((shost->shost_state =3D=3D SHOST_DEL) || + if (scsi_get_host_state(shost) =3D=3D SHOST_DEL || !get_device(&shost->shost_gendev)) return NULL; return shost; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/meg= araid/megaraid_sas_base.c index ccefe5841a17..97a81a86db82 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3075,7 +3075,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd = *scmd) =20 scmd_printk(KERN_INFO, scmd, "SCSI host state: %d SCSI host busy: %d FW outstanding: %d\n", - scmd->device->host->shost_state, + scsi_get_host_state(scmd->device->host), scsi_host_busy(scmd->device->host), atomic_read(&instance->fw_outstanding)); /* diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/= mpt3sas_scsih.c index 6ff788557294..e40913d2479e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5460,7 +5460,7 @@ static enum scsi_qc_status scsih_qcmd(struct Scsi_H= ost *shost, * Avoid error handling escallation when device is disconnected */ if (handle =3D=3D MPT3SAS_INVALID_DEVICE_HANDLE || sas_device_priv_data= ->block) { - if (scmd->device->host->shost_state =3D=3D SHOST_RECOVERY && + if (scsi_get_host_state(scmd->device->host) =3D=3D SHOST_RECOVERY && scmd->cmnd[0] =3D=3D TEST_UNIT_READY) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); scsi_done(scmd); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.= c index d598ab4126f8..c9d9fc7c81fb 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -9411,11 +9411,9 @@ static int qla4xxx_eh_target_reset(struct scsi_cmn= d *cmd) * This routine finds that if reset host is called in EH * scenario or from some application like sg_reset **/ -static int qla4xxx_is_eh_active(struct Scsi_Host *shost) +static bool qla4xxx_is_eh_active(struct Scsi_Host *shost) { - if (shost->shost_state =3D=3D SHOST_RECOVERY) - return 1; - return 0; + return scsi_get_host_state(shost) =3D=3D SHOST_RECOVERY; } =20 /** diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 6e8c7a42603e..5f7580b089e9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1638,10 +1638,9 @@ static enum scsi_qc_status scsi_dispatch_cmd(struc= t scsi_cmnd *cmd) goto done; } =20 - if (unlikely(host->shost_state =3D=3D SHOST_DEL)) { + if (scsi_get_host_state(host) =3D=3D SHOST_DEL) { cmd->result =3D (DID_NO_CONNECT << 16); goto done; - } =20 trace_scsi_dispatch_cmd_start(cmd); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index dfc3559e7e04..9480432f650b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -214,8 +214,9 @@ store_shost_state(struct device *dev, struct device_a= ttribute *attr, if (!state) return -EINVAL; =20 - if (scsi_host_set_state(shost, state)) - return -EINVAL; + scoped_guard(spinlock_irq, shost->host_lock) + if (scsi_host_set_state(shost, state)) + return -EINVAL; return count; } =20 @@ -223,7 +224,7 @@ static ssize_t show_shost_state(struct device *dev, struct device_attribute *attr, char= *buf) { struct Scsi_Host *shost =3D class_to_shost(dev); - const char *name =3D scsi_host_state_name(shost->shost_state); + const char *name =3D scsi_host_state_name(scsi_get_host_state(shost)); =20 if (!name) return -EINVAL; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 2bbe7cb0060b..9841402e8bdf 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -729,7 +729,7 @@ struct Scsi_Host { unsigned int irq; =09 =20 - enum scsi_host_state shost_state; + enum scsi_host_state shost_state __guarded_by(&host_lock); =20 /* ldm bits */ struct device shost_gendev, shost_dev; @@ -787,11 +787,18 @@ static inline struct Scsi_Host *dev_to_shost(struct= device *dev) return container_of(dev, struct Scsi_Host, shost_gendev); } =20 +static inline enum scsi_host_state scsi_get_host_state(struct Scsi_Host = *shost) +{ + return context_unsafe(READ_ONCE(shost->shost_state)); +} + static inline int scsi_host_in_recovery(struct Scsi_Host *shost) { - return shost->shost_state =3D=3D SHOST_RECOVERY || - shost->shost_state =3D=3D SHOST_CANCEL_RECOVERY || - shost->shost_state =3D=3D SHOST_DEL_RECOVERY || + enum scsi_host_state state =3D scsi_get_host_state(shost); + + return state =3D=3D SHOST_RECOVERY || + state =3D=3D SHOST_CANCEL_RECOVERY || + state =3D=3D SHOST_DEL_RECOVERY || shost->tmf_in_progress; } =20 @@ -837,8 +844,9 @@ static inline struct device *scsi_get_device(struct S= csi_Host *shost) **/ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) { - return shost->shost_state =3D=3D SHOST_RUNNING || - shost->shost_state =3D=3D SHOST_RECOVERY; + enum scsi_host_state state =3D scsi_get_host_state(shost); + + return state =3D=3D SHOST_RUNNING || state =3D=3D SHOST_RECOVERY; } =20 extern void scsi_unblock_requests(struct Scsi_Host *); @@ -942,6 +950,7 @@ static inline unsigned char scsi_host_get_guard(struc= t Scsi_Host *shost) return shost->prot_guard_type; } =20 -extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state)= ; +int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state st= ate) + __must_hold(&shost->host_lock); =20 #endif /* _SCSI_SCSI_HOST_H */