From nobody Thu Sep 24 20:36:54 2026 Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.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 CEC1D471425 for ; Sun, 20 Sep 2026 18:30:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929019; cv=none; b=Mo5PgaURTH5zgd/uzuek1eT++u0kWsdpCPSG7qNr68OIke6DXtqr4xnL4NzAV3t1RsARicRjJTuamnbSO6uZtv9YTajt+7RBaEJ4QhgWDmRI1V7tEYG3oZIKUdffiWuwDoKpViIsDnlDUG/8YCd24PpD+8e7ta1+GD+hocFx+Ok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929019; c=relaxed/simple; bh=ts9kK/iCxfz8B6jDbz11N/MxkQs9h9VuTTCL0S0YsFs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=re0nG8xD5WLolQd+koh5EoPTtOf85pAJ1YnF9gJlsL7RDNt5BnDAnixSOZgKz+dFjQDOhj1E9ortNoilVPjpwdCvGLR1Lk2Z5FX8dp/szoOsyB99Ngn8kYUSlA/zqKgRMLIpcaLFkp7eJdKrJlbtNgxenuqU1BoaV3x3BsVanqk= 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=gWFmmtEs; arc=none smtp.client-ip=209.85.216.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="gWFmmtEs" Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-398b1e63c49so2431651a91.0 for ; Sun, 20 Sep 2026 11:30:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929017; x=1790533817; 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=gWFmmtEsVK2Ldf/zmaENb36BH6rx/OjijHr50EptxxuoLdkMqmc2uUHkrF8EelPLjr zsO61cJoYkqE1ru+KUYv81N83kpE+QXiKsrxR/3GnCpA+3uM4m/w+hmF7yRXnh/3921z l64k/HT6hOz6E+3QDKm7qDMA+gfpZsXiGTOknDNLoIEe8kbh0+sVYY2fiScGvRq2YYoc UZVs9ahZSA3Qe0goMBORIp6Oh35qg/dTPDQpFolpADiRksfOuzCD3NIuNkM/SrCmZK/Q 9GnML6dWhtQTDSmyQSSGQnNvkM6V4gvWxp/JcHSUB2ZjSYW8m/jU6uife43gZOvrG6WU xV7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929017; x=1790533817; 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=Ijvt3gkXFwkQBSCot6mU9f1HcRtDPQA1vEA/tvkDvK6G7lmNPetmudHcWr86MY3/s4 TlvnUgSD+BaaVJccebbK3fWnOqiqMrlTNxFT7yTm26D7VxRv19K3MNz/zI1Cx8EKbbXO vPAk8gkAXcjsEYhXY+qTkTFmdhAzHFtB8qoV1lPCjmBNiaCRVGc4C1aM3mIxsiMy8h70 B/+K0e0lC39fHCTX9Q1t4YPGiJ41N4SMmioqeQxTsBq2PT0k7aLCzv5kZ0XV6wC6Hy83 cz1t8Iq6lMACZZhJ8+6WL0n8S67RmviCfR2vCEBxNmX89xlEfmMhtqW7yajm/efIehOq XTiQ== X-Forwarded-Encrypted: i=1; AKwUvBxOJrb2V2iYbxp7ER67ta5lk5puUBb8ARwq1wngPq6KildeV/EpXWCOzcIr3Cvm/HdNNp1xiuhziZeaXaQ=@vger.kernel.org X-Gm-Message-State: AFuF++n8zuLUxxNuLGNhTWD/uqf9+vYWp2UK8wpb7ZUyhXzegC5kmHeP RuJsu9RWcPbbzIi90Z+D34AQhx00QwxDrJQOPrFkKqZctXjmB149zOQEj/DUmT6KgOA= X-Gm-Gg: AYBFou0wDp2Y6LZcpxlZhE4DeQBzykq3+SdwxjLb6jJdLs7wi6k2NfIc3rTaYmG4jaC jowGsIMcua/0My7k9aFgQAYve+/Czm1YobBJEpJ+pDjn+nyPeLWTPxepqzfpjVQCpXR3V9gWCMk Mwzkl8LyMdMR+xlS0+GKZp/w72xNdTs0YuKIWr7tgt1iBxy7QJOWUO0HYFOSiAedzAPqv0u+71c xpA2jNXFia5fJy8kAvEGcYEU76+YlaiuoC4vfHk8xf3W2QeTF8SQwLisz8Yr0GAfdVcP0Vsqwaq Yw0ITS1/0FtT4MD0F71mKDUGziNchLl6hAtZWQ4sYPTjhf2rsr8tbGBQjBUWHmYEejyfPZuHytP h47TfWdW44zS/YOlqw4KbjTDu80LlKkHvpG3O7nqiLiSL/9t4neaw2nwh1CSo4xaXuQgxu7hk5m 5tffCz8bKHs4Rj9Y8wlQhVga1iaJRC5Q75Pj3l4ZGUBZaeEtYVL8j5XmSh X-Received: by 2002:a17:90b:1cd0:b0:396:7c01:553f with SMTP id 98e67ed59e1d1-39e36106b85mr17159180a91.21.1789929016695; Sun, 20 Sep 2026 11:30:16 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30: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, Hannes Reinecke Subject: [PATCH v6 01/18] nvmet: Rapid Path Failure Recovery set controller identify fields Date: Sun, 20 Sep 2026 11:27:59 -0700 Message-ID: <20260920182936.2317916-2-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 26F36472080 for ; Sun, 20 Sep 2026 18:30:19 +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=1789929021; cv=none; b=ZnLnSwqD3GWIGBLqV8AYgZ+HqIa+km59YU0Amk/TW2gpclmcqp6qmnpg2pRzF7sqIh1hG8trARYR69t1Mr03c+yjOOf1L1hzlaMQYgnUrrDYNcxhLpE1zvpvdoGgjKVk0xu1LKW4MxiGvbxc9fYlZXY/W+toQWYwe1B5CS7DxNA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929021; c=relaxed/simple; bh=JP1DUGRnFpKenhUQXMkCfj/AYF5XyMKm7PlfqwvLN0s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D7Mv3phJ00qW4ynbethriUql85s45HzMVJosZiGqDxAc6W1UXaSSS7Val5SQ3pmOiTHtIxP9344YVQXD4mVlWY0q4Q8lGBXtvk7SGUCVX+HN7quXIIc4wqiLwBp8EXA5Wh4R967JO19hNGHuMM7ZiqivD9b/PFFPjuQOIrQvmz8= 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=bMbdSs4A; 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="bMbdSs4A" Received: by mail-pj2-f43.google.com with SMTP id 98e67ed59e1d1-396ccafb751so1875895a91.2 for ; Sun, 20 Sep 2026 11:30:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929018; x=1790533818; 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=bMbdSs4AnnVVZ+9DLN2Mp77VluYJCb9pqlw/DcBqroNLOBJOaMrAv70WTkFt2ChojA Jqb/9vOQFOPC35jvNVIp3SHpAc8IjsVGEhrsOtPlw2nlhD/ASv7YT92AiY48nCH+DIs/ l/RVBXZMbU6M2x87CmIXwT++ANOPpoH+5kRxcXbXcmWf7uUgiu/5mOpzJTv1MN+Kpd4o lksMcKo/wXWVId6oZJo+H15w1QvU9B+wgmATMMAhNjqv9r4WNi5JvOQ9bPs5Ta139npY sOO6c0Z8OqsFdyLKoao30GtiM5otvMVyujJpAcykOw8G/wbUaO/O5srCQdsTim0yS2uu aibw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929018; x=1790533818; 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=giFkAuNtkOtpgX0dnVvdw7gRvVzmBweHTlEcriXdQwJQGvQhpahlAw7TZaheXVGq/A SJKogRfuqUhHBItoPoWD0mNvTlELw2r6SdWMWzikJYOwuUwVeXNUiBlyKFyHG53CAsXN H3hcME3YTmS09gG7gdGq/gaFyJtpd52E4QfAhcc3mtFFHcaNvRPhOIzc3kf+GRVFWnFz gc37uIwxidnqH5OI9X09xpLvq6U688+F930nYJ60lUEzs6IYnELadhvVqpMZ5exivVmU +J0lw61hFNC1yGF+Bl2yCJ3dCdL1BdEdd503pjiuiBDCJ6Cc/n+txiU6AEmZlfTzv5MF SwkA== X-Forwarded-Encrypted: i=1; AKwUvBxvcZCvJmLLIV82LpuW0RfsIWXgIm910GB5NrM2GSIAwQrOGGLnVGH6AaJDS0C0Yr0jbaCJXeAB/SoDCFY=@vger.kernel.org X-Gm-Message-State: AFuF++k7XruXfqfNKnmEf+S/GKoxfCItEYHoUz0JpPlT+nTN69Bv+4V6 GFcH9reouCiX6bYU8jkxHQ2TzzCJdSqRUJkOTDHtJJYu5SuJ40nH9kI+iRnLwVl/hcg= X-Gm-Gg: AYBFou0PdRkzROaNlYvA8MXxQPCfSBq3b0I3it1U/eTxrvXFWD7hH/kPNFvRvEaL91W 4MYtDpJsC7yy/X8sr/Swby752mwE42iT7P3vMLNhUDXVlWAKC/Zjb+LSWhsPRMxELwZhTgMWXtQ Ypk5QDLW9+PMMPbPsDu2R++/Ls1fv73BoqlYWiwyZFhT0j5ixrzx5Quw0itUmufEPF/89hZVwh1 rz+TflUS32063FiLNXSL43W/gGygRlGlto/s9+4+d76858vbHwem4SG+CZmv04zg7J5Yh5rg4iC TYzLQivBDqZsL53WO4iZk384Kq4ykFMd7cF/tgnXqxBX36+buajiWV0Oc9JLXxMBdpteVzkZooA U5NaY6NU0VoBSsfaODBlSkiq5R+A8J6UOqSmHXUw4EmV0Ha38zICwcPaqgRb6agxphYW2EwhB2M jKtoDQNGMujdTBbZ8WBQ9BlEV8mwqJOKVCR5mlHMyfrAwOKEpjnsuM2WHB X-Received: by 2002:a17:90a:1050:b0:39e:6b01:f93c with SMTP id 98e67ed59e1d1-39e6b0213b1mr6419367a91.13.1789929018194; Sun, 20 Sep 2026 11:30:18 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30: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, Hannes Reinecke Subject: [PATCH v6 02/18] nvmet/debugfs: Export controller CIU and CIRN via debugfs Date: Sun, 20 Sep 2026 11:28:00 -0700 Message-ID: <20260920182936.2317916-3-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 AA3BF472531 for ; Sun, 20 Sep 2026 18:30:20 +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=1789929022; cv=none; b=BdtEMBj5eznCxsMsVW+GwL8I5BbXwD3Le4u800rOi0mozcg3sif62GdXY/zSEhbUpV/gpxTKY9LPMkjRfZDSm6vNmBRUTSrvNXpJBGzA2lNFCklQrNQEgfUKGLI1oQnMiQyYVZmg/V1y/pRjl+01dWNDvQ4tJ0cB+2hPPe/+KJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929022; c=relaxed/simple; bh=A6iYgIlcaX5RIGEv5Q40/b2/HIHglvq8j8qJxL7H+l0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nh5rDkuhx4I9ee7WVKJexbWhEFzIfwffwkz569dXGkLA2HmRxmHwyIiaTUu8FwkF9QvprXk/A2CId/8IK1eiq/aejJXckGtCTypB62cfB3OuPQ9P1vh6o7vGk5s6TQT+ZQEkC8e7Vr1Wr+wNAWVoQa52D48E0T1Jd1wtCjhViFs= 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=U7KKEXwL; 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="U7KKEXwL" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-398beb616f5so978449a91.1 for ; Sun, 20 Sep 2026 11:30:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929020; x=1790533820; 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=U7KKEXwLvhYyxaD0TELbdJxDdlvxKab7Vkh9dodYAX9+Jk6iYv+Zq3/36sF5qU2W23 IkprgWxNK8IrxbkUECt/N2lHFQ13G+wGifwu26eDFb06QhelxSjgyOOUX8VMIYqrWdbb l3UMHvq5X4q2/fY7C/VL5nOKYr09ybjSu+WSNzE0cRTkUEMbnWifq9v1zdDVJh5/WTLF l9CepNr9XchaORxEhzZdpVDZrTEh94GnPBh7L52inZdggaRtE7ZIUVCNUmajmezBrmyD JdpWJwAu5LfnlcAkRzwVZz0yNVMBtaHSsrlY+xyyf5Av9ibzfjBH6fWyMeJUvymAAjbV Bo9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929020; x=1790533820; 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=GgiuqdLS0jsqcYPPW/pgWzqei+im9VLdU7M/D0/7Ek0n5CJhKcQ0gZr4PlRo00fhiz uoyyjYg9cCn41FWoYnfizlseVzeV8Djt7DbJyWEGFkXBJ64Rs2HvK/e5OBHtfwgGKaS4 pigLDfD8Ihy+dh+BK2DJlEvBrBbBMPuGKZDdSFGL4hiWAohbFdNUD/qGNw9JewC3rnm6 q8z/u5HGyqvP3Kzr5qTjcFSnPvAwJDMrAIZlqCNm6PPW4VGeUmhFqcGy2ATWzfdVKle2 /bbanIRVlfBD9UPTKgQvQKOAu9KGoYIfSUmi0rr56BaLciZVSk1TLmifTgIwuJmzCdsd v2iQ== X-Forwarded-Encrypted: i=1; AKwUvBwGTEnj8SG44v4BrrYpAs6ZS00AahJX/7dsKOQ+vHQER+ngzycf057v068+dF1w2rfRk6FAg19es80Pv/I=@vger.kernel.org X-Gm-Message-State: AFuF++nfIA00xOJS2XDxIFa5F7lX4zA2XeJhtwMeLMbgVQHXa+So3rpz UPIFEa9n0yrEA4Ew1Ci89/VPoih8IaSGGkPe9Bv13+t5RJVfU84R2Wuzfw+oDb8qEOE= X-Gm-Gg: AYBFou0nOWT2Jz8ko3BTszupUR6f6dmpUhfr9BsAoENJHG4aMFK8SnrmzF7zYYA9LqB DrR2Wqq6S1hGcQyL4Ecs6o+jZBwbjkideJNIqsn/as97/I2QwtLe1UXuXbVEW1KZwj1gIPPG0cx ODWeoFqQjwJaRgE9Mf5f/IhsaWOSU91KufXjT+ptA6xEtKvMBNEGMR0WlMM8pNP4GueaZiaOTEX loKkfDArRmeEbdoRd/8nw9tfn0bf5q19NLlG1mxaO0GsgrIaGbCTaMYsBeEPZ7eQShBQmtI5k1f F2CXY/uzn+d5EX9xSpqvuYvVj6Y0oouvFGtVKU39KJ7v7mHc69fYqsGDUlpBlH3yZL6LQkU/W6K aM4W5N3n61rfqFWPvqFI7kXms2IF9+zQRwAmHWbAvE49v9PWjKZXPpDnaiD+2Ff2zbVkgEGjfjA K6a9DjagkIdd8VDWZX7I7j+cY2X2z4/7ACQ6p9IDMXE9bFItzkbXhuxPoX X-Received: by 2002:a17:90b:51c1:b0:39e:6c68:fd92 with SMTP id 98e67ed59e1d1-39e6c68fee8mr4979263a91.39.1789929019742; Sun, 20 Sep 2026 11:30:19 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:19 -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 v6 03/18] nvmet: Implement CCR nvme command Date: Sun, 20 Sep 2026 11:28:01 -0700 Message-ID: <20260920182936.2317916-4-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 4EB5B472F76 for ; Sun, 20 Sep 2026 18:30:22 +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=1789929025; cv=none; b=BpalB+7abpZCFH9L4/V10mt7aGLWYX+0vGBwUJTFaiYDHYP34pWNZRJs3efH0oNncNtSmn9YavWRZKn0QsBvecG7ZEJEslunuCTx91XEZdi79omDQ5F0ttPsKE5rRNEKx6UOFoRAJA55/MMk6/tOmAIZ2bBkpiL+qwX3sIgKQX4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929025; c=relaxed/simple; bh=VQDHW9FxpODr/6qNaLXLya3/nUiKniaCJvNe7qJ4yBA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EMaEJZgQKX3NNNJECpVD9KJCQqr5S/QCrPWOFXlyxzbb1ziOorjnol9FuDIks02LTMUNkoxswoLAMQTaoV+wv+2HJCRMaNde5HgV0yiBMJ6lQ16EvyJlg83HM2fy9Chvj/xmGgDP4BocHfOY3f+UYdesRXqGEf1QsHeT/RLhyB0= 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=BfPiJq3k; 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="BfPiJq3k" Received: by mail-pz2-f42.google.com with SMTP id 41be03b00d2f7-cc433d52421so1238399a12.3 for ; Sun, 20 Sep 2026 11:30:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929021; x=1790533821; 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=BfPiJq3kXxH+z+4swL+x91YJsV9G6meHg2FaRcuDsjbH2PuX6bPiJC75DglAdr0TiF N0ZQ6d4XAjLLRYZBmv6uI7eaIs+W2B0Yt5WUq+gzEVkJeGvJXXr82uemvsiBcqn00LeG p01nV//tehqD24q8R+G5Py4txxuVAUJqREjlJektdRmEZwq2wVTpFREl0WwiKvW9NR9o Jjvi/DNWokR5uRiyKLK9P5ylZcVDd/5Q+Ru48ANiub7WCiqQr2ey71CaXB+4kP0SeLXN Y0h94w1aOfDpCm5VDG5p+6lzEhrny77RU/9Oq4H+bm8+Gw8WiyBNaFJXEZCY7fP+RTvT MD3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929021; x=1790533821; 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=PmxWNhkNelAQcC/WlUfvp9AmKT3ngqDcVeMrt/ynmaCU/WzW3H4E6NmO49Hz/SEBKU QsG7kXLEEJfVkr62io+3zVX5ZJZ744/Swse8g8o5tnpkXpEWYODrLsOyUivWpOfMv8U9 S87Gw2o73weyxDHFN9MEaVCHzpy78zmROboGhWm+XgElCPxoXn7tjXys6+XIt7lKw8j/ UkOXLHjdkvJTbnMCbXSZXwugtQIqK/7lhuR1V8O/UCuKqnxJvavEZA0VUvqBbtJzOLzF YWv85/+yYkyMYpgs4fgboIeENYm/fs5HJ/AIpuZW743AP7sMLjz0SjYHKMKKDKooJE90 eR/g== X-Forwarded-Encrypted: i=1; AKwUvBwt+N8W1p2pv6hnB0j2JX+Ppze+vOxQ5B19kKfY5dMCVR1IbvYrcmphK+zaFYe+iZ83cDxCTYKeAew94Eg=@vger.kernel.org X-Gm-Message-State: AFuF++lLUKszSGDPo9ehWnpW9dvVsb68Yv37axZbnkx21Mzc352LfbFU VYK8v4dq3hrvdRFkhQk8VWFX0GJA0iTnRfz7VaCGfZr4PbvGcjvKMHwRigMxrbePCy8= X-Gm-Gg: AYBFou0Fm6mGtO4mCK87fMTVSNafFZJ+ektdAec/x56kIXEmwFxdPhnFMYm6vZq1R39 Z2b1JCLvAj+1JQfrflwKp5byfohc1egvuMAcv7tmiz33miookXMGRhbAJr/KKFP/ZgvBKxMjffi oUgUGCPV5ZKwHzZLXaz/aanZfqxefyPdHB/IPQ0yhhzofAgRoGjkgmeSMZG05gdUxzQdNbxN2px JDT/IInKvpBxo9hzgOfLUACnbTqZi1KFxZTrF/873+6j90ZIiMdG79Rr7daAQP7zvwmISoLbH/W hk5p5D0QBVNwo8gTNGxV1IMDMFYURH81eWYF/1/D+fQFPVdSgxBOmnw8njXDRWp/p7RnEFwt3l4 q9ndTsvcGlwG4oJOLLT5R6zIunUE/RE4doGO6JhGRCWfFg2ixQVbWbcuX/m+EiiaNmc5P4wKYWR yyBbGC7OKLox9WzeDmH9EpsaJogtoy0xQBtY9Y+LTCPfh0yBqncCAgte//wA== X-Received: by 2002:a05:6a21:648b:b0:3bf:b84c:2984 with SMTP id adf61e73a8af0-3dd8c37d00emr15026114637.11.1789929021398; Sun, 20 Sep 2026 11:30:21 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:20 -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 v6 04/18] nvmet: Implement CCR logpage Date: Sun, 20 Sep 2026 11:28:02 -0700 Message-ID: <20260920182936.2317916-5-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 9EE94471425 for ; Sun, 20 Sep 2026 18:30:23 +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=1789929025; cv=none; b=ZSjkHnY0BmpMq0HPwngAs+EAEADqREIN9P5rvhskIRbsHEBaSX/N9/oH4bhVl29DRM0uShO2CSYkzFCpiiX76fTcwZAcDsf2SJR+ruOzIsZvL82RJAh7iiypE8FmKb49xvsKxu352SUebuZFXFH2r/C7zpg2t7o3erXu0FU8tSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929025; c=relaxed/simple; bh=RIVoOlmqZFMJOUfhjvyFuQR9GESlJzJLW8eoZZQuGKo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=byPqCjdl9jWX+aXkAoeW8mx8QOVVN89zEhcWCQhY0g3VklzY8rutvFBEhe9ee+DvhEG2iI+qytHThjZuIaYQfUjDCGZENelc3ywJucfUciMpSVywPIYQxcD9ua6mAa1nAmXp2rEG2T4GuvyjxKisqgoZdi3Q8KNlCPYDHKvJbWc= 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=YQ+NdpuU; 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="YQ+NdpuU" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea50db3so1295322a12.1 for ; Sun, 20 Sep 2026 11:30:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929023; x=1790533823; 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=YQ+NdpuUIk9/7P7qEFmdPsi6r/+oQ/iCWv6ABPfKfIoqFVHvSTHF5u/Ssh1+1rWgJD v7ieEUqr5Mrw5wox55CB0ESBWZHGyJ6XbuWg7/zAsHZ+4p/1ay/AHf5l9ZXsnWbJnv9q neGGx8YAxbg05FPCAa8i/oPzU/vqe4QQA5qg8sTr1vcej691U/LaFQHehFMZclsIU7sV mp2fg9ORgDEGvxg1H5jvbNfzn2KPUIZJMOZKGxb3WMJGeS3NNLKj4gAQw160XlM5bpk3 WkbO+FnQed0qxuHD2LvIqUcsVnh2l+5Wm6W74H4ZkMDOjpD0x2Tz4A4VCuFTWIWjoYGF rfuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929023; x=1790533823; 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=DVNMQFcQ5ta0lX96a1EtJtsiVRnbBzUFjtB0i+eQaj0Nfulqy27wnd4Q5WQ2ZMPkjZ sc9qJwTS6chzqr8EhcjP6djbWiGeqDTPy7Xfjj11dI8XITpqRdgVZLmiLEBIH7CmRq/S JA/ybEXyRzd8et2gBmzSu+G+KyVaDy0g9OfT6tvItWBn8AODqUIp7wDay8VQQg4j3XNm DOlEsGR0blTbVkkA3a8Fk2IGaFfT+lEYMBWA6hVrjIYAbFi+eIEuU+89OB751KWUwSVs E0Qh+0S8ySWHIBni9RfygpcnbSDlAdEp4XROmTGcinWuUg93OOp3y/tEPY5KUxWvdWd+ l5Gw== X-Forwarded-Encrypted: i=1; AKwUvBxaBIXENjzYlNCgpP0GAL1d2CWYPQ147QnzSO88XEBNNGWnufl95Xla8PqXIcn2rsbvoIvuNYqwezG6hgk=@vger.kernel.org X-Gm-Message-State: AFuF++l27QBgQISWoRz4fLwn1mfKv/v79+37Z4wpAjd6Cwv4vmzrQOBN u1ZVzIAZftT+6PA4O0X7fz7uSAdyiHnSESenbkdaP4/GA8/TG5xatJauRcypo1+j4Ac= X-Gm-Gg: AYBFou1MKJPE4xJCVqJ5trGEN9QxXtAIXPMPMP6/rNUKy46wQvDoKYhCyAXh5jyGMeq rFxwu5NcUb+J8PnRCNgThi2UAx9w7fxcbKkJl6XXyGUQ6mGiNGTVzGFHvWuhDKXihIQyywwEoEL 2auIIMOT8baIioF3D8z8coJyg3XaNymrqWC3xEDlZsWNwha6gNApCERk9gDi7DueBmLhHjKqzHt zaceTFNt/6GbTn2XFw9QmpDCewkt03jE3o8rEqSOBpRbaMXtNeQBTSESUre8seIs/oPUZmeOgLg kUXgr2jyu6kUUvPWQrNAn13taarmeo9EAjvETi2iROIKO7BAaf9bNHpWjGp4ofcHeO+Vd2IOYJS SSeoHZBsArysv4Kixyu+kF9OPWvRfBKV8t6yRE08EdEJNPx9YvNd+ug6ZIRrMpPQbt7umOyW/A6 q0BAbAo1Cx5ZnZdIV+e9g9H3VlMfyCOMK7SEjtLesy7uTAHk2xpjFOu5gz X-Received: by 2002:a17:90b:1e42:b0:3a0:345a:3620 with SMTP id 98e67ed59e1d1-3a0345a48a4mr3412173a91.45.1789929022908; Sun, 20 Sep 2026 11:30:22 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:22 -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 v6 05/18] nvmet: Send an AEN on CCR completion Date: Sun, 20 Sep 2026 11:28:03 -0700 Message-ID: <20260920182936.2317916-6-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 39A4547277C for ; Sun, 20 Sep 2026 18:30:25 +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=1789929033; cv=none; b=YLTG/ZelYafMGwzzaeEPs5agld5zuqdVkS/aC/W966Zzp8HRBfUpn7oF8cz1j0+ejnDahqZT0I23XAtYTyzSAz3sUhnN9nWF44txYFANstYIm66ZpovRrJFvcZZ/6IPbiC/AZJJizqacb0pmRc9YGQtZXlkRPLFIgJbQIaNfNsQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929033; c=relaxed/simple; bh=AnpJGEP0W1AN/GcBwLnNfGbUIBoDF6SMZ0PKVmp8Mgc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J2UnH1o6w5vj/DZvpBlOr5RkqyUXatBfEW92MsOVCLAyUWCgGHbJE9L8YoDxjCY4JHah6XXiHyvictT+obPZMiqngtKulebOpKf73clNrcJ+V6UxL3kM2/gWY7zTDCRlPpLplqWaleHBv7lyR5c+tPZJCcRFn2urKQ4N4JWZ51Y= 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=XY2KLTQB; 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="XY2KLTQB" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea34ef4so2617043a12.3 for ; Sun, 20 Sep 2026 11:30:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929024; x=1790533824; 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=XY2KLTQB9lJ6N77lVRgZZ8YQaaDGPNWyZV4qTEF3g+idh6BUmhRgxDnMCW2a2YTzVL wU1Z6vPjTPbAQ55PGxBRQ781P7hH0667cbrcwgLzBO2h0h0Aijv40lcXpnwJof6NVAXM +GoEMZhGvUqVutv1eMrZLzesweCL8oSFuSd4tLTDoL9zsP1+240flUajjyURBlxnsILf VOlq2plc5mEPNPAMIZnYoa8Y4cJOtr7DN7jp9zW1eQ6Bwj6vx2XSTNXhmKFyNqNInl9d EopBJzvpecIV4n2o5iCgNx0E+tFQq0EBmORpWFfhBYVzoto8oYhdOnVrDJ9OeOREmCgO V54Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929024; x=1790533824; 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=umg2c3OVDtcnG6t+HxV1pMGwP2nQIWJ9FOHOM3fAn9B+hx4cJKzeUb22HdPyolIv1u RwN5aIKv6FneHJ2FlSk5FCcfOhG92kIpN1cagbiUy4i+hUwAo+sZGDEcxhWU1Ep1F/Eq 5Wk+lNkljM+iXqV/NZgFqSa6L3Dn3/GFxamxkxtCTiS2CjR+BTjrvE0vXcxE8q8d7GRw OQ1xefAIWAjm6saazuIoNEIkgAcbjYHMxs93mp0c5idzC/77La2mBGWPeYft25qThlAu qtJGDUOaV9/AFcGszXj0HRSUZlGBP7lJri7x9NSSse7tpP9Avi46a8HobySGe0mkiMBx qeig== X-Forwarded-Encrypted: i=1; AKwUvBx4jMZ/jyabbcHiwzydYz/hqvsznMiAyfpUJ0ljMKQIxSJ4nV+5dA0gh+ty3xrM5XP0bvn5qsxrVV1CULs=@vger.kernel.org X-Gm-Message-State: AFuF++nU0BOtWNZebPVbVt/mty7FH4tV4y/Vk/WTOwuW44DMPxB/NPSw AawIuYKQGNYsECIl6PGpiNn2q2QqdwQ62uRzPZCk4Ll0k+fRNm4qlBI+6zKDs842GLs= X-Gm-Gg: AYBFou3FGrG/7KO+okw1nXxiFThUukaJeK6yaPEJnnF7mnqIqncR/C2RUm0f5mt7vG/ XjEPFcKhnu/EyxScvjSr28EKxxC073gswEIynHs6vqPmDgxwJS2egY7Njc1cFlbxnubUUFPXqUR Gn3coF2mvaZhjxqNgBepXs4kUCYMyYwEJTgi2RYx2+TnyBZ9LI1dMVv5fQdorsW4dDAgm6FeL4W GTLfinj9aklzTM0wBHvDOac6EWNf243GWWUvLQ22P9e7ZMi0VSCXILEFzIB6lleoJGMcmVqtY6v jH5VWotfjhq6NDztwRm2ymzL3jn4xZ0dYpAEwCOtu7001Egihc3wwuAQdGiWbMNuO+IoveGxKca uWfmTPrkSNjRgMmwNsWaXG7ZMYrcyNFsv/Fl1Y7i2EoxPPDIbYI43BIEt2xY71svs52JAmPHB+b aN09PaClJ/FSj6XL3cSKzA/t8f/Q3RA8LifDh2BSpnsJ+21UZ+DIkFE4sEzOPz9eDyRQA= X-Received: by 2002:a05:6a20:9e4a:b0:3da:e1b5:2baa with SMTP id adf61e73a8af0-3dd8c3f80bcmr14827589637.2.1789929024412; Sun, 20 Sep 2026 11:30:24 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:23 -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 v6 06/18] nvme: Rapid Path Failure Recovery read controller identify fields Date: Sun, 20 Sep 2026 11:28:04 -0700 Message-ID: <20260920182936.2317916-7-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 2026 Received: from mail-pz2-f41.google.com (mail-pz2-f41.google.com [74.125.228.41]) (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 D1C43296BBC for ; Sun, 20 Sep 2026 18:30:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929036; cv=none; b=CN0FuKjJ2KqIg57UBirlXHcHHM3KGXDymU/kdGKM4gO3BSxkaByEzbZ0/GQn8MA5IKCqOIK5Zyc24EVZRGoLsAiwL++/THw+BrzcbLoiwRyERtxva9YzJcUDMffPOrq6Q+DQBVaT0Sdut17cOY+6VMVQ39GjT3/e6/UILNlpcF4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929036; c=relaxed/simple; bh=AcE9zrysBOb+NlUMMSohIv2aatVf8yMIkkVyal8cEMQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hk63RQpEGrb0sEDsl4kOgm3Idyf1Sz/+eIgcDmwD7mL4yIZ30MQD4LjTj+ipp/8z8JlvjplsPQrnuhywKf4fEqrBd94Z1leHcl0y/t9SFH30fxAOP1V88r8jlnItoZY4qVoisuK65QvdFnqmdc29BXC91CimP9fcgyTcgxwRnd0= 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=TT/+BJp5; arc=none smtp.client-ip=74.125.228.41 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="TT/+BJp5" Received: by mail-pz2-f41.google.com with SMTP id d2e1a72fcca58-86212a185dcso2712412b3a.1 for ; Sun, 20 Sep 2026 11:30:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929026; x=1790533826; 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=TT/+BJp5iCrkIpRb5h1f64X9WK1XCbc1xfYzXRR8gy+tBQvL+iwWxqPZZ7EFasyDto GpuPgCl+TYrJRJSR0GCp56o9LwC4vrb0KEzSLqx/nYZmZBMNtmgPGKBHWKOhPwogtEJW IhUZbQWHSMOKbjM04cUPktoJSZ+vvxzAndg46ZAwHwMGWvfryGgPJPtvoyiI6l3Ipvne bWX4KYf0dy2FL601+WvUG9lbYK6DPXvREQ6H3uJ6flxNYXsQkzSNYST6OfeTjwkhOiLb s9ZFSi3PY/JRfNgqYVxNdHYGkK6LvJNa8y1tsPXuHYQ0+UiAsrOYRADyJz8Jjrm/BiDF Fkag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929026; x=1790533826; 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=V3TqaNc4LLjhcpMQU3hVKvcW+kFbilhG+D3noG4tIGGCTYQfFZwKZ66POEBZd47E2v HHjzxt76smFLWp0wegZwGpKm0YogS0lOBCEQzmPt1wPqaZzfZN/aMnVsyFEtqXLJU7f4 SSb/M2FIdn0IC/MN8fryBukdKb0nTsYJFJ4kkqKRi8gdNJwoFYYwRcXrLVyP/nNFbFlC wSOvHJZcmZp+wyhCPfkhoLzuwdiGqnJK7P5q4FtaFqjqGMLgnsCLdKgsEAM1FNDpuJRj /Qu9jy33mICMuPzPjietpozzVTG8Q1RpLOdDvcfa8bGmqKC1pQ7LmZcB8+6yxQIO75S0 0uzw== X-Forwarded-Encrypted: i=1; AKwUvByYgZb+IaqUsXeYcqdx60kIttAVFROLx6dyUXh8JhKUcu4o1C8bWRKg23fnMYoH5m3PWrBt2NKlvfnbiEs=@vger.kernel.org X-Gm-Message-State: AFuF++l8U1R/p31JMY/f87e0u93a0xqwopZdyVNyUdN1OMKY8Ein5TXK ueQmSCcrx7X4G9O9YJR9qKB1Wy+QrojjLAOS88M5+hQwQG4Wy58vtJqexNONgjImC8A= X-Gm-Gg: AYBFou1SBlVeZ9u8JeKrZWEE1xwTPHYNXeLmzK09Vy2yL7xDQX6XkjZP1WDoYuuHMFq YlRsWGLil3wNAoPTQZXqG4JzOYowkfHOspPnLx2kza8ArUAOt2uB1nJItFeuIJQ8wNHI92n+ZTV ANWRk6k9FYivQKUSaQaM/9xixuG7sAqzmjSwBGUNM+R8OlJx/pZ9Z5eoQpV5pPOYBTQIFr6/iKc GzMbeZ0mo5Fo7jqRfWGxQMykZ8fQPErIMwNdlgXVTq2+rW3ZbUxSYHKoDXxnK8DBR4jyQ/3LA2n +zRLoFw6hNHO4wammL5i9PYolfoVDyzHCU8PoI/3o3RNB7OccTqC7pTErcBM5O8UbnCkCCBraK7 yRSb9qASPBn1rIkUbFx3RtQaHX028cN3aMUKDQ6Tgar/LmZPDtfdH/NDfSQCSNq9ay8FfPTTgl2 4PA7zgDPj+Og2+MBRBWq+HaTFSbCyxuKj9m3Za2cPuKFEBLlZbV3gkXMT9 X-Received: by 2002:a05:6a21:7795:b0:3dd:a00a:1713 with SMTP id adf61e73a8af0-3dda00a3046mr6833488637.46.1789929025982; Sun, 20 Sep 2026 11:30:25 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:25 -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 v6 07/18] nvme: Introduce FENCING and FENCED controller states Date: Sun, 20 Sep 2026 11:28:05 -0700 Message-ID: <20260920182936.2317916-8-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 B2433472068 for ; Sun, 20 Sep 2026 18:30:28 +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=1789929031; cv=none; b=C9cNdJHalZ5m7BBSW9OnfOGnHrAINH0mGNk1mL080A8TfiNz5p6FIzBC7Y5AGqK2nDxY9Q0+AlCpBbZ5RCdRzw343eY4sGcs3GXDPXJaV5BI/OKKAthFXJbMdedh8EYaFh4aQFb/Re3pQLuCvor+/7pO213fKwOKweZnG6ND0Pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929031; c=relaxed/simple; bh=S2jDwvz0aywYqBJc3t2WcBsmk3CulC2TUlkQHjrBu44=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cEtvYKxhuQLc/LopmOThReVpQqf3jpqf0nnyZPXeemygJ+hEmJPXgd6Pji13PN+kMZmgAeI+LvY1iCUk79LOstiChTaFuyPkDEW5I+bNqkYjzj3jgnyrvsNyarQHV0zJeyMXmygZEiNj1Ug1ihxRNBHxpZmi/vJAtGXo4QqJ5XI= 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=dU6h7/cf; 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="dU6h7/cf" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-39dbdfaef3cso1989187a91.1 for ; Sun, 20 Sep 2026 11:30:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929028; x=1790533828; 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=dU6h7/cf6GI05e9ebTtK5AqlkBw71O8kqantZ27uQ7fSfHE1yLCeV/YtSfp18WI2Tp 18msGydYt0+/Z49HsmS1+fJQInpirNJlllQEciPzZTurvZ2wjcnVvQMYpB+2emQxZujf /m9089460+7LRJD8+WIqcea197ohvCCuqNvpGYj5VdvRAbO+01Mrq8VlthjL0oyRePu0 SGoqdaaIQJCNwMie1qVc8cjw6EAStyoaj+LhJhHzTpuBlpchcKb6v9K2KbyGXJKO3Iy8 mhSKr7GiHScjLXcIjDdO/Wggq74XKaRylAzP1AJhglQX3ta8PaGeove8PC9kFD1canVq CYcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929028; x=1790533828; 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=muJEZ8WQjZMa4EDA3sCg+zOZFJcuc+AkkwLKth2dJq4VokzE0QlBSGWOq4Y7PMmzMr ViwX6WpdDVG38DcI/WGdCl3ZDO6rDHGcOhmcXPhFDlfzCYRXlTobfQ2KPKx8pjUJNF3Z /fWknwJ8H5Ogwd78wpVgbKcH4rnrRhcfVBw8AfQEtHdhzqBLYZSrJcLjrRVrgM4JBQmo 6byuDI3ZCwDY6Dqg1B/QvGSpEiF1CTPI7EmBb645u/Pj9oqydFb6LZgJwnSGdxCF3u1b BeyVfehfyj7QMJmpmJtKmvDovvFf7ZXmn1NsSbs7u/5HksKIIdhjecEtTWE3zARFQ8jL jYew== X-Forwarded-Encrypted: i=1; AKwUvBweny6a/hjf3Ovmk0LmoLmd2MpG190XttE8xzBuOGd8lXKuvbTJAbI77CNAJJq6xMgFWSNtk9Gih780Fac=@vger.kernel.org X-Gm-Message-State: AFuF++m93OqithFvkHl8vbANRDn6Wur/Rl08CTI9hWai9zEDy8e1ll+o HLXzQRp+lETExkmU7Y7ZGmEvU7xIwwGjcxcxphf7inMUQGLHSBrdcpdH6ir8VRFajzc= X-Gm-Gg: AYBFou22kxOOfdSMtvUH66sq+MD+upyZkBf4phlXrTSBo2+RATV3S1cgzz3Ojes966E 34R3ktIUDhladTc13q2tjJoNEZjQstfGvhSQOTJYFMMH3QP6JLp8AfXaLBG5TzEzz+aUdRrSg6A 5msJCJeLz7aBXIRMPIcq3U8yQSxib5CgEO4x84+C316yqVTmZmW4IqTqNg0hOBfI6NBYdHiiTg1 a3HMLu8hNrxBONLi/2UUTWtRfb6FT7BV6O15L64oyulp6b16FJHpstm3v5jC7UNolTjROoFAEf3 75BLFYlakz0RuVWu/z3NvEc0jf05mXsz2ZcE+sZuxuhPPHfKgMBs26On92fObHn0d9lOGQW6qIE peuRx9cJNSqfi7HmgsU/6kTnC7mPv593JeBvX154ZoitbFiCDxXkCiiqoo7P6iteEpWcgfPHO1c fhZ0wcj6ofZzBXDKNCYK625dYYTW8nPbyVbFqTPLfRxHyirFq5r2n38+eA X-Received: by 2002:a17:90a:2ca7:b0:39e:6a7f:eef1 with SMTP id 98e67ed59e1d1-39e6a7ff07emr6228368a91.22.1789929027333; Sun, 20 Sep 2026 11:30:27 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:26 -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 v6 08/18] nvme: Implement cross-controller reset recovery Date: Sun, 20 Sep 2026 11:28:06 -0700 Message-ID: <20260920182936.2317916-9-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 --- 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 20:36:54 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 92D083CA4A9 for ; Sun, 20 Sep 2026 18:30:29 +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=1789929031; cv=none; b=UnMrfVeKQIWE320vPwzOtWnmTJzQdFJvfypnpm7EzNHDJRenPw5LiahJzWNaPJZHZPjX1jwvbGF4JEMII2+RzuMiW7JkjiByneKzilKUCqKV1t55N1/+qBJo6XaRKj861p/gsUKUD7DeAemp+aW8WxDopF+0dX7wkuyJc9nnoMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929031; c=relaxed/simple; bh=2stUjESmFaR5coRGRUUfSmg/ht71Le2TPTcOeb0WB+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RIYLtsdw7FkYrtt4rPtPCzufL3SZQsV61wDYxUdgQQJ68p7X61+BmfJBVpBkhsDcsuwvWjaZIDP/v+/F8pC54YEExhiADkFg2S74pYoIqxgarvrAJv1e6J9ZbFlOjiC52rk0mdrZadQ6illy7OYpaV2aTPGzB8XQ1tKATn2RKU0= 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=QJmWwwMS; 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="QJmWwwMS" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc4aa0f1a94so1565614a12.2 for ; Sun, 20 Sep 2026 11:30:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929029; x=1790533829; 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=QJmWwwMSb6ZFGvdnWbu3Uw2W4UXwe1shEu+w/n7ZDY68IksTYBBIoX1GAa4Qr0dApd PR4SEnNhQuxcp22jjnEPZOQSMID14ZmCKgsIfAqJsDamC3RZzJhjy+TOg6UbtvC4yVAe X3O69foiD3FVTc9L8P443kA0kNFFWFKDaB9+tNueDAmiFfTy/bQLIyFWTyKRd4z/Iujx iBW283LjayGIV2P6h9TH9baFp6MVDclznbz86oHr5yROShBCj5oay2LnYKFziJaxUASo FiwdzwB353L4t4IM4N1AJW8jpdWPv3egC80HmMiKcDKEnvx4KYn0f7d8KWbulOcWVZ0J HEVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929029; x=1790533829; 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=NLOOP5B1xq2AwJ81NAhAO4zCCvqbsgEu0LW4isybCMVoQq2XqjlSzHyYc1gzMK+RtL mZR7ZT8JkxbbNlvrGEsaO7vWINh/7RrmHBPph0aS25KIM63yNVCOVSxh24XbonSMZG0z CunsOiB//eR3WZPEpDTcO7sTjcc565ZNfnF1ZOfg8erwAQNG7dn6FivDCYV2V1/EelfM XHRmlArw/cid/b825pNPYY1+U7VwcyBN98MrWW7W7om98Ea/bhNdIuFyQ5LnLdE5KzJU JuJhwVNTzZQo7LFDI8361UhI2Bf5CibSCcDysP7t/d/ILQQbokYCLiwKM8eZghItIFOW vf9Q== X-Forwarded-Encrypted: i=1; AKwUvBxVgY2zS1Aj4Zph49DJt8Z7DQ5iHc/F0/02cL/teEwkAwQ9fCuYzgXnhVWLzkxYHgfd5kG8Sw+vdaf5JBM=@vger.kernel.org X-Gm-Message-State: AFuF++nSksCukk35pblmTYuN3SmZa0Bv16xJDntcyceG0eIRYLO1r6M5 VQLw4l82UfmKLL8A3PUZHv/1nXALsvGYFydz+eams0FTxIwSsHM++H+7T2J8r1u0V9E= X-Gm-Gg: AYBFou39PVJLHLMitLiA97jRt4H4orqtJVwRuRXAyw1M+PmUFRKxnYb6dR3xipXvcIm NE9lza9aC7xz3rjbyA0gTNvdxqtYgnAA79043zlnNgf+ob3YzSdBlc1++lyidmFpWgSxhXLFDST 5v7mV72xru8Gzd+xHxh7Nw+UrjoDadbVMHzyvdTxFtsk9SDJ+YDNsZnUjV+xnEtAy8K1KUhfU0K CWvqs6M6KisP5ZT9fBLCGXnsY5ndGVBHoGF0FW0dNOtV/ODDqh5JMrq9yOB3FvnChjctSPFUscB clpMEx7Wig/Fnbi7ntDIykDPEO+vDkT+t+t9X0VLNL79dka1G9VJxxs6ZhhTaULxOmKqQyBm3Qb Dx68sxXIP+jsnUFYOxhqvDzqVfk1iDLXO60aWdiPbY3MHGdY+5NNMpgzu1laDwPCbkQUryXR3Jn ym3mTN7dIqRPRPu2yr5XXA6ZfV53PME6t071XHeCqyOlv1/HiQf2zsooq4 X-Received: by 2002:a17:90b:57e8:b0:39e:4c7f:8b19 with SMTP id 98e67ed59e1d1-39e54d458b7mr14289543a91.30.1789929028929; Sun, 20 Sep 2026 11:30:28 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:28 -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 v6 09/18] nvme: Implement cross-controller reset completion Date: Sun, 20 Sep 2026 11:28:07 -0700 Message-ID: <20260920182936.2317916-10-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 5E417472075 for ; Sun, 20 Sep 2026 18:30:32 +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=1789929036; cv=none; b=qkLNKw+zrxLO3xngufWgDv2jkZjUtARjz+5X9sMOUBJm7tBJwtEYuABvwDMt2lW5wJdP/xXxObUY6wA6Ug6kD2hfjI9Ooft2TlbjO7ZmVxDb3VA47tSVdh/BoqeffPD9qaG57z7JCbqlol+LsZ8BC0oCVu+cHi/uJDk/nBfBsxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929036; c=relaxed/simple; bh=HFUI+vwDH7eJ577FDlmpoi8q2nXZKzYpl023jQ7aoks=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FMilpNnHl/ltFSF76T6EPrd8OTo8UOKorujS652+MO9mu3AzgfPYkUiRliDAY5vZ6njAQj6SnJinjhocpud0J8ZkCAK3tBJ4RVXtkibIXpMNip3mKrhpqqSagKZE3yr29KTmKJDtlcqkh2YfruhycDdnoM9YOw8tbv2tAhZYUmI= 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=EKwAw2mi; 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="EKwAw2mi" Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-396ccd5cf02so1598518a91.3 for ; Sun, 20 Sep 2026 11:30:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929031; x=1790533831; 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=EKwAw2miYi5aZdvNMg1NX4/mBbGqr5Vm7oR5BA6qt+PcIQeyRx3lHbXmZDcazFyqn/ 47nlXQLsTTmhulq5ZNv5ShcLzi4h5wTTZ9hfBaeickJwFPNsy/5cUpdTYOlsZEXTZfqu srAtdd9Ojwm3AEG01QrFFcWyGpgrHeUAtj1Sm7FKHlSoxDnx/Kqib5qUu5gIqOQyHoZj J/z36b/VSy6h3nUGCqGi9ewmvEipHTMDvpXVTUr4Uou0jiMQ51gSxpfx5zwG17afPrIx +bphu66WwueaqBgGifzdg/hzB01xGh5zI/V41Vx4S/173OolRSwBbMY8ZeIJEnUYQehc IX+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929031; x=1790533831; 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=GHVWakc1jQfYOVFRPcYhXUmfyJLN/SDJmw46SL6Kb9Ac9OCHSVY3uo5LJO6fMSowIn Ms62Udn2B8H3QDWPPPceBLh+gGYBeQ6SSA5gpn9G2hXqXSi/j6pj5A64g/PlYHtvYOc/ t/lm57m6NCHzvkOMaz/aenff6wlQiAH5DUYqiOzbgCT/PG0z4C8OYjQYLH8hQLPwm0D/ HpTQKeLHKt2/nGWZpjZIm9c5b7ZSpzcNGPXcFf3UJTEK1wlxUj5qcJPwsiQ684s4pNTk Wfq0X5f4CfbnXMPKXkLu1rglbSXIHytQwZZbMfTvgTeoLveowVxffiF/1Z/H//OE1K48 t3QA== X-Forwarded-Encrypted: i=1; AKwUvByveV6ZrWxSE4Ndnq6gLrIv/qsGJE23hiUHmuuWj5x26vVG2ZPws52+Sv+MuixAjEO1Ye3ttK6QPm36zgU=@vger.kernel.org X-Gm-Message-State: AFuF++mHPqpfXVsC1kZJqEt5Zu009bpe17EvU+6IBDk3U29vMaLNtDhh 1RSQSwHVUfadLviRzdix38j58QUCcLYKK1aqAMH7mQps8c0UhttPcpJ4fDbMz2mU5x8= X-Gm-Gg: AYBFou20CUiSUmgO65yAtlChgsznamML1NClV+u1TLdFVPJqnyYCyjeRCAK7G4tJAMf Kr/SCUazQEER7wjldQAZKwLIlP63vGW9qSRNfv9SqhrBT6YJv6QRt6bdsqu9SV11liPGaBOqHP8 TcrC7vE+5qeMiDSghkjocUpjPAL2RhfT69jUyTAtj+A3cpbMDrOF2Lgf6eQSC73Pi2uoAPKZN0a JUm1VbMEp5sYpwU41U9FFjMcP7ur3oe14kvJ6KyFwQ/hVzbNDxUx2ep1RSX1wpovP9yE2GE49Hn TP16zMdbtrPh8pMA37ZhzojyxC15TJsuyOWV6tnhA+oW6fOOgJM4jpo9GDQPdDTmajBoF8saKv9 lAbMH2toQWGlp56jRB5+4wod0dE9ECjySlcOuBaPQ9cSk+RamOpZddio8asQgNk4C1cOugkDuIM etShAeKkBchgp7O8nXnrcTIc4KP2IVRAM9cO+ED+Id3sixpuwK/B7wBJ3yEsP+dG8mMz0= X-Received: by 2002:a17:90b:37cb:b0:39e:6c69:f46f with SMTP id 98e67ed59e1d1-39e6c69f52fmr8051148a91.46.1789929031381; Sun, 20 Sep 2026 11:30:31 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:30 -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 v6 10/18] nvme-tcp: Use CCR to recover controller that hits an error Date: Sun, 20 Sep 2026 11:28:08 -0700 Message-ID: <20260920182936.2317916-11-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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/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 20:36:54 2026 Received: from mail-pz2-f17.google.com (mail-pz2-f17.google.com [74.125.228.17]) (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 3A30247252E for ; Sun, 20 Sep 2026 18:30:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929038; cv=none; b=ln5NdLyi1OWymC0+KB/xznC/ze8uv+/8G5OMe/KBhY22zPu1uNWMhWPvjSUjkX3KktToDQEvr+S+8NKhdgAwifgr0NT0DprO9Rnxch6vMnoDdnjGlLlpNvyuClFpamXBZT2nwTXZ6xckHOCNy6GS6PrmpmP5dhb2bMipdpkvrh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929038; c=relaxed/simple; bh=7rnrjjZhabphz48ZRLXoqGnFCoHX2nNlJpxQZq8SO3U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DEbyDDvMFuNjgXs//I3w15V/LRgyYAbkgtDYRjTgVqB1Jg32LSbiXYuhL928uhmmU2cF9zgcU9TiSs+2T/RjY/R8H3HnMKGYvhRnNvuLEKJ6TMkf5G7qrtupjFhqXGmHAaPyq4MGiNqES6/VmzmULxMSkQnS+bLeFqVhoVrTU4Q= 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=DSV6+/aq; arc=none smtp.client-ip=74.125.228.17 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="DSV6+/aq" Received: by mail-pz2-f17.google.com with SMTP id 41be03b00d2f7-cc4c3304784so1990721a12.3 for ; Sun, 20 Sep 2026 11:30:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929033; x=1790533833; 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=DSV6+/aqO1JFjC4/VgVC/7jNryxhKWO+OshOMy65CqL8+BnKzTHbUNQ9lE1bqLkHRT fmMMuwSAvs512y3ivBr4NTvd7oysxOnHSnLAyke3z95tadDupn/DQzcGEkPK+q7C7kcR NXnNWa7EwPmiT47NAX3puasJZj2OA3gA2Y4Jw4EsIawy5O7M9I8eHfNlp5FeQNLi9y1s p9lRQqUMgQlW0GHwrTLEwJ2FPKHPak13NiEfIb3N+kRkObc1S4dmkFxQuhHv7BuIM4iL YNRLpT5b9VpR59UwjChZA3v/2n2J3SN5VEeEsDSQzW4A0zOIiaIOlJ7ocFpJ/oFGHAkj L6hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929033; x=1790533833; 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=ycNq4witu3+LRTRbcy8bmY2SVgW2LmXM0O8LeRDSSfQ0SH7kd9OdiBW+maRHhhqdyq VuRHNJWvol/H49NlEJumyBUern2q5XlcuCbi/573e19C6pvDhWgFCL0LJ3BQsvQ/9a59 yNRC+dgomiad1kPOm/IiglW8Ffbwg2PE+Pjh60pCqVO6ZhViMvDl9G7rfat+qvSBKTn1 5y/sqx/R8BZpP89NXnqERzbVE7FOONJvxzZWHf8u8QI/skAgcIdYyP/JgdCd0GYgwN5z vBXzzZaZZBO/PsCjZ50hCDxP7lbMepVWPCKmG9PUCQ8t/zCsdJcmrKGfKED2SnP6nmO6 jv8A== X-Forwarded-Encrypted: i=1; AKwUvBzZkHHqYnI/adiFTb+77TuUKHzov8r443qtZh8AVp3WAG5Tq5yDgTKTyfOr8uT/IVFEIsJj93X+BmykLnI=@vger.kernel.org X-Gm-Message-State: AFuF++n4K0lPOxkFR/EF12Rhtx14uN6mJcl2sezRSyM46oF5nHmcJc3C oYteYrhnA0lARnKtLTQ7bNjntkBdzu9c3Yj0at1DgY13/GBnTmPRZseYs59OTQPNHgg= X-Gm-Gg: AYBFou1ZGAHgyp3bk4Vnt+O0C+HJyGCt8oYPU5QADpoL7wEn1RwtpqgJv6cdfgHVZ0S dyC7FcM6pY0DKbKgrSGkBIyP0EWfn9B6no1Tw1QV3sJ8JpUyu9gMDWrczgNmV5qyeWHHLio5kq/ 8JWI5uN0gmicL6rfRN6MgWqUGt9L1YI7HYO/ibIXXgomQ8Xybn3XoYfYgx7/TWccKlnD948VaMA YNZ6OOg0499iZ1+zRTEJvs7AfALVjZWcyatINxYNTyNLef7F543GIIrLAyGaUHza6goVcc0F5W/ 5sLrAKt+I9Ooj+7+Sh0tMqAj3722qSigT9ZyEPSbrD7Mn8jbP0dJP0V7gVhDZHHX5KzEpTquV6s qLe/AtSjgltwYq+dW/ca+HBEZrkz8LPLnNfAXQaAPzI1NT2dFoibY7BGOyMbaNJXGkOyhw3LtUq IquNX/+Nx40Au/HF3sCm5nJBGhrtdcfgRArPxdfUWvCxEpeuwDfI192rfW X-Received: by 2002:a05:6a20:2586:b0:3dd:85a8:4c66 with SMTP id adf61e73a8af0-3dd8c5db1e1mr13018748637.45.1789929033190; Sun, 20 Sep 2026 11:30:33 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:32 -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 v6 11/18] nvme-rdma: Use CCR to recover controller that hits an error Date: Sun, 20 Sep 2026 11:28:09 -0700 Message-ID: <20260920182936.2317916-12-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 D1411471425 for ; Sun, 20 Sep 2026 18:30:35 +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=1789929037; cv=none; b=D/YGRts/s8qOrs/1cCR/EA9oA6jnkbpYvWgHTHL4l3sUBASqb+kkytbp/QJwj/l1W2kn6CttgckWD5cuvGSqmOjuhZI9XIYUcpO6qTv6Ff+KD8JVspYSKFCPgnhVtEvMp14mEIGQEcLq+o69q8NwdkhC4FTI+pc0YkpApB16F8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929037; c=relaxed/simple; bh=wqPjBR1evZQ/NfBLUjWvC2B83LrJtIxtRxteAVRWHsM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iB76hNfpHbQXBaQoFVbKOpWRF+j84d6lMAnyqRJfgat8YSxNf+xF4sonv4Wd5qQwXLPJJseFi3fZ6NYWCbhTqrLA9z7dNnXHS/LwKpZMjmArBEzH1ITxPTLXSV0eKCfrtpRrZLhixkGkh008WhBHFCE1ntMkLpEmxA47R+8aGPs= 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=X0GkcNoo; 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="X0GkcNoo" Received: by mail-pj2-f12.google.com with SMTP id d9443c01a7336-2dd58e1e2c7so20187185ad.0 for ; Sun, 20 Sep 2026 11:30:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929035; x=1790533835; 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=X0GkcNooaUTP0pHbLUYkJ100ydAsl1V/MAFnRptWzBc0mih4QxsmfZcd6nRwgS5w5c x/Vqnv+weyCIbT3ZHeoyBRwOYkfNobIAjg11ZTBEJOgbYYSbLM3L1nFWH3yS+SQntAc5 ARpxytbN9/c/7FtFq2vDeYrIBd5DVCOWAOVPthOS2Ufa+UHcyKVqPrC9fTZMCX7PYZnf fLml0xiaJTHwPkA8RaKg+aDDqElG4B2QWz0K76bOhObx0C4/ubMC9i9L/Pa2wWPbAEgW 9KF1cwBubeQJweCCmrXlpFi1VnP8miKkssVAVBX9WTWzx8w4R4gUBBub3HfMzJwFKlv3 5eFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929035; x=1790533835; 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=gW/F77Cx75O/PWCagv4CFYk3n7pzH1Iog1nhRKDzexfV6hkpIauTrhWt8aH/YSSi6Z QvUtbIUcq44AHBMnGH2sYQhViQLhQBadKAKy6d5Dt9JxKoKqeuAjAB1zWXtWUjKhZBfI y0Zjn7a66R3mr/OThfRZQn63zwDFDtxXqMBsRxwRbI8LG3gbHcDSWGqn11ONl5Vxa2y4 k25nNi5An3lD2MRWkxdb0IoFqLigexfgo3vRibG1vY1HDgTrwvHRt7m5CH1aIBeO9lTM nf/+2nAkbLG9PrslIqV4TvZDcVfbI6/IvD1zhEBxccb9BaonY4hWUxsWUYV27ifLk4el jV5w== X-Forwarded-Encrypted: i=1; AKwUvBw9DgnHK/aCOKxOQQkG5aH9Wnpm94+rb2hQGIy3L3LIJR8pkKJq+QKX0BLNh4PiEoPeLPQfh5wYq5AOpkw=@vger.kernel.org X-Gm-Message-State: AFuF++mIM3+kiG0F8bGNXkcWRFkz3lJ/3BDNHoIBm3iHSn/TUkBMVRmK GFSKDAMSVxbOzexV4wfZIR37Hqwichoh6VAe07h2351EF/7QU93h937gq1zGxrtjeUI= X-Gm-Gg: AYBFou0ym1DswiKdwgHAL1ufdwQeuh6/zlE0tnYwbYMbmW9fApCugUgCM6Qos/7Ih5x lehlCFWHpYloVlJN0Kp/J8k7zM3u7ZkbyKUEI4DerI30Kkz8noYkl+OZDcjVG06jxeerfJMBKdp FyGmFHmXQOH5V98Mny7oS0NjB9ALwOOIVODtsLydtYt6NlvYssGIQXLZOPWrRkNWgjS7iYgTOQn WYeYYKThEkYVeYp3KeEpf71NH3ul8GlMa8ndHBfTpbTZvjg0uhMBS5tx5oBSIUx4FpOKlLf7v6V ZlpC0wzDyErRlc388t7AtN6+nEXYG6hfeauPmYqXmrf/Pd/CGQk+u8p6w5l9cIa/iXUxlExjzUv cY1p6SG7VIaTDmwPSFgv27bAUs6wZUZMkGrWBv5tbg+HORPzer8tWLKmFqvgwu4cxx8yc8L0aow VR3h9cMx/DykgyDAfPpoEn8nZxZuBdrBkvU/73P2nCpaajEYwMwO1aqz/c X-Received: by 2002:a17:90a:e7c9:b0:39e:6c69:34c9 with SMTP id 98e67ed59e1d1-39e6c6935f5mr7688114a91.45.1789929034766; Sun, 20 Sep 2026 11:30:34 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:34 -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 v6 12/18] nvme-fc: start error recovery instead of aborting timed out IOs Date: Sun, 20 Sep 2026 11:28:10 -0700 Message-ID: <20260920182936.2317916-13-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 --- 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 20:36:54 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 94C8F472554 for ; Sun, 20 Sep 2026 18:30:36 +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=1789929040; cv=none; b=O8pN4eF2PiTzvEKwFwSG2xWNGaNvlv/gQZQ4djQDKeua0A3ItTYpgeZQeM33+LVmAiTLmimljFkLs8YNygeT9owy3tAC3po0LJOzYpGDCWItVI0EqtV/D8LLF7Kjv2+mNnlGekHdADEH2ZeuaPzyY5Rf3KjvyQ5iBFAsGEEn0+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929040; c=relaxed/simple; bh=SI/It3Y7Nmi0Qd33uYrJsmK8dlYFazFQgXLrKfZIwhw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gvG8U5xrd2FUsEw2I2X6ZUJ7l+g4y1USrLV0KnQPeHZg3eDCmxvKZwyPhpqGHDJnafe7gwNwYvoDX12ON7NyRkZPb0mqVZ/WWRulr61Wkmss6rDcNBh4NmkNqTe5UEYvx/vnwLKj5Q6bHbF/HMj4pXyn8DmHehIbFOMZCzMc1qk= 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=VSjE9Qzd; 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="VSjE9Qzd" Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-396ccb1a98fso2077125a91.1 for ; Sun, 20 Sep 2026 11:30:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929036; x=1790533836; 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=VSjE9QzdzI4eXvJdb52BA1DX+7Wq69akq5l5L/0htrH0j1T1lH+UMJwzVGuF1LvG/M NQmflEPaUqRsRnyfFd0DgkSJknAf2FyFdLa6y/z5+k3PUMeD5oaOUG4u7x8LxVKAFcvm HPGCnvy/DH70iUU9om2uVmr2hNYGstchsvTntGg9evLf9SqVnmzvaq3XO5qHqPZAD7Vc alaeQqNd8nDpT1OODFqoZzpTHuxLf2tKXG+o1UOqSI9bGpetFnE5ZnzRBu+RNdEqitmf HS+w6OotsDptPcxcn+TiBNxIZxVoQPG+zmeFwRFhk1bqUhY8/HXJHeliUsRRXZwLfdug 3YEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929036; x=1790533836; 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=zEaet5EDhuOima0C/A7RW47QrvxY8gO65kkh0BOsDSykazqY2nxt8v2PPacJ1DPyEO 9R1Rov7DLovfIAzfqEy9n7xcFU6WPVdEvR4P1IdVq0q5svRJyy+2ODrTDIg/PHrfIJHi dPF63wYcRfMa/uuS7I7v14EUvbuYQpeQcK3tFqavRYTdWiw6QtvIsFYxxP8mmKJE2TS2 EixUbsmFTlX87phKLUPt7i+vI5AcKdE5THv5F0OQXMdqN8DLm6MSiCoMkpaQZC27girs JYGuc/gpVmmAs/aNIlgSqOc/vT2XA24lBH1xQUqbX2oxcoghXGwf8OXZxVVyObZkqTWX coJQ== X-Forwarded-Encrypted: i=1; AKwUvBy0w+5rXi4cfYV5ESF64YuENhNFuXrXGk3NeGelVirNUSfBSNcJGtvEl4hlA2a5gclFn/PdlMLwi3+6jXg=@vger.kernel.org X-Gm-Message-State: AFuF++kirklt3tHL0gJy0LvRl2uH+BAJaGYbs3RIedXerDG+fUChl0Wl w/iwkFrcLIZnm3UbRbtExskYNVQbq0koxBhGYB/MCxmYlXQ1g/pCUESOltBsCNsg2mU= X-Gm-Gg: AYBFou21ziY6Wgx+E8wFPk00fMmn3u1/7fMnuzaQ4u+xChvLhzXDP19GGzepNTl8GLU j0PahR+aEDVslVvnp30HOkme0yZYp7ZO4LRXIGvbt6NAPLBpYUq9Ws7Ok4hiXqpexdJU2upE4jq EDkysFUroC2vms39ZMWiZOUfDQ6PdnrSV1GNe3FntHS5ejberj2g/HBFLA/+Y2f/BV2h8hk58Y3 eVAHXRTTIDJmWtp7Z3RlysqxCA9wo1GMlJxEeTGoCVHoGgLBCnKMtCJSbnd+f5ei0vCjtQEGJnq 3leJicWvyoONJ1B8AuMoa79bUBkiduOnoD/tI5LCpummkMOMO6xrvDEyXrC9R8FZlb4fizMXFVe z11gCq8ROY4i8yKrNF6JSLcZ59SRdcPXfR1SAh2Z/nxGgs7zzLQXQn+aPsQ8sdsH93BXxS8LCvC BqK5hg6DHcY3WhmKrNOp+cumfTmp33+hALuIPnWy2ZAiE8gltEJIu0K00D X-Received: by 2002:a17:90b:4ac6:b0:396:65dd:4093 with SMTP id 98e67ed59e1d1-39e54c01efemr13709813a91.14.1789929036238; Sun, 20 Sep 2026 11:30:36 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:35 -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 v6 13/18] nvme-fc: perform error recovery directly from ioerr_work Date: Sun, 20 Sep 2026 11:28:11 -0700 Message-ID: <20260920182936.2317916-14-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 2026 Received: from mail-pz2-f41.google.com (mail-pz2-f41.google.com [74.125.228.41]) (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 821103CA4A9 for ; Sun, 20 Sep 2026 18:30:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929040; cv=none; b=Th7AI1aAi3qupimiCTA6QB+SUFT9npuTP8uGDCS/ms1uWT1Gw9d9UveUjShw0xfEtaOutKBLl/LSyBs5pf47OQqEFFWNZzUoA9o5yub+a2k5wsbVW33128Bp9Cv/IWZXojNFfByDRg7YO4UzH3RoUTc/HhtcViUVplDGCiUc5wI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929040; c=relaxed/simple; bh=FZt6CXZo2bmv8xm8GIXDwWDNfGUWLjZWl34Anyu+s40=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Wau+pDvxJsUnBvbKO1Nyiwvt0LsA7IUqqgLyackzU2rCJhc/lohcNTaXXilvjZsSes38vweGORXmBsrCoY8KdvzIF6b8RnhprYmDgaqI0+8c+IHvOcXUffxANZrWAPHPWFrIbOF3J25McQ3CnwKcyU4sbw1y9u/JOYPkEpKFYZM= 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=InLIRJ+q; arc=none smtp.client-ip=74.125.228.41 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="InLIRJ+q" Received: by mail-pz2-f41.google.com with SMTP id d2e1a72fcca58-85469b2e1d5so2416836b3a.1 for ; Sun, 20 Sep 2026 11:30:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929038; x=1790533838; 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=InLIRJ+qI6981Ex7D2vVGVAko3gT6HhPZxhbTBMZHGrizOHjr77gEHzjQpXP3nTQ9a qk/5zZPOemC+z/2mXCwKNOeY0HQy2krH1ILTQOnjdwl7cGyNl41QdyLGvLPhiO3jvNMh HH90H4QoYv5vIHqETLJiaNa/uATh94ugUgPjclAtFe5NbH2HPhK14zZJt8nkJgKCEsuX cZ9uUpqNK7+IuWz1Tp0dbOU9aWbyADTQouXBsJwXeafj0tGJFe9yALfoCJBjGacSyxVP bJZ2hxShxIfUmzCC8VSRmiiEEEhPMnP1UkuTRdvSZo68rl8sdM06A8TqOTut1dxfSD7R UhWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929038; x=1790533838; 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=vwGrj/+bXgLXu4MalRC6zTGXyYLmaFSlOE4GN/g9X/k8x6MrLx8h0/ERM2+C0D3CRS 5gwYqjfTMihTUGxs6lMzJwu2Usdbhvb15jSMsmO5dz7jgHMRYlcNh3KCqlU/OTacNkC9 sMhh2yIOjcEyYIeUaidGfVJIPftOmFhx3cvcZ/c7VWagip+9n94xMSGdXvvV9TKYhsYf 5D58PyQJ8TDsGbfzM8HHqj29dfRNvZ/nKihXIm1SAApJ2ZA/gptJrLQJvv4UEgC2K1FY crDdXJSyv6Z/2mj+thg8YCcHbUvDweBjBDn9w5YNFwEBnmwr2rgTeQHpMjwXtmqXxSGO qrMg== X-Forwarded-Encrypted: i=1; AKwUvBwnv01AXdP2Nww76/rM0WJ9jFeYhG4wYpnm7/5wDPapycboL6DzBbstK6OEG0UIXXAXlYblt9uPvwVUyZE=@vger.kernel.org X-Gm-Message-State: AFuF++mZ+2UbstfxCdBfyS1XGS+rT4Ds/Lp4T9hhX2MiLrzYGbDHpYXj 1yG61+OICXZRkl8LWPEUQeFcyzehAltxkDFmPlRiIjiylnWz+i3dCh5/HwCcaSERw2c= X-Gm-Gg: AYBFou3YKe1GS97AapeMCfvNrXtm4um1k5O+Iv9YfOdd62EzZNjNgD5sD4oXaLCCTWy Prz8aCYAhJOiIxIL0ERP4CXPJrdlpoHML0ggdJiEAt1YWGm6v6Y05zeLFOUYgVOjfJRFRd3xTrN UedNV2Ca4TwAU8iHxYJ1PQ6ht01jQrYGKwMgiNxqlp+pi/bYBC7QrFYe2t/0vzgrt20lVh+43dr wApsgzoPf31JdKiMlbyggIt97Lll4P0XTdWluAmFHUpJDKoakxK5WU0TRrUTPGH9PjQ2w+C3OAr mHKo3Ou0fCTatYKBQgKHGMNRbqW7GYSY04XcjEHGIV0xXSx9GvTqQkGw3ahg23MV3rs7eQQaAfu fKd7QbPM2UUlNWbBAqMLStJUirfI4x0QxCUqpc7y1jMP1N7BmuAWASaqs+1t4emWFicyjle+4IB OGpnvVPmJ2JLbzCdh4IjYlVI9M4rcnyA9Th3HZJSI/XgS7BHZsJFN/CO2z X-Received: by 2002:a05:6a20:4386:b0:3da:b761:80c0 with SMTP id adf61e73a8af0-3dd8c424e85mr15235108637.14.1789929037653; Sun, 20 Sep 2026 11:30:37 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:37 -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 v6 14/18] nvme-fc: Use CCR to recover controller that hits an error Date: Sun, 20 Sep 2026 11:28:12 -0700 Message-ID: <20260920182936.2317916-15-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 6EDB4472558 for ; Sun, 20 Sep 2026 18:30:40 +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=1789929045; cv=none; b=Fq9IlSbSXBENA+O5gqkzQX/BdAU1yzI+MusKMG3X7MtzMoq2SLQMkEId6eeT8kafMeVZeVcSUMMf6uPMNfwdJsSOQ2KOY4hqUU62xM5zVW7UYoZQNalc2QFsvdvEBS5eOPtpOVdjexdMM8SEXXsH7Jw1CS4x6fyyGnYYNcClkHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929045; c=relaxed/simple; bh=brszAfCb8xPeY2++BmqbzkUD7Gs991VIWtKQ+a7lhTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gydcSM/UptGpoJhFTi/DK/XmBZe4ncDvyBRQiXMHcqXtdPbeXNARR6Cvt0MrHgsSwmleeofBW5II7CpLWOQr/q6J329PrE7h9JyaqnV3YGPlN3iIvfHZIt0hQzweZbJpCn2yYoRzhEQvpJ7Lw80w9o+dr7otnVgroLH05Yg5NuY= 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=PLagUTvW; 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="PLagUTvW" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cebad4afso1575568a12.0 for ; Sun, 20 Sep 2026 11:30:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929040; x=1790533840; 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=PLagUTvWC+LHG0S+ARAOCOsPEHcajAUgYKk1Ub5FP5/8LYA7hKYNvhBFqui7oayMJK 3Ry6a4iFo7sfWPNmcdFSXGcATxbTTxxkUFtm53CDoiDIvfWntFI3eaf4f4ecLialfafD ylY161qwO0RXUPFMswC71b+kFG+SFcJn5a9shf7HCtStujuimgbnDEoiSZSMeQOhgwtm n4kLhDVUvpnuesoGIjn+SDUMFSIpJVT0R/OXRXtpVObWLwiS9N1qzDb1XJw8+YUd/ZOU Az41qboXCVhAM5k+9+irUczKRfkNsFUzNSyJs2YxavPOZYC0rjCCR014NRFHqIBJVunv 6Yfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929040; x=1790533840; 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=NrdCIj5Fk9qNPEPrc7v28vjLOv16r7Uo6JNfJowjJK0Q4xes1UppXZu5zyCMGSVsS9 IVwlFbyX1zCcE4X6x8dNLf9VuPYXDBT3DH3Mq80jwrdzOhBZJEvVji1+0GK/xrrq6J9s y6/n3+UrT6LElID4kdJF6walC7c0cB/x2Was2ABoUd+rFs/9WplTFb41Jsll2Lkls/dn U2bocScedoK8A6hrVYMwSf8hUlPgn5ly3NUMUpGcPW3A2Rh3MzOGIA+r+awcjzfuyQPn KNA+yG0Xvn1aHMuZvVTLOJyYeZ/0KkENgKrwFa3brtT3u5gegIc4WTXzgcZSL7UKCjMY lXjg== X-Forwarded-Encrypted: i=1; AKwUvBxhIFGQ8x20Na14lygfAbWQWuzz+mlczYxwIy0fc/upUUSidtQewD7WLezbNNk4cYip9hasQuheFXOe0zQ=@vger.kernel.org X-Gm-Message-State: AFuF++nGuEhOB5u993qsxPTLgWmWH0u7B/XSQ+P3aKk7L9UFK+C1bZ41 wLaOrUPj2Bsf/8IHx7utdtncVXqtatVYr+U+iMZ5Z+wn0rH2vk1/XE1eTgWJuggu0Ng= X-Gm-Gg: AYBFou1KMlMx2iHhszC0KTdJe5zZ1350olc2ToyuO0iWqMXl6yrdKb6oCHlC7AXOXiw Db2Ym5jrd6MdOdPEa1KcOgnvAix8nWKijjhWwRUaiQHUkliIVyJQW7U1OpjjpgIIwvHa+r8xhhQ d03SessGdfK1auPdfU0CGN//QuGKvT8yDZ5UFbd2JsYyMQcz+1Xr3CL0cc6xo8Uf6c0DnWrM0Sx LhsegMDTyajCP7MeWvt/qdn3Pi3cVgh3QUzMdmMHEgzKRjdSZ5HK6NvpVc7MToFNw8DktH9nwbt l97w5Iem35t9vrzCf4hOJGyCg4wfqklXER32B9kwbrvCf/sC0eTgcLjuvNgwPIkMxD4mN8V7CZt Yi4Qeye8zuWnl8KxESSCb5tf/o08EntHbWFq0j11uYJfurYHUGx7VsynV3qb06rQj+MWVwZHVbm Ecp0d3V2aggzhhglAaE1ZQlYz8gCqg4u7zVOkfsH6qFvhz8Hp2R1rqcJC/ X-Received: by 2002:a05:6a21:1f82:b0:3dd:a197:cf29 with SMTP id adf61e73a8af0-3dda197d873mr6832729637.77.1789929039375; Sun, 20 Sep 2026 11:30:39 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:38 -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 v6 15/18] nvme-fc: Hold inflight requests while in FENCING state Date: Sun, 20 Sep 2026 11:28:13 -0700 Message-ID: <20260920182936.2317916-16-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 E18C9296BBC for ; Sun, 20 Sep 2026 18:30:41 +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=1789929046; cv=none; b=Gkgxfgc0N7euCudraFh9BAfMjgesWVZyMx50jhioCMtk+w4O5nnnAROXGZoBBj4t6GpM1+3q8d0Zlom1w2I0MJcwlYb8BIyahKtIc5k3aNyw+5dETd5i9bb0DzZ6zOBRiDuUBZ5oD4yNh5awVQXJhEcedd0p0P+kvoi129QID+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929046; c=relaxed/simple; bh=kJlZAJC5w8Y6rxPPy96a2gpbq9yTsgzYHypSB80iKmo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DBCzyJIV0x6lKuihRTmSHkre+vXVktbyU9lJl6gyohS1qVr2yXD2qNZi7RVIqCn1jsm1wmVY9CWUUoCiiw/0VYzgI9jD42jK7nEH3KJj7G8xLlheSOznppKREusq2VUt4rC3v2ROWROkLCnYP7R58i5rakFkbn3eoCtcphpWolA= 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=gUZtZG1/; 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="gUZtZG1/" Received: by mail-pj2-f13.google.com with SMTP id d9443c01a7336-2db1ca069c8so22982315ad.3 for ; Sun, 20 Sep 2026 11:30:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929041; x=1790533841; 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=gUZtZG1/GHtq4Tq7n3iwEJzL4k/rzOw8m2gWXw1kUbFtRvyzVsysY38oxnooKmzZHW yS2/WjYrfEdIjbK2qYrm5ok0ZdLhQTCkMSFrmQVhFflXuJ7oGq7DYwmABaoN7ORrFAPO JjKRDs2y6wOOib9YFfiWtAXqE/1GgTg8t+pndqd3ZXbQHwvqaoX5B+f45u6T/ur2E6+g 7o8idRm1eDP6vnMdre8j2mse4xdCGRsreimRjybK05Oxj6DtRxbcDZSdTlyUCM+SACiH Q/QdMgwM23NAd40AvxFcHDSeh4n/Xjjt7brSZ50pY5y0R7bEJN5Txdoat4iW3+2+fTmV ssNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929041; x=1790533841; 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=GgCJ0ncIw9yc+S1C7xc8gNy5T53YOzY29L8pSt+WRfiipILLQVwcnG9S75+raehU3M 1N9BS0nffwXvSjVTz2aE9BMPif6fbSg6eesiPhJ5l+7qWs/3FPjHK20mPl7s29mFdp6u MJ++veGRcX7w3O0FbGucQRiG9Ke7y4Oz980wYyjWHKzaiJJnebppzFPNW2oJ/jtSKkd9 7yOl65UmOkKtaD+HSwtIsHE2mtR2i0dilo5sVBM7/KC0F/H/J4bVH/oLqR8hyN1PeJSE FdZ7P5JJ436pfh6AUB2hGLr9Fyzxf7gkvTRzbge+7SgZPRg8QUGLEodOW8nRlw/phe6V 9Aug== X-Forwarded-Encrypted: i=1; AKwUvBxtaGxx33Xy469YuRdePEQ72Mde6GdMoGP7Vz2opJKMZVHEfXyIMrOKoCqG50ha4+frjae+ZRTPxhp5FpQ=@vger.kernel.org X-Gm-Message-State: AFuF++kKZt3nykkeEY3qAz5VTfTKJlb0l4FWYfbP4gvLqCCgfnIsv9PR bvDKFY8E4yd+dce6XbgEsvAXsF9tOAGzc8nze6Aom1Ej4KOjtX/iNNqnpoAYakulnj4= X-Gm-Gg: AYBFou0kbyzfNwzsMvRbG+ua1tYkmPgSNCJ0iCXtbyzkWp34W/6PBYuI+1GH6osdHGZ kpPrpriMMNZbS5J7r1qNjAXzCCQQvKQ1NVcKbRth5dxjzc9uGEqjbbsaf2j8bYoRBgkqMz2pNEW bNUNK+BSBQuxnEABZnvzq4yoDzyBNn3a+z8k0KNTtz2Nk3Ql8p3+deA9es+tjEQKCl7u0P1+miK aFzRNRmhsCURyHFl0lHoPzAN138ijNrirIMe8dYmZOSzne/VQLvtUct6HEkCGXx6T2TLMKNmbyP 2XaekBi/WKmmzavqE23eBprXXlT6Hn11XiKw60aQaaQucKLKuscYagBqwW1oaaEU94d4ytkEb0J k4IDiFY8IBdv47j3g2ZB3biz850QLCvtlv+B+GwmhvHTl8i9s9Gkv6ZS1vW9+/u/6YBlKEDFG+0 sdg0Xex58VWlXaVyUeH6UXUuj8PFEW9mYUbZZhxxf091j6swidPmkuo11w X-Received: by 2002:a17:90b:5281:b0:39e:4c7f:8b17 with SMTP id 98e67ed59e1d1-39e54cf8bc1mr14650246a91.28.1789929040984; Sun, 20 Sep 2026 11:30:40 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:40 -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 v6 16/18] nvmet: Add support for CQT to nvme target Date: Sun, 20 Sep 2026 11:28:14 -0700 Message-ID: <20260920182936.2317916-17-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (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 75212471425 for ; Sun, 20 Sep 2026 18:30:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929047; cv=none; b=jw7jl/Mj7Tj/YBRXjW2ukrodU3dIwQqjZqOaWc5Xl/9SiE/gz+V85h/gf1AFr7LCD1Qq7WTpmjkoAgBjRtrW680Q4f5sw3VoTf5JoHelKFNvyzqR0RzWxu7ZMSUMFP8nQpvaHV/tvtfWKxt/ye/IGaJVer6ij9HQsQ3fFPdCkBY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929047; c=relaxed/simple; bh=N3TrYKj63SGboRNWu/OysoGDNr/HzP5uaLhsWM3pZ+A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=chTpW6q6eUmacC4zCmjEzMVuENH79lGzfr/w+fLT8dc8da2tCJ+dTuk2PSSAfwvGinWIIkSdMY/SwJyFtWeaX8bKiRcg/BMQ80BDuNxfi1mzUmXtJViuoTGhNmPlGy/9Wde3uRWXHmXPY62H+X6/H2lh3KHBsUR+tLPLfubsCoc= 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=WV8jon/P; arc=none smtp.client-ip=209.85.214.174 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="WV8jon/P" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2dd68a16955so30478315ad.0 for ; Sun, 20 Sep 2026 11:30:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929043; x=1790533843; 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=WV8jon/Py08qUgb3xmYF8N3oBfK7kRaKqasq9Kf8ArWHGiZiLsAuW03ubEalJ2aUHq LXCsV5AQL3MlKDc1e9qREETdLw3XA+WTyE6watNbdauxRQf7m6AUkmAmHZBQBPVBS3Xu 8Wb2tyTwRdkjJkdt/8MotsJ8nqpuj5enQ/2uNGrG/rwdRtkpjkYBY8HQq/HAHfIX4Z1B YE1hN2r2WNH8Ym4vQz3sYhdx5MNHmeP5UCba4lK2TFZx0YfF/a/kKNjxTNvRL1P/cWBk /ULFAV/CHyFJb/8O3CiV92AyI+sYN3n15LvnjsJzYbzxs4NYpUaeQ45doFdD4OY+7AIt 6Ikg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929043; x=1790533843; 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=XMCGNB5BQ/tJgx949BfKUMCLa8Z5RpBsx5XoSYFoAOdE3L8vW8MNr5J9CZndAF9nzf YFE2W0DnP/2Hv4rpLAUHku9IaGuUayDcQ1gNPJP1dAJ7ANHkkbUkEpbjMK9KmxWfepMf t2cKCEbx4czy5G3MR9or74Vn+VPGDDzsc7Er6xH7RKyPVGYxhQLNvm/fPja+thnUOlJM 3k4xRBe7cFUIfhVLUP8EbjYd83Mk1xro1EkzOoej7Z30BPg5q+JQF7VunuHLGSvmrRnq +L/BszQvOgpGumtaIRWdmYoheIGEajRsgaKQZa03hVCzJWdRaWJvAgPA0S8Fltc+Azir iKWw== X-Forwarded-Encrypted: i=1; AKwUvByWycuOID2d+vefdjRQ2JBviZEx1SipZvieTkkrhY48K36a2Y+QVdjhuaSozEMn9fc17kRR0dHj5iFPtLE=@vger.kernel.org X-Gm-Message-State: AFuF++mqtbU3I9cVi7O84NYo2rHlQ176388i/L61PuJIbw45ZyGYpqt7 C1qyjusS0AnImKgvRMEvabuRdpc678LSiZbvcdtll7WngLji9HbK2twRZhbSmYmfgU4= X-Gm-Gg: AYBFou2qtbBau8k8fu7VhS5AWuMLDMAxSo7uVhPhYSEPM9SlQ6Gs1E9iFDvS7NehZ4R li4VqzhDBJT/4zOVGXZGXk7uGkZrOL3lRrCofP7JlfBuDZgBvq0rDaLcS35lEAyD8/7ZkGfkbG3 QdOB7xlm/KK2NcV+RFpP6YCJIER/vzbI0tGrJ0pJSW8+oD92QodGFcMLAVtCsbb3+5HDKwxnor7 JZzNj5iVn5+VoeyVotNYbh+1N9Yt6S625OLMrrkmheoSZp1iMIs3kOk9INarvDCaJ3Z5SPu4fq8 a+LEAA1T8HVYAjMhFhtJMGCCS/Yq1nMNQ4AQbafkRhNLEmmja4aXqHMO4bRW0lwRA4GF2+mN1hv 4R8wKCKOVmrbQr1jE0h2zAuNp44yxqYlxPE0e2UDr2gBMLuHfV+0RQ59k9TZimaZxSQVl9Zh6Ey OV5GmEy7UKOA7pfWod7QTtEGbFO72lw9LPiunH2CwkwXk5awSGdqRY1g2l X-Received: by 2002:a17:90b:5403:b0:39f:6c3d:d4ed with SMTP id 98e67ed59e1d1-39f6c3dd7eemr4747809a91.30.1789929042496; Sun, 20 Sep 2026 11:30:42 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:42 -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 v6 17/18] nvme: Add support for CQT to nvme host Date: Sun, 20 Sep 2026 11:28:15 -0700 Message-ID: <20260920182936.2317916-18-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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 20:36:54 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 BBCA4472F91 for ; Sun, 20 Sep 2026 18:30:44 +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=1789929048; cv=none; b=M62KH2txcbEpYES4ERmMdemJx58kI/5kTKyt81xFAVpmt/kPpcBIx2spLWy5WjNToCzcacwywvTC0dFgb2qFbVDkY+f3G+NcXRwZJbjJgu6EV0BGWd/i1H5Ufy9Z97FbxrGxnMU9TzCL2VaKZ7JGdwfEojNKs61ivw1qs29iBpQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789929048; c=relaxed/simple; bh=D0ry5I2UO5EoVVglgccRISGqcp8rRYeGB8BrHvdM5pE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eXk++jymnvd4o//JGYtGqIcoaUtkQmpoEGDZH9cBZCwbbYClQulQFFEeLHF6Cv6EDtxAOErpTu3HcSNW4DfZ1HUNqX2M1TWcwLPyH8Jntn2Za38MvnE1imAbpD5xBdmqo5emSvYoSFDs7t67YW9oAF6f9/rw4hU8GF4CWdGsDPE= 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=b7Kv2s4i; 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="b7Kv2s4i" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-396cccbba92so2066037a91.0 for ; Sun, 20 Sep 2026 11:30:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1789929044; x=1790533844; 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=b7Kv2s4irQ0uVsPDS6sk40c+rpdFh4q/hGkz/mtFHPJGQplhQitwn8OCX8HF0HLWpJ RS4VWs/tTtLqCpNFM3cKoLbvBEj6zJFwlpfp2v2dvPvF0bSzNsGhBELB9JzayXvAHdyq KNqxexqRYAUV+nYCn8vk9xfwUjOsrjLL6vJAs+8l1jz9fwOnOCGL1ZAMy+gzzavICQxK sfyjVDkCpWSZz+A1Vv0im3a4G8ZhMBQoL0YNfjdRL8d/6qsCXTOonLIIBImIVSJtC6C4 LCJXluMLx4T4Tx4CLDzK8zXYHTMy+XeojBYKgBIf4KnEEpc3d4V3DssKwd+dCoXX1lCv Q1cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789929044; x=1790533844; 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=CTWedT9T8P1mZPGdcxcFvUBHaiT6kc6Ml0lCnDt4BcqgWtfN9hMmjUuFtdtMGbcM2t PtJajDJ+TUdHbv3x3zAExApezCgjDOiEhU/LbL2TObgkYJWQ/0ppGckmlwzeD1rTZN0I uCDZBT5krc0pcQqEGsdQp+hSH5vMzlMgfeSnoKctUT6wzL81vmYGbGaVV9sc++ew1wtE 4aRAJg+t6PhFOwQitTCxfKYGD/A/pK5kh3WfaUBB8JZwx3btjiw4vONUZFFuS5X3aT/o ZIl0iJiEdzMwaQ10TYtabUjM11lPiPIBSZr0AVqRpJ6UTSxU/kfdlPapcpur8W/zYRR1 gfcA== X-Forwarded-Encrypted: i=1; AKwUvBwUJaGfySYpHhs/4bKEH23myjCcgKHO2eIySsenaTkH0SVNebo0iZJCs6XkeqiTsosoyuqT7Wuamc1LeCs=@vger.kernel.org X-Gm-Message-State: AFuF++lMgeeYA9Ohgh3bPG2GxXGfGjRikoJQwCvMwjUlYcqaQdtGMwUW OPKqIvQC9NBUOEjxr52lYW51Zl38nO0VBcR2Un5dzy03iMJjs26i1a7NIrJSrwJXzYc= X-Gm-Gg: AYBFou1fi2rPgtOzeHy8XK9I/+oGdmI9MsCQRXsfc33daR7J8dwHeMSmanUcTIxI7Qz QlXUsEoTo/7okUU01Dz89QrddV2ag2oH30JzgFaK0BDttxX5o7gF7FhyeM6ewBCfaX1hvRAbDtJ 1jd12PvFhZkkIO6LO/SdBVHkBDJfpoKQLfRsJbRHlBZpVBr8UdHd6RTmX5NLgAg73PSyLqt01wk 31I4Ew3dR1waIMRw0162gscVTAaP59kHh3Z4bGZ21cmLUnLjHQOaLXPZwsWngojWLfRdxR/vUb7 BNnQX5d0Z1SS4wDoLPvWUMJnEZp74uMo22clrSRfKL2aKQOhkufwYu7EestumgKFqNuD/TA14UJ OGkmLGqd/+IhuTxicsHw0oi5ZX/fWMLiBtxL6kXht0e9PQ0PvDXaMkGL2edIbbUMfkHy44gdu82 54oNz7/u7A33MaZ0ZbOCHxgifIoeIYt68NcGB81S4kgrci8wI9eVEDfx1i X-Received: by 2002:a17:90a:d00e:b0:39d:fd82:de0c with SMTP id 98e67ed59e1d1-39e54aeed0emr12729347a91.2.1789929043967; Sun, 20 Sep 2026 11:30:43 -0700 (PDT) Received: from ceto ([2607:fb90:9c20:5ac0::1d8c]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-144da432647sm20924589c88.5.2026.09.20.11.30.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Sep 2026 11:30:43 -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 v6 18/18] nvme: let controller deletion wait out a fencing window Date: Sun, 20 Sep 2026 11:28:16 -0700 Message-ID: <20260920182936.2317916-19-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260920182936.2317916-1-mkhalfella@purestorage.com> References: <20260920182936.2317916-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