From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 46C49BE5E for ; Sat, 28 Mar 2026 00:45:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658753; cv=none; b=Prok2r/uRKr76dyHXGQ9wcjyBx1x/PgzZVpvct45JmSsnlH7eASt+W0yKRzEk+GbtLqSMnGIqJHLKrCUDgycqbrHmaW+2xS0R2sibA9jSRPQbAcTuYSDrg7hiK3g3qKsj/8trFJHBBgo/e31NGvkl7g+LcX1JpH8SLZZjT4/dSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658753; c=relaxed/simple; bh=cRgFapuyJhQj/+AjJmhgJtUnutaTHOiblX1w/1lxRfE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q1OhvG9tAnFeMMR4Cxx2m7MSeUiJ9KN/RpXRbYmxrmOPEzfK+2hUKNIigFCvQlcfwHsz0qnPAd1pEW2LPXJg8HAibyOxFL2sZgv/oRhB96OkJuxEE+s4vE5/ChBTHaG/yvNq+DlYNWNnliiHCZ0WwTm3ScOhn+pYk2ruGYNlWPU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=ExIE4MWC; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="ExIE4MWC" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2b23f90f53aso5401655ad.0 for ; Fri, 27 Mar 2026 17:45:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658751; x=1775263551; 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; bh=I7azvsY2lfVVrUuxgtShy75bCL3D9ds2FfFrJhMe74c=; b=ExIE4MWCtX5hlY0v2t6WM7czt8/LtHQkC/y/Q495kZe0HaeiEYUF/GLfNwmqlICwBL cg4f/A67qq+66OJ0B9g0TR9j15vqkeaFpWTYikD1yRbwEkoDGP4nJYBvRSX5KY0Utn8T oltTPUK450klfCGMMw60SzWtjnzyLZx97mtRlVGnPIOCsqDnxHPNXwjjCpcyzJgXTMHT fSjsu9rbOnWXRTpEaLLgTUa2v6yFom9HkouiowO8FEMMb6JYykrMAOKFYdf9jYUlGOOI QkZ7MhV7q8P1LHkFOdY14dyEQ97mY1dREAIWa0Rc20HIdJ2jJU7uStIrnAFDScmK1tYP M1kA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658751; x=1775263551; 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; bh=I7azvsY2lfVVrUuxgtShy75bCL3D9ds2FfFrJhMe74c=; b=f1ZEFcCRFvU/F67qgr80RRtHGDTmxQ2+x+oBrFPhTpjxW8791N8pqfaUAi3397NMY+ UulJ3yMaKHFAd3Iy+EtDzJETqKwONkMKXy8pkEcyldKWeZZNr4EQ977FRsFnaWc1ftAu uAWx4fAolCCzxH4fXzfBrN5iOBr40LcLDU221su1YD98jQ9Obdu+Dl5dBXOx5xXriPF2 RjdOABoCBoju6+ZPCO5AiULvvuUDvrALgJJEBXxWMOm53kqOobmkyj77lzHrWs9K7PMO o+Bdl7en1AcY1YoSd9fJ7lza+DscNKp2PVwygdp4Q17qffDZzJORyc3peie1Ix0HEfht PxfA== X-Forwarded-Encrypted: i=1; AJvYcCVdcsuOZYgVCxzlw0YnoCqD5PkAs6HPgMEWv+OaKYSYES0HEy/tM43Vc15diFgW+Oo49rZ0Nmol9MxiLGs=@vger.kernel.org X-Gm-Message-State: AOJu0YwfUG+6FEA/dZM3YvVaCeMIS2Balr9KcXgK2+A9n8KCt2zca0hs XRNp+rAsIR9JyOwG2PKPP/ux37Dp8HCdqkUgWgOrZoE47lC3YbBP6dfN7hTnpA+iVHU= X-Gm-Gg: ATEYQzyzVuJbfyH3wIruua2ls4GN0RY84VDjOHK6LkS8h9Y40g6uEYuj9jPJobzB11Z jd/bR14KGHF2BBVoUTZYT4gq3N0xE+QahtW+BKA4ejKErdX+dqtoVVMhM32yQXFIu3XnTeUMYEx DAD9nCGi188N5HctkQgG/KARRIhfp5B8nX370QChDq25zyqskuJjX7D96oOlOPxhpraYT+EyfVL kWTigobo0IWXfknF9ZdqX6m+VAtpitFQxhc4qTNcTF4How0H/LQebwxzeyWpVMililXkIsD3hAf f8RgL2V2XWZlQ4/1m4sdJ6ZlO/fLCihJ7lFSBvPbnB77B1V8HVWLerX9tjcH6Q76zAFXHTUrhiV IzsGEsCVsvnpX16cxdRi6lvwREhvSHnEmUABObL+HnJzErlCQYU6OPsPa+dslkUI6u8oDZXaOQ1 YSkeK8j+V4MQ1zyGwP2g== X-Received: by 2002:a17:903:46c6:b0:2b0:66bc:2282 with SMTP id d9443c01a7336-2b0cdc20726mr49307635ad.6.1774658751378; Fri, 27 Mar 2026 17:45:51 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:50 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 01/15] nvmet: Rapid Path Failure Recovery set controller identify fields Date: Fri, 27 Mar 2026 17:43:32 -0700 Message-ID: <20260328004518.1729186-2-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 is expected to 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 is 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. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- 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 ca5b08ce1211..ec09e30eca18 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -695,6 +695,11 @@ static void nvmet_execute_identify_ctrl(struct nvmet_r= eq *req) =20 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 9238e13bd480..e8b945a01f35 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1396,6 +1396,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 /* @@ -1661,6 +1665,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(); + } + /* * Discovery controllers may use some arbitrary high value * in order to cleanup stale discovery sessions diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 319d6a5e9cf0..2181ac45ae7f 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -264,7 +264,9 @@ struct nvmet_ctrl { =20 uuid_t hostid; u16 cntlid; + 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 655d194f8e72..7746b6d30349 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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (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 D3E2016F0FE for ; Sat, 28 Mar 2026 00:45:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658755; cv=none; b=hlAowLgWYMo68GiPw7H4oUdDb584Dt5NND1269FsqEltRafRcT7TmNduGSPlc2hTH6V7G/4cxwLBoDUUBYCxxZvE7RyZ8doG+fj9oOVFy43R4BG9J2IJCoj9gQxkEQmMuHAXMK9VIKfJXkcUia+ZzaYf0Bgc6HZOULRONkiR/jo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658755; c=relaxed/simple; bh=VY7znN3rP/XuecIcYOIeWnzhVhdmypuwu3Lu5HvoHig=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pFm6py+pxHjCjVnDNgFz78W9dkOyoyz1tGYoPyKqY4gCrmJr/vM9Bdq+/TDjOkQqAi9H5+2MheOR7kAEU6IAADJYpETkzMdIBzlxEnZewEa+vVIso03SOPytfLEdeTAAAN5own+qMBQeF+thMyXWQWZDpYu0HUYZ0b62dqWNpNA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=DYVKxw++; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="DYVKxw++" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2b0afa0210bso13700035ad.2 for ; Fri, 27 Mar 2026 17:45:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658753; x=1775263553; 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; bh=+voUH76g/Pq9YBKjG67uJM4aaUaY9JLa+bj+ayVk72U=; b=DYVKxw++FU98boXySbfp0riI2uf6/IBXMIjctxcN8IO5TjQb+C6zkfg/gpLeXtGK8I N+iwXuR+aN6JYF16v+XzqpR+WclFCj8bhDG/hIrx+IYMTDeJxRKbA52q7eNfQPgHZ2xT qcsKiTw0W6w5BxBjYJVmokdxvP3J/cf/ELru9KiSrGM68gZS50JJKyCs90lYAnD/t+Q2 4LkvIeZgg+OzDBHWQT56hPRTqnYZ5BkzW1uWBcpWKG8b7mmm/vh5dUczK0xucNjiUPKQ n39R7E8pSgPQrtbUjUKnxl8vYGjkKeXKn7iOTqNQWsYGpEVudtHqLD0YNkcGuKYLh/p8 ggVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658753; x=1775263553; 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; bh=+voUH76g/Pq9YBKjG67uJM4aaUaY9JLa+bj+ayVk72U=; b=qIeW+9mdrDwYnZT582fbYTsqA5GSICP+MUvbW6ZzaUBQGUPIbBi5JijkNn0pZnH9UM 0dUTNSuE0Xy3bfuFoQomAkVmM3yH7s1lu6XZp9ZkYjNOEwmXtf6m3WiWh0Zbpe71cX5b zBxAuau8G17SZPmn6O++OqAFK4kdymCAhG1GPsnIB9BFI0NxR2vUkcqXr+FXEkC75pA2 yqhmd/akyfEnM1QoiSfdriGexQPJtDRXuzmtPsqAYb4DRdGnphxKVCEBYugCsN5EmZpO hUi/2sFXu5l180i4sVbKOuL1wZcYKTOjKa78p9RO3FNmc58Af7sg4fl1ty3HGoB8pgZC Qz1Q== X-Forwarded-Encrypted: i=1; AJvYcCUIR4W8yWC3dRvTx6O2mJZjG2HwHuh52xzMCNRTeTROWv4BCfFyFLZcUawVRBtUTTvFsBjQ6Lb09n8VMyU=@vger.kernel.org X-Gm-Message-State: AOJu0YyMzMzeDPrFPNncDyLmijN5unMXSzTcYj33TwbpERNFHlY0a4SZ cg/x7zFO3LRKiwtNl/nNNK/QOn+DPJhDJ2DVnNY3b/Q4pBMoJsUtCDyzYK6+eJJN/UM= X-Gm-Gg: ATEYQzxiNXnHswsX3ghPnZrakCh75FgXuXg7jIMD0MatNJCEw1a8+vrWN3JjEB30ZuN mvhfdHSowHsRED/BoUW7/TasOwos9VmltAEPDpGIJDe0XOLvTqYEN+wXxe21Q3+nnK77w8mxsc/ W+GvmtQNO1FJYoyfUFkjaSKSWFNUAoef7PdNqQdxnl9HYuLnzJ1A2Tu/dD6IfIWlopK8nuK2QyJ e5cAGxbg1Xz0AxG/zp9yNcrek3yTnnqxZV8rRvoqGDoPBan/sq8gtf0aZoAAJSidmogh8SKcHT6 iKoNX/FE75qgiYZ1NBUm+eR8qekJM1TVG9hELoAx5Gux5kY1eAVPO6s1YR3+A3RKDutSNeEIUWD 65Q3f7zipekqsmV13QFuaRJALqrSFyx5V11jA4KTwnKK5LN0nFDbye6C0ytiI3WGbbIxJ+Z6elO GDlmnX6oU= X-Received: by 2002:a17:902:f710:b0:2b0:5b9d:4559 with SMTP id d9443c01a7336-2b0cdc764camr45037225ad.6.1774658752845; Fri, 27 Mar 2026 17:45:52 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:52 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 02/15] nvmet/debugfs: Export controller CIU and CIRN via debugfs Date: Fri, 27 Mar 2026 17:43:33 -0700 Message-ID: <20260328004518.1729186-3-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 5dcbd5aa86e1..1300adf6c1fb 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 int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl) { @@ -184,6 +201,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (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 3E1501C6B4 for ; Sat, 28 Mar 2026 00:45:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658756; cv=none; b=QiDNmmZrA5orvU/e7ibkpmCZF0SwRZ+ujLrzlzMBzVcn39H33cZClDz9y+jn2Cg6Xxz877aLcp5yw/jyc0VpE42PSSVynFWMsoWf39I9lohTz7jdEp9Qal4GWcZ3OwEFrYUIv+RKXjB6qaj54lS7imHQgEqj/BZ4U0//GM+27ZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658756; c=relaxed/simple; bh=DeedujTPrEtZADIb+NjxFrdGWc1mDzs4lo5jfHxZiRA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kxrroPYOwskRBGlmbkT33wPQLpBy1KMUGBwj2iivqtdxYuPVFAZPnsP7D77oQ1wdCjoinPrIzkF16DFn03fCiilrSHHvdilYqfwKstuiQYW107al8YNUqtA6kX2w6yzWVsbaxqUWGDFv4kgOcFMa+yEt+rpvImhH6nkkF6Wjq5s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=M876EIwJ; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="M876EIwJ" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-2aaf43014d0so18073585ad.2 for ; Fri, 27 Mar 2026 17:45:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658754; x=1775263554; 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; bh=u0vIN98NbTlxUWbhWQbufIdEJ8esjoER7iKpbr4c9ZI=; b=M876EIwJHm/y0N+j+ySoqYDHIPFXyFJS3BVx5lViHz3jg4JcnLLcvNrjqjnAU2B1fK e9txhL4vPGDulVrls3HsrHJ68ZhJv9HI49VABusTBkE0LtED8kMJ5E82n98SceAAnebz /Xoh7cuFzoqpJ4AblKB+AIGQRtidhjwZMuDUgZQT9mv9pQvmWRjV0Zz0zkT5WzUfeigd Yok83mNWFwbbPGzsTUHDowP7ynf6HCenm/maXDOp8t6HurFDP4fTunq0aR3GajQNOo1h VhvMG2+akxLZOW88VsEdMF5kYwEEySJdefnzzX6k/bZRdY3EVAmoomfKTHiDPCOlErHW gmVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658754; x=1775263554; 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; bh=u0vIN98NbTlxUWbhWQbufIdEJ8esjoER7iKpbr4c9ZI=; b=QRBbAQ0gy97vR5xGa7y0BwDLg8cuEe7I7dnKxeadSuLl2VtXvsa4txE3/KIWNTXBbT O7GPUapI62FwqfAHtAN9YaU5AlesPI03/65S7zPesvMaF9JThVgfbCyF1dCNDURyDWzk vciEJRedZKu6aKWlbm9zYxjdoaxh/jkJi2+De7AO2oUvcFN3m32I7U9CCRSTKJF6Z31t hQRoJcjNGFh0Iswx6U5hTT6JcMofLrSckGjilI8eCJk3qoArDn6PnCCNzNRJyNsm2RO2 QEqVWpcV3n/iz95PbME7xMe8Hos3AN2N9drWGi00ivO3hM0qWWKPS5fZveB5W58HVNBE R1Zw== X-Forwarded-Encrypted: i=1; AJvYcCW7hdVzqr5wrbtWyUU5Bf9UpljzwQvOpnCii9nixxrYmYNUpCdcwzpxw5St+QH5nX1ZZ8UFszhNSL9LBbI=@vger.kernel.org X-Gm-Message-State: AOJu0Yyo9380lV/uuU4cQq+qJ5icYvxOmz5e/Y1YlMvHxioodLGKOwNL qRi0D9ZI+kAbBj85m8J762t3+kc7V0iGnJFi1p9vKYs0UEj/5xY1DlKtx5arIImi6fU= X-Gm-Gg: ATEYQzwcoZmxRcAJ4KAWpyl4pWBw4EOqOWEOIyq7jnTDkPpeJLDPPwsjVqRw9AwQdZ7 SdT4A1lh9i4Vs9h/wiVVlJEPMt69hVWQunpwZyvKxngZIwKUyrQmH6n+UB1wO9sfkVbWmJSqRT3 KI+Qk91RNiQVnzhATsVJYfJ9l2YgQLFEZbPGGtQ9iPqBi46HCD7vvtUXDfi77ZNFKjikxVX9yeP N0XWly6y6j3uhuW9Ux1s70BAW9z3RpejIWfTrQ3DQhL7rwYsoYCLVxm9pCN/+DT8ZMzE/uVYBYL D+eZJV9y1hINse9AlQtbnV6IZ5xESdUIsvfqtHklg11/8nE+ZSd1iWd1kGD37WaVElGTeqyS8h8 QmA+2SRYyWPwTPj6DMnkwloA95YLi2yFLtYG3sXKubjZvPwHCDZsB2dNRwmIU0RQEHml/iCR5yl wtjy1cfWE= X-Received: by 2002:a17:903:22d2:b0:2b0:52b7:e82 with SMTP id d9443c01a7336-2b0cdc281ccmr52223235ad.16.1774658754195; Fri, 27 Mar 2026 17:45:54 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:53 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 03/15] nvmet: Implement CCR nvme command Date: Fri, 27 Mar 2026 17:43:34 -0700 Message-ID: <20260328004518.1729186-4-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 --- drivers/nvme/target/admin-cmd.c | 74 ++++++++++++++++++++++++++++++++ drivers/nvme/target/core.c | 76 +++++++++++++++++++++++++++++++++ drivers/nvme/target/nvmet.h | 13 ++++++ include/linux/nvme.h | 23 ++++++++++ 4 files changed, 186 insertions(+) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index ec09e30eca18..0a37c0eeebb5 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -376,7 +376,9 @@ 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 static void nvmet_get_cmd_effects_nvm(struct nvme_effects_log *log) @@ -1613,6 +1615,75 @@ 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; + + 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 +1761,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 e8b945a01f35..2e0c31d82bad 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; @@ -1399,6 +1413,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 @@ -1504,6 +1519,35 @@ 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; + + /* 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))) { @@ -1629,6 +1673,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); @@ -1739,12 +1784,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 2181ac45ae7f..b9eb044ded19 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -268,6 +268,7 @@ struct nvmet_ctrl { u32 kato; u64 cirn; =20 + struct list_head ccr_list; struct nvmet_port *port; =20 u32 aen_enabled; @@ -314,6 +315,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 @@ -577,6 +585,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); @@ -619,6 +628,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 7746b6d30349..bd3b3f2a5377 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 @@ -1222,6 +1223,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; @@ -1320,6 +1337,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, @@ -1353,6 +1371,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), \ @@ -2006,6 +2025,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 @@ -2170,6 +2190,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.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 683B721576E for ; Sat, 28 Mar 2026 00:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658758; cv=none; b=CX8E72OUEKHPnbFNnY1krmi/rksIWTWfqVKxT8Tq12uQO1V074w8Msbi6AvKaW1jKRDOvDtcbz+IndZNausK/iSKlNHXTCCiSE6xtLG8PevYAdPDuIp33S796d1r2aorSrJ10AA9nWR0Gjii6ccY9sy7STAXyjb+Ncc89K5GgM0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658758; c=relaxed/simple; bh=pVia+VbYshhdCkgCTVvcSNQ38rlKKVfk7qYdyS488wI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ki6gpJL8p6p+hoUQ7c3zmdsrBcAcEOzmXEcJO047Bjwsdh99NfFcYx5MSP0sklSwxvlU7m6vPOYz4JpVC3upLzPi3NdZzV1z/tbrA8iQcwDo2+8XaBVIg4qIePzmKSGJv2QOYyXX+aCFTy1FcPlY9TtCGXJv0c9oL9nppHXaGkA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=ABOVx8G1; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="ABOVx8G1" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-c76682834a3so1123253a12.3 for ; Fri, 27 Mar 2026 17:45:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658756; x=1775263556; 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; bh=nERYj0eATMlhf7gB6O2MeYTzi4vYF6Jp5+hxczBe0L0=; b=ABOVx8G1qN0dP5vooCBECTN3bP2cwO13MU5cAfYPoyJ+wlWaSvfZFm5KYjyOgxLIHj k2k+f1STVqHKa0GWHsSVG3AyMbF4gOFNsGFUDZHs8JQe8ubmVAzPIsPe4jitO4/274EG 9atI8BSrt3Bnn+r6yRVwW/m47QGynivuWryEUS6wTj5ZL6In5cWH+fic9NMtD3ZddreC UaNUBxwB5aRaqkHKj4qd+JgcoK13iYcn2RZcoh1Bc2uWJBRx0hn6ID8Y+/awzSvJko01 Vuwm9e9sgC7DMMpz/dPYwIOvnqeQwQCDGqBcHRdfAzmcfapnKGEg/sYhHvvLavOYLDs7 34Gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658756; x=1775263556; 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; bh=nERYj0eATMlhf7gB6O2MeYTzi4vYF6Jp5+hxczBe0L0=; b=oNBm/e8guIkHHQsQuJ+mQ/JsbF75sRaOFB81r+ebj4DgZW4Gn4zu8udwQxrjyNMnCo WxWh28uTEPP2Np9934LnBHaPsAwE8Bhd9M9UtbHhmUAu+UqJHX8+VMYW4fzPszFq0Qua ceb9WNdRMn4EdzjMeGtV/NBv1ZEhlreas1J6wYrq9OP+z9iYjNTH+7uYLDantvOfnuzG AUZK5dMPEQmt/xo9PWwnEpI78Fu3Qw00fY9wIGO2ySydxXh5rf66V0ioByTMA08raKVX zfOOfCu7mG9JvFk+ZYRZygCQjeA//+Tzh3TcSx9uAmWNWwRNCNYCzowd1WiBrnxhy/Eo /49A== X-Forwarded-Encrypted: i=1; AJvYcCVgy92oST3M/DmbSh35tMJxECYlrOJn1DFO7BIOLe+xBr1FDmJin4Olmu5Hg3gjhf2oXnEYtdY5+plhBp8=@vger.kernel.org X-Gm-Message-State: AOJu0YyKGgg8gYoshZwuJ/9xjH5xl9ZjC1UaoMKDJYDcmMFYPIB+p405 sHn+G484WJ+gtMV/zuioBq8q5KIzFirtlvReMFUpGuGHvEK3OsLdb0iMsbY/VOC0m2w= X-Gm-Gg: ATEYQzzbjAKL7B5PRKKzxu/0G3S6+53BJqY7YdBG4gm/7wc6uWCr/ZVRn/lM0LBxKe0 12F+pm0bT6Xl7zF78YzPLbIBvMkXYt/tfoiVhSRG86Unflp8ZSzIsOO7URu1QCJOE+yK122pw2S nrDQapNNHoIFYHSP0JYRNjO13MtaX9Thnixfkne0vps6x2ZzE75Ht/fxjEUEq+h5Cp2M9CZnASQ bMut1TJsBXj5iEbZYrOjiYVSo4izil2hvO9IFnmk6q/8jNusuj84KrYrv4SoqlzIciLWUPgexck 2oYpzTvnmHXUjIfwNu+UV0vTDYCyPhv+JQo2L+rAeiJDma3MxOwKKfLcqtT+eUfz/AzTdZqe9Lr t6W6Tm3fduVXQg/qUHUV23PAb72v5Zj65wyvnjZGMk3tWbhAy+ZNtsSio6LE+2w+gylGj2RbLea LYOnk2kqM= X-Received: by 2002:a17:903:4b2b:b0:2ae:5e75:3821 with SMTP id d9443c01a7336-2b0cdc2c4d1mr41101815ad.18.1774658755568; Fri, 27 Mar 2026 17:45:55 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:55 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 04/15] nvmet: Implement CCR logpage Date: Fri, 27 Mar 2026 17:43:35 -0700 Message-ID: <20260328004518.1729186-5-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 0a37c0eeebb5..305a5d9b5450 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); @@ -607,6 +608,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(sizeof(*log), GFP_KERNEL); + 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 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 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))) @@ -640,6 +682,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 bd3b3f2a5377..b792d488f72e 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -1432,6 +1432,7 @@ enum { NVME_LOG_FDP_CONFIGS =3D 0x20, NVME_LOG_DISC =3D 0x70, NVME_LOG_RESERVATION =3D 0x80, + NVME_LOG_CCR =3D 0x1E, NVME_FWACT_REPL =3D (0 << 3), NVME_FWACT_REPL_ACTV =3D (1 << 3), NVME_FWACT_ACTV =3D (2 << 3), @@ -1455,6 +1456,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF62B1FF1B4 for ; Sat, 28 Mar 2026 00:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; cv=none; b=G2FMqHNkuE1JT2iHWayO2uWXkdmhGqALnKOF39t6RcH4qoAkSLLvoS6baBnPWdXa/24olStnFeZoXf/POUaLiGm6lcRrdZSfYrC+O3n/iFI1IK/1n8hqjG+EW5i0gh1+pdgXmz1BvNmGP8sbN9mufTZI16GArgx0OhTTpQ8Hjts= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; c=relaxed/simple; bh=SBozTM/ZJJfjFjQbkRs3uYTNSltKV1TkjdjaGA65YT4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qKvBymzM8r+yXs/XuqWo9JDzar3MQGczuPgSa7FryVPv3iObyc9NbUYRJVqcIsBGPuxbHXAo8JOmb52RQO6IM18WRFIgDfm0fw0b9YstetDMdBOLFLfxMTubI1UorDzh7DwQaDZ8FIbR3xU1HP3yY4GgJNRa2nmVyhclZHZJRKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=epd9LjMi; arc=none smtp.client-ip=209.85.216.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="epd9LjMi" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-354a18c48b5so2574144a91.1 for ; Fri, 27 Mar 2026 17:45:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658757; x=1775263557; 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; bh=gNe2anjf3U+8vvrDpf4bS35uyUrfzt1FE8OQuJB51II=; b=epd9LjMi3zFwFdwCMzgjBvFxHDcxXtk763Ars90Xo3M5Epmhu/aw/N9gga9zVqHTBj BTO7sE1GUyaexR/5iSr1E+1WjlbayM8WvI54cI7UcvE6daILkRCitByU77IQoDjm2e4O LkghXkxBqegxt+hA0WSeWzsQAKg4/PLEUSDQNV0Omwls4HtSzTJuxInjxpczmVjh0/jd 1rfcpgnBNJYJqdzjXmh3i2r87eM5dzG+ojQFZbx+5a5aBB54q5Zox9jMsWgk6QqnCJBy f0jAK1fqfZY24eI64uMwSqLTqhWEwm9HAVyzBBdU3xBM1P3HkIYLMIoG2pnfo+XF9Mr2 Mr0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658757; x=1775263557; 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; bh=gNe2anjf3U+8vvrDpf4bS35uyUrfzt1FE8OQuJB51II=; b=UYwYkk8m39hP8hV9+8odI1KS6dcf6mESBqlJYM8NmfHEqpoGHJv1UzgunLpmSod+wx ZUeZQz5P4X+6XkumXL8z4N4NUjAUi1kgXNTLD2LJ2qk0usYtVqu9+uktqfim3x8Snj+/ zB5Vqo6kiaRxw4vY2XoGErkjdqLnn1zIYkHMgscHx4PHsAFvTlpqLlSgD2hQIgQ+QG5H ZNgS1HiY0oLha2zXx5hrKDXT4Ong+ADoXDAEKZ1ShlLaG90lfc85UXOKYoiCYyJbrp8L np/Jgo2yGE+TkZSNRINgf5P60m+xjerUIZ7kTVRqJ7bIr4ts4QyeTIn9jDKS+aZoPgHq Jkyw== X-Forwarded-Encrypted: i=1; AJvYcCU4a7Ixt15xLMU7qWOCSdHA0TEiHQmQIo1DX8F6eev5spNDoCRmkw8nPqz8On3AoXiz6REE6KOrcUYJUck=@vger.kernel.org X-Gm-Message-State: AOJu0YzGu8WgdFPbgKpINaOU42Az3sXKJoSqYcCjXotCNer9IegmYJvd EnoHAEQ6Dqrcs13SMJ9PoBxrwgoAP3o0LYJUJDkrqCj6zd3SfBtYPBTW8Vhnqm++atk= X-Gm-Gg: ATEYQzyyfGypF4R3kajfml2ppWUrxTErVND3Z0SuTiJjzJnjrpdOCLuz6kV3/xFU7PK GNG0BDSmWb6d3xgU9+uJzEZMvo5uEdBZOnDTiLwEZDhWrt82n5RF/J71ieeyHl5sEL1015soIvv McTsK4QupoBNxGpNbsHIZeEyi+rZIc6yxegAZuaWDa4qsGEkeRTJz0VPZUttKYEQbGOj4Gar/Lz ivgnONhk+0KFty3c+Av4fNXN5myquJBR9udS6UzE60zXpnES6ycarXjGfSspNtTFIef3Wkj0iVa 8ESmRPSdtg6P86WU9CLM+q6kLlE5K6jOsPych2diAu8vCAwOCDTH0h9Qj5no/IHbrQgTTL6ThBm 9GJJF8d4oHnsjmqQA3apE9jmZbu6yub05znxPDhd583ULIJa9SOHi8IDcXI6V1E7Q4ttUbG15Qq D2xeAjq3HlKDTwnEZB7Q== X-Received: by 2002:a17:903:298d:b0:2ae:483f:b23c with SMTP id d9443c01a7336-2b0cdcc6c31mr46778695ad.36.1774658756823; Fri, 27 Mar 2026 17:45:56 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:56 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 05/15] nvmet: Send an AEN on CCR completion Date: Fri, 27 Mar 2026 17:43:36 -0700 Message-ID: <20260328004518.1729186-6-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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" Send an AEN to initiator when impacted controller exists. The notification points to CCR log page that initiator can read to check which CCR operation completed. 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 2e0c31d82bad..4f1f0562cef8 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; @@ -1784,6 +1790,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; @@ -1807,6 +1825,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 b9eb044ded19..6546be25901a 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 b792d488f72e..1fbb5b268303 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -860,12 +860,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 @@ -873,6 +875,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 D7B26211290 for ; Sat, 28 Mar 2026 00:45:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658770; cv=none; b=WAIQ1gXPKydYoAyTN7GXbd+WiJYynzm7Smc7SJAFg03xc+j31nmKqCMg+q3jfPjAL/jV5BMPIHd991qwCK3mAjegosdbhlSarAhbqzS+ckNz6JNIeKepd8UKwapYhn0v6zm2X+qz4o3QEPCHwZASnusgus1y+wPJT5d87lzqA0E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658770; c=relaxed/simple; bh=ew2kVzBJghsHpl+0SnT+1OeTu964CJrGri7qAmuoVpA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XQLhgSoqduhCFK2Ch1+ImOk5FT0jcJGekz/kwrrnWOshEVvihCY+rWeVqFDkVvCXT/7FZZU95GlkKgnysiMRkwOy7/xoaQ4MFDN0ZJj2eeJ4OTVfVzvZhj1rWC0ri21ajYeuOe7U22mc6wsh4q+GxyuRKsZCm3YExU6POgmbnGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=HPicmm0s; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="HPicmm0s" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2aecc6b0861so17398195ad.2 for ; Fri, 27 Mar 2026 17:45:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658758; x=1775263558; 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; bh=Ob2hvujo7HUb7R0D4J+lODKhe78Bpwesdjiwn3j8SZY=; b=HPicmm0s499A0EXlSttmLfX+nxgdSt6jxn96xgaQwxQUv7nWctvogOs2qfOqvxLg3D /DhC8NfPJe1YAxCPZsBK63EFq0I0OuyZc88uufSqUaaqVEmYbnJF2/WPLUrp8w/hB+sY Jx6R8UXX27MoTpUeKkRkaAWR3IXvBkrD2Hm7WpIuCd2MLKDzPo/zDQ2ZZoM/ThoPTsMy eTxEUnJOEfDtzdHNvdT3bIjATLmXLbXrlzwp/leftM2VDHmsyxC6+VlPKSOBwL5RsEsI SZu9MdN+7HiMsAaL8bJl1xzXmv9kACXTfdOwPqr7J6zyGdx8326TmM4s7dlqLDwIy6GO m1mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658758; x=1775263558; 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; bh=Ob2hvujo7HUb7R0D4J+lODKhe78Bpwesdjiwn3j8SZY=; b=s4+bGZFkNo6y14QiKBTucglYDJIgFZMWb2CIw0MnaaWhky/Y9vibjx5OFKbcZmsfRB Pauwz3ITG1pjyf5rD//yd7tlQ6C9ecNANV1WEFabWcPOv0yIes83n6xEBGccqHRvJ9Eo U2/5leYHOgF4XkfWD8YAaUU2s6pDNbedc/F2E9FyGMD1exhR+FV7ktCKe8rNkzESOKFc WbP2znCH2TBf6KZQQ3CgoVlCR1WB0jYpEUdQKm6rWcA+voK/42TfnTKDXxApfHhu+bDc tETI6beDAmw+UGEbzVE/hB62fxQIXF9i32LWG12N+aoRjcfnQfKe07LtGeYkOqTLQ6b1 j4Ww== X-Forwarded-Encrypted: i=1; AJvYcCV8vVq2Jhu7d9gzXd6aRW+PGKqNZodkR34tlZq3Dci0Q3E12/4KtCLOyQ2TmllIW/Ajm1JfPt9b77xXOVk=@vger.kernel.org X-Gm-Message-State: AOJu0YwWDzqGk1KWZB3PW+rFXsyd9bkwbvbgcHsl7zf/qn2bgyhEEeMz fFfNbWcbhvICtB6egRZxKLklTAvqCg0pl5XUP5X/WZRQRdVYu65OyRIIxNCW8Jsr9P0= X-Gm-Gg: ATEYQzz+xTSv/5DZWEssPhHxQKlilTo5UJK+lak6m3HMx4ekg/GcLn2GLbyn14XB1Cd N/6j9EsjDxlu3MGt4BE3f+d1IsLv8iTpqh92Jp1zUqnmLQ32mMRvFgSnOJunrzqzoMiGoqfNcNz vzNXXCx24rhgBX40XXAMXEPnrYlqICz6w9CdxxVXR05AeL8YHUo591Jgrai971XbX+NQmkb/ktQ qgnKfA4T47dsvsG/NWM67CvL4j0hQpTH5nTiOxEp0GJv2p3wL9ALfsTcwNeRS2noQb9BT/kw6+M ethFl5NX8PjiioTjo9ACUVuzVw2nTVgS4voO+1OZE/W6jRngiGJ3eVw/7mMThI2+toiXoFy6/l7 d6Uc6XS6MvaH/PT2QY8Zf4r54lZ1SbMqlq6wJnBHn/W1clelFqL+ZoVty2V2DfY1r1lXOiRvFdL lawRv74FpipFa+K+wzGw== X-Received: by 2002:a17:902:fc85:b0:2b0:5990:cf1e with SMTP id d9443c01a7336-2b0cdcc8706mr41302025ad.33.1774658758053; Fri, 27 Mar 2026 17:45:58 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:57 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 06/15] nvme: Rapid Path Failure Recovery read controller identify fields Date: Fri, 27 Mar 2026 17:43:37 -0700 Message-ID: <20260328004518.1729186-7-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 fileds 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 directrly by user if needed. 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 766e9cc4ffca..7a07c23aefdb 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3567,6 +3567,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); + atomic_set(&ctrl->ccr_limit, 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 9971045dbc05..234f3872a212 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -382,11 +382,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; + atomic_t ccr_limit; u8 vwc; u32 vs; u32 sgls; @@ -1280,4 +1283,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 16c6fea4b2db..f182a26b38b0 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -388,6 +388,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) @@ -756,6 +777,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (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 47284199949 for ; Sat, 28 Mar 2026 00:46:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658764; cv=none; b=XttnaN3N3pU/RpNrUc9W3jdKJl/5HFBbGacTuhbMAm6kv9V7LIEpUjbywvg3bRlCoHfOY7cm6iGXLzFkwbWcXyF4AVIoBcM1C/OamMzaODFcexGiaU9ptUPdEruXO5h7vTxhFh2VqZDZ9UXPuQzwh81h06ehXdk+LfzkbeDZHh4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658764; c=relaxed/simple; bh=JfRjWSh3fGE6CuX2wYVsLvI7h9H5gjFJEgAZriEnmQU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TY1hat/fIZv5mImGhE9rTJTIbbNIVyeGTxTqPI0BShC+sVqcKa7kTXORqIRE9KS1Pycxfd91oGabw8gJVaBhaQSLK/IPbK9/XXrdaf56lCLXCDfQsgsm/ze5QQUt2lIQEtmEWRacy0fdm5TYIaiZ0vIMn4D3aF1rXf9MsOvff4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=O2qcCCuE; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="O2qcCCuE" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-c742882d2a4so1186519a12.0 for ; Fri, 27 Mar 2026 17:46:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658759; x=1775263559; 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; bh=ddfbk2XDqKMxw3Haokga/Yx24j2zOVvDwNay846hLWQ=; b=O2qcCCuE10iTvPE6QSo2UZ2VQjVGaVVNoQtpJja7YHcP4i5G2pCyAJFXgv+H+Ak7vM e04ZdqrVJXyquMCPPUIi7M4KRH4eESEjKOFnkFZBZuHe2VEoj4HgCHXCEUCEdGYKV4lZ iMsDlOR+9R9Fm6NGeompxivrMWixM+oWTdaZDqf+zwxc/4CinnwMQGDYymwgE0TQc83k dfMw24p3rHvMPHZqy2FjaMxM5VxrZULnsTJtxuxAftK7PhdHUcnGjmLr0aa8qexPu57U 9wUGqGRvkihOnq0QUCC4tpU59Zrk2ZHwvHKEgjzSngbZOP3uerYfTlaEiz9F+3c3X9M+ M7fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658759; x=1775263559; 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; bh=ddfbk2XDqKMxw3Haokga/Yx24j2zOVvDwNay846hLWQ=; b=bNZGn6gjOU3hZlW3khlJvD9ofJnpVrOa31WnBRTL9iIyzjxRIWKKuRCCAZxyNhTmSS 45GgldlG7DOXEhzTf2TYQe4V3LlW+BJXQTZI0WYiGVuvR7QVTqme2MCwyazFy5gfGsJ0 DlIdseHPfTTSzwyRC/+dvPyB+9sKQF9kAuqGk0FG17E9UFRzzDhfeHDN+5WORIBkf9a+ nXjFDqe8wi3LUgODPGHpnAGCgLl367oPx5e3NJS67bGC1xK6wfhVHo6/m8QUOpUz7TRM gC8396pVnS6sbtZdNaGca3fGGZDWOC3A2gGSgx4ywFp01NeHh6h59eWA0npL7uk9Y5Zv /Aew== X-Forwarded-Encrypted: i=1; AJvYcCWFWZzTJYpncjMGM0g8f+zjPvQRXPwSIwr1y6g1XvP2dU2npwJI6mr4L9cFZP8FVAWT+BN+H4xJPt/3DLg=@vger.kernel.org X-Gm-Message-State: AOJu0Yzo4D2O6kQJSED0CMc83Rsym2+7eRpVCYBp+kVJkp32dQ3Soaae b2/tEr5RkQ/i0IZYMA1cqUwwZQ1JmUhDIxTaXvcNlEpyZGIwaU8hBt5M33Wdr7G5rXs= X-Gm-Gg: ATEYQzyYwHWcKvLdW3MSpa5GNiGRziq5SIHwYh1ei0g6xqfA23tZWX/gfYQBZ5sxjUc 1SgtWZv3ME4GDiewe85STpxQ4jZL0lltt9IF/Awj1G2Ki9YScUxEIpW+6mvMKZBQgKuhA+HW7K0 mxr6jeHXxkHIk+SVZT2JG5XxpsIZWKnaUfN+p4KMiz3pqILI3m5Z8ZlsB6+ISWa0TBBJAX9mGQ7 HZIK4doijgDWjy8t/UtFUTUXqV4QsHu4hE0ZcXanEksiD29vTUx0R3rbfi3RCVOLCzsPdYVWpSQ bE8IETSsv8/DCwynZVZaUOYvoKICEQS7WfBN0ymzM1e1c29Vf/1OESP2Q4ARLmh55USO+bxrTXN 7fHf1PodDTX3FX4nUvEHEWHqv/PwXFcm2g8FPZg4st16Xm9g9HCyy0hqX7MSEB567NsdSZIFdaz lXA5VTVvA= X-Received: by 2002:a17:902:e809:b0:2b0:5cb4:d89d with SMTP id d9443c01a7336-2b0cdcb05c7mr47028665ad.29.1774658759359; Fri, 27 Mar 2026 17:45:59 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:45:58 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 07/15] nvme: Introduce FENCING and FENCED controller states Date: Fri, 27 Mar 2026 17:43:38 -0700 Message-ID: <20260328004518.1729186-8-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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" FENCING is a new controller state that a LIVE controller enters when an error is encountered. While in FENCING state, inflight IOs that timeout are not canceled because they should be held until either CCR succeeds or time-based recovery completes. While the queues remain alive, requests are not allowed to be sent in this state, and the controller cannot be reset or deleted. This is intentional because resetting or deleting the controller results in canceling inflight IOs. FENCED is a short-term state the controller enters before it is reset. It exists only to prevent manual resets from happening while controller is in FENCING state. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- drivers/nvme/host/core.c | 27 +++++++++++++++++++++++++-- drivers/nvme/host/nvme.h | 4 ++++ drivers/nvme/host/sysfs.c | 2 ++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 7a07c23aefdb..824a1193bec8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -574,10 +574,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; fallthrough; default: @@ -760,6 +779,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)) @@ -802,10 +823,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/nvme.h b/drivers/nvme/host/nvme.h index 234f3872a212..45e58434cf30 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -305,6 +305,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, @@ -831,6 +833,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 f182a26b38b0..6ae29fe431dc 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -443,6 +443,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.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 42EB618C2C for ; Sat, 28 Mar 2026 00:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; cv=none; b=PDpI445kDlF7mJBMOO/fb9xx3GHYo3IfFgYcdK2DJuKQm0HhdV1yNju1uCjo9O+H2B1l3aeWPYORxXrut3MFVueLzvzPD1cBctx9rZq/9gvdmVTK0lORYtUQVuFbaUkujAJiEuxZzNn2i17gEc1abEnKuixj7Kob92EAy7EaBak= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; c=relaxed/simple; bh=+EfEKxMzGB5oj4mlMMp3gM4CWJeF4oBx6URQhMBvl/g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RM7GR6hpgKl/nPg5uDq01ML17uCnzPr7V7OFE+9cPIH2IyCTNs5OTsdKM0d2YPlx7L3FxNv/QSEyhU+KXX47/NgJFE+OCH76Jslrk8ivYufEOvAhEk4no2XuN9dqtsDCKG70rufNIX2NM3vsGfOHvgGdC+gHmSTkomK0HvkQEvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=RpWzgF7L; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="RpWzgF7L" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2ad617d5b80so18622865ad.1 for ; Fri, 27 Mar 2026 17:46:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658761; x=1775263561; 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; bh=q8007HwqSMobBfviM6haQwWqU81fF+x1NKc0cN+3Dhk=; b=RpWzgF7LdxLY84qR1UFnI7f8tj3yNy8Hf2GUArrZR5m9EneorYboTyE/jcT1kWC45q mE3MpIusXoOZde0ai914AO2tZukrmAU3xRUD8OFEAMAxTjn1Qpu867z97J8xqw8DR480 Sy3pzvL30AI5vDodd9BfrRhYqrt5IjtYucl8ARXhkd/7XDH9HiUbcxaOTgE01Q8Y8XsG pnTvA2wtwEIgQqEU6jo89FzkBrJHSdmvgz/WjOx2n6bT4i0c5B0T7BjngQkQYEn1Fxxw KFzbJ34vU825v6GuNNtKGtLkkCEDOgaOAFBMqJPAtEqghRQxaoQbt4JlUenbt78yDStD Gtwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658761; x=1775263561; 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; bh=q8007HwqSMobBfviM6haQwWqU81fF+x1NKc0cN+3Dhk=; b=hOE0JAXTTMHlsRNpHp4Lu1fptxieOvZjYOnPe29SmOHthi74pLzZiouflF4Xl1trJu GoY40OfmrdJCLceCdmKCDG1xvZknP6+Y2JuCeraZvRAJtrH/UXIq2+UXIO/zXxINuPIj MaAMUlpCYz9XOCPs7s5p7H7nDBXGhvAGWa8BGlsTM/7HCoXPW4FpVbYaQ4MEEmK0nIXh nt5l77fydsvwlOO3xPAqK9sA02hbxv1aabYZCqWB5qNtRMe2W0kQ6QPsEkRooiq8bP62 op8ZLex6R5wR3KDLYKbfz7wpeTb/1GXwg/VAvHsLsLwrNDstBBmqmsQhC38buD+VtA2c NQ6A== X-Forwarded-Encrypted: i=1; AJvYcCVatub2AgfyAV20pD1NfYUlE3d1FwhuWPecwgam470RnISer9869AYDo734274sPQIdbD7oGu/4TRZrosM=@vger.kernel.org X-Gm-Message-State: AOJu0Yyeopnw155t/1A7qmyZi7av19m7rnRg11CxXXs3k68+thN91bK7 JUIMARK10HQDq4pMmDklQqbDApnEfjtjIWDm8UyNpIpH/0i2gKzizZ8Yyt2BLLVBuys= X-Gm-Gg: ATEYQzy7aaVjimoddi0beDtM06k37UgZNTJp8R7no1Nkhv/TYM1dffBpq0J4cIhwohu OnRoKQpTkquwZC8dDgnXJ6Xf2RFAmA21CcsW8pJPSDDE95Er1259O/hCT0JgR3bkA/PbqKvrLs5 sCa/W1Qn+w8MqCYtfVz0RRc6uANmFStIDIogfTK5q3wL09Hp4Vc7/acYIwwM46HENyc2tAw4KxZ Yhi6hab4CSWPUEC+DURcTdtFZXGo6Iljr97m8zR0sRb3NujLAkWdT4RQNW+DnpLMm1psbV+BYr0 cL6Qa8wlNx7AfhSTovJdviSZbzSWikbiXwyfL2Su7FLH67v7uvMjZzorHQ2sTsj/0eeAYVtgzoN 0qRoOXu5m0FlzVXeNEO6qFOUemTMHtEhVnnbpHbXVLPurDG8Ss7kiUD62fnP80hkECKAxs61fHi yrgr+yF3I= X-Received: by 2002:a17:902:da91:b0:2b0:5ec1:97c1 with SMTP id d9443c01a7336-2b0cdc238f3mr49523395ad.7.1774658761285; Fri, 27 Mar 2026 17:46:01 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:00 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 08/15] nvme: Implement cross-controller reset recovery Date: Fri, 27 Mar 2026 17:43:39 -0700 Message-ID: <20260328004518.1729186-9-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 --- drivers/nvme/host/constants.c | 1 + drivers/nvme/host/core.c | 145 ++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 9 +++ 3 files changed, 155 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 824a1193bec8..5603ae36444f 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -554,6 +554,150 @@ 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; + + mutex_lock(&nvme_subsystems_lock); + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) { + if (ctrl->cntlid < min_cntlid) + continue; + + if (atomic_dec_if_positive(&ctrl->ccr_limit) < 0) + continue; + + spin_lock_irqsave(&ctrl->lock, flags); + if (ctrl->state !=3D NVME_CTRL_LIVE) { + spin_unlock_irqrestore(&ctrl->lock, flags); + atomic_inc(&ctrl->ccr_limit); + 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_inc(&sctrl->ccr_limit); + 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; +} + +int nvme_fence_ctrl(struct nvme_ctrl *ictrl) +{ + unsigned long 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); + + deadline =3D jiffies + msecs_to_jiffies(timeout); + while (time_is_after_jiffies(deadline)) { + sctrl =3D nvme_find_ctrl_ccr(ictrl, min_cntlid); + if (!sctrl) { + dev_dbg(ictrl->device, + "failed to find source controller\n"); + return -EIO; + } + + 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; + } + + min_cntlid =3D sctrl->cntlid + 1; + nvme_put_ctrl_ccr(sctrl); + + if (ret =3D=3D -EIO) /* CCR command failed */ + continue; + + /* CCR operation failed or timed out */ + return ret; + } + + dev_info(ictrl->device, "CCR operation timeout\n"); + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(nvme_fence_ctrl); + bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state) { @@ -5116,6 +5260,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 45e58434cf30..f2bcff9ccd25 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -333,6 +333,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; @@ -350,6 +357,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; @@ -868,6 +876,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); +int 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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (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 B1094BE5E for ; Sat, 28 Mar 2026 00:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; cv=none; b=s7trdX4KwUecvEU8snW/tbQrbSj3rg5da1GMXz2n8ewM8Zkz+TQIJVOE+4mnpsoLEXgzIAvQrmqunTUmHs/vgJjbH83oVM4Z89YA3ScGMen69yvg/SdkB3x4nYmlXOVsJCnU0DGO3nsdpwMR4jNxWHQR4vVP1DKt3RIS4ofiyxs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658765; c=relaxed/simple; bh=6cqFDrB8KRq7dnTBfZSRji5wugnlZz7D17R6KE5sxt4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TCVibPvcfdXFFa7QHzEjFnPgdWW2W95xg/cGwwkAHECj9sSmexoGc23embWw76sVaU0ho78MlyN3daVzWptczbHZfW3QdC+egiafGM784vXjUtEDHStB0Ipy41diwCY7bQsNGfYTxyoNYL9eCdKguufNjHaHJ5sC/B/zWxcGfUA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=G+ZujE6e; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="G+ZujE6e" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-c73c990a96dso1321346a12.0 for ; Fri, 27 Mar 2026 17:46:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658763; x=1775263563; 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; bh=/nDAL62O5QKen/7e1sgimEPwC/7mFESAeMSDPIbvcrU=; b=G+ZujE6eUcSViWruTLGOyCIG2i0eWsaG213Ujj/d5VoMGRZmIGNciKK2F2n7L5MmaV JcTcLRntthdxLnVng0Tf50i4CTxWqk03LDsvxmxtMXaB2U0iFg+Ihw5Y4EFjvE/1dIg1 4CLHz/LnpwyhGiso5VZ2skXaZUE1vKpPY+Ya2+07SdVWCv9gEmvsSgFnOmmxQBBEL/fR 1v4H6vnDoUIHuq5Y2+WBcVLGX2d1uSD5Qi0njevvJ2xZfGCRmK4lzFniXZT/k5WFQBWf 3njcgpbIU8FV8bVKUhf/lKD/zg1V6exLCCxG1zAc3By648SHqmE3lICgrzAQS0gOAOpu eHqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658763; x=1775263563; 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; bh=/nDAL62O5QKen/7e1sgimEPwC/7mFESAeMSDPIbvcrU=; b=IwIsTdjb9I0pGqHmge6MBFS2nXhMvb2ZkbXHbQpoy3i9JPaEs80naeJPxNIm6UDsjj SXA7Cs5chWEsusSOnU0BwBuUk0IAAGNwvaDVxsESpEV3Pv3wJYPYXPjBhJXVRmPRfp1g 7IdphwTYOcdKltH2gpYJwt9t7z5HtClIOlSQIROZQkHvyL8fCl0K6C7a/yAHYWPG1Yya lFVq5J7dLU4ZvEbtAP5mwWPNn+kywxRCe8+HuVYwewyQ6VIkAQs5aPWOUJ7KA8M6cOEX lkyvKxjcOeW+8d8w4sfYHwelAx2P5OYAkPTAs1jJxf/p4g0Ij56U0TqIj2XM2WNO3uQ3 du7g== X-Forwarded-Encrypted: i=1; AJvYcCURwB/EgFynwtU//Nxw0u4JZvzkR6xphx2ynEJa/blzvIq5oazObINj45y03hSDukyPHz8ofAJiCtvwpy4=@vger.kernel.org X-Gm-Message-State: AOJu0YymNxyrjo7qm3tPI+NMtgIvqrZChrAUQfaiyoHMoFTXj6uDh1oL izAQaiAun1DgO9FzRXOZgXRInPxkZfuSWwDFRDTCnMlcBCjKd9omizOFkcYqEKOGOsI= X-Gm-Gg: ATEYQzwZxT0qL54pLGZHgYhEkPIN0Tvl2LsHpLk7/MxUHiV5XQC5MrGqVqGASRXtAss 15NXZ+S8t/5W3Pb3c0ZvE116keixWrh7R85RxoS0DN0XKhZHo//9vxufzLpr9N/7e0aylJGNYDK yc3c2rRnjrYiamNjpukrJuKbFCTXB2Dkad+qyBVKTZE0dGiRBJY/jEZvD3HcWcnaRR3oB4VOUWg Pu5jYoYdlaGMd06b30kKmLHCVFaNfGV61AVrT9DW5N90qHNi+qqXlc5w2OxlEj13jsxy6HaTiD/ vK3NOTvanaqWhD62WnahpE3vY+VHRLhFW1Fcloz4Jc4anFga8VP2/d2hCXIgaUvoy4YVjb+j3bD NSqWk2v4y+I91OFqEdAxcuwmveORtSpVYMJqUv/lXepseIkWvrS6WR/2dGUMZze4gyuQIXXJ9Nh CYXMsY3Mc= X-Received: by 2002:a17:903:1a2f:b0:2b0:6a3d:36e9 with SMTP id d9443c01a7336-2b0cdcb73d7mr45524475ad.33.1774658762760; Fri, 27 Mar 2026 17:46:02 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:02 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 09/15] nvme: Implement cross-controller reset completion Date: Fri, 27 Mar 2026 17:43:40 -0700 Message-ID: <20260328004518.1729186-10-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 sctrl->ccr_work to read NVME_LOG_CCR logpage and wakeup any thread waiting on CCR completion. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/core.c | 49 +++++++++++++++++++++++++++++++++++++++- drivers/nvme/host/nvme.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 5603ae36444f..793f203bfc38 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1920,7 +1920,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) { @@ -4873,6 +4874,47 @@ 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; + unsigned long flags; + int ret, i; + + log =3D kmalloc(sizeof(*log), GFP_KERNEL); + 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); + for (i =3D 0; i < le16_to_cpu(log->ne); 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, @@ -4949,6 +4991,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); } @@ -5144,6 +5189,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); } @@ -5267,6 +5313,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 f2bcff9ccd25..776ee8aa5a93 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -419,6 +419,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (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 3BE7E288D2 for ; Sat, 28 Mar 2026 00:46:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658766; cv=none; b=jV2+iYcfNQaKpNy9ueyEwDCDjP6yvok6ZmAPiVhR2Sz5N4oYzlst9r6Pp8oCy4eJxVMtbTXEiTZ5bclJzXmfM5uKa8cmfbrIHVWsciSKxfrLdxKavZcYGx4G23gaayW+WI+/fjefmjR8IM/OH9w2/uWaUSZHA7/kh+Uq+IWwo78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658766; c=relaxed/simple; bh=AEuUeb/ACJ7hnfuQqcIGJ3IK9iaR++KVTnnr4J79dUs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hqLIV6+D+DBvl6+KAZQcfnI0KhXM2DMHCWYkae2pBrwjhv2v7eV/e5IH+ojAhHE+NzAHdmHlm/2ZjK9yONcFzA4uFr/3IUFQoqgTN5uwurQi/RpUqap9Jtaw22ckUEZm52Qd+aUv/amgl+3dE8FoaatXV3bIVWNxG+GY4qCccN4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=OZuWiEpp; arc=none smtp.client-ip=209.85.215.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="OZuWiEpp" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-c742d7c8acfso1246801a12.1 for ; Fri, 27 Mar 2026 17:46:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658764; x=1775263564; 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; bh=D4p3ffVPEhhvzgCSyBZ1x+AvHTOlODCgnogumXFocGc=; b=OZuWiEppRjd065LRk8q2Aus5ZewQPyzlKXJ5PBzw5SXUnTj53tvblIaNSi2Sw5gq+8 cG6Uo50jk0qBsCXxwNipNP4ujzXZm6WbtV8yjDmjbacUp4bVuCtocSjjtnpahsI14lSm iyfiYTiVFvLHtPUvM63Xi1B4yL46ptTHzFiigDJ6J/ToDw1+E6C/QZyFuN09G583jPI6 JOGS11NKg6F7/He/+g/W4FksYl1BdFlwlWvvYLwZbsHcvISQBqjrLZADaKPhe489Fy5U BnVzjyvNXAfVuXbAozZVK9Y50LOZxbf5M412sNVoZ+Prlpc4BVXMZGAXVDYtCaqNvygY DFjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658764; x=1775263564; 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; bh=D4p3ffVPEhhvzgCSyBZ1x+AvHTOlODCgnogumXFocGc=; b=Yz7o7t7JCW6u6n5sKRcbVnZ9SDkj0SlCVjWPjhRiTCZs7FEO6bIKDv1jPg065IYE+q 5WUahDrPBKdZIB7dQIPq0Cinsf63CM/8pxIJs1SI8gVaVw2l1wbsvaPFeSHuAIpbKzst ocGiUTpTgVo84eELLE1ft4W4e31YEwPWw9D0+wPkwnRZopV8dUV9RMPO61KjZIA3MH5M cqozIbKMy0ecbZZI8i24G0BwAB0phNphylFAg8TzIKeXpDAwiZ+6dw7oV6Sk6GgqFa43 4KwauyotqXeKWUdzuhZBC+tbkVW18Cod/wKnD55tf8EWI+E273uwBKgrdVCypnj0tX1J eGWA== X-Forwarded-Encrypted: i=1; AJvYcCXDUYgwWTXyOQ/zblIMzN6LYPFqIRnDikNg3ZRUZtdzz7rfN+q3PJkWZwFpmyEbNa6DHP01UXKO18Wh6rs=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+TK+G6FV708/1s6+jq+UNy81w8lNVKu20yzjk+eY7DmyFIC1I zYCyLwuUJZqX3qGUovHQlDl3rnvNkm8snALfkvkYbC0i9/Gm6lLQi+/479QyALlgT/M= X-Gm-Gg: ATEYQzzt+fPoZqnpsoJC8xMdH+8Po9F14Kz2oe9/hCglsmscwIoaNNMyUnpNfGvkX3t lrkzVYx8oC4C0SQAkvcx/w9nsxfPcyHA0n7IAOisiu0H1IWKZp5jIeKHHojQkbaUPwe1t3ChNTw VMp0lM79upoxZqXwR2zRZxqFhb6kxeCOk4QXdUN2hMSFmMKJ83SKF74UbD5tYHsd91ZJyTO5/qH kOa+mrvWOHWMY2hCzlBjKFnr5+E8TTZnumK5ftYbp7fjhpzEyvs99R2wimIXwLfd3dSR7hCq4hK dBbEB7nQOyfRICNQ0TST1A75j76jTj85CMt2vtDbR/oQ12K0jRrnnzu/6ZaQMtVWa6bhA7S/81+ wo4GE3RPiQ5FB+M0SrYV6KoXzMJmN/sUG7kDMTyr0cJ88m53rhcTFZg0SMkNDFXYDW4im7Rck/G JTxfBitqw= X-Received: by 2002:a17:903:2f87:b0:2ae:7f84:79e3 with SMTP id d9443c01a7336-2b0cdc40b8cmr45255945ad.16.1774658764354; Fri, 27 Mar 2026 17:46:04 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:04 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 10/15] nvme-tcp: Use CCR to recover controller that hits an error Date: Fri, 27 Mar 2026 17:43:41 -0700 Message-ID: <20260328004518.1729186-11-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 243dab830dc8..6393ec2b3b55 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -194,6 +194,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; @@ -612,6 +613,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 @@ -2471,12 +2478,29 @@ static void nvme_tcp_reconnect_ctrl_work(struct wor= k_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; + int ret; + + ret =3D nvme_fence_ctrl(ctrl); + if (ret) + dev_info(ctrl->device, "CCR failed with error %d\n", ret); + + 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, struct nvme_tcp_ctrl, err_work); struct nvme_ctrl *ctrl =3D &tcp_ctrl->ctrl; =20 + flush_work(&to_tcp_ctrl(ctrl)->fencing_work); if (nvme_tcp_key_revoke_needed(ctrl)) nvme_auth_revoke_tls_key(ctrl); nvme_stop_keep_alive(ctrl); @@ -2519,6 +2543,7 @@ static void nvme_reset_ctrl_work(struct work_struct *= work) container_of(work, struct nvme_ctrl, reset_work); int ret; =20 + flush_work(&to_tcp_ctrl(ctrl)->fencing_work); if (nvme_tcp_key_revoke_needed(ctrl)) nvme_auth_revoke_tls_key(ctrl); nvme_stop_ctrl(ctrl); @@ -2644,13 +2669,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 @@ -2905,6 +2932,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) (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 60F7EB640 for ; Sat, 28 Mar 2026 00:46:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658774; cv=none; b=S2SJDpFBwHq9idOfkNzJuTT6uI3rtQvWPmwoJMlVHqKlD+tIrbvzT5MhP8k8jbfIhV2iKZMYgEAXq9TkGCk4uG8jDa6KTwOTZir9YhDaRsdYFJ5mJCq8gqcIT2T6qwKfs/QbynpdibOceIwuXIbAF0S58gGTPpRJ07H+Etl+G54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658774; c=relaxed/simple; bh=uttmUSzuQZfkVe81YYDNVfzLd7NOuOmOxjSzLe90qZE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Jdc1r8n5MKSJPyCRPZqj1io11w0Eqz8Ew9Ik2qeeKsMQrDx+cHykrNtVY4/cvF3CIHqaGy9kCtlMUQMH8NyQITgPclZQ/0Vxe8Y7CbGmv3OQ665vUmeSLXVfJIjtKtVx+zicU8p3K1A7DTVngKUcM9ycGgCaSUvyEkaFqSEH6eQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=GZuW/bz7; arc=none smtp.client-ip=209.85.215.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="GZuW/bz7" Received: by mail-pg1-f179.google.com with SMTP id 41be03b00d2f7-c73a5473bbdso1130478a12.2 for ; Fri, 27 Mar 2026 17:46:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658767; x=1775263567; 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; bh=HoxD5uMALorP/CUpuT5YOO2jyxxdHWPhu3WHKWZf4sY=; b=GZuW/bz78jHUdYU4UXr1dOgiSHXSZ0mcC3+6TDgnIlGA6BSdsu+EHJKgzx3uys21NS cM3gSN2j8ad0nueZJoglswgMalaq1ln+WE2/UPMusd9W+U1UlXY3RQHnhL6xB1+ip6c0 qdyoRdJmSnQwUfgo9vsafQdyC1VTQQYWAXGkSd38zV4Ks3H/L/KbGg7msLKdsMVfyENV rxNkblVuFd0DRUvshOnHefauIzSNWKPP2he6Qs2PyCnAQDjxDK37Ad6mAvFe9EXLd5m9 uPq/VJWegMZQqpUF27j3fjCUY2txpbAw4OlwTJj4Sn410Q60lGSoP6wleY8cMRBex+j3 gV5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658767; x=1775263567; 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; bh=HoxD5uMALorP/CUpuT5YOO2jyxxdHWPhu3WHKWZf4sY=; b=ZLWr7yvYTrS9Ocs6gCa4eIcnTE83YnDak1Ib/fSk/eJk4SPW26icui/bLTMx3xJUx4 i+COUYPWXJ9/W2S6FazWmMJVQgM506nUu/iivrXJApma9FZ6Z/o1mYdp/EBy8N8VFTdK TcpZY+SrD9Mbvwl+FVBJmXoc3TxJM31hdT40afHkw+ve+CpkWpQgt2ZIvw+jgd3TomOu ANGNesdqTDQUk8bftFb6jBMfgXNYVTaVsYdThX9zb/RDSviCnvU1zDa5dRIZpHwFkpZS Wj+o8CaftRribY1tqhDLpM2FyJiVxvgophVjxq2eSb/l8nVMacI2A60EzRTxbvLVqap2 tq2w== X-Forwarded-Encrypted: i=1; AJvYcCVp14CCDpBDGixffFwOtXWvXkkbQ+YVvpTFXGm9XGsZPSgFZ43SY1VvjXjOLhMkAb9XPvRlY4i7tBvI+lc=@vger.kernel.org X-Gm-Message-State: AOJu0YxetBCOqIMIjX/QI5ZwM1/KINfXRDce5HQ04P8mR3liJep4ANih caGDN8O7gEBxFn5GHpqarcsi9QWClGeaLtIL90M7aTswSlhPKw2+eKyE4Yzj05htYH4= X-Gm-Gg: ATEYQzxXrrubDFO5VHoxH85T7cmZiVD1L+CgDuVJWpidYXdrhfw/FDEcbp0QiNDngbU Q/MBSY4KErU/dGjITlmBVHvKOIHI3zBDNYec81No3pDUQ7mOeV7JziQuKMJouIeMxj59XrqAwP+ 1PHULndGb7cEmr0PEKH2OtC89/0xIcvIiV9aD/Vt5RoFtQWApP7MZHqEgYYMyMMBzwfVxNpwX8T BmLZiqLSUR3M6Pq89kcCUJ8hmBLN1ribStBfVj+0fK7dL01sWblmP5xDUStWBfD6DC5ZTSVeOAz s7JuTPbngsPeQ4eKb0dn0M+JtvuwqytNeIxmGtUc4cDRNmMBqPYQFOrpmN5+dUAP5zyXw6tKPxM kcAM6Em38tgKv68RibNB9PomVDzQQXRnKVhB3K/D5RukxHK8xDjJGf7EIfJJhRSMIwYimstXNdl U7CLCI7Rw= X-Received: by 2002:a17:903:2405:b0:2b0:62dd:3a93 with SMTP id d9443c01a7336-2b0cdc0f3f7mr47700325ad.7.1774658766541; Fri, 27 Mar 2026 17:46:06 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:06 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 11/15] nvme-rdma: Use CCR to recover controller that hits an error Date: Fri, 27 Mar 2026 17:43:42 -0700 Message-ID: <20260328004518.1729186-12-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 57111139e84f..b42798781619 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -106,6 +106,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; @@ -1120,11 +1121,28 @@ static void nvme_rdma_reconnect_ctrl_work(struct wo= rk_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; + int ret; + + ret =3D nvme_fence_ctrl(ctrl); + if (ret) + dev_info(ctrl->device, "CCR failed with error %d\n", ret); + + 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, struct nvme_rdma_ctrl, err_work); =20 + flush_work(&ctrl->fencing_work); nvme_stop_keep_alive(&ctrl->ctrl); flush_work(&ctrl->ctrl.async_event_work); nvme_rdma_teardown_io_queues(ctrl, false); @@ -1147,6 +1165,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 @@ -1957,13 +1981,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 @@ -2169,6 +2195,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_str= uct *work) container_of(work, struct nvme_rdma_ctrl, ctrl.reset_work); int ret; =20 + flush_work(&ctrl->fencing_work); nvme_stop_ctrl(&ctrl->ctrl); nvme_rdma_shutdown_ctrl(ctrl, false); =20 @@ -2281,6 +2308,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 6966320F067 for ; Sat, 28 Mar 2026 00:46:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658775; cv=none; b=IGHNhGLvWk6cGLIhbQnVMRaNN8++xKJN1LBDF7tZSAo5Pp1LomLAyAMGeppiHY6z4pV6LGGSl88uVSTkiS81vIesJzoRfFgAVscnmuQUe24uWABc+84JPnGSt/KmCfd7y9GxDrx+D69zNEswKDvUQllGlfVn76//anSo1l9uInQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658775; c=relaxed/simple; bh=Dy3iBhMbZkAMJMjAL4kWu26UsGWxIYA/RStPlOZIK3k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LBRXKgez3pzrPWLxzUYmbm+fkvkE7Uyo0yQ0epQ6wnZPD45EZdaruZA3ubF9S1WCCPj9M4gVdGnc5er5zZymsHq/5jBreY5tdtQWoEMMdToeM7JRAgjJAcCvfepoRoDeHUvzL3/eQH/G/C3vzxgne/Zgeyrg4ddYHIF1wsNASDc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=Bz8r7qfD; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="Bz8r7qfD" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-2ab077e3f32so12060145ad.3 for ; Fri, 27 Mar 2026 17:46:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658769; x=1775263569; 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; bh=sSkFes/5fA1bp01fQEuWfHcBjcSfktFD8AXFBwgiedE=; b=Bz8r7qfDG5Qx0KGp5k0s5YusXy9B5k24A85uAhzpftJKOodcglpk0kfW9YpT0qUQG9 POgHnlmFDv0Q6LO4sfs+VktxnKg1Tei93+3LN39aoSoUvY1J2Ea7G8F5boTDf0ESk89F pYg1VPEL47td2rNiJpMKqwuQ4X0/qLxVJwTvVLdr15QmNcrWYJ3cFd8ghUs0YwEaOupR M1VrHLGZMRwp1WTF5y4aq5UUBr07lEiUTiVjJzdOMF/zI3AB3ish/yzFtRl15A8y1G3v Baao1OjE6+N2CVKbgzomP+I2MlzJ4V7FACf9oQtZmGnObaPs/1bMTjqq0+wB6kss3OsE g4XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658769; x=1775263569; 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; bh=sSkFes/5fA1bp01fQEuWfHcBjcSfktFD8AXFBwgiedE=; b=kW1zZSPNF7b0/Dl7QDhHO1iYetbO7w1DALCS/u+yJFo6FanGWoVzuW2vtAdVOHCm+r 7R46AM3i+PJyNN+sBqSsSH8bhTqMZIojVrhyKncTHuWY0xi1zV0lalx3rTMgpY5meuNM Y8uDPqHDlqW6yLNSuZ2wq2MvYFTjZUbNTHdFFEWbBnFdzQCxOs/WM3H+JvwxClv2V0ka Rkww1VKd6Y1EuiYfXmWZlOK9LxC7Icmi5L4gs6jfbJe639l3gyReUOTOrcQ2sYFi8Ehg xAvO4pGqrxF8LpraRqlV+ukBOyd42LS0wSPVYPEHIFFh1juGueGWNpz+3JA4Chtm6zYU wEGg== X-Forwarded-Encrypted: i=1; AJvYcCXVEJz5z1KPPTD1GWZ+NZRHr/jySJkfP39k2abW8HnQdqirJxWiBBrj2cDQXPKfuTNRuqk4F9Si6epO1mU=@vger.kernel.org X-Gm-Message-State: AOJu0YwottLd7yXADmY42nPL9PYDOkAkrUIBp4Smjiwu6za5pEaqYOpM QemYbeIzxRHF12ztX/nId2i0XAoVouydv+vp2eOYoraGvTar9DNdNnskwdblljrw2EE= X-Gm-Gg: ATEYQzxG8U8fBG8e9cwuVkS3J69tMppkluOfNPWW3jOOt1euCqxCs3WVqKBayiKEroG ejThyy93QoQrBUE88jt9GqjomVMYXweujJyCQiXzTOCylCsEzRO3/Z+j9y4LpWTiyUhZYBbqP7t t/siEfp5xD26n4SG1T6gUYekFxerAiS4Ldg4/y5bJdnsGvtyhcaOfqMRro3OJyaJyWc7tHeK9bg VF4ktwHmzRkI4SqU5pY4IgVZ6remf4mw0lwHKp9ahQTphA/IkOcYxQTs0kik5QDotlfqfydnUNZ 7HFNYNfdSCUv8d1/T3CTb0jXHsOxqMLoCXmq3MUTj3LsrfBKzaV775R8/BFxwxPIR6hjqyhXGhO jwHRj9fXUx/1epSdZI3IpdN/ad48D02F34QY03Nubw9oq5mvIzc7rJl+JPqxUY+lONVomACtt83 2VEC2nVsE= X-Received: by 2002:a17:902:c946:b0:2b0:7a27:bb2b with SMTP id d9443c01a7336-2b0cdcc6df4mr50453325ad.34.1774658768443; Fri, 27 Mar 2026 17:46:08 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:07 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 12/15] nvme-fc: Refactor IO error recovery Date: Fri, 27 Mar 2026 17:43:43 -0700 Message-ID: <20260328004518.1729186-13-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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" Added new nvme_fc_start_ioerr_recovery() to trigger error recovery instead of directly queueing ctrl->ioerr_work. nvme_fc_error_recovery() now called only from ctrl->ioerr_work has been updated to not depend on nvme_reset_ctrl() to handle error recovery. nvme_fc_error_recovery() effectively resets the controller and attempts reconnection if needed. This makes nvme-fc ioerr handling similar to other fabric transports. Update nvme_fc_timeout() to not abort timed out IOs. IOs aborted from nvme_fc_timeout() are not accounted for in ctrl->iocnt and this causes nvme_fc_delete_association() not to wait for them. Instead of aborting IOs nvme_fc_timeout() calls nvme_fc_start_ioerr_recovery() to start IO error recovery. Since error recovery runs in ctrl->ioerr_work this change fixes the issue reported in the link below. Link: https://lore.kernel.org/all/20250529214928.2112990-1-mkhalfella@pures= torage.com/ Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 119 +++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index e1bb4707183c..6797eb17917f 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -227,6 +227,10 @@ 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); +static void __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, + bool start_queues); =20 /* *********************** FC-NVME Port Management ***********************= * */ =20 @@ -788,7 +792,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 /** @@ -985,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) @@ -1567,9 +1571,8 @@ nvme_fc_ls_disconnect_assoc(struct nvmefc_ls_rcv_op *= lsop) * for the association have been ABTS'd by * nvme_fc_delete_association(). */ - - /* 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); @@ -1871,7 +1874,22 @@ nvme_fc_ctrl_ioerr_work(struct work_struct *work) struct nvme_fc_ctrl *ctrl =3D container_of(work, struct nvme_fc_ctrl, ioerr_work); =20 - nvme_fc_error_recovery(ctrl, "transport detected io error"); + /* + * 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 (nvme_ctrl_state(&ctrl->ctrl) =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; + } + + nvme_fc_error_recovery(ctrl); } =20 /* @@ -1892,6 +1910,24 @@ 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); + + 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 +2085,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 @@ -2495,39 +2530,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); @@ -2536,24 +2538,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 @@ -3352,6 +3344,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); + nvme_stop_ctrl(&ctrl->ctrl); + flush_work(&ctrl->ctrl.async_event_work); + + /* will block while waiting for io to terminate */ + nvme_fc_delete_association(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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (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 473941FC0EF for ; Sat, 28 Mar 2026 00:46:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658775; cv=none; b=P1jSnQEJTHOSsedUcIq37csYFZ2eMmbAnBGPZSM12ATbej1y/6PFHD7D3Ec+qJWktItI8nUA1jdL/4iuVSAALnUUUvQ1is6V1yEI/H8LZbDrhpiCpjh3LpBk6Wk7tFyLXg1YLJSKQ87pSz/sDrMwDoqmPvpljlcGO4DEX37O1LA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658775; c=relaxed/simple; bh=vZLteJ83d22AjSrcVciWB0TbOCSTORkyyhL6KfKzsMw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=orGv3PRPGpasBwIsnr992GimMgMJqHJsk05YVbKeYDmRaHvPFJjKGtvV+W81d6xeA7FSl3gxztaP0080logBBmztaZb3kG1rXtcX/JaQK7oJ5TRl3ngluboG0BqEzzU6VFxFrlpdX922ZS2KSECoyQf9TaAEDjZm2UyU+g7MXCs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=SQaILWIx; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="SQaILWIx" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2ad9f316d68so13294485ad.2 for ; Fri, 27 Mar 2026 17:46:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658770; x=1775263570; 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; bh=BG9grs2JIZbnZf38OXY3X2RYCpdQyaZgWV264Kd3xHo=; b=SQaILWIxj9C3weD7Fv1ddfpr207+axUPsQsZ/26tfEDZYQI2v3E6/+ox7E1/hxQX56 jXdLDEZCcj6M/aEaRR+TcR0Pn62dhffXS1puHvXbDukGKPKSXFIZ9BE4mW8nKZJPS93+ JcbHVim2PQSyuoBDupIlACRoXh1XLGLPmsDQjZ4ZWqKjrGguRvx6S7n0oKkNwNxkFVDU +by0ElFHB2vjz1YcWCwAQqL1IOMiWjzyYHgLq9HGWpTNIcsgF2VQz1n/0Ht9QKYIbTaL 3271EmJ+yI3XsT7h3CRQaj3Hjf+vBfDkU3MHg9RfhtB3OXCsqaLvQIvQ6eS/8p+YFtRt I/UA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658770; x=1775263570; 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; bh=BG9grs2JIZbnZf38OXY3X2RYCpdQyaZgWV264Kd3xHo=; b=IDAQo22mOx5JAoTJ033KydqIqSm8+2jgI/CI5MnqVckjtugV325mhZ/3+5QAgWPOff meny1K543bp6ayAASUDErw/nkSqCmCR8/TVFJSwNVv5PlguAzBVRGDcgZW1M7wVevSqP SvJ+qCOXqKHIH0KIvrb3O3OB+tcbtC3hYoXRp8sK0pKsbiREkDbNHOi5FavtA7iyud1f 4lATE4KN9m7HDowtT+RvbklNug6osnnK2JRQSG3GzB63n24z3/ryonYBCfFJ4LZZLzKH kg5FM3+2kNGntXbALPb0VAsrPFfQ0mFfoH/NXgjaiCZx/nl4A/13J7J/U/MsyEmLoEkU C3+Q== X-Forwarded-Encrypted: i=1; AJvYcCWJwNkeMGlB+VXrEfhWLyL6xa/XKwq+fHOZz13zDHtFZf0pDZZzbM/is6RF3UaoyY+FE1Fi85j8VQGSCXY=@vger.kernel.org X-Gm-Message-State: AOJu0YwVuhf1B41M1rrwUhmzbjgn/wsmhrTOlp1/P124Ucui4UOhyX7W dGA15nZL1Cu1DsYj+/yTopD/X7SAJEE/hfZNBLKvMpGzsjlAvGXFC9k6QXNA+FL4da0= X-Gm-Gg: ATEYQzzkHdJXUs/SQOv8i+g6/zXUP4MSfbASGt23zK6JhvdJLlNPGDY4CinOv7aERhX iepN2LUalguuUVdk8IrN1n0Bdnb8aCqXzBScKFanaX0kusePgspI2fBakOoHSAjSOjOgKIxoOBr +oRF89b87q9k5J/0MK9rjIWm82Kqz6K3e1OCkjSwSXl9CaR8+1zHR7SsVcci4WeQRqF2kdsjBR2 kvLujzMJdwbGMc/VmyVannWWoDRLW5Y0hjsjKFQeC+5/LPIrJahMZGJBcaI0P/zOhtUYDeW2Hy/ jQHDHdwtj7g9rjP5M+KdfrZQfIzxBblblrALT323KfbBnKmD6oOIlFZcCWg08m7M+8dYNLtMPyi p7MEyC5aRkvNaRU8DMmXbLhZzQuNKVia1KrSZDiBTKPMUucNwfRz9BINBaqUYpuC+pTzKcuGdQK hNzFHfQ3o= X-Received: by 2002:a17:902:fccd:b0:2ae:a45b:42f7 with SMTP id d9443c01a7336-2b0cdd03fdcmr31623685ad.36.1774658770331; Fri, 27 Mar 2026 17:46:10 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:09 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 13/15] nvme-fc: Use CCR to recover controller that hits an error Date: Fri, 27 Mar 2026 17:43:44 -0700 Message-ID: <20260328004518.1729186-14-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 6797eb17917f..9f6b95415f25 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 @@ -1868,6 +1869,22 @@ __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; + int ret; + + ret =3D nvme_fence_ctrl(ctrl); + if (ret) + dev_info(ctrl->device, "CCR failed with error %d\n", ret); + + 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) { @@ -1889,6 +1906,7 @@ nvme_fc_ctrl_ioerr_work(struct work_struct *work) return; } =20 + flush_work(&ctrl->fencing_work); nvme_fc_error_recovery(ctrl); } =20 @@ -1921,6 +1939,14 @@ static void nvme_fc_start_ioerr_recovery(struct nvme= _fc_ctrl *ctrl, 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); @@ -3321,6 +3347,7 @@ 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 + flush_work(&ctrl->fencing_work); nvme_stop_ctrl(&ctrl->ctrl); =20 /* will block will waiting for io to terminate */ @@ -3496,6 +3523,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.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 B8A5319CC0C for ; Sat, 28 Mar 2026 00:46:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658776; cv=none; b=W4CAL47RplyY+n124fvXY5q72uf6S2Pa7cpDdVQBUm9kvCUesQJUsXJqC9nJ1sakCXfPGpxtz0lKgvg1RFTDKak1BvZMjW9MqTUC3oZ6SMOzxfcvQZvjHjc5uURDDB4yoqjtLQU/4U574ThSMBa9KKWz8E7KvcxtFQHkIrvQFBM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658776; c=relaxed/simple; bh=3+7rQnJk3Fb22evFyq39aviaS6XhWklwj+LajYtJcjs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XL68ATGg32ry1n7PyicxWJbz2FchzwlvaqE4vvNX+CArlSauAooFTqxdLSsC0q5WwrqKa4gsm6vpLi8EBvzw8ma6VC0p5SYTyXYGrS2Gg5t4HAUkNhtM1+sZqGduIhf10SnFLQkBDTrnnkR0/sYc8z1V8Aplj0RfGOmUntLSMUs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=YEIP0vS+; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="YEIP0vS+" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2b04d051664so22887005ad.0 for ; Fri, 27 Mar 2026 17:46:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658772; x=1775263572; 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; bh=DRU+bZBKSxxT2z3L8VYfITXheQuE4BxzAm+ofkPTK8s=; b=YEIP0vS+XFvAoDFJ6zuXuzi4xGsPttZ36Q8NEfEyjfdNi7lrLJKu4AWWUo0QVFzE48 w0OHarzpZeVXHN4Mlla6qlydkocJsQjeNJmfvkzADh921mueh3JQbDsIfTVrckhz+ox1 xpcfC4+9UZ+04OdvoN39qP6/zPY8jZy+0964pJQZ3Y/m+MuvthDTnVTsXTSAdGEdt7te rZHr2cePj92gRjlJSbiKLOlH9JDSIwwghe8MhPnQDML4GBATmI/HVmPrGkFSwXaol8Ig nBVpTJ803V8uCgd1wfcJ21t2fbVbr7uqnpsWT/eSRy2H13blBDpyETLDuJzGGW6KR33R NHgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658772; x=1775263572; 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; bh=DRU+bZBKSxxT2z3L8VYfITXheQuE4BxzAm+ofkPTK8s=; b=PYUqCiIy4/mGnzMxyb9yZOkgX9hawRJ5A78ud9UdrbUXnmC8pL2dtYHup4rTSBLWbE UPMHtJZuxXttteQFX6kPh+emzKesS5ckyxOxunDEWmZtL3uwH/BCGbK61YuvY739MxdC RwiJULUWSojvLwBRh/134FspMIIEweABuPHoynmcsWYPgFHBJ+N/49uJLOsR34o9PDoS VZfgoOE4t9Bt1qPQz3LRtgZliW3X3caiQwxgBc4YO46Zz5+TJr1tP42uL4tAOprl1Kuc kO1KlifBY/QMgjRWe1hiNnxmkA+QgDZsviGHFfo9HN4vc/yO3c1ppl7WOy19h1cPZCUl JkWw== X-Forwarded-Encrypted: i=1; AJvYcCWP/vNcaNUDJVFtaW+OohAvKnOuZ5p36hGtsz/gawx0KcH7/2bfnHYEWTeOeekIpApDxzDa8wVGAUeUPmI=@vger.kernel.org X-Gm-Message-State: AOJu0YzGeAqEi41IArnnW/7BJZQ485R/itU/a0jCxMaalhmS10GHC7yY sBSrh5p13oJ3k9NiwRihuigoRAOv9nxraYvbdLlVUMMiThUA1t/t0NfFwlnxMPY2u5w= X-Gm-Gg: ATEYQzwqOdf0dv4Afs+MQrPUwZeTJ1rRUCKKsrRE6EYVVeuB2mLsNGfXdtCWEi2Iu+V oyVNa25eaq5ErjI8xYw07bYwGq+aCIiPxzTX/l+RrcjgFiu7DN382iQdlAM8deHs8VYw23AnE0R eaACE0fjNizht8twod4Dyb5u8x/ICG3ZBAsm+xbFRWiuEpYRBndHw8Yb2UMNZHmDzx3KsEKBf15 hcU16WaY80yG/UABmS5pYQ7oNCT0bAqlhK7zxgh13xMMS75guQXh4o23L0ndBVpp5dXqz9xYhtg ep+fpV849M2TXJgwZ7/bj8Xz9Zl74LhJeMXN/rei8hRCrPZgXDwoiHMV9NusSYaJUrgTbyciPC9 0EAaD2sr40IHIlmWfSmAWjxvveyJQMjHXBgIuZPfQ/AuN6Ss84dAy5I++MwJN87gIo/K1hrsux9 ddszJJ7Ac= X-Received: by 2002:a17:903:984:b0:2b0:58a8:5f9b with SMTP id d9443c01a7336-2b0cdd2137emr47738495ad.49.1774658771480; Fri, 27 Mar 2026 17:46:11 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:11 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 14/15] nvme-fc: Hold inflight requests while in FENCING state Date: Fri, 27 Mar 2026 17:43:45 -0700 Message-ID: <20260328004518.1729186-15-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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" While in FENCING state, aborted inflight IOs should be held until fencing is done. Update nvme_fc_fcpio_done() to not complete aborted requests or requests with transport errors. These held requests will be canceled in nvme_fc_delete_association() after fencing is done. nvme_fc_fcpio_done() avoids racing with canceling aborted requests by making sure we complete successful requests before waking up the waiting thread. Signed-off-by: Mohamed Khalfella Signed-off-by: James Smart --- drivers/nvme/host/fc.c | 61 +++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 9f6b95415f25..eea5a90d936b 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]; @@ -1823,7 +1823,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 @@ -1853,20 +1853,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) @@ -1966,7 +1975,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 /* @@ -2099,16 +2109,38 @@ 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) @@ -2747,7 +2779,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); @@ -3216,7 +3249,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) =20 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); @@ -3225,11 +3258,19 @@ 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 + /* + * At this point all inflight requests have been successfully + * aborted. Now it is safe to cancel all requests we decided + * not to complete in nvme_fc_fcpio_done(). + */ + nvme_cancel_tagset(&ctrl->ctrl); + nvme_cancel_admin_tagset(&ctrl->ctrl); + nvme_fc_term_aen_ops(ctrl); =20 /* --=20 2.52.0 From nobody Thu Apr 2 14:14:41 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 B72AC1DE2A5 for ; Sat, 28 Mar 2026 00:46:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658776; cv=none; b=DUPIg47kYn6+QNGMxi+4ILOxGZMu204lcsYJFGySCKnrgIwHptkiJRTyv4wKhw9HZEQxgnV4PS6g+etypNgZIoHuLiBsJ5zBHVC1qDccJPiEm8RFjArsns3t3ZCLOiBJ1ZRkOIR2p18NHqkhHUes96CoOkCIj+zEA5FrkXNphRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774658776; c=relaxed/simple; bh=D7dzV4y0LsCNzRrDfHsQxqPYHM8cBs83Gn2MzKuxd3A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hiWb7WHBh2HbETOWlK/TVru7ejaF833JbBKBexQXUBPQnhBT5zKAwD6vmspgtSJUpeLUTwBMleh0ivlN2EEcHh02qAHfd58rdgT0Fxu2RJ0Gp1lbXE0yVqX47TS4zV5pGG1tyAreW7165KX+vHoYfMbRw1VydHwXvuyKAws4blE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=Cyl1uew1; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail 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="Cyl1uew1" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2a871daa98fso20934195ad.1 for ; Fri, 27 Mar 2026 17:46:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774658773; x=1775263573; 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; bh=5zI5jX/tvcIMUGp5fm4rmIBCKjqdOpV/MaWj1qN2SKQ=; b=Cyl1uew1snnO+HlHfP+tyDq7NEHYKC/IVo6sl+AvhBrsoIGYEZ+pZ9C/Kdhpgpgmce 1jLCVbe8ajp3pw2JrdBfpzKYXcJAzISgw1Pu0RGflme23Ks5tIco5QvUiNYDdWkYhpkP J80po/guTE2JxhQ9+AmblYlBZ5DBDizHFh/NQcu1Ib5EmRmm5REutldW2T2uqz5LXstE 4JeO5efDW8VEYMJZiHvdOFEFKXqSaeVfzmKWYzB+jLt67RPsERF50ctP6BGlO2fUsLwa wSWFrdjDXmhlXweAZwm1jOj6yCG0aKNIX3Cod9jSvmxGkyyFxXvG66mdPJysTPOkS+bO tomA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774658773; x=1775263573; 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; bh=5zI5jX/tvcIMUGp5fm4rmIBCKjqdOpV/MaWj1qN2SKQ=; b=i7mX/P+NiMAWzeFea24GlCMfQggdzHgLk/TgQ8XrD8f51t+Z1LcHXfW6qThi+EyS5e Q7YV56qe2uGJGAsDq/sbKHPGcdlpzXEEvGG4SbhRvgjNH5LSqf28qWOT4urA42SuB3FM HxvH2XH6zUoPujC5Oy0w0ycduzbmxKT6b+Y4qqWg4WVwR1b/a5iGr/e5qphcQLfg2V6C JIn6iT2WQUh3RBMZpE0r/TM3mMjuw2iDsnfUasLJrKgdL5kN22jKzDQ9z0RwQmLfxmlA WkUJFYjaSkxlYxbKgU3s3ctJQeZjnHqt+OYEgS/vy9UADssEOiVqODZ7oJa2cFquNwva 9W/A== X-Forwarded-Encrypted: i=1; AJvYcCXW1v5YwXixMxND5jV8nufkRJ3uUq2tTRbLdr6CKrx0tdygqhbQ3sbsHQl7y3fZlPblLBB2f9OfdTdUz7Q=@vger.kernel.org X-Gm-Message-State: AOJu0Yzv6xpKiwWgjjgVQIvDYZ6C70Bof6m0LLj93uxzkvZ6qDgpryVn UnAznpWY3oD9Gag1FjaZ8+GfLimqUgcFkLUW5AHhV9WeQwFHn9d3CB5IfUAkwHboWjs= X-Gm-Gg: ATEYQzyXXODDRdcBl6N9r5m45WtR78z/9Dami7xcSlVQqKS2YIMKvoN3gUR5irW3nPJ xU2O3TOFbA4u9lOXLApDRw9LEiToMV+19hks8WxTGVQpwAlCOmY9PE0yG3BpLVcmLrxB/S7krW+ GeOHnEYTNQ2UFZc3mcGisLWnikV5gzZ53Y482YfKNlkmj+wH+yI9jV8cgGVT7Wn6HDkzt/4xVQ4 DQ26ry6b6kQB88facjTHgfst4bLJyoor3s8qXlrlwGn/QYLrTLQpktsnz1qK6CdYCPiXSLZCcmB TGiOC2VUDAyJo5l5nNwUvXFtcKB5+ScJk1PYQ7+8rxIAbMBgYEgs+ttMfPKBU3Ou1yvm551YfHJ 9avBjNb7cGI2kE6n0ZYjI27Y2msrzl0mJSioEOOIzhAkaXijyXFw40BcdrkNCkqwzIaqzisL1xq B2NnD1Css= X-Received: by 2002:a17:902:cf03:b0:2b0:c90f:44b2 with SMTP id d9443c01a7336-2b0cdc1027amr46114045ad.12.1774658772780; Fri, 27 Mar 2026 17:46:12 -0700 (PDT) Received: from ceto ([2601:640:8202:6fb0::9c63]) by smtp.googlemail.com with ESMTPSA id d9443c01a7336-2b242683064sm5342705ad.33.2026.03.27.17.46.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 17:46:12 -0700 (PDT) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Jens Axboe , Keith Busch , Sagi Grimberg , James Smart , Hannes Reinecke Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v4 15/15] nvme-fc: Do not cancel requests in io taget before it is initialized Date: Fri, 27 Mar 2026 17:43:46 -0700 Message-ID: <20260328004518.1729186-16-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260328004518.1729186-1-mkhalfella@purestorage.com> References: <20260328004518.1729186-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 new nvme-fc controller in CONNECTING state sees admin request timeout schedules ctrl->ioerr_work to abort inflight requests. This ends up calling __nvme_fc_abort_outstanding_ios() which aborts requests in both admin and io tagsets. In case fc_ctrl->tag_set was not initialized we see the warning below. This is because ctrl.queue_count is initialized early in nvme_fc_alloc_ctrl(). nvme nvme0: NVME-FC{0}: starting error recovery Connectivity Loss INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe lpfc 0000:ab:00.0: queue 0 connect admin queue failed (-6). you didn't initialize this object before use? turning off the locking correctness validator. Workqueue: nvme-reset-wq nvme_fc_ctrl_ioerr_work [nvme_fc] Call Trace: dump_stack_lvl+0x57/0x80 register_lock_class+0x567/0x580 __lock_acquire+0x330/0xb90 lock_acquire.part.0+0xad/0x210 blk_mq_tagset_busy_iter+0xf9/0xc00 __nvme_fc_abort_outstanding_ios+0x23f/0x320 [nvme_fc] nvme_fc_ctrl_ioerr_work+0x172/0x210 [nvme_fc] process_one_work+0x82c/0x1450 worker_thread+0x5ee/0xfd0 kthread+0x3a0/0x750 ret_from_fork+0x439/0x670 ret_from_fork_asm+0x1a/0x30 Update the check in __nvme_fc_abort_outstanding_ios() confirm that io tagset was created before iterating over busy requests. Also make sure to cancel ctrl->ioerr_work before removing io tagset. Signed-off-by: Mohamed Khalfella Signed-off-by: James Smart --- drivers/nvme/host/fc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index eea5a90d936b..e342d522145a 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2554,7 +2554,7 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *= ctrl, bool start_queues) * io requests back to the block layer as part of normal completions * (but with error status). */ - if (ctrl->ctrl.queue_count > 1) { + if (ctrl->ctrl.queue_count > 1 && ctrl->ctrl.tagset) { nvme_quiesce_io_queues(&ctrl->ctrl); nvme_sync_io_queues(&ctrl->ctrl); blk_mq_tagset_busy_iter(&ctrl->tag_set, @@ -2951,6 +2951,11 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) out_delete_hw_queues: nvme_fc_delete_hw_io_queues(ctrl); out_cleanup_tagset: + /* + * In CONNECTING state ctrl->ioerr_work will abort both admin + * and io tagsets. Cancel it first before removing io tagset. + */ + cancel_work_sync(&ctrl->ioerr_work); nvme_remove_io_tag_set(&ctrl->ctrl); nvme_fc_free_io_queues(ctrl); =20 --=20 2.52.0