From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f42.google.com (mail-pj2-f42.google.com [74.125.227.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F1C83BA220 for ; Fri, 18 Sep 2026 18:17:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755423; cv=none; b=hyTDQnjb14SdaeKBC9/5gcSKOYwh+CcQGXKGx2X9eHt2K9/2BwzXFGi+2ud6ctkzxaXCt0RyXaK8KAVeHaJ17JAo5war3OoTKwCuAnJiJ0tuhrXkpbFvEX6ugG9CoElFFWmw5lgS3HGW1N9aZKN2aUbInhtDP8yyfHP6qFojoCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755423; c=relaxed/simple; bh=ts9kK/iCxfz8B6jDbz11N/MxkQs9h9VuTTCL0S0YsFs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=trOhlFOoGJff5m+7/GYu8q8haLlrIx6l7YH2/F0BN2oql0Me7NEfb1LqsAyTYXPjp0YRZDUXFM+8Vn+iImcsMZX1Bfe3Vmjpd0b9KLGKZVkt43pVQMNXGY4x1DxPXQY7mGCW4ne8U8dWBEqswq02BWDTLuR+1Bl1gDnXf9kP5sU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=IXWZY6Az; arc=none smtp.client-ip=74.125.227.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="IXWZY6Az" Received: by mail-pj2-f42.google.com with SMTP id d9443c01a7336-2ddb44ad1c1so11230975ad.3 for ; Fri, 18 Sep 2026 11:17:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755421; x=1790360221; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+O4TueAKYiHtgRqWfBMj1NI12Pv4z04h49FFgSbHBPc=; b=IXWZY6AzPSmdIFXuuaUOw1gv1u0J7pO9SgdEKol1SSj41vNAsfQN3e90rv43VD6NGz ZKX8WrRy3iHqSmsIMREcv/7npGG3zq4UuIoV5VC6xSKHWWrWjHYnp+M35qXUQSqXZzPm pI2y5ZlgiVOE7mUrdQc6gOu1vAfs58lGMrnZi9++EyKYi6wEmnx1eblpnIxZWTPE5x/D llIyvx5kzRZsEqvEcSzDdMHG77J3FIRiuuxrT+8V9VB9GmvePyH1XoZBLCfRUDJGw5RQ 9buu5UC5X0QkpxDOEbc++azVW43oed4hoUCgV+B42jIvWrj/nLHR1tLEPIvLOkqWlzPS uKcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755421; x=1790360221; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=+O4TueAKYiHtgRqWfBMj1NI12Pv4z04h49FFgSbHBPc=; b=jFsBJ50oToc8jRxTaM4U5+nwLWPtXUg7twlB4MnCiH9pPDYIh4aNsPlmII1Pqnsuaf CAMON/Dzc80fTp+6cLhucyDNqezT/NOPcng9j/XK/Ffnal20GqUVeRZpz2UkND36Hddd YxDFYDYaZ7YW6P0kXNLPleFULk1Y+L6OpkoSSfR4HSV5R5qL5k2UNlXaM0r6YCRwlHK6 vrnEqrBgqCf7X8+smaA64RbHgUNRpFb3BTBQ5khQpVJ7VCj3B63V1MhFupy0eWoTA14N iP+7nVDUAExlIE6In1qoPjbp9dUgxCNrCGlVcGS8Tx4gTj/msDIi/ixYTFb/ymKAGpr8 xlsA== X-Forwarded-Encrypted: i=1; AKwUvByOsAtzEqNkgTU5zRPEerux2DpX1KeuH3Zl8zn1yvlHtdggYoEoEuCABHSs91zTlMVUK5Aq990Az6iD1sU=@vger.kernel.org X-Gm-Message-State: AFuF++kqPzHqisKnezVPSVVyK0+cuOT3tdmm72fr/76AhaTZKUuTFcsq kkCIZqupvrCAd79GM03vRZw1F1R6ZHCaS0otynPU9+X+re47pZwQwij5v+5FiNQ8GSI= X-Gm-Gg: AYBFou0otqy5BdQYs84TjUOOvUentZ0ET3PF3zen/B5vY5qOY/buUlyVOBAO7cpnoYq cfk7PuaVlnA9+Ne5I7q+eWnXjmj2OvwaCOMFTQuzyZkzjV+Uhqm2L9CJB0kND9itmKbK17NDfV4 lOPD20YbqgpmEpYpzS77RYcGeeL1Z7wLCGCTH7Y9Ues3djd5ZUNLsVcMABiguniHDKrTxziA0gq ITkH71/Zh4JilfKgFo8WQCkeDOkoW1NK6exVk5hkuES9xmTohQUzYkCjEbsrmcbWRfFOCi2ZtA6 5k5scy1NDLMdaE5UhNv8vPw+UfuN951olsykbUC/KqJzNCOQEJvtEflY7CrA/7xhQyGD43aGa5k Tm4QyOIjqKkvbPO9kIkFoxyAZufmvs0AXW3QQ9APK6g90pX7A+Wuk2ozC0I9WI2F2hjvxBezy0O CaAhLY64bJ9IJchLhVFR0ungFGoZwPL6Driuk8/gPBJRfSm5FM+NUSemPeZYE79m3YOpOs1SD/l 6u52gGB8PAOD/cVoRoMeXKO0vITKpAE X-Received: by 2002:a17:902:f546:b0:2dd:c053:82f2 with SMTP id d9443c01a7336-2ddc0538461mr10467265ad.41.1789755420559; Fri, 18 Sep 2026 11:17:00 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.16.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:00 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 01/18] nvmet: Rapid Path Failure Recovery set controller identify fields Date: Fri, 18 Sep 2026 11:14:01 -0700 Message-ID: <20260918181614.3947933-2-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TP8028 Rapid Path Failure Recovery defined new fields in controller identify response. The newly defined fields are: - CIU (Controller Instance Uniquifier): is an 8bit non-zero value that is assigned a random value when controller is first created. The value will be incremented when RDY bit in CSTS register is asserted. - CIRN (Controller Instance Random Number): is 64bit random value that gets generated when controller is created. CIRN is regenerated everytime RDY bit in CSTS register is asserted. - CCRL (Cross-Controller Reset Limit): is an 8bit value that defines the maximum number of in-progress controller reset operations. CCRL is hardcoded to 4 as recommended by TP8028. These fields are set for non-discovery subsystems only. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/admin-cmd.c | 5 +++++ drivers/nvme/target/core.c | 9 +++++++++ drivers/nvme/target/nvmet.h | 2 ++ include/linux/nvme.h | 10 ++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index 7764a3c0195c..bf7c5f5927e3 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -693,6 +693,11 @@ static void nvmet_execute_identify_ctrl(struct nvmet_r= eq *req) id->mdts =3D nvmet_ctrl_mdts(req); id->cntlid =3D cpu_to_le16(ctrl->cntlid); id->ver =3D cpu_to_le32(ctrl->subsys->ver); + if (!nvmet_is_disc_subsys(ctrl->subsys)) { + id->ciu =3D ctrl->ciu; + id->cirn =3D cpu_to_le64(ctrl->cirn); + id->ccrl =3D NVMF_CCR_LIMIT; + } =20 /* XXX: figure out what to do about RTD3R/RTD3 */ id->oaes =3D cpu_to_le32(NVMET_AEN_CFG_OPTIONAL); diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 43871a8f56ca..4c8f30c5ff7e 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1412,6 +1412,10 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl) return; } =20 + if (!nvmet_is_disc_subsys(ctrl->subsys)) { + ctrl->ciu =3D ((u8)(ctrl->ciu + 1)) ? : 1; + ctrl->cirn =3D get_random_u64(); + } ctrl->csts =3D NVME_CSTS_RDY; =20 /* @@ -1695,6 +1699,11 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_all= oc_ctrl_args *args) } ctrl->cntlid =3D ret; =20 + if (!nvmet_is_disc_subsys(ctrl->subsys)) { + ctrl->ciu =3D get_random_u8() ? : 1; + ctrl->cirn =3D get_random_u64(); + } + ret =3D nvmet_ctrl_init_pr(ctrl); if (ret) goto init_pr_fail; diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index dbda55895f4f..e3e414ef68d3 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -269,7 +269,9 @@ struct nvmet_ctrl { uuid_t hostid; u16 cntlid; u16 max_qid; + u8 ciu; u32 kato; + u64 cirn; =20 struct nvmet_port *port; =20 diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 91ce434a7e8d..cbaf02b0cf07 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -21,6 +21,8 @@ #define NVMF_TRADDR_SIZE 256 #define NVMF_TSAS_SIZE 256 =20 +#define NVMF_CCR_LIMIT 4 + #define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" =20 #define NVME_NSID_ALL 0xffffffff @@ -328,7 +330,10 @@ struct nvme_id_ctrl { __le16 crdt1; __le16 crdt2; __le16 crdt3; - __u8 rsvd134[122]; + __u8 rsvd134[1]; + __u8 ciu; + __le64 cirn; + __u8 rsvd144[112]; __le16 oacs; __u8 acl; __u8 aerl; @@ -389,7 +394,8 @@ struct nvme_id_ctrl { __u8 msdbd; __u8 rsvd1804[2]; __u8 dctype; - __u8 rsvd1807[241]; + __u8 ccrl; + __u8 rsvd1808[240]; struct nvme_id_power_state psd[32]; __u8 vs[1024]; }; --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98EC14F55C7 for ; Fri, 18 Sep 2026 18:17:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755424; cv=none; b=j/Rm1mPeX/fsvi0Ls9G+ZaafeNNmPhi/wiMm3O+krsHz5niCHxN2G5OEPGjBpV+CkYIOMQYJ1yg9WNYtARJc2o2keZy4sbeq+dOGTQOhgOLaAQOLFU7MVcKWMawhXerEerCzqt1Udu3foQ1+9jrUdEpOgBwNllmaKzLABrx7AUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755424; c=relaxed/simple; bh=JP1DUGRnFpKenhUQXMkCfj/AYF5XyMKm7PlfqwvLN0s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tA6oKJ1wAGJi1n0CCdasoe0bvgbZyoQdgQDWcDoVsAigo4PEcT4FWVUmN3sdOnrgLQHyaCl76Fbg/ZMaF0E6R28gAmvKl1wBYcl0UM6cOkTozbCP4g+8kOJt1NxbwFNb48TXZ9rVchA4hsE1jek5ZhV/azRD881mBw/UoRGpFjY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=ddJraQtS; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="ddJraQtS" Received: by mail-pj2-f13.google.com with SMTP id d9443c01a7336-2d747eb79f7so7818055ad.1 for ; Fri, 18 Sep 2026 11:17:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755422; x=1790360222; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=dVQz5nhnRw3JFcVZi/bpaRY30mlHvfzPq9aZRP4f2wk=; b=ddJraQtSYmRqaD681Qz5bRkasgrsJf9f+/9SLwhpJyGGftRnc2IsyMGGfEFoHhLkS9 xbu10gf45oD9M2DaAlQnrOH7XXZXAfUpFM+aB7FtWztOFVoXow6n8mqEr7O+NRmP2wPp cTwDPynawk0Adff8mM92PohA9F4xBijj+PoNKmZRXIgmzwAMK83WUDXCZ/1mmQkqh4lf 4wwWClpmq1SB5IUG5KCpbjX1wr6bOBiq33xQixiZGdVJCpoERiQgroBzi7uPma+bYVrb jOxatIH9DXiOKJNvYyuenbOlE0u6HtCh2ackCFpvWZ8eD1CyxvaenCiDus9fkGETCOmC PxRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755422; x=1790360222; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=dVQz5nhnRw3JFcVZi/bpaRY30mlHvfzPq9aZRP4f2wk=; b=Q0xoqRchNxatimOBBdu4BDrtwljKze2xJ1GvCKL446YDO/QaCglyNl6G+KWevPjaV/ U+wDbWDquIXrtzEXSBRV8qjhDb68/U9dbZ2j/YcrGCs7wNipJQtWlnSryhR6h23OIRhL r7pKMm6Ji2zXL6wRO2p/72PzAcfeBWcok84b8z+6yvBSM/5QhGp4z0xC1wYAB2UF+CLZ POKx5Jup/fdyrG3RpDxURtyBINsQQBIAc7+9KCJHLvhQ4SLQuu4r1gtfZpVY7EkLUYu6 pfcQxOx/sv4p0A3+LXx/KX0o9k5893BalLGaZGMLe/zrAMrVYIQ/qTKpBCbTvldJigUW WPUg== X-Forwarded-Encrypted: i=1; AKwUvByh7rNdZhz3YuyiZKOaBsATFGSZNy0HkTk1ePpQZxyUm1EFmBNQx3ok9IXgqWQVToIdy30ppHZcodc0Kzc=@vger.kernel.org X-Gm-Message-State: AFuF++m04rz7g9u1vdXgna0ZFd6A0nqB8XWUjCmjywwk41yDf41yVHFV R07z3w2a2EDVnDvgzCcXOJ8eLrdGk2D3ZkwPaezcVQPu68Lk3VpAWgkHshl2iaN7I9k= X-Gm-Gg: AYBFou3OLiYo6TKXUKKBSrYPUCi0gMKPw/NBN8jrABSS0yF6+XhDj7JZwiAEed8Bu1S K5GMbWnT+Pt2DLOUeQpXjidJ9PBlLO8H9mOw70oZESBJIGvN2h00pVHZ044XRZZOFQTkLTCwsYb 2Zrq8Jm2f9bV4+KkTozgFfOArSKH12hYP7S2pzufHc9fba2+ZKd/OvagCwrYLsOBV4IaUQam9Ax NcR/VY09r5OtqbtTcA7oksD4NdbGR6On1aicH6LwaHVJc1aw7ZvYtcxK1e1sa2h5qdj2amJ+sIG UJod8bhXaEni2YDbyiu7ytscTWV9fXW6Jf1wKiyLi5ZasAQHQIlDh5wYpkzFvV7rdmaKbA/zeQD kOmuxZqi4eqVtqcFXd/kkp/61uSwmedDAREqk5e4qFHk+/I/USUiJv3HAF705Dvwpf+7jqzDkkx 8MFiCruotcokTl2xKH/aBUkeA43jqUS2vGU3qvKkwsuIUqk/ztQe/wBxHy7QWheC9PWnRmHNZaD xE240/WCd/DgkXtM7CJGXZehhiRlDSw X-Received: by 2002:a17:902:d2d0:b0:2dd:c0ff:e72c with SMTP id d9443c01a7336-2ddc0ffea23mr6053395ad.62.1789755421554; Fri, 18 Sep 2026 11:17:01 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:01 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 02/18] nvmet/debugfs: Export controller CIU and CIRN via debugfs Date: Fri, 18 Sep 2026 11:14:02 -0700 Message-ID: <20260918181614.3947933-3-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Export ctrl->ciu and ctrl->cirn as debugfs files under controller debugfs directory. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/debugfs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c index e85fe1d4c9f8..4de460879d0b 100644 --- a/drivers/nvme/target/debugfs.c +++ b/drivers/nvme/target/debugfs.c @@ -152,6 +152,23 @@ static int nvmet_ctrl_tls_concat_show(struct seq_file = *m, void *p) } NVMET_DEBUGFS_ATTR(nvmet_ctrl_tls_concat); #endif +static int nvmet_ctrl_instance_ciu_show(struct seq_file *m, void *p) +{ + struct nvmet_ctrl *ctrl =3D m->private; + + seq_printf(m, "%02x\n", ctrl->ciu); + return 0; +} +NVMET_DEBUGFS_ATTR(nvmet_ctrl_instance_ciu); + +static int nvmet_ctrl_instance_cirn_show(struct seq_file *m, void *p) +{ + struct nvmet_ctrl *ctrl =3D m->private; + + seq_printf(m, "%016llx\n", ctrl->cirn); + return 0; +} +NVMET_DEBUGFS_ATTR(nvmet_ctrl_instance_cirn); =20 static const char *const nvmet_pr_type_names[] =3D { [NVME_PR_WRITE_EXCLUSIVE] =3D "write_exclusive", @@ -287,6 +304,10 @@ int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl) debugfs_create_file("tls_key", S_IRUSR, ctrl->debugfs_dir, ctrl, &nvmet_ctrl_tls_key_fops); #endif + debugfs_create_file("ciu", S_IRUSR, ctrl->debugfs_dir, ctrl, + &nvmet_ctrl_instance_ciu_fops); + debugfs_create_file("cirn", S_IRUSR, ctrl->debugfs_dir, ctrl, + &nvmet_ctrl_instance_cirn_fops); return 0; } =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC67C2ECD32 for ; Fri, 18 Sep 2026 18:17:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755425; cv=none; b=Vl9J+5tLQabdWnj9K8JMHaL3EwB88nv189if93erjs/LRmWnKmff3XAfJXmigsnQ9eJhcJ6t57UmoDw+vG5SapE1N0FUNyN7xFp0iSzOq5Nl4tyHuLap94f/MXHIz6FhW4Qu4PWcviSWGbS/09HSClnvnzCaPHe+JZ71GrMsNSc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755425; c=relaxed/simple; bh=A6iYgIlcaX5RIGEv5Q40/b2/HIHglvq8j8qJxL7H+l0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QJtz8c9Ro7dSPsA24ppQiMFPwZVTQoAJFrs4d2Zq3nRpKKRIMm2YWMOGKawlWDx8pA17CQP8fz2v+V3OOvyxcLEsEFnbX0uRmlYYIB0j5xfz7sYVCq4f2w44tptc+ehVtMz10cxSocLRJ7TMUEsJxiu489/COrTtgXu795O4Zgg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=DoxMBfDD; arc=none smtp.client-ip=74.125.227.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="DoxMBfDD" Received: by mail-pj2-f12.google.com with SMTP id d9443c01a7336-2d91c22d27dso6989745ad.1 for ; Fri, 18 Sep 2026 11:17:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755423; x=1790360223; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Ax76daz0K/pDtfH+NZe4NT0sGw0WCKRLANYGH5AA2/Q=; b=DoxMBfDDeOIz5T2Ix0CBLv0jBsnydBtdlrAR1iGGa1fvSzH80zLClAGeBVi00KZQiP paBSdycitZkOc9nW4Z+G1idd2lLaa/iyBUzG8hjo2WEGpgRssygXKQ3DX5TmilaZADb3 ihWhwyE2ds469TFy2oI2i50fuVlBs7T4sBjfPxNp3hbMn2tS4EQyTunligOANNSQxDBO g3nRh80Wc23wZTbgBPsk6sS8UD1+rSo7EjViIAlhyQA/u7UVB4IQRGG52YlLopGg4NH8 IZRwYctOsBoloM/Q6xVErbArYjOWMBA9iekYlUoV8M2z6ImX1Oyq6pkvJGKJ/g6uZgYh ThSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755423; x=1790360223; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Ax76daz0K/pDtfH+NZe4NT0sGw0WCKRLANYGH5AA2/Q=; b=gjzk/9zF+Z5afr1EAnWr5rJ5/xeIF5b7dWYSCl5G+68U0f3KTOi2oEIC2h9bOJdA08 RSRSoo9hovJhjwe3QgggBfLGvIo/hnICxkklFOKZ5+Q1AN9kay8kQ/F0vMEC1KoSmLuW 1rlajRBW5rvztAF7HrE+XJUCO0wWOJ6DV0A/Gv/NoxLGqpyTtnc17J3fDazc+NX8c8NI MzViGusvcwp6G4kGqPpSjBMkqPpyGgxWHQUsa8z5SOhen4eYo4xyfbpWvZ49DOeJ1LJ8 APf0rOZxhaH3eS4D580QsLGFEybP1tV6DS48POVSog/G6pmeW3T5SO5uTlUnhkuNkFo8 wyzA== X-Forwarded-Encrypted: i=1; AKwUvBypMoU5d6L/cqrN34nHhb8QM4rj3rja7nP+42Rvc8tBzqoY+jP4YYMVJQvNE97czQr6FvHR3zvVtCGoB2g=@vger.kernel.org X-Gm-Message-State: AFuF++nxCN9Z5OrPoKhbQr4p0plZ8Hg46GCFgqpeQKbMKfbOh9+ZPpUH 0GjpUKa+DPVGLhpkB6xWIIwueRI0vM8oIMheLjktcs0KsHIoleDjor7EtsdszH8X0oQ= X-Gm-Gg: AYBFou29FMgSGUsrSKpo71QWFVyWoMKRnhtIjJ4ZDextJMqpkbF7Q/BiePfTfU+QeZ9 /VDsy2mbU7y7pK03W89bujV9GkdYAzyF9gHuu4ZIWQV8RTTyYoYMqVOfhXMAFUtNPO8P7DTOEfG IfAlKyuTfOcaIvode96oGNGvdGf9xPBsSLnMrT5O0G1m1GO+j6Zu+L8ikrecDVrVVbHs6gop7TB WN2Xnui4TGfvhBdCeRk6y0UY6BqpdLOmUBN3NalEl/sOb4LE+I/meFEqluN0HRC8JIC5tULAOgv bCQjMyyXVVr2zWMiN4/5ajGTnXJ7IMaEh3nUKY7Ydf9Ae24U/yANufI4UwlOOywzVu0H5+VRQEH 1TtCORMOImRPR5l0xA6zvrBgt3I0vHMj9NLDCThQREF/S2MuKWznjc6Amre7Ht8N+rKJtf9h7nj PQ3g/mcEa6YlQcNcQB/VEaqxgxfrAGX9y0Cu9M+rWAL+ZJt2tXYQyLHy60rUY4+wt73VOv7pFuz NrOerEFxLU22hGhqaL6Kg== X-Received: by 2002:a17:90b:3fcc:b0:39d:e523:8f3e with SMTP id 98e67ed59e1d1-39e54d36e33mr6919225a91.3.1789755422583; Fri, 18 Sep 2026 11:17:02 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:02 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 03/18] nvmet: Implement CCR nvme command Date: Fri, 18 Sep 2026 11:14:03 -0700 Message-ID: <20260918181614.3947933-4-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Defined by TP8028 Rapid Path Failure Recovery, CCR (Cross-Controller Reset) command is an nvme command issued to source controller by initiator to reset impacted controller. Implement CCR command for linux nvme target. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/admin-cmd.c | 76 ++++++++++++++++++++++++++++++++ drivers/nvme/target/core.c | 78 +++++++++++++++++++++++++++++++++ drivers/nvme/target/nvmet.h | 13 ++++++ include/linux/nvme.h | 23 ++++++++++ 4 files changed, 190 insertions(+) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index bf7c5f5927e3..21538e7c83be 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -378,6 +378,7 @@ static void nvmet_get_cmd_effects_admin(struct nvmet_ct= rl *ctrl, log->acs[nvme_admin_get_features] =3D log->acs[nvme_admin_async_event] =3D log->acs[nvme_admin_keep_alive] =3D + log->acs[nvme_admin_cross_ctrl_reset] =3D cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); } =20 @@ -1613,6 +1614,78 @@ void nvmet_execute_keep_alive(struct nvmet_req *req) nvmet_req_complete(req, status); } =20 +void nvmet_execute_cross_ctrl_reset(struct nvmet_req *req) +{ + struct nvmet_ctrl *ictrl, *sctrl =3D req->sq->ctrl; + struct nvme_command *cmd =3D req->cmd; + struct nvmet_ccr *ccr, *new_ccr; + int ccr_active, ccr_total; + u16 cntlid, status =3D NVME_SC_SUCCESS; + + if (!nvmet_check_transfer_len(req, 0)) + return; + + cntlid =3D le16_to_cpu(cmd->ccr.icid); + if (sctrl->cntlid =3D=3D cntlid) { + req->error_loc =3D + offsetof(struct nvme_cross_ctrl_reset_cmd, icid); + status =3D NVME_SC_INVALID_FIELD | NVME_STATUS_DNR; + goto out; + } + + /* Find and get impacted controller */ + ictrl =3D nvmet_ctrl_find_get_ccr(sctrl->subsys, sctrl->hostnqn, + cmd->ccr.ciu, cntlid, + le64_to_cpu(cmd->ccr.cirn)); + if (!ictrl) { + /* Immediate Reset Successful */ + nvmet_set_result(req, 1); + status =3D NVME_SC_SUCCESS; + goto out; + } + + ccr_total =3D ccr_active =3D 0; + mutex_lock(&sctrl->lock); + list_for_each_entry(ccr, &sctrl->ccr_list, entry) { + if (ccr->ctrl =3D=3D ictrl) { + status =3D NVME_SC_CCR_IN_PROGRESS | NVME_STATUS_DNR; + goto out_unlock; + } + + ccr_total++; + if (ccr->ctrl) + ccr_active++; + } + + if (ccr_active >=3D NVMF_CCR_LIMIT) { + status =3D NVME_SC_CCR_LIMIT_EXCEEDED; + goto out_unlock; + } + if (ccr_total >=3D NVMF_CCR_PER_PAGE) { + status =3D NVME_SC_CCR_LOGPAGE_FULL; + goto out_unlock; + } + + new_ccr =3D kmalloc_obj(*new_ccr, GFP_KERNEL); + if (!new_ccr) { + status =3D NVME_SC_INTERNAL; + goto out_unlock; + } + + new_ccr->ciu =3D cmd->ccr.ciu; + new_ccr->icid =3D cntlid; + new_ccr->ctrl =3D ictrl; + list_add_tail(&new_ccr->entry, &sctrl->ccr_list); + +out_unlock: + mutex_unlock(&sctrl->lock); + if (status =3D=3D NVME_SC_SUCCESS) + nvmet_ctrl_fatal_error(ictrl); + nvmet_ctrl_put(ictrl); +out: + nvmet_req_complete(req, status); +} + u32 nvmet_admin_cmd_data_len(struct nvmet_req *req) { struct nvme_command *cmd =3D req->cmd; @@ -1690,6 +1763,9 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req) case nvme_admin_keep_alive: req->execute =3D nvmet_execute_keep_alive; return 0; + case nvme_admin_cross_ctrl_reset: + req->execute =3D nvmet_execute_cross_ctrl_reset; + return 0; default: return nvmet_report_invalid_opcode(req); } diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 4c8f30c5ff7e..f5d7cb9c943a 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -117,6 +117,20 @@ u16 nvmet_zero_sgl(struct nvmet_req *req, off_t off, s= ize_t len) return 0; } =20 +void nvmet_ctrl_cleanup_ccrs(struct nvmet_ctrl *ctrl, bool all) +{ + struct nvmet_ccr *ccr, *tmp; + + lockdep_assert_held(&ctrl->lock); + + list_for_each_entry_safe(ccr, tmp, &ctrl->ccr_list, entry) { + if (all || ccr->ctrl =3D=3D NULL) { + list_del(&ccr->entry); + kfree(ccr); + } + } +} + static u32 nvmet_max_nsid(struct nvmet_subsys *subsys) { struct nvmet_ns *cur; @@ -1415,6 +1429,7 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl) if (!nvmet_is_disc_subsys(ctrl->subsys)) { ctrl->ciu =3D ((u8)(ctrl->ciu + 1)) ? : 1; ctrl->cirn =3D get_random_u64(); + nvmet_ctrl_cleanup_ccrs(ctrl, false); } ctrl->csts =3D NVME_CSTS_RDY; =20 @@ -1520,6 +1535,37 @@ struct nvmet_ctrl *nvmet_ctrl_find_get(const char *s= ubsysnqn, return ctrl; } =20 +struct nvmet_ctrl *nvmet_ctrl_find_get_ccr(struct nvmet_subsys *subsys, + const char *hostnqn, u8 ciu, + u16 cntlid, u64 cirn) +{ + struct nvmet_ctrl *ctrl, *ictrl =3D NULL; + bool found =3D false; + + mutex_lock(&subsys->lock); + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) { + if (ctrl->cntlid !=3D cntlid) + continue; + if (strncmp(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE)) + continue; + + /* Avoid racing with a controller that is becoming ready */ + mutex_lock(&ctrl->lock); + if (ctrl->ciu =3D=3D ciu && ctrl->cirn =3D=3D cirn) + found =3D true; + mutex_unlock(&ctrl->lock); + + if (found) { + if (kref_get_unless_zero(&ctrl->ref)) + ictrl =3D ctrl; + break; + } + } + mutex_unlock(&subsys->lock); + + return ictrl; +} + u16 nvmet_check_ctrl_status(struct nvmet_req *req) { if (unlikely(!(req->sq->ctrl->cc & NVME_CC_ENABLE))) { @@ -1645,6 +1691,7 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_allo= c_ctrl_args *args) subsys->clear_ids =3D 1; #endif =20 + INIT_LIST_HEAD(&ctrl->ccr_list); INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work); INIT_LIST_HEAD(&ctrl->async_events); INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL); @@ -1760,12 +1807,43 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_al= loc_ctrl_args *args) } EXPORT_SYMBOL_GPL(nvmet_alloc_ctrl); =20 +static void nvmet_ctrl_complete_pending_ccr(struct nvmet_ctrl *ctrl) +{ + struct nvmet_subsys *subsys =3D ctrl->subsys; + struct nvmet_ctrl *sctrl; + struct nvmet_ccr *ccr; + + lockdep_assert_held(&subsys->lock); + + /* Cleanup all CCRs issued by ctrl as source controller */ + mutex_lock(&ctrl->lock); + nvmet_ctrl_cleanup_ccrs(ctrl, true); + mutex_unlock(&ctrl->lock); + + /* + * Find all CCRs targeting ctrl as impacted controller and + * set ccr->ctrl to NULL. This tells the source controller + * that CCR completed successfully. + */ + list_for_each_entry(sctrl, &subsys->ctrls, subsys_entry) { + mutex_lock(&sctrl->lock); + list_for_each_entry(ccr, &sctrl->ccr_list, entry) { + if (ccr->ctrl =3D=3D ctrl) { + ccr->ctrl =3D NULL; + break; + } + } + mutex_unlock(&sctrl->lock); + } +} + static void nvmet_ctrl_free(struct kref *ref) { struct nvmet_ctrl *ctrl =3D container_of(ref, struct nvmet_ctrl, ref); struct nvmet_subsys *subsys =3D ctrl->subsys; =20 mutex_lock(&subsys->lock); + nvmet_ctrl_complete_pending_ccr(ctrl); nvmet_ctrl_destroy_pr(ctrl); nvmet_release_p2p_ns_map(ctrl); list_del(&ctrl->subsys_entry); diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index e3e414ef68d3..3c70ef13c9b4 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -273,6 +273,7 @@ struct nvmet_ctrl { u32 kato; u64 cirn; =20 + struct list_head ccr_list; struct nvmet_port *port; =20 u32 aen_enabled; @@ -319,6 +320,13 @@ struct nvmet_ctrl { struct nvmet_pr_log_mgr pr_log_mgr; }; =20 +struct nvmet_ccr { + struct nvmet_ctrl *ctrl; + struct list_head entry; + u16 icid; + u8 ciu; +}; + struct nvmet_subsys { enum nvme_subsys_type type; =20 @@ -584,6 +592,7 @@ void nvmet_req_free_sgls(struct nvmet_req *req); void nvmet_execute_set_features(struct nvmet_req *req); void nvmet_execute_get_features(struct nvmet_req *req); void nvmet_execute_keep_alive(struct nvmet_req *req); +void nvmet_execute_cross_ctrl_reset(struct nvmet_req *req); =20 u16 nvmet_check_cqid(struct nvmet_ctrl *ctrl, u16 cqid, bool create); u16 nvmet_check_io_cqid(struct nvmet_ctrl *ctrl, u16 cqid, bool create); @@ -626,6 +635,10 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_alloc= _ctrl_args *args); struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid, struct nvmet_req *req); +struct nvmet_ctrl *nvmet_ctrl_find_get_ccr(struct nvmet_subsys *subsys, + const char *hostnqn, u8 ciu, + u16 cntlid, u64 cirn); +void nvmet_ctrl_cleanup_ccrs(struct nvmet_ctrl *ctrl, bool all); void nvmet_ctrl_put(struct nvmet_ctrl *ctrl); u16 nvmet_check_ctrl_status(struct nvmet_req *req); ssize_t nvmet_ctrl_host_traddr(struct nvmet_ctrl *ctrl, diff --git a/include/linux/nvme.h b/include/linux/nvme.h index cbaf02b0cf07..7e6150d9494a 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -22,6 +22,7 @@ #define NVMF_TSAS_SIZE 256 =20 #define NVMF_CCR_LIMIT 4 +#define NVMF_CCR_PER_PAGE 511 =20 #define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" =20 @@ -1233,6 +1234,22 @@ struct nvme_zone_mgmt_recv_cmd { __le32 cdw14[2]; }; =20 +struct nvme_cross_ctrl_reset_cmd { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __le64 rsvd2[2]; + union nvme_data_ptr dptr; + __le16 icid; + __u8 ciu; + __u8 rsvd10; + __le32 cdw11; + __le64 cirn; + __le32 cdw14; + __le32 cdw15; +}; + struct nvme_io_mgmt_recv_cmd { __u8 opcode; __u8 flags; @@ -1331,6 +1348,7 @@ enum nvme_admin_opcode { nvme_admin_virtual_mgmt =3D 0x1c, nvme_admin_nvme_mi_send =3D 0x1d, nvme_admin_nvme_mi_recv =3D 0x1e, + nvme_admin_cross_ctrl_reset =3D 0x38, nvme_admin_dbbuf =3D 0x7C, nvme_admin_format_nvm =3D 0x80, nvme_admin_security_send =3D 0x81, @@ -1364,6 +1382,7 @@ enum nvme_admin_opcode { nvme_admin_opcode_name(nvme_admin_virtual_mgmt), \ nvme_admin_opcode_name(nvme_admin_nvme_mi_send), \ nvme_admin_opcode_name(nvme_admin_nvme_mi_recv), \ + nvme_admin_opcode_name(nvme_admin_cross_ctrl_reset), \ nvme_admin_opcode_name(nvme_admin_dbbuf), \ nvme_admin_opcode_name(nvme_admin_format_nvm), \ nvme_admin_opcode_name(nvme_admin_security_send), \ @@ -2022,6 +2041,7 @@ struct nvme_command { struct nvme_dbbuf dbbuf; struct nvme_directive_cmd directive; struct nvme_io_mgmt_recv_cmd imr; + struct nvme_cross_ctrl_reset_cmd ccr; }; }; =20 @@ -2186,6 +2206,9 @@ enum { NVME_SC_PMR_SAN_PROHIBITED =3D 0x123, NVME_SC_ANA_GROUP_ID_INVALID =3D 0x124, NVME_SC_ANA_ATTACH_FAILED =3D 0x125, + NVME_SC_CCR_IN_PROGRESS =3D 0x13f, + NVME_SC_CCR_LOGPAGE_FULL =3D 0x140, + NVME_SC_CCR_LIMIT_EXCEEDED =3D 0x141, =20 /* * I/O Command Set Specific - NVM commands: --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3627E411F80 for ; Fri, 18 Sep 2026 18:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755427; cv=none; b=SF/VFMEDmEjTqr8mx7vsWanH5mE8ifk89+ltZC+NjLwAZuJM0TZ84D+toWWm3XEmIiSrMRb+xgcHy78h1vIpB5xUDsCJ2+xz5kepft374bn6HwrQ3AUhK8hSbCTyVsWGtVGE7UYRsMbaQ/diaraRZ052alCdPDLGZ7HgfqYFANw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755427; c=relaxed/simple; bh=VQDHW9FxpODr/6qNaLXLya3/nUiKniaCJvNe7qJ4yBA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eMnydKDk0JAg4PsEWxtZajYFE3ZXFsqNJFaq8GJRt+NFGeWI2HfOgLgjSYB9BdvMXzhPY1iJZv30b7mAkhH9vyvJRFvIzuWBOc9f/PjF3tPJ4WpHPPcs8WbbG9qiqQHZd6qB3VUvV0+NE7kVD3pnvv3thbPHDerFnlUvBpItOHQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=ABj7IW6X; arc=none smtp.client-ip=209.85.216.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="ABj7IW6X" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-39e588a7a12so800168a91.1 for ; Fri, 18 Sep 2026 11:17:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755424; x=1790360224; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=XucfLuTS9otn5RCUHBJMmZsLBhJtMpUV15kULQxOZKo=; b=ABj7IW6XvzydpSMBXV0TmaVIR3rzZmABl0HzLsVYS+OkIbH6NrC7jNI6Sq7tDaBERy nIB5wi7rJFPoZY9FpPKgySQT4ZEkDvmXS8UG6sifQxM4mDclbhrnvOZkSnlQa29fiaJ5 v7jPboevXufKSW5SAP1h5sgj89+BOpiOMCl3Q2K2sMsc0OC39hON0O91+6ZXpbzsXs+a njoSf0LbdIXaKTrCQ3qYZqVdYmLLoCLd05QrsmMJNUsgYov4DQGcttg0mw+rANvmEE/x 9qObeVZ4exioUnKQvKbdY1Noh66J8XfJHDtr02tKOjdTfniqyOYbI3TLGWsiVhcNcxEj ZXPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755424; x=1790360224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=XucfLuTS9otn5RCUHBJMmZsLBhJtMpUV15kULQxOZKo=; b=chu/n7sLScBSBohRfdDvZGwxevYWA1aDB20PXwj+XmRPSFFIEtt4veTlDAlNW1tz6I 9hXKsQEOSgOM5jVPbZi9raiEfZAVTFEeK0ybxKso5n7IcRk6m/6l1aHZo2oazYu8Mre3 R0i7cA+wHZt66jlH3N6yS/6zNTVn9SMuBpzoaDh/Vu589Ja1WZZ4hzEZp6Bj2EyXA0tO IJMAoBY7e3ZRM8r/XluaganEfX4rlXtfshW0eVL0IlH+cB8jHnQKQ75wkzmLZ5mmqRTg PTS3ND4QzzmBNyB6Q1Pv0HFaWQlzE/We91uQ6oNV36fXb0dXSXhi9TZDeCPmEktatc8w v4Yw== X-Forwarded-Encrypted: i=1; AKwUvByhfHeSjUrSQ+p7Coy7UUopepQPmtJpHJeCkod7PrgXMJcJuFtHJnG7KSSpLRaJRkbR4oASiuAl6eASGZQ=@vger.kernel.org X-Gm-Message-State: AFuF++ma5nb0wPPkTryJ+G7sm+tSFa1j6szXxsEluhQuJ+qI1j/JhHj6 vU6oqXIimTQDu45R2XdMDMJ6AYWIcIrsyFsjcveoRJBOuhzlMCfpFGy9eVD0q6fs83A= X-Gm-Gg: AYBFou0klXDwlBpVN9sFwMiRi15sLR1I9XBa7vlrqpy/irU3ud/arc5+JbFl0rGLDKZ HHWQW8VEdkYqOjAYpvc38Azo4DEj66LB5owOz/2ldW3bn6OeW3TUPFcs/DH2VdVC4ZzjVC1CKt6 Cprjj+4lzdwvM0F8PqMpHZpXNNbI3IQRZpD2HND5E0/ABe8LIzgDkDNuVwQBUIpw8XqCS8QB8m6 SPVm0z61BcW6rJ9GECxV0/Uf+0FP6t/y5w7xN6CQYa1FiRY7/aZZuhGl3SIDjtC2A7pHyxHyIXe YtMbSP3aw0e+OZK71yX4DujdUtbzpQ3u3RWnnHqcKmPcWabxPJN7fJh9pzZ0wR/NZ0hC6oYdzU3 rx5OsG4cTi0tUTRviLqnJo7FUr/eYITX5VyepCn2rmnRMSC5yd6o6PnVmzQooYEMbqFFQOb6HKa wJkJiGWwpjjZq+1VciWuLLvd7oReFDD0lBlGCfdMGtkwuhhAc8lg8X0YRruh8kh1HBjNPIWqr1J 04k3W+KL/4P5H0PLtaV0g== X-Received: by 2002:a17:90b:3c92:b0:39e:542d:a8c5 with SMTP id 98e67ed59e1d1-39e542da9ecmr4678007a91.7.1789755424265; Fri, 18 Sep 2026 11:17:04 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:03 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 04/18] nvmet: Implement CCR logpage Date: Fri, 18 Sep 2026 11:14:04 -0700 Message-ID: <20260918181614.3947933-5-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Defined by TP8028 Rapid Path Failure Recovery, CCR (Cross-Controller Reset) log page contains an entry for each CCR request submitted to source controller. Implement CCR logpage for nvme linux target. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/admin-cmd.c | 44 +++++++++++++++++++++++++++++++++ include/linux/nvme.h | 29 ++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index 21538e7c83be..a60b2f271e98 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -220,6 +220,7 @@ static void nvmet_execute_get_supported_log_pages(struc= t nvmet_req *req) logs->lids[NVME_LOG_FEATURES] =3D cpu_to_le32(NVME_LIDS_LSUPP); logs->lids[NVME_LOG_RMI] =3D cpu_to_le32(NVME_LIDS_LSUPP); logs->lids[NVME_LOG_RESERVATION] =3D cpu_to_le32(NVME_LIDS_LSUPP); + logs->lids[NVME_LOG_CCR] =3D cpu_to_le32(NVME_LIDS_LSUPP); =20 status =3D nvmet_copy_to_sgl(req, 0, logs, sizeof(*logs)); kfree(logs); @@ -608,6 +609,47 @@ static void nvmet_execute_get_log_page_features(struct= nvmet_req *req) nvmet_req_complete(req, status); } =20 +static void nvmet_execute_get_log_page_ccr(struct nvmet_req *req) +{ + struct nvmet_ctrl *ctrl =3D req->sq->ctrl; + struct nvmet_ccr *ccr; + struct nvme_ccr_log *log; + int index =3D 0; + u16 status; + + log =3D kzalloc_obj(*log); + if (!log) { + status =3D NVME_SC_INTERNAL; + goto out; + } + + mutex_lock(&ctrl->lock); + list_for_each_entry(ccr, &ctrl->ccr_list, entry) { + u8 flags =3D NVME_CCR_FLAGS_VALIDATED | NVME_CCR_FLAGS_INITIATED; + u8 ccr_status =3D ccr->ctrl ? NVME_CCR_STATUS_IN_PROGRESS : + NVME_CCR_STATUS_SUCCESS; + + log->entries[index].icid =3D cpu_to_le16(ccr->icid); + log->entries[index].ciu =3D ccr->ciu; + log->entries[index].acid =3D cpu_to_le16(0xffff); + log->entries[index].ccrs =3D ccr_status; + log->entries[index].ccrf =3D flags; + index++; + } + + /* Cleanup completed CCRs if requested */ + if (req->cmd->get_log_page.lsp & 0x1) + nvmet_ctrl_cleanup_ccrs(ctrl, false); + mutex_unlock(&ctrl->lock); + + log->ne =3D cpu_to_le16(index); + nvmet_clear_aen_bit(req, NVME_AEN_BIT_CCR_COMPLETE); + status =3D nvmet_copy_to_sgl(req, 0, log, sizeof(*log)); + kfree(log); +out: + nvmet_req_complete(req, status); +} + static void nvmet_execute_get_log_page(struct nvmet_req *req) { if (!nvmet_check_transfer_len(req, nvmet_get_log_page_len(req->cmd))) @@ -641,6 +683,8 @@ static void nvmet_execute_get_log_page(struct nvmet_req= *req) return nvmet_execute_get_log_page_rmi(req); case NVME_LOG_RESERVATION: return nvmet_execute_get_log_page_resv(req); + case NVME_LOG_CCR: + return nvmet_execute_get_log_page_ccr(req); } pr_debug("unhandled lid %d on qid %d\n", req->cmd->get_log_page.lid, req->sq->qid); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 7e6150d9494a..70dd0770e032 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -1440,6 +1440,7 @@ enum { NVME_LOG_ANA =3D 0x0c, NVME_LOG_FEATURES =3D 0x12, NVME_LOG_RMI =3D 0x16, + NVME_LOG_CCR =3D 0x1e, NVME_LOG_FDP_CONFIGS =3D 0x20, NVME_LOG_DISC =3D 0x70, NVME_LOG_RESERVATION =3D 0x80, @@ -1466,6 +1467,34 @@ enum { NVME_FIS_CSCPE =3D 1 << 21, }; =20 +/* NVMe Cross-Controller Reset Status */ +enum { + NVME_CCR_STATUS_IN_PROGRESS, + NVME_CCR_STATUS_SUCCESS, + NVME_CCR_STATUS_FAILED, +}; + +/* NVMe Cross-Controller Reset Flags */ +enum { + NVME_CCR_FLAGS_VALIDATED =3D 0x01, + NVME_CCR_FLAGS_INITIATED =3D 0x02, +}; + +struct nvme_ccr_log_entry { + __le16 icid; + __u8 ciu; + __u8 rsvd3; + __le16 acid; + __u8 ccrs; + __u8 ccrf; +}; + +struct nvme_ccr_log { + __le16 ne; + __u8 rsvd2[6]; + struct nvme_ccr_log_entry entries[NVMF_CCR_PER_PAGE]; +}; + /* NVMe Namespace Write Protect State */ enum { NVME_NS_NO_WRITE_PROTECT =3D 0, --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1BFB351D509 for ; Fri, 18 Sep 2026 18:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755427; cv=none; b=GYOeAScH0C8KAnJXLC75UOyM1ToAWkzwJoS190IiL51DYnMyEHrU6lxiCEVNjQEONA/4nyxex8UxjDF88TY6fffYjDCeXVH5WdX9+RkniM/PtdrjAYbPYj2ang5STMc3Ef8//OFYGDPDb0BjZ6vVLHcmhOWHYVRPRZq9VKA4RfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755427; c=relaxed/simple; bh=RIVoOlmqZFMJOUfhjvyFuQR9GESlJzJLW8eoZZQuGKo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NJ/aleF5/7v2xrChMSmwgMI0Vet6nG1e7lEbhD5N4TUwqfpFsinJTEs0xsMa/nOcpaQ3aJWg6JTKDidxjdDlRSi9Ya0gZm35bvTPl5nwdRsIlcOGPVdJkNBeaT/092NImqIR4tgiq30NdIEbEHdorBL/f0YU/ojhZ9HID8ss6+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=DnFgGCHv; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="DnFgGCHv" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-398cb5615deso1201309a91.3 for ; Fri, 18 Sep 2026 11:17:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755425; x=1790360225; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=tcg806D5vzEHCLipGmbi/V7P1l0j+1hngUNt1RnsJGI=; b=DnFgGCHvJ9HlYG+oLRQ4UU3+XtKyAWYIA1seTx1vYWf3uMQELFd6WG5L/UHZzsgpDA qfG5nSLZVTpvliedYZqm7szjLFmCe6DTGP6UNvEchMmP9PehAmIOiATX5zVgG2NjXzhB ZcmSNFNXEMSU4lZy9xX3s9B5tPnKnfPBYZpc6a5ymo+7CCwCzwflxOx2rYd08cYLiB3m HGMnjMMlWs5fbc4IgCea1UnhhbS8HYZ84Maut6qpEheARm4aKzr0Jp8Eyhtm7XglO8DA /zSDat+z7cBak3sn3v5E3aD1Lqf9d8+vTJ5y340q9JbkTp2XCvy9245uGMlpjLe6HYxF KFBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755425; x=1790360225; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=tcg806D5vzEHCLipGmbi/V7P1l0j+1hngUNt1RnsJGI=; b=FY+haeLEogXuAZFVByE4wfrWln13rnwMEcAcmGiT2qgPG3esn5aHbVoUKGe7TSdUzD s+bLsB0FzI4N5v/DpgfWwGfvXrh1u6apOdNp1yZuPEp64ngiFmOxLnC7QRbv3PrhzDKA qetoWWieaJDXIFJbr0UjqjCqz1ftghTiDxms0DaoRt+E6nga6DUiTrcG/kRci6NhFyLf jtubLGEG5xkwdO+fiHRROqZKyDTLRchfDoZieHEYPKPhbiMq3V8lGqtVD42ZDBK1EvXL 3gc+ACX1eCwI5CFBY75Ul3fGYqZYWZ+lsdqiTAUyMtK65O5xUKsSt3gsctImQg9qOCfL vtqw== X-Forwarded-Encrypted: i=1; AKwUvBwE4PqKvcf3LKZJwPRaeThviyWCAFr3R53tvDXalrDUvy9Wsn97Dg8eVNfE+qJ4p+YlbmA44Ol+vwPdr0A=@vger.kernel.org X-Gm-Message-State: AFuF++kFuRjqazz7n0CD0H+UzEnzT16R6kAV7mvALLax/LFPlnxbhgGO Grvv5p8CKFbFRSEEGj9b5YrSJqvbV7Ep4TYFLJ6CoSSqvGHqtztMD8Xq24gqZIIrDIY= X-Gm-Gg: AYBFou1Ux1sdBvQWBtacsk1lGY70Gxy4EAinh2jauOQeP/qkjXRobcVaFRo1hHb8e2M fXf0g4MjuB4BKYoMgONLv5lSv7FN/rwCN4QML14LeKz+s2ZbOT98MCo8AOD0bI0nTYdj1QiVDPK 7ovYx0W6magTLs8KJWp5f+WPFmiHPaUymSNuGMlJXWhWS1RKtpjYCrU0TEQR1yHcJmiVAZYID8g n7ylCIeN6BMPZoFIpOBdewXsVd3XCujQ5rPN1hFvzolE5cbhBdm3UD2Vv7UUS0kd6ij5gK8IrtJ L0OgiRFQpwJBMqufzgaFt5YEnCz+/CCxuCOwvzUwlQw2ihw/JoxSg9slYa773cfAbL/dlrzx4rV 85ti7WoJuG0zP1KpACDZC9i/JlbDu1f53+9d/Du8Kp4uTieySKebJzh2kyo6D0n18UYHOY3u5xh MyPtKCTfmJlBxD6K3eDKdEVckUiLZMIn8zkurhA5PttfehET64dF5xRn1I8qv5P2W9q/lA/t3K2 MQvQMhcnQVqwjZzxKxoiQ== X-Received: by 2002:a17:90a:3f10:b0:39e:5cd8:2140 with SMTP id 98e67ed59e1d1-39e5cd825f0mr3188400a91.20.1789755425376; Fri, 18 Sep 2026 11:17:05 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:04 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 05/18] nvmet: Send an AEN on CCR completion Date: Fri, 18 Sep 2026 11:14:05 -0700 Message-ID: <20260918181614.3947933-6-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When an impacted controller that is the target of pending CCRs is torn down, send an AEN to each source controller that issued a CCR against it. The notification points to the CCR log page that the source controller can read to check which CCR operation completed. Split nvmet_add_async_event() into a locked helper so the AEN can be queued while ctrl->lock is already held. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/core.c | 25 ++++++++++++++++++++++--- drivers/nvme/target/nvmet.h | 3 ++- include/linux/nvme.h | 3 +++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index f5d7cb9c943a..69491e8e52ba 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -205,7 +205,7 @@ static void nvmet_async_event_work(struct work_struct *= work) nvmet_async_events_process(ctrl); } =20 -void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type, +static void nvmet_add_async_event_locked(struct nvmet_ctrl *ctrl, u8 event= _type, u8 event_info, u8 log_page) { struct nvmet_async_event *aen; @@ -218,13 +218,19 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u= 8 event_type, aen->event_info =3D event_info; aen->log_page =3D log_page; =20 - mutex_lock(&ctrl->lock); list_add_tail(&aen->entry, &ctrl->async_events); - mutex_unlock(&ctrl->lock); =20 queue_work(nvmet_aen_wq, &ctrl->async_event_work); } =20 +void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type, + u8 event_info, u8 log_page) +{ + mutex_lock(&ctrl->lock); + nvmet_add_async_event_locked(ctrl, event_type, event_info, log_page); + mutex_unlock(&ctrl->lock); +} + static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 ns= id) { u32 i; @@ -1807,6 +1813,18 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_all= oc_ctrl_args *args) } EXPORT_SYMBOL_GPL(nvmet_alloc_ctrl); =20 +static void nvmet_ctrl_notify_ccr(struct nvmet_ctrl *ctrl) +{ + lockdep_assert_held(&ctrl->lock); + + if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_CCR_COMPLETE)) + return; + + nvmet_add_async_event_locked(ctrl, NVME_AER_NOTICE, + NVME_AER_NOTICE_CCR_COMPLETED, + NVME_LOG_CCR); +} + static void nvmet_ctrl_complete_pending_ccr(struct nvmet_ctrl *ctrl) { struct nvmet_subsys *subsys =3D ctrl->subsys; @@ -1830,6 +1848,7 @@ static void nvmet_ctrl_complete_pending_ccr(struct nv= met_ctrl *ctrl) list_for_each_entry(ccr, &sctrl->ccr_list, entry) { if (ccr->ctrl =3D=3D ctrl) { ccr->ctrl =3D NULL; + nvmet_ctrl_notify_ccr(sctrl); break; } } diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 3c70ef13c9b4..88fa11aa0587 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -44,7 +44,8 @@ * Supported optional AENs: */ #define NVMET_AEN_CFG_OPTIONAL \ - (NVME_AEN_CFG_NS_ATTR | NVME_AEN_CFG_ANA_CHANGE) + (NVME_AEN_CFG_NS_ATTR | NVME_AEN_CFG_ANA_CHANGE | \ + NVME_AEN_CFG_CCR_COMPLETE) #define NVMET_DISC_AEN_CFG_OPTIONAL \ (NVME_AEN_CFG_DISC_CHANGE) =20 diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 70dd0770e032..3757d11ffea3 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -871,12 +871,14 @@ enum { NVME_AER_NOTICE_FW_ACT_STARTING =3D 0x01, NVME_AER_NOTICE_ANA =3D 0x03, NVME_AER_NOTICE_DISC_CHANGED =3D 0xf0, + NVME_AER_NOTICE_CCR_COMPLETED =3D 0xf4, }; =20 enum { NVME_AEN_BIT_NS_ATTR =3D 8, NVME_AEN_BIT_FW_ACT =3D 9, NVME_AEN_BIT_ANA_CHANGE =3D 11, + NVME_AEN_BIT_CCR_COMPLETE =3D 20, NVME_AEN_BIT_DISC_CHANGE =3D 31, }; =20 @@ -884,6 +886,7 @@ enum { NVME_AEN_CFG_NS_ATTR =3D 1 << NVME_AEN_BIT_NS_ATTR, NVME_AEN_CFG_FW_ACT =3D 1 << NVME_AEN_BIT_FW_ACT, NVME_AEN_CFG_ANA_CHANGE =3D 1 << NVME_AEN_BIT_ANA_CHANGE, + NVME_AEN_CFG_CCR_COMPLETE =3D 1 << NVME_AEN_BIT_CCR_COMPLETE, NVME_AEN_CFG_DISC_CHANGE =3D 1 << NVME_AEN_BIT_DISC_CHANGE, }; =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA88451D531 for ; Fri, 18 Sep 2026 18:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755428; cv=none; b=LTglPK1r4OxVqM7G8dEFDu6bEwrIXkY5FAdynt7OFIoCkzXk4F5UAsYmg2SeYNeIxwxbp0sWI2P5+6XYmnNbVfddY+E25/f6A/C0oUqH31g8B3YmzeP3i5yt3VIMcQCFbNq0FiFOVMUNgkQXz5MwAO0PBMQMEplKrLc4PBJS8Z0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755428; c=relaxed/simple; bh=AnpJGEP0W1AN/GcBwLnNfGbUIBoDF6SMZ0PKVmp8Mgc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TfqazFLuowpTeWj54PUTgt5yhY2APIsE7w1AaMPVW/eC4pNHZoPrA2oG5bgnZbq4aRq5YsmC2zSiFB+SD6/0JK2XxpY5y2uUhXiwXytF/Nr3dUgSlZOetVCw5WKuQ5Lc+32Qxv8SqroFyG9xYkr+T36Q3kzeERC5CIdVD2bbdGE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=ZaoiC3Pp; arc=none smtp.client-ip=74.125.227.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="ZaoiC3Pp" Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-398cb5615deso1201322a91.3 for ; Fri, 18 Sep 2026 11:17:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755426; x=1790360226; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+9AGoVe097CFQTljKQVnFARTDua53EnwrZ8dQWbEJDU=; b=ZaoiC3PpnpPh8uD0E5FymqWwoYM13qco9SH0zP06OLsYeU8dJhaZuC879BxIxtG76d 7lCxmlCjkv1/BS5LcoJbKAiui14GVBna4z3OHTyyRjcOQ+oQ475vEaMpRTEhwnscszlM JP/Q4xbZettkTmD4U3MiSd3zL4Xh/YIkOHXs2d+5RG9yVoA+lBJJC93+UVf/vEBzpyDI 6m7NNxUqm/EV96SF4Zt38vdxztkGSGT7esQKisEK8E+y5tVwYqPcjlLRfQtlVUSagKKk 9FgQMLn06gFvCKe5DvfnsBjHm/VnY4sHDqcrxB5hvnX8XTPiQlxLD/2vauafMCCCq/5k ov9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755426; x=1790360226; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=+9AGoVe097CFQTljKQVnFARTDua53EnwrZ8dQWbEJDU=; b=UWJCTX7m6UFBYOSDBnebugQ8wT3Mqo98TJs9tS2IE3qeAYIAhC3OaO7tWPsiIcsh29 fDNtFfa6UzCPgajgtu9fsbiFchXHmeQ4gbg8ehD2aDhlZxeaS8GC5BkvkSdTvr4lMTlM vTY5EOcoWUoyV8cBoWDuqHQuZwbnTFezqo3AlEq1TFUmz83S05/LLBiPA29mCUuwcq2Q UeMkHF6lB2fm1efe5xzNaOOcfWF+HqsGi5eOL+ImTbixJ27F1GL71Z5/7yr+opIlJxE3 S+e6u5kfop7nCqG5I0usKPLxXkVyUxYUim2oU+NvYImiZq7Ay3wESzK5dW+RvllWG3ml DBKw== X-Forwarded-Encrypted: i=1; AKwUvBwkjVt8EYSxmI69poFmaWPI02OalOeHQhi3pmsj1F18zcqdVQ/ZitHKgk4X6mS5+DS3pgO2Cgbo6reEqPs=@vger.kernel.org X-Gm-Message-State: AFuF++lodjIj7cuFUk5ff0hvDDN2QdNo4Gzp4AnHkA1ysB8QhhSGz48u Uw6ivREUGDHA4kCpZl1F4/8oI9rHYWsgSnHx34Q7G8BThtk9yWaatSiFSIBB85NLdf8= X-Gm-Gg: AYBFou0pOhGDyPrMCHTzmlbhrxLrRXIGYT4fSGFwE3q+dTUmp1ceKQoZOsJNcvKGlMC 6ug8TiHReTVTiFHBWaCbx5GtwmqZWtVJH1V7gai70h191XuL+voWx0koHGLo3Vm8vZcB5h1Dk6M 9XCQFTPz1f6Zv/t31eEWD2Wu/SbFfxSDwB2MTSxhsKqxs/l0ItpFEvUiTjpN0+ZBrKlGBPflPlY W3x211zWJWiuDC/pXUYJIsNlmqaz4OONOygzspapwJfYRr/teTb78aao/QRjdXCIfTOE16xtqF4 kTVlRAXwvMdoiOtXQRpjEWbcxwCZPRpVDzpd7k/3qQ5QEWeHU8u0lfMEoXGa24Ed3kc+WVKuXoq G0Un7vVX3PfNHY1LErQDsjT35mhgVoFY2fAn0dp6QIOZ0StUf4UGwZSHxT30+2JYWl7470A/B0i rrCmJeRILNARHVdFmNe7aN531BdSAhjy5SqJu2BV79B14wMEEHk2sskGQ0LIeGq5ylf1/GdtxnW IVVBx6/LzKt5Td9T+3M6VdiBn8Qj1GD X-Received: by 2002:a17:90b:4c03:b0:39e:6c69:9b90 with SMTP id 98e67ed59e1d1-39e6c69b206mr680725a91.53.1789755426270; Fri, 18 Sep 2026 11:17:06 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:05 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 06/18] nvme: Rapid Path Failure Recovery read controller identify fields Date: Fri, 18 Sep 2026 11:14:06 -0700 Message-ID: <20260918181614.3947933-7-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TP8028 Rapid Path Failure added new fields to controller identify response. Read CIU (Controller Instance Uniquifier), CIRN (Controller Instance Random Number), and CCRL (Cross-Controller Reset Limit) from controller identify response. Expose CIU and CIRN as sysfs attributes so the values can be used directly by user if needed. Also add the nvme_fence_timeout_ms() helper that derives a fencing timeout from the controller keep-alive timeout (kato). Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/host/core.c | 4 ++++ drivers/nvme/host/nvme.h | 10 ++++++++++ drivers/nvme/host/sysfs.c | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 758245c799a1..ae7c04b77a3e 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3666,6 +3666,10 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl) ctrl->crdt[1] =3D le16_to_cpu(id->crdt2); ctrl->crdt[2] =3D le16_to_cpu(id->crdt3); =20 + ctrl->ciu =3D id->ciu; + ctrl->cirn =3D le64_to_cpu(id->cirn); + ctrl->ccrl =3D id->ccrl; + ctrl->oacs =3D le16_to_cpu(id->oacs); ctrl->oncs =3D le16_to_cpu(id->oncs); ctrl->mtfa =3D le16_to_cpu(id->mtfa); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 2cff9fcbf740..cb9d7f45188f 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -393,11 +393,14 @@ struct nvme_ctrl { u16 crdt[3]; u16 oncs; u8 dmrl; + u8 ciu; u32 dmrsl; + u64 cirn; u16 oacs; u16 sqsize; u32 max_namespaces; atomic_t abort_limit; + u8 ccrl; u8 vwc; u32 vs; u32 sgls; @@ -1339,4 +1342,11 @@ static inline bool nvme_multi_css(struct nvme_ctrl *= ctrl) return (ctrl->ctrl_config & NVME_CC_CSS_MASK) =3D=3D NVME_CC_CSS_CSI; } =20 +static inline unsigned long nvme_fence_timeout_ms(struct nvme_ctrl *ctrl) +{ + if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) + return 3 * ctrl->kato * 1000; + return 2 * ctrl->kato * 1000; +} + #endif /* _NVME_H */ diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c index 02a2490a9ed7..b60f5b66a1d1 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -487,6 +487,27 @@ nvme_show_int_function(queue_count); nvme_show_int_function(sqsize); nvme_show_int_function(kato); =20 +static ssize_t nvme_sysfs_ciu_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%02x\n", ctrl->ciu); +} +static DEVICE_ATTR(ciu, S_IRUSR, nvme_sysfs_ciu_show, NULL); + +static ssize_t nvme_sysfs_cirn_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%016llx\n", ctrl->cirn); +} +static DEVICE_ATTR(cirn, S_IRUSR, nvme_sysfs_cirn_show, NULL); + + static ssize_t nvme_sysfs_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -941,6 +962,8 @@ static struct attribute *nvme_dev_attrs[] =3D { &dev_attr_numa_node.attr, &dev_attr_queue_count.attr, &dev_attr_sqsize.attr, + &dev_attr_ciu.attr, + &dev_attr_cirn.attr, &dev_attr_hostnqn.attr, &dev_attr_hostid.attr, &dev_attr_ctrl_loss_tmo.attr, --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f43.google.com (mail-pj2-f43.google.com [74.125.227.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79B3051DAF6 for ; Fri, 18 Sep 2026 18:17:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755430; cv=none; b=Dy6ysucnQcIQlXC3aN3eMXTbaMGbr8l0NbQbSR7lbWMeg4wYpCO485I8vp5kNtW5e6WPkFzaCj4Ijx0Hd2a3hGGLM8/D2OWURIolXSEvybF1U467AvC7w2cugJFQmHwN8XpOt6qZD1eXfZHtm50v3mWG8EDs22B9hvevkMN0gGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755430; c=relaxed/simple; bh=AcE9zrysBOb+NlUMMSohIv2aatVf8yMIkkVyal8cEMQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ILezj8fUYn78tSnzqJYwCu91XQyBWPXD2ud1a/J+yV5OL/giOn6vby5m7iJhiYhc91kiwZID4oBfonxTjQIELmH4R1XXTVpIzjX1D8bJmtOt0pzExFvGoX4AtA8RLgnsA+tGDZXA7dfemkTtXyPHFw2Q6yaC07dITUtMJULW4nA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=WXsA8Qbq; arc=none smtp.client-ip=74.125.227.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="WXsA8Qbq" Received: by mail-pj2-f43.google.com with SMTP id 98e67ed59e1d1-396ccc02279so913344a91.1 for ; Fri, 18 Sep 2026 11:17:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755428; x=1790360228; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lHWLxN1z9UCBkM9IJvLJg4YXBPTZaz9qxxb7LJ22R7c=; b=WXsA8QbqFVvas52YEURIudSqRMSYScJbKLCvprBpiOF7lMpwv6vQeetoWoF/2/uYOf Fex/7aopHkgPh8sXCBh3ozaHJdP4QDdT/XHl+otU/mlecKrysPUjtkmGYxbYYhGHcLOp kof1CnhOU37mC9510KzYBIoM+u3BC4qML1xEpThAOPaGogMf64V2lN2jER/lYqcfJKGI ZBHgaZCPWKKP0dP+gjvJq0Mha6ONaxKmoZn6oTBRU335DG9Ukvmt8updhh/PDQOu1+1a ow4iT+koj9Qq2rsJzPZAI67Io66N67YowDnIvosTN9rJIHdLjgtw9ahqgfGM0nHpK4xv Lxew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755428; x=1790360228; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=lHWLxN1z9UCBkM9IJvLJg4YXBPTZaz9qxxb7LJ22R7c=; b=m5fwAq97usJcIDUu/Aq79ynf9uq1Lgl5qghO/L6wVDpywl/lfCwJYQa+FYWYfG7wK7 D3j4/7ktRwJImRXLcCPebiS3sg9M/IEZdj6rtO75yh7OdaukQp9oFQL7uiF192H4Gc6e U7pFjKQsh8+exKujAB/XaZVt8r2yNUp1OcMM42aXe0PiXNw96Azt13V2RHrIIS4bAzGj M2mlz07O18pYGote2rawGOGv8v4V5eBullxPR0BfQCB1I46j4XRJ+wVyjzu9KZh7cdvZ d2Qfs4oarVXN1HVPjL0ElJ1381k5Xqo3uI+N9bdP5YQ9r6sc3JU4UhuDeAatJhkmQIlF o5Uw== X-Forwarded-Encrypted: i=1; AKwUvBzTD1WPYLtkKt/soNwQ4maG6IyMTI30KrfksMDeikyLTlbkpen9UIXGPgyyqMwHX9N1cfVEIqWP23bLkiA=@vger.kernel.org X-Gm-Message-State: AFuF++l+YAKsGi50c9MmxCMGlnzGbZYdlbTOearREl1FtYSxnprhTKtz thfMjEUT1humHKOXx8+M3iTwlfcV0KS2goncnr5pV5yQuB9Ot84l3gtcp3NIDCMqwXg= X-Gm-Gg: AYBFou2i116/mZLehN1GJZBO2JwT9K8P/YW63YO+XAVEABDsljy2x0b9zqgXt/M+S5u +LY5TzvA/B70uo+QQCFfrqp3bZ84PzeYv+niwM0coU3pCRyz25+Ns7wiHQ71MNlIo9G/SkJW9e1 c89eTGvlshFYVkSfGeRQWdmpyluVa2DI51wNXjedVAMnjEf7CNmybW3YmxfAyPUO6uaZvm07IIp PVd8EhwGLt/jG3B18ZGqpJ68itNAMBfZ7v5kUMQ/U10UlAPeDCd7S6lFyK0fLaAUj+HJFfI8hcp BlMmdke9vTLloEbQpjXKwu7tZbbH8yIe8paIVlCUpybYylEzg3S+8DmNIHst98mSFI2y+Csw4np IdzHjAYIomyIYeofSYle4CIrA3xuyI2vyW+1yF+1ShlJWPKOQjUgs1fFr8bhCI4HVRcfPssYIlz dF2I5aWqgGCoulZombidTV5/zwOJTOBGqoRgb/ofx/5ENfcz6E5n5c/MNBcdmqK3Ru0vBuvdg8D ThQikVz8xRzx9eYJ64yAw== X-Received: by 2002:a17:90b:4c0b:b0:39e:6c68:c77f with SMTP id 98e67ed59e1d1-39e6c68ca6bmr654464a91.53.1789755427466; Fri, 18 Sep 2026 11:17:07 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:06 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Hannes Reinecke Subject: [PATCH 07/18] nvme: Introduce FENCING and FENCED controller states Date: Fri, 18 Sep 2026 11:14:07 -0700 Message-ID: <20260918181614.3947933-8-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce two new controller states, FENCING and FENCED, and the state machine transitions needed to support them. Transports will move a LIVE controller into these states when an error is encountered; this patch only adds the states themselves. FENCING is entered from LIVE. While in FENCING the queues remain alive but new requests are not allowed to be sent, and the controller can be neither reset nor deleted (there is no transition from FENCING to RESETTING, DELETING or DELETING_NOIO). This is intentional because resetting or deleting the controller cancels inflight IOs, which should be held until either CCR succeeds or time-based recovery completes. FENCED is a short-lived state entered from FENCING before a reset. It is the only state from which RESETTING is reachable, so it exists to prevent a manual reset from taking effect while the controller is still in FENCING. Update nvme_available_path() to treat a controller in FENCING/FENCED as an available path, both states are non-terminal states, and finally add the state names to be exposed via the sysfs state attribute. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Randy Jennings Reviewed-by: Sagi Grimberg --- drivers/nvme/host/core.c | 27 +++++++++++++++++++++++++-- drivers/nvme/host/multipath.c | 2 ++ drivers/nvme/host/nvme.h | 4 ++++ drivers/nvme/host/sysfs.c | 2 ++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index ae7c04b77a3e..e4e18fb72159 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -596,10 +596,29 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, break; } break; + case NVME_CTRL_FENCING: + switch (old_state) { + case NVME_CTRL_LIVE: + changed =3D true; + fallthrough; + default: + break; + } + break; + case NVME_CTRL_FENCED: + switch (old_state) { + case NVME_CTRL_FENCING: + changed =3D true; + fallthrough; + default: + break; + } + break; case NVME_CTRL_RESETTING: switch (old_state) { case NVME_CTRL_NEW: case NVME_CTRL_LIVE: + case NVME_CTRL_FENCED: changed =3D true; atomic_long_inc(&ctrl->nr_reset); fallthrough; @@ -786,6 +805,8 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctr= l *ctrl, =20 if (state !=3D NVME_CTRL_DELETING_NOIO && state !=3D NVME_CTRL_DELETING && + state !=3D NVME_CTRL_FENCING && + state !=3D NVME_CTRL_FENCED && state !=3D NVME_CTRL_DEAD && !test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) && !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) @@ -828,10 +849,12 @@ bool __nvme_check_ready(struct nvme_ctrl *ctrl, struc= t request *rq, req->cmd->fabrics.fctype =3D=3D nvme_fabrics_type_auth_receive)) return true; break; - default: - break; + case NVME_CTRL_FENCING: + case NVME_CTRL_FENCED: case NVME_CTRL_DEAD: return false; + default: + break; } } =20 diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 75dbb58286a3..023d09f3c8ba 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -512,6 +512,8 @@ static bool nvme_available_path(struct nvme_ns_head *he= ad) case NVME_CTRL_LIVE: case NVME_CTRL_RESETTING: case NVME_CTRL_CONNECTING: + case NVME_CTRL_FENCING: + case NVME_CTRL_FENCED: return true; default: break; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index cb9d7f45188f..84ea3f2728bd 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -312,6 +312,8 @@ static inline u16 nvme_req_qid(struct request *req) enum nvme_ctrl_state { NVME_CTRL_NEW, NVME_CTRL_LIVE, + NVME_CTRL_FENCING, + NVME_CTRL_FENCED, NVME_CTRL_RESETTING, NVME_CTRL_CONNECTING, NVME_CTRL_DELETING, @@ -865,6 +867,8 @@ static inline bool nvme_state_terminal(struct nvme_ctrl= *ctrl) switch (nvme_ctrl_state(ctrl)) { case NVME_CTRL_NEW: case NVME_CTRL_LIVE: + case NVME_CTRL_FENCING: + case NVME_CTRL_FENCED: case NVME_CTRL_RESETTING: case NVME_CTRL_CONNECTING: return false; diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c index b60f5b66a1d1..3a12b07149d2 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -542,6 +542,8 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, static const char *const state_name[] =3D { [NVME_CTRL_NEW] =3D "new", [NVME_CTRL_LIVE] =3D "live", + [NVME_CTRL_FENCING] =3D "fencing", + [NVME_CTRL_FENCED] =3D "fenced", [NVME_CTRL_RESETTING] =3D "resetting", [NVME_CTRL_CONNECTING] =3D "connecting", [NVME_CTRL_DELETING] =3D "deleting", --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f43.google.com (mail-pj2-f43.google.com [74.125.227.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B25A51CF6B for ; Fri, 18 Sep 2026 18:17:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755431; cv=none; b=bctoj8pzoYpHA1NG4e+TrVycNUCVgxAI0+Yrx1BCulMAqb+kVYrxgVnKbr1/iaRmR+DxSPRaSdlDn8GXsomK42+yZt7D3Eo3I2PeW/TASgx661kpKnfOIdLzFCctOpNnAVXCF25Nsis4aURhx27C4TwWY3CW9chmfdDVOxu9iF8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755431; c=relaxed/simple; bh=S2jDwvz0aywYqBJc3t2WcBsmk3CulC2TUlkQHjrBu44=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kCl5/DA8ps7M0aRrxrtc/Ou8KXQ7FU/IOK0Hl/ZHygPHFQrBA12ZC45rf7RaC9QYlyTs4kNpxGgEVMPD0IftveTtS9Sg4eZsgZkyseDU3J8M1KOl9/6kutx59caadpmt5vuMxnde+6tEA3XA5ty9W4ILjS7f+SIpIXEl5umD/Ps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=K/w2vW4V; arc=none smtp.client-ip=74.125.227.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="K/w2vW4V" Received: by mail-pj2-f43.google.com with SMTP id 98e67ed59e1d1-396ccd5cef0so818519a91.0 for ; Fri, 18 Sep 2026 11:17:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755429; x=1790360229; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Pt50IjaPgH08hi1k4e76/CT4Nc9n3avKxSKgQhL0Gzo=; b=K/w2vW4VpEY4vBJlIIYtMitkeC38XJLCFgYdur2JIwIIdLkA9EU1PI2Dwn3cHOwyXs IAl2WMp4JDQMMIdonLR2fvikN5FHGL75lgymfelW2iLUTsVkPF1tuclvqofm76ZTSQzI nP/l6Hbh3GoG2kn8Xkl3XrEgzUWgSjVK1yzPB6wn6MNpytu9Cd+nHVEMPn5lLsmzGraG DQC6tAbCWMlvotl7D9MBiDXjbt4uWvJOsx4KPqBfW1P0XMeo3FMzdb93CISG0glocIAg mYlii2s28rPhNQrbdiGpmsbSYWoKVLZedvQ1+6XP/uZnCMNsuMndFmmMhiaIaVO1FGDH g4ZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755429; x=1790360229; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Pt50IjaPgH08hi1k4e76/CT4Nc9n3avKxSKgQhL0Gzo=; b=QSf2n0QzIGMe2FWiPFxt7TpoYqEkuz19hKcL5XZjPC6q+r1nBKmVEJZ3uXT49RFJsL gHV+QViMTvE5U7NsOq1YQAwRukB4/Bgh7sJ21o7RCSZgFvGn5dZSee4l82UGZPk732bg H26ZcJac23fsZBOO5D0w3qs2gElox16lNNRpCahjiCSGKxAUizXIZxQRYuy/8xmMfbNu avCVVIq+HKSMfFkZWh5TcolTLYx63UuvuQncJ9OyKY+tOcDPQR8tk5hVYXZe05j+eI3i nEqDYmWIybJ2lxbgbzBOnacjLxTk0IXoyh8lsiF2Z663llaE8flSdhCautX4mPk7/DrG es3g== X-Forwarded-Encrypted: i=1; AKwUvBzjl31aO90e77McaQ/dSbO9McrmrCliWL+uezQDa5C5rguKp8qXwQcfYxPLQFKsXx13oXYQqRAGaUfDt6E=@vger.kernel.org X-Gm-Message-State: AFuF++nSlWy+pSzQCRTjHFSvBeYa9u9V7o6B16vXX8iP7VnQ88qZqxVs 7dlWNNgPOkA1Xwkzpv+VhvMDpq65/6RLo9f337o3r/NZHWZR1E9Xmb5jdM9oKS0DVFU= X-Gm-Gg: AYBFou075gJtVWytFt4rX6V8NGKEmf1gWXxidNAb+hP9euvj+ERoNhpYltXM7jpCPtx 7H2idSUZPUgg/ftw5cnrwupKdn4nFNTe+BctEldHtKT0dfFgRmFbykPF15LdmdEgzfZdo4wIswy pHwAY9ne/VV5BddL+oOXDoxB3aY0g/OoPlcoEiZHO4TSeaCAe7AgFYAm7G9WWXAXyZhsVeabwCI eXqRq0yX8vTZeODFMq90a1mqYQbNGSTK02Zsoa1GeLfdC9eMpbWkTnAj+UBK/BbW6eCT1ghqAqP qT0BJw16c80Sa5sXas1+h3fKnFec02pH8a9OApgCkzDzEjYDGmzoqhmecxC1LLPzTe5+fdVIhOe vlO54Imel2C2S5wklbeKzziaWfPynH2MhebAR6F339+wdotDh/OobSm9a7FKgUG4R3PicQe13Yt Gsndd3HF6U6WctnIHJfZ381C/nWZ+eYG4a6FBUHcgIahYFUhWhWaZ1fODLCnXwQNslZi8XcFjaI kBrkMBMcj9LCBou7kvbor0BGnakQFNP X-Received: by 2002:a17:90a:d2c7:b0:39e:3558:f91c with SMTP id 98e67ed59e1d1-39e54eb1b00mr7254420a91.24.1789755428576; Fri, 18 Sep 2026 11:17:08 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:08 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 08/18] nvme: Implement cross-controller reset recovery Date: Fri, 18 Sep 2026 11:14:08 -0700 Message-ID: <20260918181614.3947933-9-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A host that has more than one path connecting to an nvme subsystem typically has an nvme controller associated with every path. This is mostly applicable to nvmeof. If one path goes down, inflight IOs on that path should not be retried immediately on another path because this could lead to data corruption as described in TP4129. TP8028 defines cross-controller reset mechanism that can be used by host to terminate IOs on the failed path using one of the remaining healthy paths. Only after IOs are terminated, or long enough time passes as defined by TP4129, inflight IOs should be retried on another path. Implement core cross-controller reset shared logic to be used by the transports. Signed-off-by: Mohamed Khalfella Reviewed-by: Sagi Grimberg Reviewed-by: Hannes Reinecke --- drivers/nvme/host/constants.c | 1 + drivers/nvme/host/core.c | 152 ++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 10 +++ 3 files changed, 163 insertions(+) diff --git a/drivers/nvme/host/constants.c b/drivers/nvme/host/constants.c index dc90df9e13a2..f679efd5110e 100644 --- a/drivers/nvme/host/constants.c +++ b/drivers/nvme/host/constants.c @@ -46,6 +46,7 @@ static const char * const nvme_admin_ops[] =3D { [nvme_admin_virtual_mgmt] =3D "Virtual Management", [nvme_admin_nvme_mi_send] =3D "NVMe Send MI", [nvme_admin_nvme_mi_recv] =3D "NVMe Receive MI", + [nvme_admin_cross_ctrl_reset] =3D "Cross Controller Reset", [nvme_admin_dbbuf] =3D "Doorbell Buffer Config", [nvme_admin_format_nvm] =3D "Format NVM", [nvme_admin_security_send] =3D "Security Send", diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index e4e18fb72159..c8e3129d84a8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -576,6 +576,157 @@ void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_cancel_admin_tagset); =20 +static struct nvme_ctrl *nvme_find_ctrl_ccr(struct nvme_ctrl *ictrl, + u32 min_cntlid) +{ + struct nvme_subsystem *subsys =3D ictrl->subsys; + struct nvme_ctrl *ctrl, *sctrl =3D NULL; + unsigned long flags; + int ccr_used; + + mutex_lock(&nvme_subsystems_lock); + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) { + if (ctrl->cntlid < min_cntlid) + continue; + + spin_lock_irqsave(&ctrl->lock, flags); + if (nvme_ctrl_state(ctrl) !=3D NVME_CTRL_LIVE) { + spin_unlock_irqrestore(&ctrl->lock, flags); + continue; + } + + ccr_used =3D atomic_inc_return(&ctrl->ccr_used); + if (ccr_used > ctrl->ccrl) { + atomic_dec(&ctrl->ccr_used); + spin_unlock_irqrestore(&ctrl->lock, flags); + continue; + } + + /* + * We got a good candidate source controller that is locked and + * LIVE. However, no guarantee ctrl will not be deleted after + * ctrl->lock is released. Get a ref of both ctrl and admin_q + * so they do not disappear until we are done with them. + */ + WARN_ON_ONCE(!blk_get_queue(ctrl->admin_q)); + nvme_get_ctrl(ctrl); + spin_unlock_irqrestore(&ctrl->lock, flags); + sctrl =3D ctrl; + break; + } + mutex_unlock(&nvme_subsystems_lock); + return sctrl; +} + +static void nvme_put_ctrl_ccr(struct nvme_ctrl *sctrl) +{ + atomic_dec(&sctrl->ccr_used); + blk_put_queue(sctrl->admin_q); + nvme_put_ctrl(sctrl); +} + +static int nvme_issue_wait_ccr(struct nvme_ctrl *sctrl, struct nvme_ctrl *= ictrl, + unsigned long deadline) +{ + struct nvme_ccr_entry ccr =3D { }; + union nvme_result res =3D { 0 }; + struct nvme_command c =3D { }; + unsigned long flags, now, tmo =3D 0; + bool completed =3D false; + int ret =3D 0; + u32 result; + + init_completion(&ccr.complete); + ccr.ictrl =3D ictrl; + + spin_lock_irqsave(&sctrl->lock, flags); + list_add_tail(&ccr.list, &sctrl->ccr_list); + spin_unlock_irqrestore(&sctrl->lock, flags); + + c.ccr.opcode =3D nvme_admin_cross_ctrl_reset; + c.ccr.ciu =3D ictrl->ciu; + c.ccr.icid =3D cpu_to_le16(ictrl->cntlid); + c.ccr.cirn =3D cpu_to_le64(ictrl->cirn); + ret =3D __nvme_submit_sync_cmd(sctrl->admin_q, &c, &res, + NULL, 0, NVME_QID_ANY, 0); + if (ret) { + ret =3D -EIO; + goto out; + } + + result =3D le32_to_cpu(res.u32); + if (result & 0x01) /* Immediate Reset Successful */ + goto out; + + now =3D jiffies; + if (time_before(now, deadline)) + tmo =3D min_t(unsigned long, + secs_to_jiffies(ictrl->kato), deadline - now); + + if (!wait_for_completion_timeout(&ccr.complete, tmo)) { + ret =3D -ETIMEDOUT; + goto out; + } + + completed =3D true; + +out: + spin_lock_irqsave(&sctrl->lock, flags); + list_del(&ccr.list); + spin_unlock_irqrestore(&sctrl->lock, flags); + if (completed) { + if (ccr.ccrs =3D=3D NVME_CCR_STATUS_SUCCESS) + return 0; + return -EREMOTEIO; + } + return ret; +} + +unsigned long nvme_fence_ctrl(struct nvme_ctrl *ictrl) +{ + unsigned long now, deadline, timeout; + struct nvme_ctrl *sctrl; + u32 min_cntlid =3D 0; + int ret; + + timeout =3D nvme_fence_timeout_ms(ictrl); + dev_info(ictrl->device, "attempting CCR, timeout %lums\n", timeout); + + now =3D jiffies; + deadline =3D jiffies + msecs_to_jiffies(timeout); + while (time_before(now, deadline)) { + sctrl =3D nvme_find_ctrl_ccr(ictrl, min_cntlid); + if (!sctrl) { + dev_dbg(ictrl->device, + "failed to find source controller\n"); + return deadline - now; + } + + ret =3D nvme_issue_wait_ccr(sctrl, ictrl, deadline); + if (!ret) { + dev_info(ictrl->device, "CCR succeeded using %s\n", + dev_name(sctrl->device)); + nvme_put_ctrl_ccr(sctrl); + return 0; + } + + /* + * CCR command or CCR operation failed on this path. + * Try another path as long as we have time. + */ + dev_err(ictrl->device, "CCR failed using %s, ret =3D %d\n", + dev_name(sctrl->device), ret); + min_cntlid =3D sctrl->cntlid + 1; + nvme_put_ctrl_ccr(sctrl); + now =3D jiffies; + } + + /* Fencing timed out call it done */ + dev_info(ictrl->device, "fencing timeout\n"); + return 0; +} +EXPORT_SYMBOL_GPL(nvme_fence_ctrl); + bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state) { @@ -5254,6 +5405,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct dev= ice *dev, =20 mutex_init(&ctrl->scan_lock); INIT_LIST_HEAD(&ctrl->namespaces); + INIT_LIST_HEAD(&ctrl->ccr_list); xa_init(&ctrl->cels); ctrl->dev =3D dev; ctrl->ops =3D ops; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 84ea3f2728bd..8da75a15ac04 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -341,6 +341,13 @@ enum nvme_ctrl_flags { NVME_CTRL_FROZEN =3D 6, }; =20 +struct nvme_ccr_entry { + struct list_head list; + struct completion complete; + struct nvme_ctrl *ictrl; + u8 ccrs; +}; + struct nvme_ctrl { bool comp_seen; bool identified; @@ -358,6 +365,7 @@ struct nvme_ctrl { struct blk_mq_tag_set *tagset; struct blk_mq_tag_set *admin_tagset; struct list_head namespaces; + struct list_head ccr_list; struct mutex namespaces_lock; struct srcu_struct srcu; struct device ctrl_device; @@ -402,6 +410,7 @@ struct nvme_ctrl { u16 sqsize; u32 max_namespaces; atomic_t abort_limit; + atomic_t ccr_used; u8 ccrl; u8 vwc; u32 vs; @@ -902,6 +911,7 @@ blk_status_t nvme_host_path_error(struct request *req); bool nvme_cancel_request(struct request *req, void *data); void nvme_cancel_tagset(struct nvme_ctrl *ctrl); void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl); +unsigned long nvme_fence_ctrl(struct nvme_ctrl *ctrl); bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state); int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown); --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f42.google.com (mail-pj2-f42.google.com [74.125.227.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9AAE51DDEA for ; Fri, 18 Sep 2026 18:17:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755432; cv=none; b=IXkF0EWw4Khc/F0CqBJEIlquU0xOe8yZhsB3hhKcX0cAzZFTdN9iVrkgfnRcAqSer5/2mtA/IONAF+JzsfOlg0TAcrKTRxSBBMsXaWC7Tb+H6c+YH0I9JUj3cC/g2D8MPD5/GYMyRxoUW7/n2YgirLmPy/iPX/ztcdWtAv88P/c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755432; c=relaxed/simple; bh=2stUjESmFaR5coRGRUUfSmg/ht71Le2TPTcOeb0WB+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NA2hHjSnchuzQdKwPymRF0TH2ieC5sS2G4MdcaCPjiv11PJfMkZEYC1Rj9k358AmCuowmzG5EwI/4KWIrKVA3aCuhDKypSXRFv1iiiuf/R0tG3iQIz4BOFvHxAqvDYWMMJVQRP5ufHlP8/ugcBdRRcdyHRpt4whEcHZDYWXjgEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=KkncAB1N; arc=none smtp.client-ip=74.125.227.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="KkncAB1N" Received: by mail-pj2-f42.google.com with SMTP id 98e67ed59e1d1-396ccafb74fso1193797a91.3 for ; Fri, 18 Sep 2026 11:17:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755430; x=1790360230; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Oy2h80BFMwGiM7nqEwALNuYmImDNZDmz38YPaRdaUi0=; b=KkncAB1N4mqmEw0gleA6WDsMv1rBWGhnzOAH6WfRbrCS8VXlapCD3YOw6DWWIz40we QMJCfuOBx2ngUd/6so4n7SDSwQvAKGraGL+OMyZ6foSh95Tnp3iySJeW3DStlKhzxAM8 qoTNl9wbOP6dcWeruHGULMPH2+FcMRC2os0CWuzQs8+dyIusVMxCo/NME3xhqW2jqhXk 0m4y8Gt/8jbEssTPOAQHhcacZ7pcC4UmLDCCdA5QQV8uwH8mRwXCQPiXvKA3jcsYR/o1 mSvRJjKgj61Bx7KorBBphZbZlyaKjiFsLSTk/Kc0bP9r2uNJqLOGYPm0lE762nnMgJMW RGAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755430; x=1790360230; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Oy2h80BFMwGiM7nqEwALNuYmImDNZDmz38YPaRdaUi0=; b=RoIea/mDu2YPfVMmX+T2iI5MiCCmSdo2NVC7jhaSWYqV9oE6QuT1fMEE+5SVjiNaS5 nzaOpRC09+Mchow3rNGM+iAlQGLqubbWKvdzgh0AJumNg6QR0hfzvfmroMBJpGE+7uF2 x8y60r8MlyiHAkRHoA7WldWFtw2IXTT6zXPVfbGoo4ERFzScsg5KyOnmM0JQI68suWw4 QNFsgVAX5fQuKP84ppaF0vW2Ds0wvRENUIsOOIucpZLL9vSV8BjGfPx0MATmwrJBh9G7 2nxux4eYs1HOVuwRKhYm1SQNTcJJWJtdBcQXF2Q1/G+UW54vyc6jD757nERH8s98qMbW qJyQ== X-Forwarded-Encrypted: i=1; AKwUvBzk6UQzWgGvfpL4gpgjThtx9XY/+ocJwwDwDvfKDD6iqDLwE5J6FTo57JOR/vdCi5Wxqhng0nKnHyZf7Jo=@vger.kernel.org X-Gm-Message-State: AFuF++lOzNDUy7xRTdwJIYDsvTIROiQApvejWDc1Y7koHKVt0nx2tDbR 5EcOkUlCbjcjG3cnm5+Rdlp73Q5T/VtRVeuOhO0yq5wpbgpYXjdkWFx8Z3WrulBPvXQ= X-Gm-Gg: AYBFou3ogDb5l9ZXGKhJpmKEz5guDEuB4sbQ7nU/MX3f9TZFxAcupVzYLwZaS+RpI+r au32sMXGSqTaYFOpBUhlsRHNQ45wJlxPKte0rxUD9iHe6NGJOdmp4aAnlSYXT6OhWxRZfZeqnHX pbNkOnh9+JWGcWgMaxa7KH6LmlskFP7Fpud4605cuLG7KwkMkQEN4ZWTlVqnO37PwuEb0BvInN7 w6Cafg/R9fC7vS9fCXiqp4uvTd+aY6yICk5UGvPc4Th89MpK810+a3b0un3KQqXIIPOz2OtSFrX mieHyXYLlPoi5LcTrdpgObdbmDe22xuQP8ocpUJSSHxKFTV8xeuh/5YACkpy6wXw/w3qxIm2o/d HL4tXrIe4gSMkhD1J1hqFvFQYWK6PozHdb3m4I7Y5ZccVTG1ME5yxkAiiOtqbt0UuXWCEv1K+lM weLNosIzdZlUxdAO82UxbN3fbyhs5Q6FW090B3D3bu6fKsXocBv0t9xzc3MnhqcwC5I2eDiOCOR /lHug0zAPtk57roHCKGtg== X-Received: by 2002:a17:90b:57e8:b0:39e:6c69:7774 with SMTP id 98e67ed59e1d1-39e6c697961mr1142954a91.29.1789755429684; Fri, 18 Sep 2026 11:17:09 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:09 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 09/18] nvme: Implement cross-controller reset completion Date: Fri, 18 Sep 2026 11:14:09 -0700 Message-ID: <20260918181614.3947933-10-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An nvme source controller that issues CCR command expects to receive an NVME_AER_NOTICE_CCR_COMPLETED when pending CCR succeeds or fails. Add ctrl->ccr_work to read NVME_LOG_CCR logpage and wakeup threads waiting on CCR completion. Signed-off-by: Mohamed Khalfella Reviewed-by: Sagi Grimberg --- drivers/nvme/host/core.c | 50 +++++++++++++++++++++++++++++++++++++++- drivers/nvme/host/nvme.h | 1 + 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c8e3129d84a8..5509b58b51db 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1959,7 +1959,8 @@ EXPORT_SYMBOL_GPL(nvme_set_queue_count); =20 #define NVME_AEN_SUPPORTED \ (NVME_AEN_CFG_NS_ATTR | NVME_AEN_CFG_FW_ACT | \ - NVME_AEN_CFG_ANA_CHANGE | NVME_AEN_CFG_DISC_CHANGE) + NVME_AEN_CFG_ANA_CHANGE | NVME_AEN_CFG_CCR_COMPLETE | \ + NVME_AEN_CFG_DISC_CHANGE) =20 static void nvme_enable_aen(struct nvme_ctrl *ctrl) { @@ -5023,6 +5024,48 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *= ctrl) kfree(log); } =20 +static void nvme_ccr_work(struct work_struct *work) +{ + struct nvme_ctrl *ctrl =3D container_of(work, struct nvme_ctrl, ccr_work); + struct nvme_ccr_entry *ccr; + struct nvme_ccr_log_entry *entry; + struct nvme_ccr_log *log; + int num_entries, ret, i; + unsigned long flags; + + log =3D kmalloc_obj(*log); + if (!log) + return; + + ret =3D nvme_get_log(ctrl, 0, NVME_LOG_CCR, 0x01, + 0x00, log, sizeof(*log), 0); + if (ret) + goto out; + + spin_lock_irqsave(&ctrl->lock, flags); + num_entries =3D min(le16_to_cpu(log->ne), NVMF_CCR_PER_PAGE); + for (i =3D 0; i < num_entries; i++) { + entry =3D &log->entries[i]; + if (entry->ccrs =3D=3D NVME_CCR_STATUS_IN_PROGRESS) + continue; + + list_for_each_entry(ccr, &ctrl->ccr_list, list) { + struct nvme_ctrl *ictrl =3D ccr->ictrl; + + if (ictrl->cntlid !=3D le16_to_cpu(entry->icid) || + ictrl->ciu !=3D entry->ciu) + continue; + + /* Complete matching entry */ + ccr->ccrs =3D entry->ccrs; + complete(&ccr->complete); + } + } + spin_unlock_irqrestore(&ctrl->lock, flags); +out: + kfree(log); +} + static void nvme_fw_act_work(struct work_struct *work) { struct nvme_ctrl *ctrl =3D container_of(work, @@ -5099,6 +5142,9 @@ static bool nvme_handle_aen_notice(struct nvme_ctrl *= ctrl, u32 result) case NVME_AER_NOTICE_DISC_CHANGED: ctrl->aen_result =3D result; break; + case NVME_AER_NOTICE_CCR_COMPLETED: + queue_work(nvme_wq, &ctrl->ccr_work); + break; default: dev_warn(ctrl->device, "async event result %08x\n", result); } @@ -5287,6 +5333,7 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl) nvme_stop_failfast_work(ctrl); flush_work(&ctrl->async_event_work); cancel_work_sync(&ctrl->fw_act_work); + cancel_work_sync(&ctrl->ccr_work); if (ctrl->ops->stop_ctrl) ctrl->ops->stop_ctrl(ctrl); } @@ -5412,6 +5459,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct dev= ice *dev, ctrl->quirks =3D quirks; ctrl->numa_node =3D NUMA_NO_NODE; INIT_WORK(&ctrl->scan_work, nvme_scan_work); + INIT_WORK(&ctrl->ccr_work, nvme_ccr_work); INIT_WORK(&ctrl->async_event_work, nvme_async_event_work); INIT_WORK(&ctrl->fw_act_work, nvme_fw_act_work); INIT_WORK(&ctrl->delete_work, nvme_delete_ctrl_work); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 8da75a15ac04..7096f1e4f84e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -431,6 +431,7 @@ struct nvme_ctrl { struct nvme_effects_log *effects; struct xarray cels; struct work_struct scan_work; + struct work_struct ccr_work; struct work_struct async_event_work; struct delayed_work ka_work; struct delayed_work failfast_work; --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B061151DDFC for ; Fri, 18 Sep 2026 18:17:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755433; cv=none; b=b5UyeMt0hImsrT2U2QCrBCOvCVt3TZcBQJxKbZIfBn7q6Cxb5+vsKv5fWTmqtarSkQm60l/kvA4kRKovZxWhU8ZaZf1YatbqN8/tNVMaO2djXWcMb9BMysl7Ize3PWpwneAduPLlbIcPGp2N5Xxm1l4qtvNs3FQzAJga+PskfWM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755433; c=relaxed/simple; bh=HFUI+vwDH7eJ577FDlmpoi8q2nXZKzYpl023jQ7aoks=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oYp/gu63dtgtZeD+J9oFWz9K2F2kMQHRPlQP+5xuEP+Y/PS17RuRA60A8vRMsw7JUWo1pQ7khzC9aH92thjOB6DkN9dwMNgxUoQVfYQtDs2C/xIXceSPL95taqUZy8kxOHmJPvNwIAwlZZxmYEjTRjgxlsBLyMKxd7jjoZ/hnIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=L9xI4twL; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="L9xI4twL" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-39dbdfaef3cso1026488a91.1 for ; Fri, 18 Sep 2026 11:17:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755431; x=1790360231; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UEWXTR1kghd8H69+9xfipKsLZLRrTMB1ZhrH2/JIMpI=; b=L9xI4twLXn+I43o5+yRbfj7eVqGxcvomHlTy/iDryKZwKdijSAG52Wq6nEUfhqr419 3A11UcFfsb5dnyhg/NdIjJi67tH9ghkrzCOMJzYLPc3EQeWemzJ2lb5bjkL6zGhx+6Xo goEIpjUNxuuKQMYympvT52rmOi7Q88ZflyrpWfn3/HYqo0Be88mJ6pHByOFk+E3f93S1 G1dcH3uj6zrW+uIHObvYW9LtrX07ASQr8CgWjfwAHr1veYCnjDZqJD5FJbhCn3tpMfOH JQAhxfivRT06GuXr8e8INtIByFVlUmPx4E1cIhlAHlXySzxigKk0OfbgmFOCibZHdnpa 7RXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755431; x=1790360231; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=UEWXTR1kghd8H69+9xfipKsLZLRrTMB1ZhrH2/JIMpI=; b=w1YEn3z4+znpoyKiG3gIpCiALFtUIeDNocO0tk7TetfQeVE13dklOll3fysfjsH8Sv 3NEgsqG/a68mnpSkogVDW+eD1OJcRnNTyKgurmS/tmW1ewef+XX7eoundc5/5QXZlyVR aL4H1OMG958o6Sava6qIf3FtLYfs78cubvN0mmczDDxSfdYQ0RcCtszexo7NLLtJeYUo u3dgvIpkzcBG0D7PK9SiuTVKrlJUJzIWbm+V1gbdbQhIdNq2Ga98LlpmL/vVST6Rq/D2 vDfofMHjkEcsIAHtNGcAN+VQo10QYaZ2mbKmkaRqfZdYEGlD4tJLoVpru67BAEK+j21k epjA== X-Forwarded-Encrypted: i=1; AKwUvBypql2kZCGvQMGFOMTy9vz2zbITIuV3Q2p6WxpvWUP27eF7ENxtyd51OInJKEWhUFISjbBJfyRR1102BHA=@vger.kernel.org X-Gm-Message-State: AFuF++kU7OD3ko8CEqSSTGnIuMRCTv7CvwsWovJ2myX94XKdgMuBNORc BNIt4jtJDEvh1a7kjiI8e3q0XZ29O1C7Hia2x3wTtyUrxVq8ipYfNRHLC7tInZGrrts= X-Gm-Gg: AYBFou23OHq+mW/B0CQ+endZZxzOt9fWzzQ4fbtPCUKoZ/41/K060QE48XnD4TcIh8r sZXy6cdrFHk1xSDmLlnlSJaaaU2e1+28sEYEHpqYuht3eefjWNHg1i2cgvJ37q/wyketY55E3jk lyw4U8rgriMxQlabLYGX2UDKZLeoN7ucDeB9WPLltbT910Rwkd3gD+jyAATGE3dp+b+TFA52Gye PB5DK6tglHtupNcM6pthiv4p/t6YFZmxHacBDlwP3ypbSUFQYCalrSIbSXDZCAj0KXk3fu//p9w 3zEgpsfLHMmqHBwwjAt7FmpXguqLhqz6+Hoe+jv/cOkjrYhJCHO7hKUB5Y9LHxG6MofJ2hqrCy8 CMNPSIzyXu15RGbe5cBwBd7OBEqwg0ZTDY9NDvexUQWALBkgWBZ+/qqRY3QN3OXe0HuCxegtfV7 ysxQw8blNMgMoUx0uoZ9+SL8aTziAU14quQ/8GO/RUBWuExULFZucIIGe6iUoH6kWoYklrnN4i0 GdVL9kq2NSWWUEi1c+iXg== X-Received: by 2002:a17:90b:4cc3:b0:39e:6a7f:eeee with SMTP id 98e67ed59e1d1-39e6a7ff08amr1968530a91.19.1789755430699; Fri, 18 Sep 2026 11:17:10 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:10 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 10/18] nvme-tcp: Use CCR to recover controller that hits an error Date: Fri, 18 Sep 2026 11:14:10 -0700 Message-ID: <20260918181614.3947933-11-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An alive nvme controller that hits an error now will move to FENCING state instead of RESETTING state. ctrl->fencing_work attempts CCR to terminate inflight IOs. Regardless of the success or failure of CCR operation the controller is transitioned to RESETTING state to continue error recovery process. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- drivers/nvme/host/tcp.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 921934028e0b..febbe8954473 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -167,6 +167,7 @@ struct nvme_tcp_ctrl { struct sockaddr_storage src_addr; struct nvme_ctrl ctrl; =20 + struct work_struct fencing_work; struct work_struct err_work; struct delayed_work connect_work; struct nvme_tcp_request async_req; @@ -616,6 +617,12 @@ static void nvme_tcp_init_recv_ctx(struct nvme_tcp_que= ue *queue) =20 static void nvme_tcp_error_recovery(struct nvme_ctrl *ctrl) { + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCING)) { + dev_warn(ctrl->device, "starting controller fencing\n"); + queue_work(nvme_wq, &to_tcp_ctrl(ctrl)->fencing_work); + return; + } + if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) return; =20 @@ -2558,6 +2565,22 @@ static void nvme_tcp_reconnect_ctrl_work(struct work= _struct *work) nvme_tcp_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_tcp_fencing_work(struct work_struct *work) +{ + struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(work, + struct nvme_tcp_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &tcp_ctrl->ctrl; + unsigned long rem; + + rem =3D nvme_fence_ctrl(ctrl); + if (rem) + dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &tcp_ctrl->err_work); +} + static void nvme_tcp_error_recovery_work(struct work_struct *work) { struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(work, @@ -2633,6 +2656,7 @@ static void nvme_reset_ctrl_work(struct work_struct *= work) =20 static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl) { + flush_work(&to_tcp_ctrl(ctrl)->fencing_work); flush_work(&to_tcp_ctrl(ctrl)->err_work); cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work); } @@ -2731,13 +2755,15 @@ static enum blk_eh_timer_return nvme_tcp_timeout(st= ruct request *rq) struct nvme_tcp_cmd_pdu *pdu =3D nvme_tcp_req_cmd_pdu(req); struct nvme_command *cmd =3D &pdu->cmd; int qid =3D nvme_tcp_queue_id(req->queue); + enum nvme_ctrl_state state; =20 dev_warn(ctrl->device, "I/O tag %d (%04x) type %d opcode %#x (%s) QID %d timeout\n", rq->tag, nvme_cid(rq), pdu->hdr.type, cmd->common.opcode, nvme_fabrics_opcode_str(qid, cmd), qid); =20 - if (nvme_ctrl_state(ctrl) !=3D NVME_CTRL_LIVE) { + state =3D nvme_ctrl_state(ctrl); + if (state !=3D NVME_CTRL_LIVE && state !=3D NVME_CTRL_FENCING) { /* * If we are resetting, connecting or deleting we should * complete immediately because we may block controller @@ -2996,6 +3022,7 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(stru= ct device *dev, =20 INIT_DELAYED_WORK(&ctrl->connect_work, nvme_tcp_reconnect_ctrl_work); + INIT_WORK(&ctrl->fencing_work, nvme_tcp_fencing_work); INIT_WORK(&ctrl->err_work, nvme_tcp_error_recovery_work); INIT_WORK(&ctrl->ctrl.reset_work, nvme_reset_ctrl_work); =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f43.google.com (mail-pj2-f43.google.com [74.125.227.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D609E51CF7D for ; Fri, 18 Sep 2026 18:17:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755434; cv=none; b=fHQVrtYwTWFd4A3JjAl3JxE5+M19Zlg23GCmBLR2+nJrYRNomsPn2v5p4gVre1QxefSwiY0BA4FIASWi0Sg9l+l8zIQCz0dRbU1KJsVeP6nf8B3QFmoeMZD23pfn4nMP5LmO957yRvx5xP0k7tHK4BveqEQbFOYCU0P4KXBJ51k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755434; c=relaxed/simple; bh=7rnrjjZhabphz48ZRLXoqGnFCoHX2nNlJpxQZq8SO3U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VIFTIUSa039M0NN9QwAqY6fOZ6wygHDELce4jsWvkXrh2WTKeDMDw38RMBrHZzptU2+ukpPDEXqn7TXW+ijY5tOKwUlDjN7uzcPVekfKhjFlweveZb1P60JsC35vhFU3zJaNkYlcp0h9Dbslc2onbS106T84iiEY7c7xlFCBhzU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=IMwkyL7F; arc=none smtp.client-ip=74.125.227.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="IMwkyL7F" Received: by mail-pj2-f43.google.com with SMTP id d9443c01a7336-2d90ba1d807so13413435ad.3 for ; Fri, 18 Sep 2026 11:17:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755432; x=1790360232; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=i0UuleHNrFJL7Ac1BNRBp4u482qJaS6x4l4kwP4ak8U=; b=IMwkyL7FTeyBhyjiZrp73OnCqdWeyKOJ4l7SgHhs4b9H7m9f7x43VfPN/XWU0c1XdF bOL8JD//rR8B5CLjVfT3cCEvcRLRwEeq1dXcKBptvvFjnQVpGhL5BmMDR9xryFIpom7U Y03OJBP2KPJ/j5d1zGI4UWD7Gt522uZv/VljsVsI6+iRU+oSyOJCAdSxTSe34OMEB0UN Ri2Zxkej0sXoI8ykwRxEqiA6mlS2fsrxszxRcCdkUjMfr6ehEzZyMEeisE9ZwypMAWAG ZRDXFC0tuTeH0Xce/Kyf5oeAY/OT+0d64K0rPeWqQBy3CwmI/0C/wZWpg4ycxEmywYn5 pcoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755432; x=1790360232; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=i0UuleHNrFJL7Ac1BNRBp4u482qJaS6x4l4kwP4ak8U=; b=Oj7+IoZoh89lJgSl9ixJZ/qMbQ7QmPwdtGLCERbCuxn5pyqM5Qi0AilxdML/dSuziP jMITHY5wSxv8geAO53LjbTEtgPBiPDZQTTbv+Tm0C6qAfK+Zp2kbN3mhDB36qx8RL6Y1 oM5dU4O1fxkEPr8gN5JWtO0JiwUOXbvv4lk6EPsxMsiCHSsMK35i9bIJA8HQqn8Lc1dt b2IE1tWu9KDwhc1+lNnlBWGpjBg5DNkUX17iALKLm6ZNqnvUng18VnHBF2C+oKCC3tkw 439/OGti4iFKku8FCUcNiT2RCl/1HhmKExeT0PAlANHOEICc+vk7Q/RaTNnsfgEJhazQ qFFg== X-Forwarded-Encrypted: i=1; AKwUvBw2+inpXgaMpstlZlq4aYahZDS+OfnUWhzzbEjef0DkikyK5+/mawL/q4DfgoJuX/PGcSrLAZvTDdw/czY=@vger.kernel.org X-Gm-Message-State: AFuF++kAANf7X8a9xREbFzod8chJBdtvQjAFNcMhzD0KqzggvWKsKC3/ /1GK4eonzMfmJ5MWQQn3LqQo6ddySmcAqgvkZ6grP/xUYNBc6Sfqugn6YG8HzfiSxSo= X-Gm-Gg: AYBFou2QC1w07Wl45P/F8+PiGAUbTiyWeGFQGKAVoFWPSXJRN+A0i3TUnNX3EROPLUl 9aNmHQNp/F9R0tmEpa2f5su1Ze84H2h4gu65BsgxlQmK5RYcsbzmk/CZhMCY0uFGaaHiAq/Qyqq 58Ow883+31U6fMLjfc1cznNTlVw4LcNLqTPgbG0Z/65IevfcM/vdQGAw10cfjuvOmIw6P7n90LJ 3wQNZHhfCDs0LN5Bp0LUTTsHACT8RFuZjxEZgbcy/HmrKCVo53TdWARI9q3fGWsUMHYjyygj/zQ 2yJTlFnh33/1IYxbjko6U04nUlVma2/3i+adFb0UAMOrtrHr1cy3szpJP1h67U5KlB99KAkMpdr 9c1N40OuMtGgK1GkXKcclS810wslXaxC6FnQXKIagLoCV0JHoJo1dsTe/e2i+NRCvzH7yLxQObq QoMiKI9bU0iJDQC8kpI4cIyY478KfDpI3sBMiNdKkSvXn9sBAzaOig5C1TFlLA6G91SxX8fowk/ CbDJRjxRtFBmRDbN2eM5A== X-Received: by 2002:a17:90b:3b8d:b0:39e:4c7e:f03d with SMTP id 98e67ed59e1d1-39e54f0e5e7mr6453388a91.26.1789755431659; Fri, 18 Sep 2026 11:17:11 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:11 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 11/18] nvme-rdma: Use CCR to recover controller that hits an error Date: Fri, 18 Sep 2026 11:14:11 -0700 Message-ID: <20260918181614.3947933-12-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An alive nvme controller that hits an error now will move to FENCING state instead of RESETTING state. ctrl->fencing_work attempts CCR to terminate inflight IOs. Regardless of the success or failure of CCR operation the controller is transitioned to RESETTING state to continue error recovery process. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/rdma.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 29ecbe71bb2e..9c50421d79c4 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -119,6 +119,7 @@ struct nvme_rdma_ctrl { =20 /* other member variables */ struct blk_mq_tag_set tag_set; + struct work_struct fencing_work; struct work_struct err_work; =20 struct nvme_rdma_qe async_event_sqe; @@ -992,6 +993,7 @@ static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl) { struct nvme_rdma_ctrl *ctrl =3D to_rdma_ctrl(nctrl); =20 + flush_work(&ctrl->fencing_work); flush_work(&ctrl->err_work); cancel_delayed_work_sync(&ctrl->reconnect_work); } @@ -1153,6 +1155,22 @@ static void nvme_rdma_reconnect_ctrl_work(struct wor= k_struct *work) nvme_rdma_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_rdma_fencing_work(struct work_struct *work) +{ + struct nvme_rdma_ctrl *rdma_ctrl =3D container_of(work, + struct nvme_rdma_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &rdma_ctrl->ctrl; + unsigned long rem; + + rem =3D nvme_fence_ctrl(ctrl); + if (rem) + dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &rdma_ctrl->err_work); +} + static void nvme_rdma_error_recovery_work(struct work_struct *work) { struct nvme_rdma_ctrl *ctrl =3D container_of(work, @@ -1180,6 +1198,12 @@ static void nvme_rdma_error_recovery_work(struct wor= k_struct *work) =20 static void nvme_rdma_error_recovery(struct nvme_rdma_ctrl *ctrl) { + if (nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_FENCING)) { + dev_warn(ctrl->ctrl.device, "starting controller fencing\n"); + queue_work(nvme_wq, &ctrl->fencing_work); + return; + } + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) return; =20 @@ -1990,13 +2014,15 @@ static enum blk_eh_timer_return nvme_rdma_timeout(s= truct request *rq) struct nvme_rdma_ctrl *ctrl =3D queue->ctrl; struct nvme_command *cmd =3D req->req.cmd; int qid =3D nvme_rdma_queue_idx(queue); + enum nvme_ctrl_state state; =20 dev_warn(ctrl->ctrl.device, "I/O tag %d (%04x) opcode %#x (%s) QID %d timeout\n", rq->tag, nvme_cid(rq), cmd->common.opcode, nvme_fabrics_opcode_str(qid, cmd), qid); =20 - if (nvme_ctrl_state(&ctrl->ctrl) !=3D NVME_CTRL_LIVE) { + state =3D nvme_ctrl_state(&ctrl->ctrl); + if (state !=3D NVME_CTRL_LIVE && state !=3D NVME_CTRL_FENCING) { /* * If we are resetting, connecting or deleting we should * complete immediately because we may block controller @@ -2327,6 +2353,7 @@ static struct nvme_rdma_ctrl *nvme_rdma_alloc_ctrl(st= ruct device *dev, =20 INIT_DELAYED_WORK(&ctrl->reconnect_work, nvme_rdma_reconnect_ctrl_work); + INIT_WORK(&ctrl->fencing_work, nvme_rdma_fencing_work); INIT_WORK(&ctrl->err_work, nvme_rdma_error_recovery_work); INIT_WORK(&ctrl->ctrl.reset_work, nvme_rdma_reset_ctrl_work); =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C460151CF5A for ; Fri, 18 Sep 2026 18:17:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755435; cv=none; b=ihVeUULNISvN6yZVKD/hnb9PQzOHJ+XlOMJLOcMlf1PVaqBZcZ2Zyqf3wTa80oXaWEw22E0tqtjGg3i7bWd7qQZWVqoxFtk+bfCOXNFcuvkz2UVZWbHyaylkmBGuCtJdukYwugzopX2cwQhGFMlL0LuI9lpG6cMfbPIVjcNJjBQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755435; c=relaxed/simple; bh=wqPjBR1evZQ/NfBLUjWvC2B83LrJtIxtRxteAVRWHsM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DaedUgh5adknW3cnsVmwYoXJ6/Mt1TBJ9STp+B0nQFC0sH5QNuyWDF0e8Pz/d0iHm3C/NjrXzWY0g5rOfkpNydbNt2ZmMtyguZjQRqeswV38QvmOLrVfRRpT3d518WxcPZ7PZuEVVq46J7a/WI9BAqHTAqTx4R4w318Esi0GF3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=H8AV/Ql3; arc=none smtp.client-ip=74.125.228.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="H8AV/Ql3" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea4ae2dso653737a12.3 for ; Fri, 18 Sep 2026 11:17:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755433; x=1790360233; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=pmH177YS3gZ19sjEKDEKKTFEFMiPIMvZkv9++g5knBc=; b=H8AV/Ql3jyu5Hz3zBmYL1y8/BWk+aHDHBHdmFX+6KAVfeM3Wsroigk9YTSffSxGvPu prWFRv58Tsd3NiRRxOKSE2YNmwB+eQ0MD1Kcn9JImq01wtBRRSKEyWucBOFr1UX6ATke 5OcHYQvuXLlJYLXjL7JO9US8qgd1BXMm/WT1jis02r+bShrgeXKeXjR3OK3TRkvbzoi9 4E9JRYXxkXopK80tOlvl9Lcue7KhWdFGRMWnuAf6djgd6z7b2rxuDySFOm1O0YbRRAAY IWI4fECJI8ICwUjBp4dpTcxxakzHcYQrEPwECqAV6e7tnaAp6/rhAu5nPyWtYDZ6ijxY 1n3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755433; x=1790360233; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=pmH177YS3gZ19sjEKDEKKTFEFMiPIMvZkv9++g5knBc=; b=uZx1mjeozMjv5ps9ptxmeWvYFtY6H03VnJHNIwGNV1aipFrvjqvmS1whc7cqTWjs/n 5z3R51bkBkvl/Igoc/BKPxeOQIHOSgPLjdKMWUGOM+LoolHhY/fX6ROcGuXRmW9lY/Ce ep0pX8nv0hEBIiBGX78eZqJazoONDy5kxhIBNonqeU+qnerGMYRToQzHpD6zY2x/D1I/ 4pIVz/N0KT0cGdxuQEKgF4yrbOjBtpcbKG4q2SNKeCujHKHKmJQEqm3OpOz3VogMcVNf PfbGjnMoT2fHXJYg2GCn6BGxVI6wHFXe7nddLY8gZUHC/TqCopYgX9t2FI713AkZJHxy x93w== X-Forwarded-Encrypted: i=1; AKwUvByoTF4lQsWKnedgcwlJ/gz8q3Zjgnk1+jvedM6xWhc7herXsr3Tgh6qY2fxk02Z4IRNyahtIBr+sIgy2Xs=@vger.kernel.org X-Gm-Message-State: AFuF++l52Bt3S/+YPnjAATnipZTMp8zJlJmk0YnwkhTyABK6na1aeMy2 rv2cepLCAHg4Mm7QsorZmJ9sas/yfUTnin5LzbrnXYusBRfY7oKpws82/5aUNwSwiyc= X-Gm-Gg: AYBFou2VgSLfIw9451BKnWSoTpbCdynn0gAkT9uqbcQS4oY/mNQ/Szs8VkZErLN9xi2 OC0IT4dZUCGAkr3O1J5e/7NlU7uMm0jpWmSc95B+LR9hrt1j6zqlca7YNXFithcyI4MMrsdOun2 n4wkkQ0wyoEqwRValbtP5dZHijV9FZTTfcJhXHJXzzdF1mOLhz22fOmuHlY3+cXYfmJvn7no3VS 7sr4xYO1a/VCMDA3l8clUrCG7qW5zID4QPj0duZqvEu4rIDvsh1B1GEyg/w/j29Zm5M7XfdAesP KpDI/bphe2rx6k5C1bpeLKNDpRnXOICOgdk++82YudiFTNwUG5403q2vZoUn/0b3MUESMd7MN+a /BgepYlgONxGotcPYAB/9TlMpOXxq/wJwngyfSQ05Ugpm5b6uMMDavYdHvuJhBHbtmApJGrfjH2 uts+Y2tAMfBjnKeuyjMXFMcRoK9KYthWYBuZBET9BCzB69LLI0BH6hGFRDokkONjX1Sw7frnEVk RWwrdZsIdRlhDwhmMVmyR9z3e0toEIL X-Received: by 2002:a17:90b:4c:b0:39e:6c68:c780 with SMTP id 98e67ed59e1d1-39e6c68ca53mr592406a91.54.1789755432638; Fri, 18 Sep 2026 11:17:12 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:12 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 12/18] nvme-fc: start error recovery instead of aborting timed out IOs Date: Fri, 18 Sep 2026 11:14:12 -0700 Message-ID: <20260918181614.3947933-13-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Aborts issued from the timeout handler run outside the FCCTRL_TERMIO window, so they are not counted in ctrl->iocnt and nvme_fc_delete_association() does not wait for them. The association can be torn down while the LLDD is still working on the abort. Instead of aborting the timed out command, reset the controller like the other fabrics transports do. All aborts now happen in nvme_fc_delete_association(), where they are counted and waited for. The new nvme_fc_start_ioerr_recovery() queues ioerr_work directly in CONNECTING (abort the IOs so the connect attempt fails) and in DELETING/DELETING_NOIO (tear down the association so the IOs the delete path is draining get completed - the timeout handler no longer aborts them, and a dead target would otherwise hang controller deletion). In all other states it moves the controller to RESETTING first. Connectivity loss, disconnect LS and IO errors now go through the same entry point. With nvme_fc_timeout() no longer aborts timedout IOs the reset code in nvme_fc_reset_ctrl_work() needs to be updated to teardown the association before stopping the controller. This is important because nvme_stop_ctrl() waiting for ana_work or fw_act_work to be flushed can get stuck forever. Link: https://lore.kernel.org/all/20250529214928.2112990-1-mkhalfella@pures= torage.com/ Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- drivers/nvme/host/fc.c | 54 ++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 48454cb7a0fc..6181cb7ea8ce 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -227,6 +227,8 @@ static DEFINE_IDA(nvme_fc_ctrl_cnt); static struct device *fc_udev_device; =20 static void nvme_fc_complete_rq(struct request *rq); +static void nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ctrl, + char *errmsg); =20 /* *********************** FC-NVME Port Management ***********************= * */ =20 @@ -788,7 +790,7 @@ nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctr= l) "Reconnect", ctrl->cnum); =20 set_bit(ASSOC_FAILED, &ctrl->flags); - nvme_reset_ctrl(&ctrl->ctrl); + nvme_fc_start_ioerr_recovery(ctrl, "Connectivity Loss"); } =20 /** @@ -1569,7 +1571,8 @@ nvme_fc_ls_disconnect_assoc(struct nvmefc_ls_rcv_op *= lsop) */ =20 /* fail the association */ - nvme_fc_error_recovery(ctrl, "Disconnect Association LS received"); + nvme_fc_start_ioerr_recovery(ctrl, + "Disconnect Association LS received"); =20 /* release the reference taken by nvme_fc_match_disconn_ls() */ nvme_fc_ctrl_put(ctrl); @@ -1892,6 +1895,30 @@ char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req) } EXPORT_SYMBOL_GPL(nvme_fc_io_getuuid); =20 +static void +nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) +{ + enum nvme_ctrl_state state =3D nvme_ctrl_state(&ctrl->ctrl); + + /* + * In CONNECTING, ioerr_work aborts the outstanding ios so the + * connect attempt sees the error. In DELETING/DELETING_NOIO it + * tears down the association so IOs the core delete path is + * draining get completed. + */ + if (state =3D=3D NVME_CTRL_CONNECTING || state =3D=3D NVME_CTRL_DELETING = || + state =3D=3D NVME_CTRL_DELETING_NOIO) { + queue_work(nvme_reset_wq, &ctrl->ioerr_work); + return; + } + + if (nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) { + dev_warn(ctrl->ctrl.device, "NVME-FC{%d}: starting error recovery %s\n", + ctrl->cnum, errmsg); + queue_work(nvme_reset_wq, &ctrl->ioerr_work); + } +} + static void nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) { @@ -2049,9 +2076,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) nvme_fc_complete_rq(rq); =20 check_error: - if (terminate_assoc && - nvme_ctrl_state(&ctrl->ctrl) !=3D NVME_CTRL_RESETTING) - queue_work(nvme_reset_wq, &ctrl->ioerr_work); + if (terminate_assoc) + nvme_fc_start_ioerr_recovery(ctrl, "io error"); } =20 static int @@ -2548,24 +2574,14 @@ static enum blk_eh_timer_return nvme_fc_timeout(str= uct request *rq) struct nvme_fc_cmd_iu *cmdiu =3D &op->cmd_iu; struct nvme_command *sqe =3D &cmdiu->sqe; =20 - /* - * Attempt to abort the offending command. Command completion - * will detect the aborted io and will fail the connection. - */ dev_info(ctrl->ctrl.device, "NVME-FC{%d.%d}: io timeout: opcode %d fctype %d (%s) w10/11: " "x%08x/x%08x\n", ctrl->cnum, qnum, sqe->common.opcode, sqe->fabrics.fctype, nvme_fabrics_opcode_str(qnum, sqe), sqe->common.cdw10, sqe->common.cdw11); - if (__nvme_fc_abort_op(ctrl, op)) - nvme_fc_error_recovery(ctrl, "io timeout abort failed"); =20 - /* - * the io abort has been initiated. Have the reset timer - * restarted and the abort completion will complete the io - * shortly. Avoids a synchronous wait while the abort finishes. - */ + nvme_fc_start_ioerr_recovery(ctrl, "io timeout"); return BLK_EH_RESET_TIMER; } =20 @@ -3348,10 +3364,12 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) struct nvme_fc_ctrl *ctrl =3D container_of(work, struct nvme_fc_ctrl, ctrl.reset_work); =20 - nvme_stop_ctrl(&ctrl->ctrl); + nvme_stop_keep_alive(&ctrl->ctrl); + flush_work(&ctrl->ctrl.async_event_work); =20 - /* will block will waiting for io to terminate */ + /* will block while waiting for io to terminate */ nvme_fc_delete_association(ctrl); + nvme_stop_ctrl(&ctrl->ctrl); =20 if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) dev_err(ctrl->ctrl.device, --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pz2-f42.google.com (mail-pz2-f42.google.com [74.125.228.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6A6E51D501 for ; Fri, 18 Sep 2026 18:17:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755436; cv=none; b=l5S+EDQYFY6n5iWvvLLi6PawIsJxAUX7VIYUie9/FpsRVQmz4Fbj5/55HXEOZbZBRvgAm2pPXBIeX43HgSj2pasvonruDHx13T96vbw8vYh/84ho8tuJKQPEaxfPnRqmMtvW6xjZl+dI3cJZ0bZAqGVhGZfTWlVDksw1MVIX0G4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755436; c=relaxed/simple; bh=SI/It3Y7Nmi0Qd33uYrJsmK8dlYFazFQgXLrKfZIwhw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oCgGZKsNc51+GAaM9+9oYahBqSyTL1NzY9Txr8/RIEzNyq98/KxlyfcVVHfl8lewEGM5Z13VVPmsUsV7PAdA8va95/o3JkTe/NjhqV64E0iJUhWwTQMWpWBLR/LSrtiSA3DU1WKc10s/QreMkHxLJ7hkYINva5hvbuK7/VhYs7U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=GGf3VJUj; arc=none smtp.client-ip=74.125.228.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="GGf3VJUj" Received: by mail-pz2-f42.google.com with SMTP id 41be03b00d2f7-cc1cebad4aeso855206a12.2 for ; Fri, 18 Sep 2026 11:17:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755434; x=1790360234; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=cVhzIJ0voivWryYWZvH7CE/nJwrk1ooSyz4ZIVHdKLo=; b=GGf3VJUjxBSUpxPEgag3v7lFnw8BDpLcdSZ2PM0TB8UZOVx3F/N/xs225tga5UCwp9 47VBzOcHSHzOjr/RLXtzxHgipUnJ9IqjE4buAtTlqjhaCbf/HIO74TMrOgVD3DlWBunw zg4AgP35p9+8YUD3hoNPUA8sN/mdNIpbT1xn1dvdy8LPDeYIGEmZpLruRxSZ7b7sYdW3 GnUeN1JEs8D2PIw6a2Df3OjFcZUZDdWJd0pWk5EDSlSdCEug1L7GCx85m9tGjU/809xm raNyHK9VLMcM3CDjgVlmotV46syXLIAfNqpvw0dDdXy6HXUcNEvLFdli/f+cmnKDzZjm pw2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755434; x=1790360234; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=cVhzIJ0voivWryYWZvH7CE/nJwrk1ooSyz4ZIVHdKLo=; b=xBzl1mHcHQKlf7+2xIJ1ZYUoPXyxF3/E8UnwaCCI1NyJnWxl+vp3htxnz+l3CLMUyv ITuvaCF4cIqHPyOA5cU8lEw9S+X3HzZR4Z9VgiWpblgm2MfCTAovFnfM0cLh85L/P3OZ xjCMNU0nz2myG+8eTr8Ag7DvIvZAE6xbVM9k7M2yE15IZbXFdFf5YkN+PsdB1WaT0Mk3 kGvGl2sNjUL+K5estjp2qxxbZzhqLnWVi9clX1iUyCqgBOj8SYHn8jbS7CvA/ALD3qZX 1PZhCw9GIFL2zFtoKl9Jwe9TFGQaz8nmL4X5ZvP/GXvfB0I06na5xtASTzuxHjhTT4qt Lx7w== X-Forwarded-Encrypted: i=1; AKwUvBwrql9zYNirHwfwlAdZGz/Qhdj5rM5Xdf5yh+UVOnFQX8cMWgISY/EaytGpAK949wTC2zf0t3fOimdY1jo=@vger.kernel.org X-Gm-Message-State: AFuF++mDn4JbN24l7eT7to4e912eJRZX12QLIHHWIqmkI1G3r2tNwOXY 83ZE2zvXkJDfQrQCJw7AkmbP8h7a/As0uRMcaaPmuynaZTkr5u+xgbXD5FBCGI/42tU= X-Gm-Gg: AYBFou3NTjA8GD+FyE78lyt1ovCKZlnQXlLEYu3rPFIGhXO9jUH5G2MHEFUjk3Eifx5 +TZW2CIJaxiDRkkEFXgVAI0G1pAw0kUf07UN0MoBwwZURHvTiMES95RImOrXX9IKspEaanmiZKn tK4cFjmXmPv1QiMyufa+lqMGBvn/ZWbtmnnOGaAFkRvY9X4YV/bWxYdWVVgbNOhr208L+JfZ41V rEppwK2xLAPTpKDPX3dTIeikcc+J00RCOcD/KqwzV/mEQZXWIwDvtSGKFe2aDSxSAS7bT4bbrbH Pl0ra4NIgQ1KuNYnKsyjYjycRd0cgtM3LHdnumFop/7KS+t8I629IMBT5qW02ieYvWOoIfj3ZCm a/GpggrTaXEruFuCu2x96mL37MpSk4VMNUz+YpRbNtipbOHPG/swHV3xGS5lsLURAxRWyLHhEpb FlOoovp+FanXuZ5Kgop+c9Q9OBQzuuJUmQnCt6KD50dx31jvKgFA4rfF/y1uOZNVVef0UsGreBW PwKYaPEENzs6tlFG42D+w== X-Received: by 2002:a17:90b:2784:b0:39e:6a7f:eeec with SMTP id 98e67ed59e1d1-39e6a7ff073mr2104953a91.17.1789755433632; Fri, 18 Sep 2026 11:17:13 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:13 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 13/18] nvme-fc: perform error recovery directly from ioerr_work Date: Fri, 18 Sep 2026 11:14:13 -0700 Message-ID: <20260918181614.3947933-14-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that nvme_fc_start_ioerr_recovery() moves the controller to RESETTING before queueing ioerr_work, the nvme_reset_ctrl() call in nvme_fc_error_recovery() fails with -EBUSY and no recovery runs. Do the recovery in the work itself instead: stop the controller, tear down the association, move to CONNECTING and schedule a reconnect, same as nvme_fc_reset_ctrl_work(). If the CONNECTING transition fails the controller is being deleted and the delete path finishes the job. This is how rdma and tcp structure their error recovery too. The work now re-checks the controller state when it runs. A work queued while CONNECTING can execute after the connect succeeded and the controller went LIVE (a timed out connect command that completes right after the timeout fires). Claim RESETTING in that case; if that fails, a concurrent reset or delete owns the controller and will complete the outstanding IOs. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 96 +++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 6181cb7ea8ce..5a530aa37641 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -229,6 +229,8 @@ static struct device *fc_udev_device; static void nvme_fc_complete_rq(struct request *rq); static void nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg); +static void __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, + bool start_queues); =20 /* *********************** FC-NVME Port Management ***********************= * */ =20 @@ -987,7 +989,7 @@ fc_dma_unmap_sg(struct device *dev, struct scatterlist = *sg, int nents, static void nvme_fc_ctrl_put(struct nvme_fc_ctrl *); static int nvme_fc_ctrl_get(struct nvme_fc_ctrl *); =20 -static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg= ); +static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl); =20 static void __nvme_fc_finish_ls_req(struct nvmefc_ls_req_op *lsop) @@ -1873,8 +1875,44 @@ nvme_fc_ctrl_ioerr_work(struct work_struct *work) { struct nvme_fc_ctrl *ctrl =3D container_of(work, struct nvme_fc_ctrl, ioerr_work); + enum nvme_ctrl_state state =3D nvme_ctrl_state(&ctrl->ctrl); + + /* + * if an error (io timeout, etc) while (re)connecting, the remote + * port requested terminating of the association (disconnect_ls) + * or an error (timeout or abort) occurred on an io while creating + * the controller. Abort any ios on the association and let the + * create_association error path resolve things. + */ + if (state =3D=3D NVME_CTRL_CONNECTING) { + __nvme_fc_abort_outstanding_ios(ctrl, true); + dev_warn(ctrl->ctrl.device, + "NVME-FC{%d}: transport error during (re)connect\n", + ctrl->cnum); + return; + } + + /* + * Tear the association down only if this work owns recovery via a + * RESETTING claim, or if the delete path is waiting for IOs to + * complete. + */ + if (state =3D=3D NVME_CTRL_LIVE && + nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) + state =3D NVME_CTRL_RESETTING; =20 - nvme_fc_error_recovery(ctrl, "transport detected io error"); + switch (state) { + case NVME_CTRL_RESETTING: + case NVME_CTRL_DELETING: + case NVME_CTRL_DELETING_NOIO: + nvme_fc_error_recovery(ctrl); + break; + default: + dev_warn(ctrl->ctrl.device, + "NVME-FC{%d}: error recovery skipped, state %d owns recovery\n", + ctrl->cnum, nvme_ctrl_state(&ctrl->ctrl)); + break; + } } =20 /* @@ -2533,39 +2571,6 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl = *ctrl, bool start_queues) nvme_unquiesce_admin_queue(&ctrl->ctrl); } =20 -static void -nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) -{ - enum nvme_ctrl_state state =3D nvme_ctrl_state(&ctrl->ctrl); - - /* - * if an error (io timeout, etc) while (re)connecting, the remote - * port requested terminating of the association (disconnect_ls) - * or an error (timeout or abort) occurred on an io while creating - * the controller. Abort any ios on the association and let the - * create_association error path resolve things. - */ - if (state =3D=3D NVME_CTRL_CONNECTING) { - __nvme_fc_abort_outstanding_ios(ctrl, true); - dev_warn(ctrl->ctrl.device, - "NVME-FC{%d}: transport error during (re)connect\n", - ctrl->cnum); - return; - } - - /* Otherwise, only proceed if in LIVE state - e.g. on first error */ - if (state !=3D NVME_CTRL_LIVE) - return; - - dev_warn(ctrl->ctrl.device, - "NVME-FC{%d}: transport association event: %s\n", - ctrl->cnum, errmsg); - dev_warn(ctrl->ctrl.device, - "NVME-FC{%d}: resetting controller\n", ctrl->cnum); - - nvme_reset_ctrl(&ctrl->ctrl); -} - static enum blk_eh_timer_return nvme_fc_timeout(struct request *rq) { struct nvme_fc_fcp_op *op =3D blk_mq_rq_to_pdu(rq); @@ -3389,6 +3394,27 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) } } =20 +static void +nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl) +{ + nvme_stop_keep_alive(&ctrl->ctrl); + flush_work(&ctrl->ctrl.async_event_work); + + /* will block while waiting for io to terminate */ + nvme_fc_delete_association(ctrl); + nvme_stop_ctrl(&ctrl->ctrl); + + /* Do not reconnect if controller is being deleted */ + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) + return; + + if (ctrl->rport->remoteport.port_state =3D=3D FC_OBJSTATE_ONLINE) { + queue_delayed_work(nvme_wq, &ctrl->connect_work, 0); + return; + } + + nvme_fc_reconnect_or_delete(ctrl, -ENOTCONN); +} =20 static const struct nvme_ctrl_ops nvme_fc_ctrl_ops =3D { .name =3D "fc", --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C113051D511 for ; Fri, 18 Sep 2026 18:17:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755437; cv=none; b=WN3KZKV/knTFkjiBhHK5eM412zVKbr9b1cTr+mqSuYos/QSP+RhPMoxvA0RVtW9g75ZUUlEglJTsD+1olLI/YPG+ykdP/PFpi21+itij61zkmoajavvkd1sD/4mTIZwSfrvoJPkSFQQZ6cuzmQjw0Ati9bNa8en+BpHuWW80s+o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755437; c=relaxed/simple; bh=FZt6CXZo2bmv8xm8GIXDwWDNfGUWLjZWl34Anyu+s40=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M2bcc2U8OUGUpNAubJ6VdQXxquRcU1wH+4pJx1ampmEds8U2hHvJcidw/yZ3m05L6t4Oetaka1Ir6dgjo6TjuWRhhsO0+fcnpefKX8qiZNZfblRcr0Kf8cuxnNMld+oSXPSemkEFuhDHbBpnyEz5VrFiLQloghVeQTW3HZlzwCI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=PQtCEkDg; arc=none smtp.client-ip=74.125.228.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="PQtCEkDg" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea34ef4so1099600a12.3 for ; Fri, 18 Sep 2026 11:17:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755435; x=1790360235; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UBOnOOrLTxtHRzBhBZsycN4YkbFFBvPMpRlDpWA+7GA=; b=PQtCEkDgjfk2NO1FMS7NogrPN3u/VleK/fOrhpSwsb8rDH5pw84VqPZ0iWmHpn1opG 7el7HnMO7ZHBPIf8VjJgsABIiDjVgNF0EfkbFoxnoshfIrHpwB3Fyyb14vbhm4i3owBI 5TGy5TvSIPK0uAJXb/cqbY48TRpwf7lRwMqMmvZ2LY1iCWBMHV6zZwBacznzXhOHsLHK qm2lXVrWlHsCuAbKBSZjcMzBt5XmEXwY8fIAgqzFAGdq5Qhe+Z6Vb7laV3b0A6JYjyJL ooSqbYSiOUWmwFw9q8SJ5h9es/N6eatLtR5FrMQ+B1IxDtEuh4XfWg+kokYJD/wZflKX rOHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755435; x=1790360235; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=UBOnOOrLTxtHRzBhBZsycN4YkbFFBvPMpRlDpWA+7GA=; b=dhbR/SwVgVEw+AwVUz28dXuSe+QDpM8B2iAf4h8YcVKqJEBTL+mUDP8BaQpeUz5SpF ALustbxIKfzb5E/9/yAUQ5XnS0bfWjvSeEzdJ61KIPTrvMfRxKtaIDRXJWGmczq0u08f SWYyjJTsqg4PkFrDLNFe4phd2OVZkDXdcJHJ7Hk6CRik9yad7PveLBSI326w9zwn+JEf VJH12N5qR6e7Ta6kJ1J+vQsAY/c7d/XIQXFIs5KXFHcp0Rxv65dG/T+u/P3I/NtCBma/ rQoGqittz40cX4M3uY4aIHR9ZK9QWQh51fKWeCr2F9SPboXOvFpupGtfqAY4ddxdqkdp 2TGg== X-Forwarded-Encrypted: i=1; AKwUvBzTGXEUc3n/64kWYI9h0gQXFLLOEvQpZ80YEmWe3fS/A9EWNp9O5otUZoEGflxt/FQA6exO6IfEy80e7YQ=@vger.kernel.org X-Gm-Message-State: AFuF++mxEhsJUYDnPMApxfG8qnfXG8AAqZ1T8/616OyACNkOzBmXHeFn i/TlyjI1dU/CDl4GD8gphsCh8WCYVHhfL0oZMRQWtRv6gYEwTJBDnWxjIJFzju3YuOk= X-Gm-Gg: AYBFou2T+6UPXjRJTZP0xXzMLLrJOapBlh2Q873IeA+RuFw4k3KgNpQGFA76jABtnx5 aYOuI5ch/NOegHVP2Ln/dcOT4Okyoo/6XesT+bCfm70vOAN71SQjku1fG6RVHIwEJf6LGIzXGVY DIPK2bg10uiM+k4BVxUIqPKzwSZEX4F+XZopcpS9ghk37TM7epfcpHZ6GmApMpgG3ESBiNmDYAv cqrzuMPTn/QA1YBKL2W8jIqC8uSUtcU+PjyV9VwoQ10LoA692jzi1birif7iBYXhKm0hUg7/zjY n6eKv0QGRFHS5a2EQntEZNlzuMuxCjs/u9mORd6t7k91Z0A9UOmQ6dxOxE8xB/Qwl4faZzXgqbx DpxvQzk9pSBygmm7O7vmoKcdG7WWYGucMGUSLyRYPHaemeU6GeDS/JTQ0ocnHvTt2r+1qYEh4J6 viM6duSvJNEea9iDY98Y4MGBDIlukuZ5KuFs5TPr3dwjEVMOnSqdFnrE71PxIi6lkIHgBRDo5Wt 22bolOIadwXEoXER+Fjew== X-Received: by 2002:a17:90b:2686:b0:39e:6c69:9b9c with SMTP id 98e67ed59e1d1-39e6c69b2bemr656537a91.65.1789755434694; Fri, 18 Sep 2026 11:17:14 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:14 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 14/18] nvme-fc: Use CCR to recover controller that hits an error Date: Fri, 18 Sep 2026 11:14:14 -0700 Message-ID: <20260918181614.3947933-15-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An alive nvme controller that hits an error now will move to FENCING state instead of RESETTING state. ctrl->fencing_work attempts CCR to terminate inflight IOs. Regardless of the success or failure of CCR operation the controller is transitioned to RESETTING state to continue error recovery process. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 5a530aa37641..42671cca439f 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -166,6 +166,7 @@ struct nvme_fc_ctrl { struct blk_mq_tag_set admin_tag_set; struct blk_mq_tag_set tag_set; =20 + struct work_struct fencing_work; struct work_struct ioerr_work; struct delayed_work connect_work; =20 @@ -990,6 +991,7 @@ static void nvme_fc_ctrl_put(struct nvme_fc_ctrl *); static int nvme_fc_ctrl_get(struct nvme_fc_ctrl *); =20 static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl); +static void nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl); =20 static void __nvme_fc_finish_ls_req(struct nvmefc_ls_req_op *lsop) @@ -1870,6 +1872,30 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *c= trl, } } =20 +static void nvme_fc_fencing_work(struct work_struct *work) +{ + struct nvme_fc_ctrl *fc_ctrl =3D + container_of(work, struct nvme_fc_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &fc_ctrl->ctrl; + unsigned long rem; + + /* + * Tear the association down now so the LLDD can finish unregistering + * the remoteport/localport while the fencing this controller. + */ + nvme_stop_keep_alive(ctrl); + cancel_work_sync(&ctrl->async_event_work); + nvme_fc_delete_association(fc_ctrl); + + rem =3D nvme_fence_ctrl(ctrl); + if (rem) + dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &fc_ctrl->ioerr_work); +} + static void nvme_fc_ctrl_ioerr_work(struct work_struct *work) { @@ -1950,6 +1976,14 @@ nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ct= rl, char *errmsg) return; } =20 + if (nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_FENCING)) { + dev_warn(ctrl->ctrl.device, + "NVME-FC{%d}: starting controller fencing %s\n", + ctrl->cnum, errmsg); + queue_work(nvme_wq, &ctrl->fencing_work); + return; + } + if (nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) { dev_warn(ctrl->ctrl.device, "NVME-FC{%d}: starting error recovery %s\n", ctrl->cnum, errmsg); @@ -2463,6 +2497,12 @@ nvme_fc_ctrl_get(struct nvme_fc_ctrl *ctrl) return kref_get_unless_zero(&ctrl->ref); } =20 +static void +nvme_fc_stop_ctrl(struct nvme_ctrl *nctrl) +{ + flush_work(&to_fc_ctrl(nctrl)->fencing_work); +} + /* * All accesses from nvme core layer done - can now free the * controller. Called after last nvme_put_ctrl() call @@ -3428,6 +3468,7 @@ static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = =3D { .submit_async_event =3D nvme_fc_submit_async_event, .delete_ctrl =3D nvme_fc_delete_ctrl, .get_address =3D nvmf_get_address, + .stop_ctrl =3D nvme_fc_stop_ctrl, .get_virt_boundary =3D nvmf_get_virt_boundary, }; =20 @@ -3547,6 +3588,7 @@ nvme_fc_alloc_ctrl(struct device *dev, struct nvmf_ct= rl_options *opts, =20 INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work); INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work); + INIT_WORK(&ctrl->fencing_work, nvme_fc_fencing_work); INIT_WORK(&ctrl->ioerr_work, nvme_fc_ctrl_ioerr_work); spin_lock_init(&ctrl->lock); =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pz2-f42.google.com (mail-pz2-f42.google.com [74.125.228.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3E7E509F10 for ; Fri, 18 Sep 2026 18:17:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755438; cv=none; b=Vawydzxt6XIG6Hx1heTh2L5gMUgELO5qqZ6JjBQEIhwdefbvIq9GiQ85/rIg2ZacG5x/0YVYF5R/mqDe4HwYKVW0xenJdpS7k0HFI9yUir+ao/bl12Ur6/cVev5wyjiTY6zoabSoJQ3AjLWU1Huh8GMgoDd6oYGTUHELOmGSCgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755438; c=relaxed/simple; bh=brszAfCb8xPeY2++BmqbzkUD7Gs991VIWtKQ+a7lhTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DR2F8kH7wxSCT0ameWja696b92CJd5L+o19gYl7tHcmTs5Jz5L3OqdwLpeTqm1tgUgsnFMBEWIU9vHtyL80AKGeBgvKtaq9145Vii0KgjEAGOYSiTo76lEW7AST9YI/prSL7IRt2aNb1w73v7TBTYrnEvdcN/vViaAEfLcNs57A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=MlZkJLwS; arc=none smtp.client-ip=74.125.228.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="MlZkJLwS" Received: by mail-pz2-f42.google.com with SMTP id 41be03b00d2f7-cc4c3304784so902063a12.3 for ; Fri, 18 Sep 2026 11:17:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755436; x=1790360236; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=7jjZqkSxtF056SbAAw5d/uzyUYxqOIAwzrV4C8XoM0U=; b=MlZkJLwSaWcYt7RTPzQ66mLjPxFpJSQQlugav351cPBDj42DLfYJrWSPtmxlaW1fdp CwrewX4Y0cTPqmGRutpWYS9Mj5zVOFJyQ10WwrREYcr7DNirT1XGDWuYSBfxheGnn87Z GCCwIq91llCnnHm98kBtQ4iELbGkDQfQbZwvGqY+rblmhP+HdY2sKs0XCVzSwLLvw3nr HVdPkBsRlvQ/82Cf+swcSKilengahHMbCVMVGa0KV+xNzx+KhB+QqEneaEfkPu6S7z8O rLvE2bs8oPOPzenSbGk28/YJAFw9ITfeKo+f4GxT0GuyO8yhcfaFKRJUZOcbET2J7j/5 dyTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755436; x=1790360236; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=7jjZqkSxtF056SbAAw5d/uzyUYxqOIAwzrV4C8XoM0U=; b=WTgHRFVILs2Oe86NUrBnb68L123WQASqvKt/5ftJuAbhMvix+IKXa+59idtPRGgRxI LDmxcQ2UXillvrokDP1QoSn2YXmVvddPM/Dc7EEHXHDP2Uex1J4RvBG0S3Rda5wBCtso ibA0KqXIcs2lJ5RYh/ij5r6ouRTbu845SuPjkwin2bAUF12m9n8yfIKhqJjdxPROKrUI Cok74jkMdioWDiEqx0i/vtuMZ+y0huEoaN8RQ4h4bZ8Ke2C4yQsPc0Y93C2DQfJbaEBt CzdIQUbLZsHihMf9r9OVVSeRPF8RtQDIh8hv5tdx0P3SPtedlMkEFCnNhwaAoA1juBI6 Qaag== X-Forwarded-Encrypted: i=1; AKwUvBxgkde2Ii3HG9BrhaW0vZJBFpS8hMNxonXuQKmwUa2lHSCHk4es3+Mf96TQIf2kaNlLJTlxvdt0OCbdQuM=@vger.kernel.org X-Gm-Message-State: AFuF++ksfWNk8d4tFUDShP8qVE5xmPmD2sbny8M+Uq+ihsJVKhowG1gd dTTP/GaqqpvgLEgGK4oX9Kbs2QXklnMbu6rrpe5FAMXm4zoILbxL7JIRniivwebqFyw= X-Gm-Gg: AYBFou0j4lkDPLmTYYifJNystAAQuoA5OzWfjlPoOr0b8zdxV8EsvsoUN2bGJsHea9z BsehWx+r4fFwBFpiXQqQphFY5TbnP1UBxKcYf5VVX+R4XrXLlhwTuMaJfWf+zh7vPQnT7Es3dXg tGdNuCyYRRzsBAmuyl3BfkIdl7Sfu6XC5mLA99rPgizmTgjhUnCts02jytRvx6g80wK7jJGCQfV 8hos3yoD++bdroDiSFeaTeDZ1fg+UYmgedg6zQdjKZrJx9tU5Y9UU2q7M3jvxj+SPVCQRrNazVU Yh20ZVKnmSUdYfF+leeUECjTGYnHLZQ4souCXpAz8aTVH/3tEUaN38sS8O3uj1j3lYvopTGLWv7 IwxGHTFJG3RPdCOQ/JAyij7TrwQq4gZJ0chguzIM9RAQmbBdUA1myA7fR1SQm/r+I4hEfgSo+BA RMHx61wue/fsUODTfkX8FAWsVfOUrXGihNMgAKwJJDXqwkU8gPWfZreoMN6PKEyAfQOZ5xetGkh DllYywvlNeAXBeolX30Jg== X-Received: by 2002:a17:90b:4b82:b0:39d:f06f:79be with SMTP id 98e67ed59e1d1-39e5502546cmr10108721a91.15.1789755435735; Fri, 18 Sep 2026 11:17:15 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:15 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 15/18] nvme-fc: Hold inflight requests while in FENCING state Date: Fri, 18 Sep 2026 11:14:15 -0700 Message-ID: <20260918181614.3947933-16-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With the association torn down at the start of nvme_fc_fencing_work(), canceling the held requests inside nvme_fc_delete_association() would complete them at fence START, letting them fail over to other paths before CCR/CQT guarantees the target can no longer execute the original commands - defeating the hold this patch introduces. Split nvme_fc_delete_association() into __nvme_fc_teardown_association() (LLDD-facing teardown, no request completion) and nvme_fc_flush_held_requests() (cancel tagsets + unquiesce queues). nvme_fc_fencing_work() now runs only the teardown half up front and flushes the held requests on the FENCING -> FENCED transition. The queues stay quiesced across the fence so nothing new reaches the dead association. Update nvme_fc_fcpio_done() to not complete aborted requests or requests with transport errors. Held requests cannot be forced out mid-fence by the block layer, nvme_fc_timeout() always returns BLK_EH_RESET_TIMER and nvme_fc_start_ioerr_recovery() is a no-op in FENCING state. Every held op is FCPOP_STATE_COMPLETE before the fence starts (aborts drained, synchronize_rcu() done), so the flush never touches the LLDD. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 116 +++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 42671cca439f..a6e0fa2dc341 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -172,7 +172,7 @@ struct nvme_fc_ctrl { =20 struct kref ref; unsigned long flags; - u32 iocnt; + atomic_t iocnt; wait_queue_head_t ioabort_wait; =20 struct nvme_fc_fcp_op aen_ops[NVME_NR_AEN_COMMANDS]; @@ -991,7 +991,8 @@ static void nvme_fc_ctrl_put(struct nvme_fc_ctrl *); static int nvme_fc_ctrl_get(struct nvme_fc_ctrl *); =20 static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl); -static void nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl); +static void __nvme_fc_teardown_association(struct nvme_fc_ctrl *ctrl); +static void nvme_fc_flush_held_requests(struct nvme_fc_ctrl *ctrl); =20 static void __nvme_fc_finish_ls_req(struct nvmefc_ls_req_op *lsop) @@ -1826,7 +1827,7 @@ __nvme_fc_abort_op(struct nvme_fc_ctrl *ctrl, struct = nvme_fc_fcp_op *op) atomic_set(&op->state, opstate); else if (test_bit(FCCTRL_TERMIO, &ctrl->flags)) { op->flags |=3D FCOP_FLAGS_TERMIO; - ctrl->iocnt++; + atomic_inc(&ctrl->iocnt); } spin_unlock_irqrestore(&ctrl->lock, flags); =20 @@ -1856,20 +1857,29 @@ nvme_fc_abort_aen_ops(struct nvme_fc_ctrl *ctrl) } =20 static inline void +__nvme_fc_fcpop_count_one_down(struct nvme_fc_ctrl *ctrl) +{ + if (atomic_dec_return(&ctrl->iocnt) =3D=3D 0) + wake_up(&ctrl->ioabort_wait); +} + +static inline bool __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *ctrl, struct nvme_fc_fcp_op *op, int opstate) { unsigned long flags; + bool ret =3D false; =20 if (opstate =3D=3D FCPOP_STATE_ABORTED) { spin_lock_irqsave(&ctrl->lock, flags); if (test_bit(FCCTRL_TERMIO, &ctrl->flags) && op->flags & FCOP_FLAGS_TERMIO) { - if (!--ctrl->iocnt) - wake_up(&ctrl->ioabort_wait); + ret =3D true; } spin_unlock_irqrestore(&ctrl->lock, flags); } + + return ret; } =20 static void nvme_fc_fencing_work(struct work_struct *work) @@ -1885,12 +1895,14 @@ static void nvme_fc_fencing_work(struct work_struct= *work) */ nvme_stop_keep_alive(ctrl); cancel_work_sync(&ctrl->async_event_work); - nvme_fc_delete_association(fc_ctrl); + if (test_and_clear_bit(ASSOC_ACTIVE, &fc_ctrl->flags)) + __nvme_fc_teardown_association(fc_ctrl); =20 rem =3D nvme_fence_ctrl(ctrl); if (rem) dev_info(ctrl->device, "CCR failed, starting error recovery\n"); =20 + nvme_fc_flush_held_requests(fc_ctrl); nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) queue_work(nvme_reset_wq, &fc_ctrl->ioerr_work); @@ -2003,7 +2015,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) struct nvme_command *sqe =3D &op->cmd_iu.sqe; __le16 status =3D cpu_to_le16(NVME_SC_SUCCESS << 1); union nvme_result result; - bool terminate_assoc =3D true; + bool op_term, terminate_assoc =3D true; + enum nvme_ctrl_state state; int opstate; =20 /* @@ -2043,6 +2056,9 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) * association to be terminated. */ =20 + /* Pairs with synchronize_rcu() in __nvme_fc_teardown_association() */ + rcu_read_lock(); + opstate =3D atomic_xchg(&op->state, FCPOP_STATE_COMPLETE); =20 fc_dma_sync_single_for_cpu(ctrl->lport->dev, op->fcp_req.rspdma, @@ -2136,20 +2152,44 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) done: if (op->flags & FCOP_FLAGS_AEN) { nvme_complete_async_event(&queue->ctrl->ctrl, status, &result); - __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate); + if (__nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate)) + __nvme_fc_fcpop_count_one_down(ctrl); atomic_set(&op->state, FCPOP_STATE_IDLE); op->flags =3D FCOP_FLAGS_AEN; /* clear other flags */ nvme_fc_ctrl_put(ctrl); goto check_error; } =20 - __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate); + /* + * We can not access op after the request is completed because it can + * be reused immediately. At the same time we want to wakeup the thread + * waiting for ongoing IOs _after_ requests are completed. This is + * necessary because that thread will start canceling inflight IOs + * and we want to avoid request completion racing with cancellation. + */ + op_term =3D __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate); + + /* + * If we are going to terminate associations and the controller is + * LIVE or FENCING, then do not complete this request now. Let error + * recovery cancel this request when it is safe to do so. + */ + state =3D nvme_ctrl_state(&ctrl->ctrl); + if (terminate_assoc && + (state =3D=3D NVME_CTRL_LIVE || state =3D=3D NVME_CTRL_FENCING)) + goto check_op_term; + if (!nvme_try_complete_req(rq, status, result)) nvme_fc_complete_rq(rq); +check_op_term: + if (op_term) + __nvme_fc_fcpop_count_one_down(ctrl); =20 check_error: if (terminate_assoc) nvme_fc_start_ioerr_recovery(ctrl, "io error"); + + rcu_read_unlock(); } =20 static int @@ -2802,7 +2842,8 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struc= t nvme_fc_queue *queue, * cmd with the csn was supposed to arrive. */ opstate =3D atomic_xchg(&op->state, FCPOP_STATE_COMPLETE); - __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate); + if (__nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate)) + __nvme_fc_fcpop_count_one_down(ctrl); =20 if (!(op->flags & FCOP_FLAGS_AEN)) { nvme_fc_unmap_data(ctrl, op->rq, op); @@ -3260,25 +3301,25 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctr= l) return ret; } =20 - /* - * This routine stops operation of the controller on the host side. - * On the host os stack side: Admin and IO queues are stopped, - * outstanding ios on them terminated via FC ABTS. - * On the link side: the association is terminated. + * This routine tears down the association on the link side and releases + * all LLDD resources: outstanding ios are terminated via FC ABTS, hw + * queues are deleted and the controller is marked inactive on the + * rport. Requests that nvme_fc_fcpio_done() decided to hold are NOT + * completed here, the caller must follow up with + * nvme_fc_flush_held_requests() once it is safe to release them. + * + * The caller must own the ASSOC_ACTIVE bit (test_and_clear_bit()). */ static void -nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) +__nvme_fc_teardown_association(struct nvme_fc_ctrl *ctrl) { struct nvmefc_ls_rcv_op *disls =3D NULL; unsigned long flags; =20 - if (!test_and_clear_bit(ASSOC_ACTIVE, &ctrl->flags)) - return; - spin_lock_irqsave(&ctrl->lock, flags); set_bit(FCCTRL_TERMIO, &ctrl->flags); - ctrl->iocnt =3D 0; + atomic_set(&ctrl->iocnt, 0); spin_unlock_irqrestore(&ctrl->lock, flags); =20 __nvme_fc_abort_outstanding_ios(ctrl, false); @@ -3287,11 +3328,18 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctr= l) nvme_fc_abort_aen_ops(ctrl); =20 /* wait for all io that had to be aborted */ + wait_event(ctrl->ioabort_wait, atomic_read(&ctrl->iocnt) =3D=3D 0); spin_lock_irq(&ctrl->lock); - wait_event_lock_irq(ctrl->ioabort_wait, ctrl->iocnt =3D=3D 0, ctrl->lock); clear_bit(FCCTRL_TERMIO, &ctrl->flags); spin_unlock_irq(&ctrl->lock); =20 + /* + * Wait for a started nvme_fc_fcpio_done() to complete before we + * proceed with cancelling inflight requests. This guarantees a + * request is completed by one of the two codepaths, not both. + */ + synchronize_rcu(); + nvme_fc_term_aen_ops(ctrl); =20 /* @@ -3323,13 +3371,37 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctr= l) __nvme_fc_delete_hw_queue(ctrl, &ctrl->queues[0], 0); nvme_fc_free_queue(&ctrl->queues[0]); =20 + nvme_fc_ctlr_inactive_on_rport(ctrl); +} + +/* Complete the requests held in __nvme_fc_teardown_association() */ +static void +nvme_fc_flush_held_requests(struct nvme_fc_ctrl *ctrl) +{ + nvme_cancel_tagset(&ctrl->ctrl); + nvme_cancel_admin_tagset(&ctrl->ctrl); + /* re-enable the admin_q so anything new can fast fail */ nvme_unquiesce_admin_queue(&ctrl->ctrl); =20 /* resume the io queues so that things will fast fail */ nvme_unquiesce_io_queues(&ctrl->ctrl); +} =20 - nvme_fc_ctlr_inactive_on_rport(ctrl); +/* + * This routine stops operation of the controller on the host side. + * On the host os stack side: Admin and IO queues are stopped, + * outstanding ios on them terminated via FC ABTS. + * On the link side: the association is terminated. + */ +static void +nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) +{ + if (!test_and_clear_bit(ASSOC_ACTIVE, &ctrl->flags)) + return; + + __nvme_fc_teardown_association(ctrl); + nvme_fc_flush_held_requests(ctrl); } =20 static void --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8841151EE02 for ; Fri, 18 Sep 2026 18:17:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755439; cv=none; b=imhLsDjHWKHTrjzIbcC3BndLwnkm4wc/Oft+6FtPFGLuBX5IQafs3AE+2hlcJkzQhOOusGtTjKLOUIAY1qEx7BBEf0yoyPrLJ0Xpm2UYwgDQ6EOZR813t7bma6qMXcPkKqbfoLInAhT6EFwCGSVhuyuPn5rjTHELRLfM1hDpfHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755439; c=relaxed/simple; bh=kJlZAJC5w8Y6rxPPy96a2gpbq9yTsgzYHypSB80iKmo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u8TUoo+dPmDmEoqomQIjrDqSOQG/MrtJE1PQ+oV+92RGHOuS0rrL5pKNriYeciWaCEX2Bjssz0R1Rve8O4DStSeqBeeuqslQqqeDVE+IGz68CmEvEWg1F8gc2bN7fyf/24NGTz2II4ZePs21isJpJEiuIFQ6j7U8igYRYQTwo0o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=OtuOdH9c; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="OtuOdH9c" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-396ccb65437so926354a91.3 for ; Fri, 18 Sep 2026 11:17:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755437; x=1790360237; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=AW01tuh8hRVQtK4qarvblwO+ofGvSgZdhu/67l8Xj60=; b=OtuOdH9c4rWDpDQiilL1JUY/4XrxXbfDzZriUB5e4GFzC9NclgSaZVh98d+brcAWw4 KWeuo6d/LL0blCw+MEX8+WssWc3+ubvhAaJTNkSxTEDG8/TLfGr420ALXLBQ99pUbuP7 NdbZJ6dXAuGdkjtAjuNEa3ys1UMZ9kRNinctXFarjsQZYN7zTBhn9SW1DzkoO+AeewWD 3BSuWoJ12aDTeBf0p5JTFOcoMk9TZEnuicIqi5IISegxxMOHlUX5JDqbBJ4f0ywg74es 4eF1U7qKlgK+X28h7qBNBDbc0tN+hGltLIgvdc4A0FS21UGIQkpSMzCz834xaeffal+S pe/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755437; x=1790360237; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=AW01tuh8hRVQtK4qarvblwO+ofGvSgZdhu/67l8Xj60=; b=KPbQA9njHabEXg6iMsbdsxiEJ2hwxsfxZTaEs040YirMy8H8OZAUkTHClVW2jOMuVi lEBOd2oGwu7WGegTMzCMTa3ziiXQjpGXGp0tfKNYutPDHSd6uY2Ju7EpPcDSyu8Vba0o iwGMVQshYFPgqwGT2YYRoPonP3+L4yycs4e31A0bI3r5Qs2RIttaf/prwzVOnPWpG6oU mVXtV+ZrvAL6fRzgQRXzCPLrTIvQchAs3eKlT6wYUrB8zkIuqIcq89rZD+AAAQniB37a dm5yiHT8QrUVVSyd7O+ty0EVMj5kbdT9ipp5Pg/zNWy0/KsZNp5G/yWE3mKd1HTwjHOI e8CQ== X-Forwarded-Encrypted: i=1; AKwUvBx4rk+RSsOMtmmTlVnaMHkz/ylTsT/Fnqj1HN2eVeN8P0ZUbI5+/kgc2tyMy5XC+wFai2zd2IqmHLp52jA=@vger.kernel.org X-Gm-Message-State: AFuF++nqMBzCqpWBk2ZoEHjUPzNi1Uj/9QXwfc7lerlkvuWDyBC9Jak2 JDvYhSvrYHRVLOGjr57qF1eK0F3VrPeHB1lQ13DCWIeYypDjxSh4Gh0kaM3Nq2o8qCsI3LIgvOY fbRT0 X-Gm-Gg: AYBFou0QM37mJS7sfS5BdUCLO0uE3RgNNTaK5Q/Gn5ajJHU08Enik5OgttofC3WMN8i oVSqc1tw3WvYPdkXzxnylStPRdM2ML24xfog34QcLOCu0CtzwlUF4nfTmfwNBgmZF4QtAJr+13n h0QW7mpstJ1KGlaoNDRlSO85InjK1sqNT42nGz9z+FPsOSFHryucet/I+aRd4sjbS+fCYqmim6H TOG94P9tkYwpLu6yrjJAQHJ0oSV/QhNsGqInoa7YMs6cZ0LacyXokMUR98BRlKonTwNpW6aUbfO stWa19oXzdPx1xvckmj3ece2+fNmxcHSCRq3hjhHRa3jpqji2wmmjr28dJD9w6xH04eV8rEVyFn JmDa2cTzIh/HkRffmUL8qQKAz2ROwg8a7YBjPCOscw9pN8cwGLsgR7r9hCnaqqicwALuQMIfd3a kZUl7o361WOrl8K/LJYlW3/EVFnWM8u/9YMePh/cpEGmR9ifAZzi+os4o7hL5sxkdBgABGQgOo3 kNU+Fg1KdCSpPt5ZsHs0A== X-Received: by 2002:a17:90b:4ac7:b0:39e:6c6a:4b6a with SMTP id 98e67ed59e1d1-39e6c6a5812mr574016a91.52.1789755436728; Fri, 18 Sep 2026 11:17:16 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:16 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 16/18] nvmet: Add support for CQT to nvme target Date: Fri, 18 Sep 2026 11:14:16 -0700 Message-ID: <20260918181614.3947933-17-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TP4129 KATO Corrections and Clarifications defined CQT (Command Quiesce Time) which is used along with KATO (Keep Alive Timeout) to set an upper time limit for attempting Cross-Controller Recovery. CQT is added as a subsystem attribute that defaults to 0 to maintain the current behavior. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/target/admin-cmd.c | 1 + drivers/nvme/target/configfs.c | 36 +++++++++++++++++++++++++++++++++ drivers/nvme/target/core.c | 3 +++ drivers/nvme/target/nvmet.h | 2 ++ include/linux/nvme.h | 5 ++++- 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index a60b2f271e98..c0cd233048eb 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -739,6 +739,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_re= q *req) id->cntlid =3D cpu_to_le16(ctrl->cntlid); id->ver =3D cpu_to_le32(ctrl->subsys->ver); if (!nvmet_is_disc_subsys(ctrl->subsys)) { + id->cqt =3D cpu_to_le16(ctrl->cqt); id->ciu =3D ctrl->ciu; id->cirn =3D cpu_to_le64(ctrl->cirn); id->ccrl =3D NVMF_CCR_LIMIT; diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c index 6286e38436dd..88a59ac1e93a 100644 --- a/drivers/nvme/target/configfs.c +++ b/drivers/nvme/target/configfs.c @@ -1663,6 +1663,41 @@ static ssize_t nvmet_subsys_attr_pi_enable_store(str= uct config_item *item, CONFIGFS_ATTR(nvmet_subsys_, attr_pi_enable); #endif =20 +static ssize_t nvmet_subsys_attr_cqt_show(struct config_item *item, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cqt); +} + +static ssize_t nvmet_subsys_attr_cqt_store(struct config_item *item, + const char *page, size_t cnt) +{ + struct nvmet_subsys *subsys =3D to_subsys(item); + struct nvmet_ctrl *ctrl; + u16 cqt; + + if (nvmet_is_disc_subsys(subsys)) + return -EINVAL; + + if (sscanf(page, "%hu\n", &cqt) !=3D 1) + return -EINVAL; + + down_write(&nvmet_config_sem); + mutex_lock(&subsys->lock); + if (subsys->cqt =3D=3D cqt) + goto out; + + subsys->cqt =3D cqt; + /* Force reconnect */ + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) + ctrl->ops->delete_ctrl(ctrl); +out: + mutex_unlock(&subsys->lock); + up_write(&nvmet_config_sem); + return cnt; +} +CONFIGFS_ATTR(nvmet_subsys_, attr_cqt); + static ssize_t nvmet_subsys_attr_qid_max_show(struct config_item *item, char *page) { @@ -1703,6 +1738,7 @@ static struct configfs_attribute *nvmet_subsys_attrs[= ] =3D { &nvmet_subsys_attr_attr_vendor_id, &nvmet_subsys_attr_attr_subsys_vendor_id, &nvmet_subsys_attr_attr_model, + &nvmet_subsys_attr_attr_cqt, &nvmet_subsys_attr_attr_qid_max, &nvmet_subsys_attr_attr_ieee_oui, &nvmet_subsys_attr_attr_firmware, diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 69491e8e52ba..a93cf7e3a704 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1753,6 +1753,7 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_allo= c_ctrl_args *args) ctrl->cntlid =3D ret; =20 if (!nvmet_is_disc_subsys(ctrl->subsys)) { + ctrl->cqt =3D subsys->cqt; ctrl->ciu =3D get_random_u8() ? : 1; ctrl->cirn =3D get_random_u64(); } @@ -1980,10 +1981,12 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char = *subsysnqn, =20 switch (type) { case NVME_NQN_NVME: + subsys->cqt =3D NVMF_CQT_MS; subsys->max_qid =3D NVMET_NR_QUEUES; break; case NVME_NQN_DISC: case NVME_NQN_CURR: + subsys->cqt =3D 0; subsys->max_qid =3D 0; break; default: diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 88fa11aa0587..ddf88c772938 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -270,6 +270,7 @@ struct nvmet_ctrl { uuid_t hostid; u16 cntlid; u16 max_qid; + u16 cqt; u8 ciu; u32 kato; u64 cirn; @@ -347,6 +348,7 @@ struct nvmet_subsys { #ifdef CONFIG_NVME_TARGET_DEBUGFS struct dentry *debugfs_dir; #endif + u16 cqt; u16 max_qid; =20 u64 ver; diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 3757d11ffea3..0b69ed53f347 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -21,6 +21,7 @@ #define NVMF_TRADDR_SIZE 256 #define NVMF_TSAS_SIZE 256 =20 +#define NVMF_CQT_MS 0 #define NVMF_CCR_LIMIT 4 #define NVMF_CCR_PER_PAGE 511 =20 @@ -368,7 +369,9 @@ struct nvme_id_ctrl { __u8 anacap; __le32 anagrpmax; __le32 nanagrpid; - __u8 rsvd352[160]; + __u8 rsvd352[34]; + __le16 cqt; + __u8 rsvd388[124]; __u8 sqes; __u8 cqes; __le16 maxcmd; --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95F2851EE18 for ; Fri, 18 Sep 2026 18:17:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755440; cv=none; b=ErNdppWEUDxHhk0TCTfEIAXcUSFxVjfDJV+vtz3trNAXg9a2ks4StusKDwMyfdh6HixZe4EEyiwvOhAp8Dt/w50DrqPRzYEUVgb0F/ebTy1a3Cxnna7bKoGP5dnhrZpVyiqqsUBacI+1DdlmPSHoh5dD6gsaxB5pISNHZ3feZnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755440; c=relaxed/simple; bh=N3TrYKj63SGboRNWu/OysoGDNr/HzP5uaLhsWM3pZ+A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CoGmhoaWkXwKIZiDys/WjgvS1jrzWif7hvKY3Ah888jQZZU4ihcvncjIWYHOIhs1ReciYVgdeRIb38kpNz4y0gkTqBzEZUz5gvzi/gqbMXnNvwtY3F86Ix0qMFGKLpkJcKMRWYhtYiTxucLgjcRgfBc1tu4jOfy0uFd8K59w6sU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=aOSEnO6s; arc=none smtp.client-ip=74.125.227.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="aOSEnO6s" Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-396ccd78e6eso399835a91.0 for ; Fri, 18 Sep 2026 11:17:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755438; x=1790360238; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=xpEVTaDIEqTTyPgj4k8QhiOl8bbLm2x6tGVGdtqRrPM=; b=aOSEnO6soKUMY2vwaWIIPtM8IjcKwrYaRnhS+dNCTON5wjxlCq8zuURg/aYAsPBnso nJJgd78sD9YSJnjXJ3kqJQgaoxZBMm1VqF2b5Mx7AA2zVdf9W4QH7KD/y63Yo8BkfQhx tjL5Q/iW+sNuUlZ+lIxSfCsC0sMVQ92pYr7nqCigFZeHZIm+hE06Z9yozfHJ29mXdls/ DaN1xb0aQhhbvk5cpSORUkfi91ptsBK9yA81rh+ErYw4+V0XSYp72YSw3h29CSvbNF/U yGeAZ7ZrDRR7NEdCcEJpGZJSN7SJguzBwGnNwaDDPqktALHfC4VeqUfcVbiXHhb46JGo tP0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755438; x=1790360238; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=xpEVTaDIEqTTyPgj4k8QhiOl8bbLm2x6tGVGdtqRrPM=; b=jr0jttoCnXnY2+F2+o6bpTrwsV4DFxnNoNlqXvXW9BDkllJdKpNUEzDwtMR8f2N3un +GH5aBeLYBpV7ByAPV5Jy6w4tKCeCE+v26bQQYsWk1GukKqeX0hVdKl7/CAJ697Zlof/ srDeLUMsTw5KJPLKYFkXprpCtg6pD9FjUkP8/jFxBREvcK0gkAFxH4FszBCJH7HmDxJ0 Alxk4+OjLu+qZ6hZQf+p4SCA1Rz4846rjGjh9vJePvzyzxpSLdGj391FPyN8V7ORz7NP vvz06rce4AnSdzbPaymsKrYOyh8MdoA0JsQipMjPfG6fDFPPgqzYNQmeZ7+l1N6oOW3m 5zSQ== X-Forwarded-Encrypted: i=1; AKwUvBytR+Oik2YeGY/APv3V0DKmD1k1e/LuF4dsptftl8WF/7M3gZ9cWRyONADeC/0cLlNQ1Y9G8MRD9NRve9E=@vger.kernel.org X-Gm-Message-State: AFuF++m8afVUNvmxQ/hvGKNq71lGBFqW7gfskhj9N5bsHccKqKD+AyTI k5iTeeSAV8A6sOQUcZQwv0mU89AKUkjZRWuEcZeAhpqouO98PXB+tHKCmatzLGZQrpw= X-Gm-Gg: AYBFou1ZnXXNzNy1+TxMhZsrH4gYNeFKYSogTenocVODeK0F5NA203HQOBqJFHXG1vz ACs45kjwcsiXdKj8ZWSzuyd5d3rqWrGqcH27zsmuEYsqnnLQKQpzNdVH4yfezi8G6RKdjBm+Ybs CotR29MNAvNTbe79exWWBqJ4uf2Bta29/lUSBjN1sfRENVPEj9JagImqjLbpcrTsOqzSbnn2/XR 7XsS6bX4rxvfavSKAownjqqb26QSfGXKnWiW0YTeCv2Wm9TQ5S3Rr1F8Ya1a3st8YCaczZVVjK1 bNRUrtsfazhrY1/H72RZMhp8wZbwHw+77XlO8tMW/Wg7rWS9gwQ/BtnScWBVYlglO1/pXnJeUlR E1korI3KU4uG+a0hsf1uGKMZfYcr/jT3bATD7OOKLLU4WT6lGu51uIDTxtvTC8gC8VwPTKsxTwj 18IErQIiiGwyhuDaSMUIEQhWse8iTROExVvvXjffyyb33OmU+xsqQ7YnGH6HQIsFWtl0k5DxaUL Fq9oa1U82DOFb5jTbsOaBb/6ToGKjc+ X-Received: by 2002:a17:90b:38c8:b0:39e:6a7f:6187 with SMTP id 98e67ed59e1d1-39e6a7f6404mr766298a91.24.1789755437763; Fri, 18 Sep 2026 11:17:17 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:17 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 17/18] nvme: Add support for CQT to nvme host Date: Fri, 18 Sep 2026 11:14:17 -0700 Message-ID: <20260918181614.3947933-18-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TP4129 KATO Corrections and Clarifications defined CQT (Command Quiesce Time) which is used along with KATO (Keep Alive Timeout) to set an upper limit for attempting Cross-Controller Recovery. Add ctrl->cqt, read its value from controller identify response, expose it via sysfs, and have nvme_fence_timeout_ms() account for it. Use CQT to drive time-based recovery in fc, rdma, and tcp transports. Add a fenced_work delayed work to each transport controller. If CCR fails, fencing_work switches to error recovery immediately if CQT is not supported. Otherwise it schedules fenced_work after the remaining fence timeout, which also switches to error recovery when scheduled. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke Reviewed-by: Sagi Grimberg --- drivers/nvme/host/core.c | 1 + drivers/nvme/host/fc.c | 33 +++++++++++++++++++++++++++++++-- drivers/nvme/host/nvme.h | 5 +++-- drivers/nvme/host/rdma.c | 32 ++++++++++++++++++++++++++++++-- drivers/nvme/host/sysfs.c | 2 ++ drivers/nvme/host/tcp.c | 32 ++++++++++++++++++++++++++++++-- 6 files changed, 97 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 5509b58b51db..dc44e3af5f14 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3844,6 +3844,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl) ctrl->ciu =3D id->ciu; ctrl->cirn =3D le64_to_cpu(id->cirn); ctrl->ccrl =3D id->ccrl; + ctrl->cqt =3D le16_to_cpu(id->cqt); =20 ctrl->oacs =3D le16_to_cpu(id->oacs); ctrl->oncs =3D le16_to_cpu(id->oncs); diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index a6e0fa2dc341..3db111accd0c 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -167,6 +167,7 @@ struct nvme_fc_ctrl { struct blk_mq_tag_set tag_set; =20 struct work_struct fencing_work; + struct delayed_work fenced_work; struct work_struct ioerr_work; struct delayed_work connect_work; =20 @@ -1882,6 +1883,19 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *c= trl, return ret; } =20 +static void nvme_fc_fenced_work(struct work_struct *work) +{ + struct nvme_fc_ctrl *fc_ctrl =3D container_of(to_delayed_work(work), + struct nvme_fc_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &fc_ctrl->ctrl; + + dev_info(ctrl->device, "Time-based recovery finished\n"); + nvme_fc_flush_held_requests(fc_ctrl); + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &fc_ctrl->ioerr_work); +} + static void nvme_fc_fencing_work(struct work_struct *work) { struct nvme_fc_ctrl *fc_ctrl =3D @@ -1899,9 +1913,22 @@ static void nvme_fc_fencing_work(struct work_struct = *work) __nvme_fc_teardown_association(fc_ctrl); =20 rem =3D nvme_fence_ctrl(ctrl); - if (rem) - dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + if (!rem) + goto done; =20 + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } + + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &fc_ctrl->fenced_work, rem); + return; + +done: nvme_fc_flush_held_requests(fc_ctrl); nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) @@ -2541,6 +2568,7 @@ static void nvme_fc_stop_ctrl(struct nvme_ctrl *nctrl) { flush_work(&to_fc_ctrl(nctrl)->fencing_work); + flush_delayed_work(&to_fc_ctrl(nctrl)->fenced_work); } =20 /* @@ -3661,6 +3689,7 @@ nvme_fc_alloc_ctrl(struct device *dev, struct nvmf_ct= rl_options *opts, INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work); INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work); INIT_WORK(&ctrl->fencing_work, nvme_fc_fencing_work); + INIT_DELAYED_WORK(&ctrl->fenced_work, nvme_fc_fenced_work); INIT_WORK(&ctrl->ioerr_work, nvme_fc_ctrl_ioerr_work); spin_lock_init(&ctrl->lock); =20 diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 7096f1e4f84e..bcecaaf06f7e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -401,6 +401,7 @@ struct nvme_ctrl { u32 max_zone_append; #endif u16 crdt[3]; + u16 cqt; u16 oncs; u8 dmrl; u8 ciu; @@ -1360,8 +1361,8 @@ static inline bool nvme_multi_css(struct nvme_ctrl *c= trl) static inline unsigned long nvme_fence_timeout_ms(struct nvme_ctrl *ctrl) { if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) - return 3 * ctrl->kato * 1000; - return 2 * ctrl->kato * 1000; + return 3 * ctrl->kato * 1000 + ctrl->cqt; + return 2 * ctrl->kato * 1000 + ctrl->cqt; } =20 #endif /* _NVME_H */ diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 9c50421d79c4..8ff5aa312377 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -120,6 +120,7 @@ struct nvme_rdma_ctrl { /* other member variables */ struct blk_mq_tag_set tag_set; struct work_struct fencing_work; + struct delayed_work fenced_work; struct work_struct err_work; =20 struct nvme_rdma_qe async_event_sqe; @@ -994,6 +995,7 @@ static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl) struct nvme_rdma_ctrl *ctrl =3D to_rdma_ctrl(nctrl); =20 flush_work(&ctrl->fencing_work); + flush_delayed_work(&ctrl->fenced_work); flush_work(&ctrl->err_work); cancel_delayed_work_sync(&ctrl->reconnect_work); } @@ -1155,6 +1157,18 @@ static void nvme_rdma_reconnect_ctrl_work(struct wor= k_struct *work) nvme_rdma_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_rdma_fenced_work(struct work_struct *work) +{ + struct nvme_rdma_ctrl *rdma_ctrl =3D container_of(to_delayed_work(work), + struct nvme_rdma_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &rdma_ctrl->ctrl; + + dev_info(ctrl->device, "Time-based recovery finished\n"); + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &rdma_ctrl->err_work); +} + static void nvme_rdma_fencing_work(struct work_struct *work) { struct nvme_rdma_ctrl *rdma_ctrl =3D container_of(work, @@ -1163,9 +1177,22 @@ static void nvme_rdma_fencing_work(struct work_struc= t *work) unsigned long rem; =20 rem =3D nvme_fence_ctrl(ctrl); - if (rem) - dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + if (!rem) + goto done; + + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } + + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &rdma_ctrl->fenced_work, rem); + return; =20 +done: nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) queue_work(nvme_reset_wq, &rdma_ctrl->err_work); @@ -2354,6 +2381,7 @@ static struct nvme_rdma_ctrl *nvme_rdma_alloc_ctrl(st= ruct device *dev, INIT_DELAYED_WORK(&ctrl->reconnect_work, nvme_rdma_reconnect_ctrl_work); INIT_WORK(&ctrl->fencing_work, nvme_rdma_fencing_work); + INIT_DELAYED_WORK(&ctrl->fenced_work, nvme_rdma_fenced_work); INIT_WORK(&ctrl->err_work, nvme_rdma_error_recovery_work); INIT_WORK(&ctrl->ctrl.reset_work, nvme_rdma_reset_ctrl_work); =20 diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c index 3a12b07149d2..e8dad4722347 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -486,6 +486,7 @@ nvme_show_int_function(numa_node); nvme_show_int_function(queue_count); nvme_show_int_function(sqsize); nvme_show_int_function(kato); +nvme_show_int_function(cqt); =20 static ssize_t nvme_sysfs_ciu_show(struct device *dev, struct device_attribute *attr, @@ -966,6 +967,7 @@ static struct attribute *nvme_dev_attrs[] =3D { &dev_attr_sqsize.attr, &dev_attr_ciu.attr, &dev_attr_cirn.attr, + &dev_attr_cqt.attr, &dev_attr_hostnqn.attr, &dev_attr_hostid.attr, &dev_attr_ctrl_loss_tmo.attr, diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index febbe8954473..7b1d9e2cb00d 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -168,6 +168,7 @@ struct nvme_tcp_ctrl { struct nvme_ctrl ctrl; =20 struct work_struct fencing_work; + struct delayed_work fenced_work; struct work_struct err_work; struct delayed_work connect_work; struct nvme_tcp_request async_req; @@ -2565,6 +2566,18 @@ static void nvme_tcp_reconnect_ctrl_work(struct work= _struct *work) nvme_tcp_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_tcp_fenced_work(struct work_struct *work) +{ + struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(to_delayed_work(work), + struct nvme_tcp_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &tcp_ctrl->ctrl; + + dev_info(ctrl->device, "Time-based recovery finished\n"); + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &tcp_ctrl->err_work); +} + static void nvme_tcp_fencing_work(struct work_struct *work) { struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(work, @@ -2573,9 +2586,22 @@ static void nvme_tcp_fencing_work(struct work_struct= *work) unsigned long rem; =20 rem =3D nvme_fence_ctrl(ctrl); - if (rem) - dev_info(ctrl->device, "CCR failed, starting error recovery\n"); + if (!rem) + goto done; + + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } =20 + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &tcp_ctrl->fenced_work, rem); + return; + +done: nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) queue_work(nvme_reset_wq, &tcp_ctrl->err_work); @@ -2657,6 +2683,7 @@ static void nvme_reset_ctrl_work(struct work_struct *= work) static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl) { flush_work(&to_tcp_ctrl(ctrl)->fencing_work); + flush_delayed_work(&to_tcp_ctrl(ctrl)->fenced_work); flush_work(&to_tcp_ctrl(ctrl)->err_work); cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work); } @@ -3023,6 +3050,7 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(stru= ct device *dev, INIT_DELAYED_WORK(&ctrl->connect_work, nvme_tcp_reconnect_ctrl_work); INIT_WORK(&ctrl->fencing_work, nvme_tcp_fencing_work); + INIT_DELAYED_WORK(&ctrl->fenced_work, nvme_tcp_fenced_work); INIT_WORK(&ctrl->err_work, nvme_tcp_error_recovery_work); INIT_WORK(&ctrl->ctrl.reset_work, nvme_reset_ctrl_work); =20 --=20 2.55.0 From nobody Thu Sep 24 22:56:42 2026 Received: from mail-pz2-f42.google.com (mail-pz2-f42.google.com [74.125.228.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC93B51FCBF for ; Fri, 18 Sep 2026 18:17:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755441; cv=none; b=mAUdTDS4zhaTW3x4OQu7GHz546x1xY2dMO1RjpwRopQvefUl2UQjj8SMyT7U7xmJg0b32O5GKUjxMFwflU8B52XDXJ3XXVSiyJdsn3s0t+wruVNvh6zS6v7D3RjeGHOz6ag7B4EaNfqPG9jKIkfwqKGCZMZkmJIVGPehqXCukyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789755441; c=relaxed/simple; bh=D0ry5I2UO5EoVVglgccRISGqcp8rRYeGB8BrHvdM5pE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k0D+3zOuCsWHc7bGmiwkX7bai3ZMPOOiR8XmVPnPweTOQ/fyFZR06guPakIW5H1+luqW8gNMbvI3tS1taMzLkPdp4pw6XDrFJ/XR5p4WrGJJpf0PxKrSWOOll2vqjeXNonCGtGIeGzKejUoaZao/BJV57Q7qMUxuHHq4KdosoS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=aIyTwY2N; arc=none smtp.client-ip=74.125.228.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="aIyTwY2N" Received: by mail-pz2-f42.google.com with SMTP id 41be03b00d2f7-cc50b9e8a45so635970a12.2 for ; Fri, 18 Sep 2026 11:17:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789755439; x=1790360239; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Dih43qxI5dfgAB3392PAv6zbxSUobiO7FmfsRmituIk=; b=aIyTwY2NHWsrV2FaRalS6mA+gBKXQ+FQPxtDBLhUokoMfvw7tTaouGjcqXp1yg8A2z HO1lwntxzV7k7loB4DCBbvD+qTsQQmN+t6IFr13KIooC2ACoBK18Wq3Fp2eEkllmdnwh jO0ARacSk9HS9iJTr3CfDwukuHNxpi6IPKCLsegq59yymtTQnOQ/GUtEOortsImyhxy0 8wcafcs76bf3/1Xw8Y2BM1vUe5CoNg7KtDUNFYXUBsHVyQNKCWxEQ8xWMOYff8no3NcT LV/XZgB2DXjxuZ14GCwQ5y2X2RF5HKQ2CjBtvAtYX1ouXKPhzRsGG5ov68OKEXQQnbPG 3pOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789755439; x=1790360239; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Dih43qxI5dfgAB3392PAv6zbxSUobiO7FmfsRmituIk=; b=UrhYpc+lwIylfxxC4MpIO4/g6t1ya1QFWDZQY6KPFRolNKvXAuxSCClqmP5CywVZNn zvAhP/OsZyXe1zjkqeWSNukbGfA6MdXGsj1iN8LTOdhiCnem8ZoVL55RWVZTPqFBlCqN A5vlg2nsO5dDHkl8PphalNZdgx7cAalqvXPtzB78Hc4tciNitv0xwTipvwyUWwy/NoMV KaP6EsdL4WnpryrEMQ2EoHbYQpkQQwCTBwZAXfl/EeLFj3fwGHej9PsPlNU1SqKNmclA tFJ0RZVWQjxKp6eQcGb65SA7tQ8pJagTKO6rmTduc9htyYWtgTdvLMvt46PYcZjJk9Rw IPzg== X-Forwarded-Encrypted: i=1; AKwUvBxGdyvMWTv4uzP5c2xjl5CXgbrs+M6n8vKMxjXKiWx4ml+5EAbRVcvH7ZFCv2n+FIQQkCNHZyIt+b3vvvk=@vger.kernel.org X-Gm-Message-State: AFuF++mqPEYwoovXA/SYFew2Vaoevrqd8Nb0j8Q5Kdr9vhzudQQA/2s+ dl32QAu5aHaRnBrV7Lkja8Org3GC4Do/DnR4d+LJA6wRiz3pdwE7APY8ARs/TdKw+/I= X-Gm-Gg: AYBFou3Qvc95h4U6vqb/Nl1hzJgMDLCjQJFb0a8eyp6cBCfMECajPqr0GTpcPBy5ey7 PePY0lO7WfQ75iF0mbt9qQnwUZqApUfZ4E+9Kf0Xq+UoNo6kuycda9ZgzVd43GovB4vy3kvdwR/ DCo/ahqRpdXEZMsdarVVjEryyAqfh98HhHRzqEt9c6KN7EP8aaKk9gyVAT0MG6cOYk19zGv5Exn YgxPMxuN+ARldVmLcKJxr+ufyH/04dXplHTm9eZfW0yiWV9VYFHUB2+/DlaLrybD1Q6z7Hvjayd hSRHbgfBbhs2XUt382SHnpzuRLWPxsNn4Fkiyl+K8Dsr6/EV/eXd15yInf2XcQCzTbnSK00SlVG jyvStjLXjhzajYKM+eMM5RxKv3Yr23pjmuGmU3riEDy300+V509Hb03kVfE77KSgFtp6M5qQxwv 65qrho9407fLVaftyQjllom3jT70wYf3gdhVDtQmoznF+hKkeV+NSKwMh6WcrxxatNkqRLc2fTr Twirp4AqnaGjciCRMcz8Bk= X-Received: by 2002:a17:90b:4a03:b0:36d:9e0b:3801 with SMTP id 98e67ed59e1d1-39e54d38c48mr11469185a91.8.1789755438885; Fri, 18 Sep 2026 11:17:18 -0700 (PDT) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id 5a478bee46e88-33c331aeeddsm335107eec.24.2026.09.18.11.17.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 11:17:18 -0700 (PDT) From: Mohamed Khalfella To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Justin Tee , Naresh Gottumukkala , Paul Ely , Hannes Reinecke , Chaitanya Kulkarni , James Smart , Randy Jennings , Mohamed Khalfella , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 18/18] nvme: let controller deletion wait out a fencing window Date: Fri, 18 Sep 2026 11:14:18 -0700 Message-ID: <20260918181614.3947933-19-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918181614.3947933-1-mkhalfella@purestorage.com> References: <20260918181614.3947933-1-mkhalfella@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" DELETING is not reachable from FENCING or FENCED, so during a fencing window nvme_delete_ctrl() fails with -EBUSY. Its callers assume deleting a live controller cannot fail: a sysfs disconnect is silently dropped after the delete_controller node is already gone, rdma device removal returns with the controller still holding resources on the outgoing device, and module unload leaks live controllers. Fencing is time-bounded and always ends in a state that allows deletion. Add nvme_delete_ctrl_wait(), which waits on ctrl->state_wq for the fencing window to end and retries, and use it in the tcp/rdma module exit paths and rdma device removal. Make nvme_delete_ctrl_sync() wait the same way so a sysfs disconnect during fencing is delayed instead of dropped. nvme-fc's remoteport unregister with dev_loss_tmo =3D=3D 0 keeps the non-waiting call since it runs under rport->lock; it does not need to wait, as dev_loss_end has already expired and the reconnect path deletes the controller once fencing completes. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/core.c | 41 ++++++++++++++++++++++++++++++++++++++-- drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/rdma.c | 4 ++-- drivers/nvme/host/tcp.c | 2 +- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index dc44e3af5f14..ca7f083702f5 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -271,6 +271,38 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_delete_ctrl); =20 +static bool nvme_ctrl_fencing(struct nvme_ctrl *ctrl) +{ + enum nvme_ctrl_state state =3D nvme_ctrl_state(ctrl); + + return state =3D=3D NVME_CTRL_FENCING || state =3D=3D NVME_CTRL_FENCED; +} + +static void nvme_wait_fencing_done(struct nvme_ctrl *ctrl) +{ + wait_event(ctrl->state_wq, !nvme_ctrl_fencing(ctrl)); +} + +/* + * Like nvme_delete_ctrl(), but waits for a fencing window to end + * instead of failing with -EBUSY. May sleep; callers that cannot + * sleep must use nvme_delete_ctrl() and handle the failure. + */ +int nvme_delete_ctrl_wait(struct nvme_ctrl *ctrl) +{ + int ret; + + might_sleep(); + + for (;;) { + ret =3D nvme_delete_ctrl(ctrl); + if (!ret || !nvme_ctrl_fencing(ctrl)) + return ret; + nvme_wait_fencing_done(ctrl); + } +} +EXPORT_SYMBOL_GPL(nvme_delete_ctrl_wait); + void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) { /* @@ -278,8 +310,13 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) * since ->delete_ctrl can free the controller. */ nvme_get_ctrl(ctrl); - if (nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING)) - nvme_do_delete_ctrl(ctrl); + while (!nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING)) { + if (!nvme_ctrl_fencing(ctrl)) + goto out_put; + nvme_wait_fencing_done(ctrl); + } + nvme_do_delete_ctrl(ctrl); +out_put: nvme_put_ctrl(ctrl); } =20 diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index bcecaaf06f7e..bf8c2bf91ad3 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -1026,6 +1026,7 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl); int nvme_reset_ctrl(struct nvme_ctrl *ctrl); int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl); int nvme_delete_ctrl(struct nvme_ctrl *ctrl); +int nvme_delete_ctrl_wait(struct nvme_ctrl *ctrl); void nvme_queue_scan(struct nvme_ctrl *ctrl); int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8= csi, void *log, size_t size, u64 offset); diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 8ff5aa312377..ce37e3eafeae 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -2483,7 +2483,7 @@ static void nvme_rdma_remove_one(struct ib_device *ib= _device, void *client_data) list_for_each_entry(ctrl, &nvme_rdma_ctrl_list, list) { if (ctrl->device->dev !=3D ib_device) continue; - nvme_delete_ctrl(&ctrl->ctrl); + nvme_delete_ctrl_wait(&ctrl->ctrl); } mutex_unlock(&nvme_rdma_ctrl_mutex); =20 @@ -2523,7 +2523,7 @@ static void __exit nvme_rdma_cleanup_module(void) =20 mutex_lock(&nvme_rdma_ctrl_mutex); list_for_each_entry(ctrl, &nvme_rdma_ctrl_list, list) - nvme_delete_ctrl(&ctrl->ctrl); + nvme_delete_ctrl_wait(&ctrl->ctrl); mutex_unlock(&nvme_rdma_ctrl_mutex); flush_workqueue(nvme_delete_wq); } diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 7b1d9e2cb00d..9331a3e0bd9a 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -3208,7 +3208,7 @@ static void __exit nvme_tcp_cleanup_module(void) =20 mutex_lock(&nvme_tcp_ctrl_mutex); list_for_each_entry(ctrl, &nvme_tcp_ctrl_list, list) - nvme_delete_ctrl(&ctrl->ctrl); + nvme_delete_ctrl_wait(&ctrl->ctrl); mutex_unlock(&nvme_tcp_ctrl_mutex); flush_workqueue(nvme_delete_wq); =20 --=20 2.55.0