From nobody Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f48.google.com (mail-dl1-f48.google.com [74.125.82.48]) (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 BE08538A70F for ; Fri, 30 Jan 2026 22:36:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812587; cv=none; b=hSAda6CL/9MD9+THaUwVsbd6yrO6bwVkTxZkyWyWadNsxNPnLbIJb8mAjxAWqb6zP2bU9kiRy/NNwl56AWx36WK3daBysm/RmtgwxM3f9xhz8GI6/p6IaFWuReiNDPdKYhn/zkBcauuuEcmEm9+XWFLPw5bqS0D64qJu2BrknYI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812587; c=relaxed/simple; bh=N5sLm5Nh8pdXJyKaO0nmafIvgpZjyP2ePrjW4o1mWe8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EnCOGo2/VvhDSjc3JUg60kOfGktdjQ4O6RtvaT03HgCvFU/8BGrE3pj81+/YZKUSJTQKFLC95imcm37ngyDvfLXBg8WmNeN4oDlQubsLxUrtFAPjjcFWsSNqWqHA1TWsFOglBOyEgrwumeK11tbZxruk191LYNxmiELzpG4P5ck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=OILvaSdj; arc=none smtp.client-ip=74.125.82.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="OILvaSdj" Received: by mail-dl1-f48.google.com with SMTP id a92af1059eb24-1233c155a42so4518746c88.1 for ; Fri, 30 Jan 2026 14:36:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812585; x=1770417385; 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=+6koEg3ORYOvIi3e26txsgR/nhwrNI8Ae21Mw02k0to=; b=OILvaSdj3kzI9qXPEH/R7ElmTjMQpOgxtD5zIHbD3jRPvAv4qfzsxz8uON2r9jrTq5 mOT4m7HlhX7l6h4/oKWQobGIXlsKa0UBJooi30sMuS3KbqrbuHSK+Fc4JtyVpFMgF6L4 4FO2+a2H8J0AAsPY6q8ELWuZsJpdGyrE469mL9EGMVZRdyjtJjLbTVI5AOcMJBHMXYA8 F1IcsNPTDZXYRzJvy9uSDekfxJfaYHgxW/Mo8egHsJjg7uOIiSI+5BK64IqivvB6AENJ 8UdJ0FyA7dRDWxRxN0kO3HXSJZ2ue9afwbGpzfnf6yO34wQuYKzBQBN/e2/JKPDK+3YN oobQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812585; x=1770417385; 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=+6koEg3ORYOvIi3e26txsgR/nhwrNI8Ae21Mw02k0to=; b=hCMOwhdE93sWSnUka6j4Q2eSFrIkCbOWrN1vAvcFqG5X+H0//UvAkUR4uq7WMchCp4 s8A9GYuIzM9QzJdPwkAYRqQrBJDMNWwLUc1j536bQMaY4bNh5uHcNMzsAMwyNheUegVR R3GDPVlvbViYQNYxit5GRm5W5prIf1UYzRtgoLBvo7Rf6jSz0Q4pO8wgLw2fbMji0UBy cyHGgdAgmG7sYgJz3xtB6zw77HBWEHAh5efQ9D/yQI9ctdiCfzrW/sqivO7UvdbAh0RG gNU+d7LVmNb8l0h9GAMFgcF3HXlt/I80GAdHW/vSlYETDvRr8joxh1kDVAG7SeviS/Ua RVKQ== X-Forwarded-Encrypted: i=1; AJvYcCUYvOl7L2KLJbIyc5Wo+DekKWl3CKL2vfSwP9L/OVDr9sTAmfTxKuXg5Ks4DgAJItKEha7M6gm7GA4d7YY=@vger.kernel.org X-Gm-Message-State: AOJu0YzCytpbVd/U8AMrMv37sqUdfwyK2yjMttLKT6aLulsVREQer3CK s2p724qR7vuhadBcaTLBEbUawMV1FLrlJQ5C92iZ3pks7e/Af4T18KnS1MQaaIQmLB8= X-Gm-Gg: AZuq6aLAR7CsfVcVNX7dUM8Jlz7mqQFmsKpRFg3dxE5zOUpuTwIwrrI+uLpy2qr6dkG RANmY+RUoI45GNwrjFPKFykTD66qJdyAms/E2a589Gw18HZF4qlJLjk94xCO7rG5iRWKnWUIpWI eEBuZP0EVMF6hIEsHzzFAxhEyJZVuYnxjKLA+wVckWZIGGt1WDAyMQLUv208jOnEybnyDwVWcLd RlOojtzoFHufk1v3449IM8Icnmh1P2uzuNgYPPGpBXfNcEELgWVC1euUtT+eGGWCwtZAzwAlMzQ j6+UmdfiOM/bcaA6RHYXmkxJ1Teb59Ut18tK8Tpmuw8gcgli92fFR8g7ZTNCrALsRfN76cqDnwG 2yzWwKwtWBuvrYbbHqRgQnmwPlWYhQGkU1VM5BXTcqeNYnR62O9lxGYbjd53ChFz4R07vMMtTWE kjuIrccbwXLtYOWSoT1hayzw2kJYBicv+Pnw== X-Received: by 2002:a05:7022:f103:b0:11d:f44d:401d with SMTP id a92af1059eb24-125c0fab3b7mr2177552c88.22.1769812584699; Fri, 30 Jan 2026 14:36:24 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:24 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 01/14] nvmet: Rapid Path Failure Recovery set controller identify fields Date: Fri, 30 Jan 2026 14:34:05 -0800 Message-ID: <20260130223531.2478849-2-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 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 crated. 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. TP4129 KATO Corrections and Clarifications defined CQT (Command Quiesce Time) which is used along with KATO (Keep Alive Timeout) to set an upper time limit for attempting Cross-Controller Recovery. For NVME subsystem CQT is set to 0 by default to keep the current behavior. The value can be set from configfs if needed. Make the new fields available for IO controllers only since TP8028 is not very useful for discovery controllers. Signed-off-by: Mohamed Khalfella --- drivers/nvme/target/admin-cmd.c | 6 ++++++ drivers/nvme/target/configfs.c | 31 +++++++++++++++++++++++++++++++ drivers/nvme/target/core.c | 12 ++++++++++++ drivers/nvme/target/nvmet.h | 4 ++++ include/linux/nvme.h | 15 ++++++++++++--- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index 3da31bb1183e..ade1145df72d 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -696,6 +696,12 @@ 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->cqt =3D cpu_to_le16(ctrl->cqt); + id->ciu =3D ctrl->ciu; + id->cirn =3D cpu_to_le64(ctrl->cirn); + id->ccrl =3D NVMF_CCR_LIMIT; + } =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/configfs.c b/drivers/nvme/target/configfs.c index e44ef69dffc2..035f6e75a818 100644 --- a/drivers/nvme/target/configfs.c +++ b/drivers/nvme/target/configfs.c @@ -1636,6 +1636,36 @@ static ssize_t nvmet_subsys_attr_pi_enable_store(str= uct config_item *item, CONFIGFS_ATTR(nvmet_subsys_, attr_pi_enable); #endif =20 +static ssize_t nvmet_subsys_attr_cqt_show(struct config_item *item, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cqt); +} + +static ssize_t nvmet_subsys_attr_cqt_store(struct config_item *item, + const char *page, size_t cnt) +{ + struct nvmet_subsys *subsys =3D to_subsys(item); + struct nvmet_ctrl *ctrl; + u16 cqt; + + if (sscanf(page, "%hu\n", &cqt) !=3D 1) + return -EINVAL; + + down_write(&nvmet_config_sem); + if (subsys->cqt =3D=3D cqt) + goto out; + + subsys->cqt =3D cqt; + /* Force reconnect */ + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) + ctrl->ops->delete_ctrl(ctrl); +out: + up_write(&nvmet_config_sem); + return cnt; +} +CONFIGFS_ATTR(nvmet_subsys_, attr_cqt); + static ssize_t nvmet_subsys_attr_qid_max_show(struct config_item *item, char *page) { @@ -1676,6 +1706,7 @@ static struct configfs_attribute *nvmet_subsys_attrs[= ] =3D { &nvmet_subsys_attr_attr_vendor_id, &nvmet_subsys_attr_attr_subsys_vendor_id, &nvmet_subsys_attr_attr_model, + &nvmet_subsys_attr_attr_cqt, &nvmet_subsys_attr_attr_qid_max, &nvmet_subsys_attr_attr_ieee_oui, &nvmet_subsys_attr_attr_firmware, diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index cc88e5a28c8a..0d2a1206e08f 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1393,6 +1393,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,12 @@ 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->cqt =3D subsys->cqt; + 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 @@ -1853,10 +1863,12 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char = *subsysnqn, =20 switch (type) { case NVME_NQN_NVME: + subsys->cqt =3D NVMF_CQT_MS; subsys->max_qid =3D NVMET_NR_QUEUES; break; case NVME_NQN_DISC: case NVME_NQN_CURR: + subsys->cqt =3D 0; subsys->max_qid =3D 0; break; default: diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index b664b584fdc8..f5d9a01ec60c 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -264,7 +264,10 @@ struct nvmet_ctrl { =20 uuid_t hostid; u16 cntlid; + u16 cqt; + u8 ciu; u32 kato; + u64 cirn; =20 struct nvmet_port *port; =20 @@ -331,6 +334,7 @@ struct nvmet_subsys { #ifdef CONFIG_NVME_TARGET_DEBUGFS struct dentry *debugfs_dir; #endif + u16 cqt; u16 max_qid; =20 u64 ver; diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 655d194f8e72..5135cdc3c120 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -21,6 +21,9 @@ #define NVMF_TRADDR_SIZE 256 #define NVMF_TSAS_SIZE 256 =20 +#define NVMF_CQT_MS 0 +#define NVMF_CCR_LIMIT 4 + #define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" =20 #define NVME_NSID_ALL 0xffffffff @@ -328,7 +331,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; @@ -362,7 +368,9 @@ struct nvme_id_ctrl { __u8 anacap; __le32 anagrpmax; __le32 nanagrpid; - __u8 rsvd352[160]; + __u8 rsvd352[34]; + __le16 cqt; + __u8 rsvd388[124]; __u8 sqes; __u8 cqes; __le16 maxcmd; @@ -389,7 +397,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f51.google.com (mail-dl1-f51.google.com [74.125.82.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 7CA7238A71D for ; Fri, 30 Jan 2026 22:36:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812588; cv=none; b=c7p5Te6OtnCO+KJvOBWc1yWjnvntOuve5xUEguJfJRZWvJDsFUFHgFh5+hUovF0U4ctdZ+ocYlvzxXA2TJvDvJqREcPw6kd1rYbNiRXU7SJgJLTXxSi0kvY8ASQgzNsY746XO+dtBdqMxMvMJXtg0Gb9LFTQzdadNkQziGMK0vc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812588; c=relaxed/simple; bh=015mSL064ofEgXov54j0GAqTzrivrTmV8y9r3y1tJnI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G5U1sUMQ3ZLy1DLzjEShtGrshu15Qq09ddl5l7hYRwqu48dsGZazRD9wwbodmNNQivbfC6zQl+YoSnCOsQzIiRlGOyUMDUms78B2sKye5K1/05O2REqtxcD0g62LQvGBgEHlO+ke61lTcWpnMkXPVpFfCaUq5bWEoDiPuFypZvQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=Z28p3zH/; arc=none smtp.client-ip=74.125.82.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="Z28p3zH/" Received: by mail-dl1-f51.google.com with SMTP id a92af1059eb24-124afd03fd1so4079136c88.0 for ; Fri, 30 Jan 2026 14:36:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812586; x=1770417386; 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=X8PyANzTtrT2xWhov1X2x7JVr0z6OuDiAP84R/ndncw=; b=Z28p3zH/a1GLryz/bR6cp/zJV7QNsYxQX42CJug/egPhsFwNFtBomecXVW4pJpxnfX W5smWoMJO0Uicc9F/+u1+mSigRkW9jU92ESugrmtrpeLObh4z3qxKhc8dmIbz4Vsh8pG uCP6Y+XtavPnvv3QrZMf9gg6Qrwye163wY4no1Wk72P7DxRWaWlngZ7M8yq6n5wfZuyU 2g8f5nV4grO/P3wnYMA0CwbURoqrTLb1oIR+nvbnEnQrGoui/88GjxfSaSjyT2TrAzw0 1fB2ZL41yuUWtiobexszYIoOyPPjmkyUifPr/4/+wAZh6bn/oD3X38nWk0qhY8v+GNb3 NQjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812586; x=1770417386; 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=X8PyANzTtrT2xWhov1X2x7JVr0z6OuDiAP84R/ndncw=; b=Owr/dglh/uQHJQmzMmJqg1kKlmsUoBfdWoZB63ExOzGz5AFZblSxerya/xjziSprf/ Dp3In6LjqgOeB2y3tJOf4AxBVdAzhf1F57oMzTj/QugryZLBsdofYOfTfV59gziy6611 Wb7XZo458XHfZNT61zI9JBxtIqY6jRc0QPA6tg7iOxPFDf3TDze8l0am72GuUBDzIFET xwmniWFWBUA/4mNeqO+2vCnrIal/9gjRHHoA7+cDWQhITPYS3y71+EV3uvOvoIh1YDUb wG3lPLl/MReCDLsoOskeJrun1fYtyZTH355Bqf+tPecW4W/9lYUE1DQaF1aURls54T1j 9CNA== X-Forwarded-Encrypted: i=1; AJvYcCU51USyQELF3GYJPWC0G1o6m17nZtIELeLc2tM2aPfa3gJ/BdM7YGLEad15WLVJ3SPeTUw9Ty4r9+Ze0A0=@vger.kernel.org X-Gm-Message-State: AOJu0YxO2kHaMNTHaC3Kzwu/ZvQ7IQ+JrPMJpwXlDIfYU3Xccsi5dYBW MJAYoe/xukQFFtHbTvMsSkTe+C9UDCbzopBpz+N5XOHCDgsMfnYksGhBJ0yZQuAEVcs= X-Gm-Gg: AZuq6aJ4wPvc70mFd46RpiMMQn1v0M6qCsl3qdPLQ8MRoKREY6mfVdghdqpcZtnkO8n E3RWbOrUJsOa4vMCdglDYwXKFgHx+XWAXBzHaGwDGkjFfUE2K/ZHp1SkFWLPm2F2wQSX2d5HvFM f0+ilHQkxkUz9k/Hf92JcHdETd5u+TB2ySDR+N1/hFnAR5CqDGEgLZsPMLiNPdxGsUsWS+/DaFi EyCrr6C/dP97gz3rXSZXxsNL/mKmKU5+UV/A+6QauIygR/1g7zHMA38q7k4n4H4EpZ1mKl02ULf wAHyem85FB+21c6R4KUO4LDtWCoFTGxLe+wbT/mY6qm/gXKsaWqeBMbsQh0s1YEziPQq/Ywzg2N nr+XJDePCifFXiibmF/HDH/JAo2rUQoPUNh/8Y9kTTUCcmaUDeaE+acY+4EakXyvdSPl1u7eYJq boK/6fyjuCpc8NupbObJ6rB/G40gGTIKxSatx2jbXCf2eV X-Received: by 2002:a05:7022:6b94:b0:11a:e610:ee32 with SMTP id a92af1059eb24-125c0fe0435mr1902226c88.25.1769812585515; Fri, 30 Jan 2026 14:36:25 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:25 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 02/14] nvmet/debugfs: Add ctrl uniquifier and random values Date: Fri, 30 Jan 2026 14:34:06 -0800 Message-ID: <20260130223531.2478849-3-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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->random and ctrl->uniquifier as debugfs files under controller debugfs directory. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- 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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f52.google.com (mail-dl1-f52.google.com [74.125.82.52]) (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 9F96638A726 for ; Fri, 30 Jan 2026 22:36:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812589; cv=none; b=UKDXdRP2JjDwl2eWTiCV2KxbJCi2BvlCpO4AAV4yRVB01Sjwi6T/GnIaDVkxv1xwPzQGNoaaJxMD3iND1wXXjQlVv6mTTp6t7I1Jrk7sbnUIyyXb4rsaK3TVmpySfp9Vq/Qd6xIk99+XBTs6XnRZyYW3HkX6dzS0swCpeEQBre8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812589; c=relaxed/simple; bh=Ii+8h7+Xuq1VumG609ZXrtcoXUz6OCffjVM5sZCstxA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nhv/aPqqzXs1/1vx03b7i9FoD1WDKwurbZ2KixiRpTcDL1LdLQsBem0Z0LrUZHIpnKyM1vO803w6L0cXjfc1LRBs1ccUgPiYulKHnoQonVOjvSnHKGTzUE63BFTAivTx62YcwAIBlXnEuPWeKraitOQ6RvWccBfWfT6GHQYEPf0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=XJHm4bI0; arc=none smtp.client-ip=74.125.82.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="XJHm4bI0" Received: by mail-dl1-f52.google.com with SMTP id a92af1059eb24-124a1b4dd40so2352348c88.0 for ; Fri, 30 Jan 2026 14:36:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812587; x=1770417387; 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=glaln7DrWwA1N4gnatCDQ5Gt2F6Qo/2j3cZTsMw5m/s=; b=XJHm4bI0b6ThItg6XP/LPlLrClnP/T2x14hL3BE9A+NtlTq7wsH882FxTwJqOKy2T+ 8v3NodUTVAopYTA0XIamDTflOF3hwUwFZs/6YkYnIBFVCYGmG9+3QoR5HjbIoopO8Owd 4mwD4vo7gRjLRYmnNQfxUrtYkBU6Oxw0plbBYJN2US6PCLGPoTHnrlb+kvwAWWrZPyjS 5rC51SC3byk/+XTWwMVSkyzhkZhsDD2pHvFptds24Rvr8TAfJ/Ip+0umhkIzyWF6Im9W lA2NMUWPttSzybZEUk5ROkKlu//aOODP4tFEPHVWy7d/oist4cvgXHHo9Zk0VKplvTpw KDSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812587; x=1770417387; 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=glaln7DrWwA1N4gnatCDQ5Gt2F6Qo/2j3cZTsMw5m/s=; b=nKis/heufuiGr8ZzpGO87ybA71gEmNMAgw9fSIHArq6mAhHfbJyS941zwm90QjYYQy 96f0FHtZafWCOWuILlTRw/sZyK0NehUXuNMFSg/u5fI0Ef4JqZMLZqsQ5Gk5n82efrsO uwTVcVe918sqbMlQLQMXI4g5nYnVl9RFBkmyL8Pxs0/bcq1AA34zqSAiedbvPC4EYsPU zdvtFTUWqri2JOl6doBRP/TkuMkLn6W5HN3dZKRwuxpuFtavdu2+MZNXqGajtuu4j1ct crvf2YRjsuXz0fcntGVyM6PwzkadIbxWOyCff/LbwmlVP0gNa5yafS9X25KvLKM6FJhc R/wA== X-Forwarded-Encrypted: i=1; AJvYcCUTJ9QnHw59t2Mf2jSwVkKn1XuOHUZA64bwlaiBdt1N0dXN9bJ43X4oNGL5DLanGDCMaHXb+fQsOSCiIa0=@vger.kernel.org X-Gm-Message-State: AOJu0YzXISzJUEO0tpV0qCMSFvewMUzNsgRRPomhmNIt4Ib5cZPscToL FTqEugJeiKi0e//6IqDpri+10JR/bpvl+nM9vAsqvAo7h7hDlmar8M/PusGqzOPoZms= X-Gm-Gg: AZuq6aLVLw3o0ZtusYlcDl49EHcrbeqdUDGkR37+0lIqrwggXsHx1FAV46w9WVtSWL9 s6TypZerRaxMySSLYOj/S/Vt7dgdPUoSWUoZLBJi5GULEvLg7TDR0SlKYNlqqWRwYe5Zmg+Z+U0 dFhuFMMr1z127WjtTnAKJEMX9wPYK6Rh7zl/RQitcVbENaGCfyYag2IbOUjTC0/tyRga4UL/9yE zLDmYyvcAQRbCsbwIAViN7WdLtQ6827Kscj2ehhUpC0y7OhCdllJbrjMRrCElOJkVGq9erFDAvs G7buRDbhFvUw0AoOvmN+XY9W6BvuI0c8rUWvtgrjqoWXGQyIMozww7F7eJMhYZncE86kavdYgkZ 90gTlpzqBhuCK8d8KviC5CErneTt76aCgwwY+VM1iHzNdglVpXkk8utXBVTtbXc5BewzVscEC/6 equy8fBiXc/pxN0Fk6M+Otf+kz+Pp2muuSQA== X-Received: by 2002:a05:7022:68a7:b0:11d:fc72:e17f with SMTP id a92af1059eb24-125c0f97b39mr2898691c88.18.1769812586514; Fri, 30 Jan 2026 14:36:26 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:26 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 03/14] nvmet: Implement CCR nvme command Date: Fri, 30 Jan 2026 14:34:07 -0800 Message-ID: <20260130223531.2478849-4-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 | 71 +++++++++++++++++++++++++++++++ drivers/nvme/target/nvmet.h | 13 ++++++ include/linux/nvme.h | 23 ++++++++++ 4 files changed, 181 insertions(+) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cm= d.c index ade1145df72d..c0fd8eca2e44 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) @@ -1615,6 +1617,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(sizeof(*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; @@ -1692,6 +1763,9 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req) case nvme_admin_keep_alive: req->execute =3D nvmet_execute_keep_alive; return 0; + case nvme_admin_cross_ctrl_reset: + req->execute =3D nvmet_execute_cross_ctrl_reset; + return 0; default: return nvmet_report_invalid_opcode(req); } diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 0d2a1206e08f..54dd0dcfa12b 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -114,6 +114,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; @@ -1396,6 +1410,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 @@ -1501,6 +1516,38 @@ 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; + bool found =3D false; + + mutex_lock(&subsys->lock); + list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) { + if (ctrl->cntlid !=3D cntlid) + continue; + if (strncmp(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE)) + continue; + + /* Avoid racing with a controller that is becoming ready */ + mutex_lock(&ctrl->lock); + if (ctrl->ciu =3D=3D ciu && ctrl->cirn =3D=3D cirn) + found =3D true; + mutex_unlock(&ctrl->lock); + + if (found) { + if (kref_get_unless_zero(&ctrl->ref)) + goto out; + break; + } + }; + ctrl =3D NULL; +out: + mutex_unlock(&subsys->lock); + return ctrl; +} + u16 nvmet_check_ctrl_status(struct nvmet_req *req) { if (unlikely(!(req->sq->ctrl->cc & NVME_CC_ENABLE))) { @@ -1626,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); @@ -1740,12 +1788,35 @@ 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; + + mutex_lock(&ctrl->lock); + nvmet_ctrl_cleanup_ccrs(ctrl, true); + mutex_unlock(&ctrl->lock); + + 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 f5d9a01ec60c..93d6ac41cf85 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -269,6 +269,7 @@ struct nvmet_ctrl { u32 kato; u64 cirn; =20 + struct list_head ccr_list; struct nvmet_port *port; =20 u32 aen_enabled; @@ -315,6 +316,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 @@ -578,6 +586,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); @@ -620,6 +629,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 5135cdc3c120..0f305b317aa3 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -23,6 +23,7 @@ =20 #define NVMF_CQT_MS 0 #define NVMF_CCR_LIMIT 4 +#define NVMF_CCR_PER_PAGE 511 =20 #define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" =20 @@ -1225,6 +1226,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; + __u8 rsvd10; + __u8 ciu; + __le16 icid; + __le32 cdw11; + __le64 cirn; + __le32 cdw14; + __le32 cdw15; +}; + struct nvme_io_mgmt_recv_cmd { __u8 opcode; __u8 flags; @@ -1323,6 +1340,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, @@ -1356,6 +1374,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), \ @@ -2009,6 +2028,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 @@ -2173,6 +2193,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f53.google.com (mail-dl1-f53.google.com [74.125.82.53]) (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 6D21938A724 for ; Fri, 30 Jan 2026 22:36:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812589; cv=none; b=Ymz0ZUiTQ4iWFzoIsPOwOB0zjiM72nZCB91vmlO9CAqQvimoQBw3US0Bn6h6uAomVwICV9KpKXAEFRKE+11zu89Ay7lbD+4S8ysqHyhr/LAv67D/j62d43AMmzBjFuWxjHOereiKmXNtlZpKPDNWDdM6EL6TBrAblBeTaDMKeOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812589; c=relaxed/simple; bh=Ok8YjddGySHfJBNHeM3Vds8mfYwv2GCUrjELYN69mLA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uDdwV80SJofk8jIF7G3f+vmPTMEyLTAnNBLw6LKoMYoHELyDcDrTTR1IJUgKRi6XBbeJEWcGhJvcPTHlVmzGdXQU4boDCjDBEBnGYXfHossQEPaYEyLJPuGy+qXd7VfuMzHYh9wrXdL8AFIaA+NiV1aw8zDAJ8PfEAIyBSoTWQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=V0HsLeUR; arc=none smtp.client-ip=74.125.82.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="V0HsLeUR" Received: by mail-dl1-f53.google.com with SMTP id a92af1059eb24-12336c0a8b6so3674791c88.1 for ; Fri, 30 Jan 2026 14:36:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812588; x=1770417388; 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=zdXGSegTzhmsQ5qZhBP6CsinO53oPJTvN/vUTL8HtC8=; b=V0HsLeURTUyVEMYKXXcfY4W9LtS1rtoyo4fHPQ3mTjcuhJTlCKXyX0LZs5n5VB96A1 IYTr6FotrpX7PmRLpRJ+sN/TGD5uP2KTZTFE4GSH/y04cwRehM5gaMhZMV3n4Bgfj3Gn aZMAEr3o1N7A2H6dy8nJevoT5xWwjcX037brUtDyIaq+ruUdLSjJqm/henjq685/4r+D 0uBy0SetTwapbc/hE2Ry+Gp9FsoAbpc4xI9TmNg55kAB3SQREwUWviEElqg7AtMynRiA TE15tXK0cMgoLigjGVC+wXR5ILgxSd+sYPQ5aYKViKlk3zrw54UkXvm50Vyhqyqp6t0I NyXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812588; x=1770417388; 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=zdXGSegTzhmsQ5qZhBP6CsinO53oPJTvN/vUTL8HtC8=; b=pqQfjvQqL9VJM/LBEhWnsOw/YM2KceI3ugX/Hb4blRxz2QZmrJ86okBaoLwGa1jTDg Rly3g4W6gU2qob7XdVJjjXT3nNxLGtTV8YUbrAdywCNyEkqSrTyDt+TddiVOBPVvvQmt +IhO5ErSiggPvL6jpFs6lbCW3a3ScsorDMDol1ila18F0YdR2L4Agr+YCPnAOxjZsYvA rYj6wz7ctJT52gpCkwzbXmPfeYR3+zCtEU3l/HTxRVB9dRkazcf5IWHaiEayPiucXBZP Z7WVvRKs75Cp2mWDKbg+0pJZz1FZ2UGDcoX0AWA8lEAJ2PIToktsuJMcNPQYhk1C89Ov if0Q== X-Forwarded-Encrypted: i=1; AJvYcCXFaC70b9ror9MXA2mJeXG1LtfElos+3rvA6+ed4DDDDwrzQW2czkfPIhl/NoHpIS7PTZvv5ihuQXOPgOs=@vger.kernel.org X-Gm-Message-State: AOJu0YyCQx/1AgLO5SNNolmHM8CkD4ARfROINafNVeRgmffPFnC/7SWV cvKUIeUBFtjqru+ZAMp1EkBu91mdqwReTpW8q7QoBjTZYkQ/m1DozhWjili7CB+X+R4= X-Gm-Gg: AZuq6aIOmfuiUDqlKwD+FRWM3H7wgvmTXjX3B7CuSAK0CO5FEdHNmOpb5urmBuhdqRK zcSzkTOQdV8xxfYcQIFvHEi8ruPyit77/k/DNYTrOap9PM+VV5W+mRUToYEhXneYlz2vPyedNBK g2+5XwXxNiM0rG2UKMipB0+gSUbZaEFWYPKnm92JdmsIj7fM5YVRI30/e+0Ry5UiNXU0db2Jx82 cqCAIkIH8F9JsgtMoSKhxPzOX3fBoNvcIh5p41ol8go4j+8uHA4B0RHmdkvY1X1zR0KSJPxtLyZ qfeAH144xUZAeU5lbRl38HG2TpZuOprEC34oVVSb5QDOJeWIw6uN0JmdvtP2owM8sy9UDZfcwln e2oIZWr2kZniZL0u0NAUtcBOk/l3aMsaAnnD6tfqbWbkK6/3ByxSJo9+zDvv5cK0LPWSDugP0YM bmnCIIeUNoYjnYhBJ8b+OkbL5++uyIT0+g8w== X-Received: by 2002:a05:7022:419:b0:11e:163:be60 with SMTP id a92af1059eb24-125c0fff8f3mr1909114c88.31.1769812587500; Fri, 30 Jan 2026 14:36:27 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:27 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 04/14] nvmet: Implement CCR logpage Date: Fri, 30 Jan 2026 14:34:08 -0800 Message-ID: <20260130223531.2478849-5-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 --- 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 c0fd8eca2e44..fdeb79ec348a 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -220,6 +220,7 @@ static void nvmet_execute_get_supported_log_pages(struc= t nvmet_req *req) logs->lids[NVME_LOG_FEATURES] =3D cpu_to_le32(NVME_LIDS_LSUPP); logs->lids[NVME_LOG_RMI] =3D cpu_to_le32(NVME_LIDS_LSUPP); logs->lids[NVME_LOG_RESERVATION] =3D cpu_to_le32(NVME_LIDS_LSUPP); + logs->lids[NVME_LOG_CCR] =3D cpu_to_le32(NVME_LIDS_LSUPP); =20 status =3D nvmet_copy_to_sgl(req, 0, logs, sizeof(*logs)); kfree(logs); @@ -608,6 +609,47 @@ static void nvmet_execute_get_log_page_features(struct= nvmet_req *req) nvmet_req_complete(req, status); } =20 +static void nvmet_execute_get_log_page_ccr(struct nvmet_req *req) +{ + struct nvmet_ctrl *ctrl =3D req->sq->ctrl; + struct nvmet_ccr *ccr; + struct nvme_ccr_log *log; + int index =3D 0; + u16 status; + + log =3D kzalloc(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))) @@ -641,6 +683,8 @@ static void nvmet_execute_get_log_page(struct nvmet_req= *req) return nvmet_execute_get_log_page_rmi(req); case NVME_LOG_RESERVATION: return nvmet_execute_get_log_page_resv(req); + case NVME_LOG_CCR: + return nvmet_execute_get_log_page_ccr(req); } pr_debug("unhandled lid %d on qid %d\n", req->cmd->get_log_page.lid, req->sq->qid); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 0f305b317aa3..3e189674b69e 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -1435,6 +1435,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), @@ -1458,6 +1459,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f49.google.com (mail-dl1-f49.google.com [74.125.82.49]) (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 72E4638A71E for ; Fri, 30 Jan 2026 22:36:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812591; cv=none; b=UzFvfQiYFuSktJgvN1CNlcwUQ2ldAptmoX2egsq0a4pCvlU+8RkQDaiWVtu5IaUoCc14tNY1e3LUJhjmXGMbHXlXmLHq6FlE2uGfwm4rW/YJHEvN+6IRoiTbgCOAkioB3lIwgsX9KXnuu4Yp0YvGCw12t4YQehiPBI+tKq7Efpo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812591; c=relaxed/simple; bh=r03Sk0joiETzSq+0ZPvKaeDMCFA6xVpQcIfUtvPeUt0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OTbOUmM60ADGz2+FVYPQ5+AqBzB4aYK8DYsGJ2ej5cS/A7NN7GEKhgVltYQjLUXRYlzl1sn3amGmS4MDjjz/4PtiBMVhH64/tHcHAiEHNUc27JazQAHApIBCaijIRYgO/S07MQ19L8QTC+tnfbs3dPoPtdaz9AknXOx38UBxg5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=HJ2QwqQB; arc=none smtp.client-ip=74.125.82.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="HJ2QwqQB" Received: by mail-dl1-f49.google.com with SMTP id a92af1059eb24-12336c0a8b6so3674821c88.1 for ; Fri, 30 Jan 2026 14:36:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812589; x=1770417389; 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=BAKqZ559mBTag/q6sjzJcnNya5CtOd9zWOEoYKABV/Q=; b=HJ2QwqQBrkC9XHRvwWt+uCF1GyFOZDaKX1bOcmmtA5kw1K6odAqb72G48aXKE6bwsG hIQMJOvKxLoBJ+bnrUrBdNz5IQBEGz0+WlGR2HBbjDoOQL4I7OkpJOvlDJy39qvY+s2x lY+05oUGpHijm6B4V+RvDNuI16p7k7rF4oj4uvEVQOEQv8df0qXsjTiDOuJzddjQd5hl b7xhbivV4BeEvJVd7sEKb1zPnDuUG/uRbLp1b5CiQmKNp8mjPscoVLS8F08yGy7WmgMT nycHrFCCKSO20gjV7jyFXFvbmxi2+m8CTYDN2gk4pd+tkvoiSvsBP7mXUl5njdXL4ICQ CKSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812589; x=1770417389; 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=BAKqZ559mBTag/q6sjzJcnNya5CtOd9zWOEoYKABV/Q=; b=Ojm02khatnS2UINvj4QiPGJiD+PR3eQPWhN0tCzJ85CjlhiPlVs510wLK/i6k52JlW L7TKbBj2wKEAbr5mrGhe1/zfRBr0i5GizaBOGOMVeFDbxkJH1bk9l73KSzF0AYfmFuVz KoTxBlIB8OOahwTqm5VvAXgaBbRqzgoRfnBqq3jFa4Vs5ZDOXw2Gle17y6ihIHPtJmel eRzgMWdHOJ2BTV6rm7Qc0hk9rDOdBaUNTuR4QxIQjN1BCCUDv5IoERrS92tL+mix1f71 V1czjhxhooTb5k5UkXGH6kXtnb8J13A1EOzENmadsK8cXWazgzniVHaaSvuh5zB/cG6v F6ew== X-Forwarded-Encrypted: i=1; AJvYcCUSJbnBDpleOndG0eO3T3ElORZ899T2g5CJjuCoyW6UsOZik8ky5JJI7qTtH03zvEtgds2v+6UcbBpOJ0I=@vger.kernel.org X-Gm-Message-State: AOJu0Yy9sSiCkVezjJ6UX9TQ9E27IYdYAunvUnPGMbNUGcizq9R7GtXl j/Q8K849Kx+/M3gw5Arr2g1X9zTKSVxR0dvQfIQkZJHS2/IKKOnaK3jU8ANk9v7Im5Q= X-Gm-Gg: AZuq6aKpIy8ybOM37Ni9u3qOVMIlfuqVW0Tw1B+xGXbXXxt/c0gvYrYLvnW5Roh+opa p8nsjYsTYE3mhNHeFlXQXQ8yZ18fmHnDe/XGA2um8iGcZzTJ2v6wMD83Wz5uA09pjn0173T80hs zQdz5SO74swdizNNY4/ZxTq0ose8kkQZWKP9IdoZwFIXsgT2u5OnDWmzIksWInlsEM2GDepgB3U OJRmspfjR41fZK25cfroioeEqbMIGbp/181qU/LxwbApJ0SjhrNX8BVeSXxH8kbLKNoUKU6ftAs Gr6u57O2ysafmqbNdmbwK0Uj0pl/gwDE4/GeYkwV1h0xbn2RRFacpK9oL6Y12lx8SeoDwVfgjE7 Lt51p/h7/dQdU+JnmYMnzdPOcBvrH3JhwNuIl7Dy6vXH0e351RkBVtmE1pvHhXhZDJjXYdCdgRw jwH6WxtYumChgPJf9qI/W+ZCBiYdjifXJIaw== X-Received: by 2002:a05:7022:68aa:b0:119:e569:fbb2 with SMTP id a92af1059eb24-125c1008c5cmr2553740c88.33.1769812588458; Fri, 30 Jan 2026 14:36:28 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:28 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 05/14] nvmet: Send an AEN on CCR completion Date: Fri, 30 Jan 2026 14:34:09 -0800 Message-ID: <20260130223531.2478849-6-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 --- 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 54dd0dcfa12b..ae2fe9f90bcd 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -202,7 +202,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; @@ -215,13 +215,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_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; @@ -1788,6 +1794,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; @@ -1803,6 +1821,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 93d6ac41cf85..00528feeb3cd 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 3e189674b69e..f6d66dadc5b1 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -863,12 +863,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 @@ -876,6 +878,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f52.google.com (mail-dl1-f52.google.com [74.125.82.52]) (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 5552938A728 for ; Fri, 30 Jan 2026 22:36:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812595; cv=none; b=lHTZHdErCZ5cB6aKZFVGZrPWkjvOAtrUqYzCTtO8XX8mgxKny5EgKke6ZL6DzYlEw6os+UsK3I37zQAeZor0tIvc4oS+yaW70EWriiTM1LHB1Vu4+MtgPpLub5hGeskT1iGDrtSVsFe1Xk01ALSUpFhZWp3LNjd5MY2I2rcsrE4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812595; c=relaxed/simple; bh=URQ1XMCWlLNVomKc60HFCpi+RzOzz75KlJGEQqBAS5Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qrRGH3Pp1yL9ddcnWKBjf/gcm0WSPk7fG8GuZGYfDoQVKTplh4qDizPXg2VAPbu85lm0KdearmEsMwj0bBj7zAh66/8gj3G2FdDbNfCsmAJWmW73mI4q/cOHSth6ku7ZDzDSRlSlZzXkt8J37wm5iy8hsXCuZ23uTkPJ1K734bA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=DCcg2Cbc; arc=none smtp.client-ip=74.125.82.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="DCcg2Cbc" Received: by mail-dl1-f52.google.com with SMTP id a92af1059eb24-124877d78a6so3345017c88.1 for ; Fri, 30 Jan 2026 14:36:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812589; x=1770417389; 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=3tS4KzqYbhEL6jev7Qh8Wf78xstwgPnfDr7XEbpNCcA=; b=DCcg2CbcvhuxpWJ8OX2afEzpbuYJpdl1sWSioQHErpcUmu0vsgNgSUZh9DbJSSYs8F KjnzgsMrLAdPT7SU5LeYKcXEYcO3V1mReh/mDE9YgTCcTHNd4/NXhP3WV44hvGjzyitw eqYxFCzjGu3ehjH0uB7kyJ6l8lpNexTxfkPaoAP1gjWBFvgpbPanixTu/XDJmqL8ydzO 0iGPWCE5E3IO4AA+UHsVxxbyjxwRTIGRtAlrR/VkSzWi3b83XvRypPuoOHXhumSrYS38 OHgObkWOaS1jPyOg8N4QePJqg1+U+vXkwdNeu7nbxbiAp7YJNRPhl5npQN0p+rswHh2o s3sQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812589; x=1770417389; 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=3tS4KzqYbhEL6jev7Qh8Wf78xstwgPnfDr7XEbpNCcA=; b=ELur/AuXGuevXymTv1yqqo6bn7r+aBB2qgzDfNlHgYIk+IGRPf6MWdNI+uF2bAdQa2 PO3bym5q+e9aBFEx98fM4A9p+Oac0mNRLtaIZ/fIopj29voKX7S0pV5rGn4j/UopuRcS ZykFBDtCQDhbci7BVDtqkiPrJhCemNaL5nOJq4xDBLM0zj9bAnd5At0Jz7SsDYM36lpD gur0MUljfDV+W6OSmO/eHtW+Y5aq0ndwVdJOOkSR/a2ifCeUG2/38KS5OqsULxmsxpLf qAGlouo+s/JR4Sl1frjToaQ3uWJSrwkLaE8FD/4UrBn3qFxbYY5UAsKNkGSCHvHxmsca 61sw== X-Forwarded-Encrypted: i=1; AJvYcCXJbomhrdO0OLQcDP2JpVjcVnxHLdGJ58Z/SNnp4+ZlSlS8Yap+HneO0VD2ZIfZRnWFzImNTulUvxEBYic=@vger.kernel.org X-Gm-Message-State: AOJu0YxuMqTJV4yBuNl+gKK85Hol+5xIe2qsL6fNX1N+a4TgTOJPmZrx yJeX2/M3LYFc1kccIUdikM7iQzvdtsDru5cKbsF2Cb0iK2cJIgudtXR66CJ9/7h8FjY= X-Gm-Gg: AZuq6aLzWR2FTttopcnC1cM2hu49T/cJm0JHgUFFmet88XtkSc3kRskkxY2W0pye6po KKNRuEUfrM4USU8QWL+74aeX0vdnp5LkeVTzWfyZwCcC0n+qzUMRsozVbf7tn+lcrzY88wo6bpt ZZPJumWjLZs3In1gxAYUXAx1ZuK6Zw8v6WFYgaJ0NK9U9elxQRKnwUlTAOVGes+BFnur2SiVhnh u+fsR4CWNtBkHIsEAvn8VvSKLPQ77Kp6kV9Y/dbtLNj2Y0e3I/pSvRRCc9OevhSf1xoXcfn5vBg GW+Q6AyzEX6hpa9xpBZYKCparzyoLzORIPLvPlWroSmvYlD5NyrFshBKtgX+6ZOrAjogwhYO2bA CU6x/THtcc2jtjokhwlWpVFTu7k2gm+8uIqZrbZQCYnt+Y8sAuERfLyG32tM3sCloKF1Au19SYm dJT8LN5futdPhyl9y/priU7S8wcD2oVMTv9A== X-Received: by 2002:a05:7022:e98d:b0:11e:65b5:75ce with SMTP id a92af1059eb24-125c0f9ab5fmr1931557c88.10.1769812589406; Fri, 30 Jan 2026 14:36:29 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:29 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 06/14] nvme: Rapid Path Failure Recovery read controller identify fields Date: Fri, 30 Jan 2026 14:34:10 -0800 Message-ID: <20260130223531.2478849-7-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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. TP4129 KATO Corrections and Clarifications defined CQT (Command Quiesce Time) which is used along with KATO (Keep Alive Timeout) to set an upper limit for attempting Cross-Controller Recovery. Signed-off-by: Mohamed Khalfella Reviewed-by: Hannes Reinecke --- drivers/nvme/host/core.c | 5 +++++ drivers/nvme/host/nvme.h | 11 +++++++++++ drivers/nvme/host/sysfs.c | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 7bf228df6001..8961d612ccb0 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3571,6 +3571,11 @@ 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->cqt =3D le16_to_cpu(id->cqt); + 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 9a5f28c5103c..9dd9f179ad88 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -326,13 +326,17 @@ struct nvme_ctrl { u32 max_zone_append; #endif u16 crdt[3]; + u16 cqt; 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; @@ -1225,4 +1229,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 + ctrl->cqt; + return 2 * ctrl->kato * 1000 + ctrl->cqt; +} + #endif /* _NVME_H */ diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c index 29430949ce2f..f81bbb6ec768 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_IRUGO, 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_IRUGO, nvme_sysfs_cirn_show, NULL); + + static ssize_t nvme_sysfs_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -734,6 +755,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f48.google.com (mail-dl1-f48.google.com [74.125.82.48]) (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 5E9F438A738 for ; Fri, 30 Jan 2026 22:36:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812593; cv=none; b=EsasN8CLXDd24pvPiT5IBoVcMICsNIqO/WZK62eW1pIbjqmeCwUWktfyQVADFnHJ3RKLfg8IY6Bk8hLwatpZwoihmG6ZIstZxIWyPi139xpn4bBvQqH+nOYjsV9Q2Ekyg7x3UZqi+6eVWTh0GZVje1q9P09nLenupJaBx+hVYGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812593; c=relaxed/simple; bh=u9JVQhvvNbGXFAdUSgQouSxTuRVLeuZidGri0Z149oc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pRm1qhWpz9+dJmUJqzL+GYr1FMe2RtHfmEmUibxXcXzeIFBNv226BIZ608X04DWL8TakS5aphA1UrYll9sjdDz46TO4mB96KOjiQjktwtCFkgH8ivv/wDi8D9xkbtmmKyWV486BSXv44Jk0QSakFFMN73+AY/F7Hz2OGX0shZBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=IFUHwVJb; arc=none smtp.client-ip=74.125.82.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="IFUHwVJb" Received: by mail-dl1-f48.google.com with SMTP id a92af1059eb24-124b117776fso2025596c88.0 for ; Fri, 30 Jan 2026 14:36:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812590; x=1770417390; 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=LVIdRGLqMsWSyf1RS7DGFOpPJ0jysmOUh1LqSt0/BVA=; b=IFUHwVJbal9P4qcwWaZ+ehBOi9JYNf+Glul3Ubm1UiSjQ4M/GsbACXaiIwTmVn414i 3TIkKe+1pw/0OMzo9B4ZbmmEs4mao8a12Au6GIujgnZaL/DUfnDQ9IoM4EokgceshKzu 1AM4AHqWfFV8lnml+7aIoKJ0d8aaW3I5kCsudmz+JK2wYvpsdq+twhsyNY1QS2z9M4gD vkfJb8Q9luXM2CX+6hfzwRb/GBtAOZ1EzpVvk/0hrzyLvxZl/QuzVaueldKCmku5BGcr BFo4/ZTCJUmS7Ca10okxm+SC4LGkzDWWquyYwGGm1bAZAW18AQ+0tsnQUdLW+m5xLeYi +7qQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812590; x=1770417390; 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=LVIdRGLqMsWSyf1RS7DGFOpPJ0jysmOUh1LqSt0/BVA=; b=f7WikrQcj6wu1P2gXZQzqcJdnTcPKyYJwHNQO8lC4YS1OWFq/xLjGDNsq9VHDP+C5I UcE+IGw+YbSU6DcOeepZyJkJ3BaqVq3ce7xKcFZkkDmJYol2uk22hxVSoaoJG0MHMvnH Ns+wv0bmm+0D+XoV1xfoST+rbV5hciPVP9glw/qqE96mSlDUr9IzvOm1ZMdZ+7Z1SIIG 7NXlTYzehxz5nuobsLf2RaHpbjlXBb8BcWi9GPiitOOq/fe86vtOPQgW7qxYXesC6HB7 qq2whZIRQqus5c+lZ5hfArkXxmYOpiT2H8yRBqUueQ4t5x6fSLoNdU5+57L08JYh+Z+8 habA== X-Forwarded-Encrypted: i=1; AJvYcCWkY+V6SbHUGiRiEqVubYDjaIGsM8vZuqGCOuqxJd3SvhYd6pwpYmeRNuQ227XreFi0Cl7XISMOcCD+b5s=@vger.kernel.org X-Gm-Message-State: AOJu0YylbPsbFySeq/wM6+SQ5D4A5iW31twD1ASjj3DH5+YllxsCG2uZ dIGFQKvcPyUCyflu5zTHu/OvGPixIm4tKirYu4FCNXFPCRWF6UDWlvyTVm+nNpTHBqI= X-Gm-Gg: AZuq6aKphjT+874lwtVcVmkc21HE6YZ2YKPZrC0CGXzDaUXcWMW/ofpAj4rlal55gsG oiWeJaqoV1xcOZap8Lm7WcRiZtJZrwLSv548nABNLbkmQb6GA2Eu80qIVaxpz1bl2PN0TVucSiH jWsPSN7+CpWCf3HtlkCk30EEWvLtZeg32LtBscN2/WUx5c6YfndSWtzlK4mlCDR0CvmhWCh1+Zy kS5jUEg/roKb6bIOb3wJge4eXRlqpNWGpALkHy1I6SurusLy68lmsOgZFRaZRFvggXSrafCG5Oc 6UrpiFEZZFmuZY9kMushOoeShYtbkRm0F/mxkmfx3v/Sml8T4hvEaeEQo/2Kg1kh/gp701KkbDP 4XL3/uAM+AJ4YsSZoYchv9O+LIhCRkE7XKqOr+A8YnsIZ0bNGOlxLyOU7ZlBOHFkqN2X54YO5Pb J95d732vIo9stM1apnIw20u6KmaTbnksPcjg== X-Received: by 2002:a05:7022:6281:b0:11b:9386:8271 with SMTP id a92af1059eb24-125c10081bamr2364267c88.46.1769812590220; Fri, 30 Jan 2026 14:36:30 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:29 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 07/14] nvme: Introduce FENCING and FENCED controller states Date: Fri, 30 Jan 2026 14:34:11 -0800 Message-ID: <20260130223531.2478849-8-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 enter 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 can not be reset of 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 to happen while controller is in FENCING state. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/core.c | 25 +++++++++++++++++++++++-- drivers/nvme/host/nvme.h | 4 ++++ drivers/nvme/host/sysfs.c | 2 ++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 8961d612ccb0..3e1e02822dd4 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,7 @@ 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_DEAD && !test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) && !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) @@ -802,10 +822,11 @@ 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_DEAD: return false; + default: + break; } } =20 diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 9dd9f179ad88..00866bbc66f3 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -251,6 +251,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, @@ -777,6 +779,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 f81bbb6ec768..4ec9dfeb736e 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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f43.google.com (mail-dl1-f43.google.com [74.125.82.43]) (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 3B46C38A711 for ; Fri, 30 Jan 2026 22:36:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812598; cv=none; b=WFBPPPeGFRcjDWEwifMnikifVSWw541+dAKx3h7P9hSOy280sfWIxMn1h3rqOLtVU9CzA/NuZ1i8I4whRdFLmWsCKf1mlRFsTJrjKN9+326yL5wjHzc98I5qSneZTpcsCSP4qNZIOBH9xkyvL9IqWBYk0jyIrCPMyjPwygkBqCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812598; c=relaxed/simple; bh=KgdNhX+eTsfBJ/zKhAov0VGkz5Hffh5D9AH/hpozRPw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GRg7eeNb6s3Tvs2oqzhNbCG+VXjJNwB5u/Gon7p7SWX16cPla9xuanO5Smut4qFLHGWAOHhzT2otMJnn40VttVaBsobrbJlTR87eheQn+YAaFfnyeebNx0vHIwVdi6ZVSwMiSxDlJXXHnIhoPV+BsE+gV4yzKvSff4UoeLakx9c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=QvkHPuer; arc=none smtp.client-ip=74.125.82.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="QvkHPuer" Received: by mail-dl1-f43.google.com with SMTP id a92af1059eb24-1233c155a42so4518901c88.1 for ; Fri, 30 Jan 2026 14:36:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812591; x=1770417391; 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=UYqxizsivYL+kINzdcPOhMPZJZrAVTcG/K2aY25NvUc=; b=QvkHPuer1cxjtHq+jra8EUV/nO2qVh0Ee1P/jXaKk5T4yTBXodW7BoO45OLkBEb0NI 99+cbe6XQR9Vst24udXQ8F50UjMqq889J4C0LaY+/0ApjaEG0Fby4LBBb/zWxFuICQuB uYOI5N/CcYzYBAPMSbXvPpUuwmZLCpsNWfCGquFUkrTrASQP011GEBVA+ckstrOLtkFq XNq0SX5Mo09p0+oT5Kiw5dX2PZUxAGo6zO3ZPsdjs/mJOU9Mu2RuN/pDHvfHYuhgBWEj Fe/+t//vSY9wFBJeCbNSQL14XJmx3b18UVJlhKCUsBRzmMh+B4Pk+S2r+5MwmLQMhxE+ LLKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812591; x=1770417391; 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=UYqxizsivYL+kINzdcPOhMPZJZrAVTcG/K2aY25NvUc=; b=Y3RaWtvBTL9IWpK18SqDBHT2x5nMiaMNDUAQiTymbSNaesAmCP8wxyQUiT/WNXVTq6 2VibS0sMy6OyoGDjFW/XDK+AVptkp4CXIF5cW+z5NUrpkf4pXC0oUKLmfAqT9r9caHKS 0IInDZSE9wnWMVNfuf5vuB/Cr6mcYffF7hVAFEQ0DcIdbs5PIVR0Tnspot/SvQP4nwlv BuwN4NWYxqtfFmkPId0O7k1yLw5hUv3CELfdemNnVWpUH/SZGH50jXFNPx8g6oYZUkkO /ihWLSDxkBXJ5CTIHAqHQIxG9ADL+br1sKLCoD1W3W58VpLePOE6RY6pO80HY7bQkvet aijw== X-Forwarded-Encrypted: i=1; AJvYcCVPgHpEdjaZQ7YIzq+OK/R+4a99h4F2aFMfh3+udGLm7stOumvfpMnuNl0UMcyu/484PKZcPSm6Oock0cc=@vger.kernel.org X-Gm-Message-State: AOJu0Yy5J6yLKUVitb6zeGs8RAY6ZwpXidsiNPLWBcwVxlMwe78xlk57 IRvE2LB58kumW9QGkOetIPx45YN4vtdMFBX/GuTbWGKx1e/w+m87eXlAKl/XS+gTAas= X-Gm-Gg: AZuq6aKPAb3Hmqmy5fwGoV0+DVPvwQVIENmf1LEgLPdYTsRzRvl2tPv4tCh5VLoD+RQ MoBQOFhIQwJbbtufOmOqpSzXSGI/rhMQCvsffFLJilYIpFqGite7nTBK44U4xgMDotS4WlpDzTz qZUvyCTI/kd+pdS9GYRjhGCG0t2VwtyvU3hP+ICSrdWcwoy8C9jl2RlurU69TCYkWlE2JFAu4QY YuUc0f6KrI7gp8bSj3neQK8LdqTf8odCjx82PCrw0VMFN1hvGp2lgeq76BTQKQZREyzqcmsgPbO 5iY6EaEHDaeJA09MCaJ/Jzl6onj2rLnrtEt7aLCTVFSwyLdAB9ynYIBPiCUS6j1DxZbMmkXSye4 fOTrVgaoB4WLlwr4ee3fGlHzJle6TBzENb/MWgPm5C6yJ5uzeTJKjKLAQ2Ull2FW3UnBGTlCZS9 Pc0lhj3/kJ2/my+iOveInQ2uc+ecmPq2rA9w== X-Received: by 2002:a05:7022:226:b0:122:a2:ffcd with SMTP id a92af1059eb24-125c0feb1f8mr2186268c88.23.1769812591032; Fri, 30 Jan 2026 14:36:31 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:30 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 08/14] nvme: Implement cross-controller reset recovery Date: Fri, 30 Jan 2026 14:34:12 -0800 Message-ID: <20260130223531.2478849-9-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 | 129 ++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 9 +++ 3 files changed, 139 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 3e1e02822dd4..13e0775d56b4 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -554,6 +554,134 @@ 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 *sctrl; + unsigned long flags; + + mutex_lock(&nvme_subsystems_lock); + list_for_each_entry(sctrl, &subsys->ctrls, subsys_entry) { + if (sctrl->cntlid < min_cntlid) + continue; + + if (atomic_dec_if_positive(&sctrl->ccr_limit) < 0) + continue; + + spin_lock_irqsave(&sctrl->lock, flags); + if (sctrl->state !=3D NVME_CTRL_LIVE) { + spin_unlock_irqrestore(&sctrl->lock, flags); + atomic_inc(&sctrl->ccr_limit); + continue; + } + + /* + * We got a good candidate source controller that is locked and + * LIVE. However, no guarantee sctrl will not be deleted after + * sctrl->lock is released. Get a ref of both sctrl and admin_q + * so they do not disappear until we are done with them. + */ + WARN_ON_ONCE(!blk_get_queue(sctrl->admin_q)); + nvme_get_ctrl(sctrl); + spin_unlock_irqrestore(&sctrl->lock, flags); + goto found; + } + sctrl =3D NULL; +found: + 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) +{ + struct nvme_ccr_entry ccr =3D { }; + union nvme_result res =3D { 0 }; + struct nvme_command c =3D { }; + unsigned long flags, tmo; + 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) + goto out; + + result =3D le32_to_cpu(res.u32); + if (result & 0x01) /* Immediate Reset Successful */ + goto out; + + tmo =3D msecs_to_jiffies(max(ictrl->cqt, ictrl->kato * 1000)); + if (!wait_for_completion_timeout(&ccr.complete, tmo)) { + ret =3D -ETIMEDOUT; + goto out; + } + + if (ccr.ccrs !=3D NVME_CCR_STATUS_SUCCESS) + ret =3D -EREMOTEIO; +out: + spin_lock_irqsave(&sctrl->lock, flags); + list_del(&ccr.list); + spin_unlock_irqrestore(&sctrl->lock, flags); + return ret; +} + +unsigned long nvme_fence_ctrl(struct nvme_ctrl *ictrl) +{ + unsigned long deadline, now, timeout; + struct nvme_ctrl *sctrl; + u32 min_cntlid =3D 0; + int ret; + + timeout =3D nvme_fence_timeout_ms(ictrl); + dev_info(ictrl->device, "attempting CCR, timeout %lums\n", timeout); + + now =3D jiffies; + deadline =3D now + msecs_to_jiffies(timeout); + while (time_before(now, deadline)) { + sctrl =3D nvme_find_ctrl_ccr(ictrl, min_cntlid); + if (!sctrl) { + /* CCR failed, switch to time-based recovery */ + return deadline - now; + } + + ret =3D nvme_issue_wait_ccr(sctrl, ictrl); + if (!ret) { + dev_info(ictrl->device, "CCR succeeded using %s\n", + dev_name(sctrl->device)); + nvme_put_ctrl_ccr(sctrl); + return 0; + } + + /* CCR failed, try another path */ + min_cntlid =3D sctrl->cntlid + 1; + nvme_put_ctrl_ccr(sctrl); + now =3D jiffies; + } + + dev_info(ictrl->device, "CCR reached timeout, call it done\n"); + return 0; +} +EXPORT_SYMBOL_GPL(nvme_fence_ctrl); + bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state) { @@ -5119,6 +5247,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 00866bbc66f3..fa18f580d76a 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -279,6 +279,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; @@ -296,6 +303,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; @@ -814,6 +822,7 @@ blk_status_t nvme_host_path_error(struct request *req); bool nvme_cancel_request(struct request *req, void *data); void nvme_cancel_tagset(struct nvme_ctrl *ctrl); void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl); +unsigned long nvme_fence_ctrl(struct nvme_ctrl *ctrl); bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state); int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown); --=20 2.52.0 From nobody Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f49.google.com (mail-dl1-f49.google.com [74.125.82.49]) (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 E262438A9BB for ; Fri, 30 Jan 2026 22:36:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; cv=none; b=jkWNAy9dE+vBbLUeEp7EiBTRf2JcomSz8T2JNUlFEeBmC5tar2JwgIYWUJlbqCv3Bzu8Ud6cr3FFcbUkYTZLA/nhnfX1rYPEpMeEDOQhZVQy9i0TyMq59ewTbnyhQpOpeJ7lzkO92EgZ1z67QTOAvXWm2CNh3pN9pzAHE2Za3GI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; c=relaxed/simple; bh=kPyEV+2h+j3BgxBngQrzBVVOKqZ7gKJgCU7qZ5evXnE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bMxBWIJs0Oyex60CFPFYxl6eKS092WiSi38ilUV6GW8Sl/rxVVykDOkwliyqnUBa/6ydvopm/e3GYjWCjgXt2M6szHma4mWaspynffxoYTcRtQfMF5/eWDWNROguwoovSU1BB7/kmuUuFAVUKlJ6baAzDe10b8Ykc00kCbr2k/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=B+ImF6wP; arc=none smtp.client-ip=74.125.82.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="B+ImF6wP" Received: by mail-dl1-f49.google.com with SMTP id a92af1059eb24-124566b6693so2426788c88.0 for ; Fri, 30 Jan 2026 14:36:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812592; x=1770417392; 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=ZjQY91Zj2Uen3s+F0p7lNd7qUdF+rUOyKxsGPKTZUoQ=; b=B+ImF6wPOKAk7mPh3TNvqMJVAROhcRb6eHZoHhZRP+7MLjL7fnrcmvsRUZaGyXeODI kqNM4hc1pW8t6Mg3q6ryVvHZCH0X00RbUjH/xh3c9CgyFeJzG4crUtnzbWmgVcynzAcY S9uYlNpGkV5kmwrBGdKyMmKIOhTIcNzYLzeWwyigIvlfLDyRzjJvaeC69qgcVt2gZBuZ WhWGQMZxAPm97AZXvA++Ve6Ldu6cvTQ+7vcPXlscuJ0UNR16nB781kY9TtUnFJJzTyuq koV12OTkzQMzPFugs78acgn7CTxCReIJZdAapQUZL9Hqpeo15Z+rNFCO5aICrU1I/47B P1dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812592; x=1770417392; 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=ZjQY91Zj2Uen3s+F0p7lNd7qUdF+rUOyKxsGPKTZUoQ=; b=ENqily8mIbXyjxAdql74AwPkOv2IMd7sLekTbM0n3q8TuaT5SaABv2Ms/xyhT+wMnO irlxDH98bw4dLlFgaj92lq7LP1O3my1Leoh07w2JM9+K/3pTHON63MpnEM5WXEz1StXS qzhv2je0L8oqTZuDwvUrjpPtO0R/AXmCwLuOY5kgH+za1vF3vrbuVdlc+eTp2Hlk+C0v API5XfhMtoptsLbs3pe1IFfPSIo68JEvSUqPArqZb42+/+vPQwFLhMOWAwc8HMLdcSnG /dK9q2wAAmNcK0UBFhavLSU6trM35DnyKPZx7p+GYHhtkBtK/UUuUnQPOigdvmb8gqV4 TDlg== X-Forwarded-Encrypted: i=1; AJvYcCVuwCjWn216AeMK5sss9ByR7ARpikcrPr4Den08IM83nxi4prKfbiAV0rEl6L0Z/ZRaycg5GWE7EwD9mcM=@vger.kernel.org X-Gm-Message-State: AOJu0YzTTXaHWe9ZAoek9t8W56a/qHtTnYiZNwXY8usw7n5kWwM1c9+y R7R9bG49VfVpdV9Wa4KE0GRrMS5vXzkZZJLa5wlEMFKWeuyrc/mQA+IgSajjZtGa844= X-Gm-Gg: AZuq6aLHwDXM4MUO496RHsbOqKx39dyI+oGj64n7GMdaZN/L55IxYeZMxAsv9O2WkVW HzC4n1qij3QWOATiWGaf5kyDlvBVeHWqcBH9M49t4wwgvwkmnrYbcfw5T2JIBkSMy/Chk27Py7F Zw47JopwcfkO2p6L1lUpT7NFz7ODCtjlkyEf9yCG9sr5CeJY0C27KJlF5kFmoe9h6Sk3+umeNle dUuKnzlle7T5x9R9BAsXe+wR5bXHelDgnWZ/SYDIDg2a7qf22Ut27f3BjWP+4SMK6TRSwgsfBLY FF+iqpQr4vyVsC0rRhzO+O5mbI03c6LKMgH83RoDC3cTX1VibvjizVUkRHfG0c1CYoLZb2AImaR 3IZ3rrg8JNaM23csQr55l19g7mEmnu0DLch3jl3VPRohWq9bBDnZK3jn0N8Q5p/lAPn1WC72aIY O200Zm0EV7wkPFmHBp2fxNmwa1zXJ3fI85hQ== X-Received: by 2002:a05:7022:e02:b0:11b:9386:a3be with SMTP id a92af1059eb24-125c103f66dmr2278348c88.41.1769812592008; Fri, 30 Jan 2026 14:36:32 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:31 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 09/14] nvme: Implement cross-controller reset completion Date: Fri, 30 Jan 2026 14:34:13 -0800 Message-ID: <20260130223531.2478849-10-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 13e0775d56b4..0f90feb46369 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1901,7 +1901,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) { @@ -4866,6 +4867,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, @@ -4942,6 +4984,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); } @@ -5131,6 +5176,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); } @@ -5254,6 +5300,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 fa18f580d76a..a7f382e35821 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -366,6 +366,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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f48.google.com (mail-dl1-f48.google.com [74.125.82.48]) (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 4EA8F38A9C6 for ; Fri, 30 Jan 2026 22:36:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; cv=none; b=P+BFGAOZM18NMAlkKx8iDRETin8dCqHXMRHXeBPUK9N+zz+T5k4EQasGMZIpaojfWY48ohBe4RmVtl5JjYNANbxpVJn0lLKMkdSxXFHsH90TW1kZzMNl8ZlGVpfB5K/5MazqOyE6c0n4SUYJW88H8ESXK0Tb8CXAcLWLQukq5Jo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; c=relaxed/simple; bh=+DCK/lb5J8eX53TqCpHbTMAXo4LWmuWp48ouPQr88/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G/z/uuDIxDIL74lmuMvIWEok75rnI5US3oyivRPLoDnCXHvD1Md+haWbOiA96uok68TwV99mPptfC9H+0/fQ1HSKu2+4ykKtQ5SsDEXbalOBPhxATh9a909Dgq3DH1NJpwmZRClwGHgXYO25F2o7kKoaao7CClgMvrwZqr9W5go= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=ZDIzzuKk; arc=none smtp.client-ip=74.125.82.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="ZDIzzuKk" Received: by mail-dl1-f48.google.com with SMTP id a92af1059eb24-1233bb90317so3047257c88.1 for ; Fri, 30 Jan 2026 14:36:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812593; x=1770417393; 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=xDu7rcI44pdZ7ozlYZ8/MRynW2sKdwev0diNQdJpydQ=; b=ZDIzzuKkNWcJp4De+Og6fPsp4dxfDCAtcBdGHqN7CVv/2+YC8Zal24Pud+0YPpZvcD vxC+WCiI93lwFnnTwy7nkFHrSeOrdMTtb0yMvTMPNvig+9haIH8w0p4EPOcBc3ObhHeb PPJmaSupZCGH5gW4FBcsoUoB8i7mWRrnQDHvp7S3nIWwYS2hQAMe2/1t3MBzwj/fy6Vy WfKvO16F9PMC7bNGJDZJzxzAhyV+mQLbclJAwbLCdtup4f4v8KxA8H6JPZWoyoCgGf6X bJomCOmSWpCEeAr23dXTT9my0xJOqElM5MAK8Khhx9ln+i0PVZ4KKWEYzHZnmQBSb3WW HWKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812593; x=1770417393; 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=xDu7rcI44pdZ7ozlYZ8/MRynW2sKdwev0diNQdJpydQ=; b=NOs2JwUJAtc/ExC7MTjrY/IFu+xvyZqkCX4oepbIdcSJ8i7DrF9SF+FGn8qIJehWYj zFWLifwxRsvQEBtPQQQOj0WHPhU+D+uJ+CNti2hUkxEkUbs74h0xgNxwNObEjzd7rGlo OGtFQEIkQL2GL93oniFlZgczyBOrTIfh6MKUuMJqul1ARTxWTPRGvJA+aQA1Mvz4t/st BwE59uZNkSDevjN7gu42FBLLyRkZUuMrSJjLajeTHqox38gGoJQi8wC7rChT7UeEXnm+ 67ChG2FsyWN+4TJ/k2DlmXW36In4+IlADyd8fQTl7xse7inab15G/O8+2FCMBHcqadAF tKTw== X-Forwarded-Encrypted: i=1; AJvYcCW2kKKfEqqMcJWEsXMsUwZ8FRC7YAABRWPTdhqWJy8F8PX2vAByygZ7EiS3m+oVWDuJQJb4zsuueOtK8gQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwsdzegHQYiqRBTY+gWNm4CY+8t0bb9AOoRks2m/rh2BqusFuA+ yZa2zsCYxdVZu2dijKD0z+ogVIICYQgW31oIBV9ZZVxR+SaFraGoQho+cUt1f1ib9p8= X-Gm-Gg: AZuq6aI0WhTwt2vvcjNSYiNdTq68cn5Pnl41CJoXqpTEil0bfRhNIwIcjmD68Co0vNe 9nR5q4aXhp9czroJ6nicV5uHw9D2ma1mt6CvjFou6YjInl4BFa+iXq3uuqI6OBKQryOgGNi52IW j9w3hZKKR+jMU2ojOvZOl7sH212Wi8ttzxcA3KUPu6ul+dlVv9TQUSug4runrhcks/x7y92KbSV Qvo76JfkpdQ7N4io5KokmHcAxi97u6SU6G4eu54LGwbqPGiRq0mWPktwjd6sJhz/TCBoZtSa7/6 E6TZsrLiEz6gyR8II1BO3f8v2Ohd7yGzAMYVk3Lm3AgWLfn8rayAFEy1XTsL/NY5FZVO3852ihF hGOjiewuUqNWZxl3VwnMNZSew87/TUcwK19YlsDyrHZZSjx10pEFgl9ZRZl5dL6eCbH7HsQdC6h bvvTdIV03H18TrgKpQs8fOsKT3uTV6mXoheg== X-Received: by 2002:a05:7022:4589:b0:11e:4fc:9b33 with SMTP id a92af1059eb24-124b100d8d5mr4190399c88.1.1769812593015; Fri, 30 Jan 2026 14:36:33 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:32 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 10/14] nvme-tcp: Use CCR to recover controller that hits an error Date: Fri, 30 Jan 2026 14:34:14 -0800 Message-ID: <20260130223531.2478849-11-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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. If CCR succeeds, switch to FENCED -> RESETTING and continue error recovery as usual. If CCR fails, the behavior depends on whether the subsystem supports CQT or not. If CQT is not supported then reset the controller immediately as if CCR succeeded in order to maintain the current behavior. If CQT is supported switch to time-based recovery. Schedule ctrl->fenced_work resets the controller when time based recovery finishes. Either ctrl->err_work or ctrl->reset_work can run after a controller is fenced. Flush fencing work when either work run. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/tcp.c | 62 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 69cb04406b47..af8d3b36a4bb 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -193,6 +193,8 @@ struct nvme_tcp_ctrl { struct sockaddr_storage src_addr; struct nvme_ctrl ctrl; =20 + struct work_struct fencing_work; + struct delayed_work fenced_work; struct work_struct err_work; struct delayed_work connect_work; struct nvme_tcp_request async_req; @@ -611,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 @@ -2470,12 +2478,59 @@ static void nvme_tcp_reconnect_ctrl_work(struct wor= k_struct *work) nvme_tcp_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_tcp_fenced_work(struct work_struct *work) +{ + struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(to_delayed_work(work), + struct nvme_tcp_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &tcp_ctrl->ctrl; + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &tcp_ctrl->err_work); +} + +static void nvme_tcp_fencing_work(struct work_struct *work) +{ + struct nvme_tcp_ctrl *tcp_ctrl =3D container_of(work, + struct nvme_tcp_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &tcp_ctrl->ctrl; + unsigned long rem; + + rem =3D nvme_fence_ctrl(ctrl); + if (!rem) + goto done; + + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } + + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &tcp_ctrl->fenced_work, rem); + return; + +done: + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &tcp_ctrl->err_work); +} + +static void nvme_tcp_flush_fencing_work(struct nvme_ctrl *ctrl) +{ + flush_work(&to_tcp_ctrl(ctrl)->fencing_work); + flush_delayed_work(&to_tcp_ctrl(ctrl)->fenced_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 + nvme_tcp_flush_fencing_work(ctrl); if (nvme_tcp_key_revoke_needed(ctrl)) nvme_auth_revoke_tls_key(ctrl); nvme_stop_keep_alive(ctrl); @@ -2518,6 +2573,7 @@ static void nvme_reset_ctrl_work(struct work_struct *= work) container_of(work, struct nvme_ctrl, reset_work); int ret; =20 + nvme_tcp_flush_fencing_work(ctrl); if (nvme_tcp_key_revoke_needed(ctrl)) nvme_auth_revoke_tls_key(ctrl); nvme_stop_ctrl(ctrl); @@ -2643,13 +2699,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 @@ -2904,6 +2962,8 @@ 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_DELAYED_WORK(&ctrl->fenced_work, nvme_tcp_fenced_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 Sat Feb 7 07:24:33 2026 Received: from mail-dy1-f174.google.com (mail-dy1-f174.google.com [74.125.82.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 F060838A9CE for ; Fri, 30 Jan 2026 22:36:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812602; cv=none; b=LlM/qsNgnUKuXTUimJua46yioGqmakz/QKQI6q01hH4l0QxrRez8/OyqQO+zzRW4IKkj0mF6v8C1/DPh9NgTKjbZwUdkME2rnymh5j1+57BiMkjM/UjH4USg2orN4kfugEgx5FhwGOj7bm0aIanH+FWl/iOIYKhQn+CUEezKo64= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812602; c=relaxed/simple; bh=JrMt4s1tXI63Lv/Bo+8XTaWzdhJgsEhkmX1LEgLUMjs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eNggcbemNrndhnLTKgXkNtmzMzYVwmtXHRtEcJIj2DaND4tfj1LZfRE660wkNzbpwsw8IBzLT+fdHB/egn+ydNTUmdBkh/uauVY4YPhmBXJ+yuTvykUmI1TIicAqbE0BlmKjolOIBwx5GoJpm57zSjL/Tcdg2udimwt4YYxVrqU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=B6BDBDI2; arc=none smtp.client-ip=74.125.82.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="B6BDBDI2" Received: by mail-dy1-f174.google.com with SMTP id 5a478bee46e88-2b71515d8adso2691866eec.1 for ; Fri, 30 Jan 2026 14:36:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812594; x=1770417394; 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=zyhzdc6roNohqktXVF46V+5k877QRUEUXl/CXU7Oa7c=; b=B6BDBDI2/ajzP9tInfqi2RRrlME9AOCpVoof7m7vic50neiMVqt9iVrRm+EYXTBD2o xI8Bsy/+xR2v93OEouYt7UkyT9LkWG8GwZGFLSoMnQo9oxN77XPigQD0OKY7hQjsZHdm 2nZARlg9v29FoUH3H/EeOnX6aqvzC9vi4vbhbWEE5Ka9KxmixT0NyTX1Pe+TFSNu6DHx 30eAAwsuZgnlJfszU1eXkJE3XGzDOE0Bf6ntLLz4UANibJ1t1hYdyMdbiAQ8+axpBuuN HXTu16Bzq0ZgOINbma17KPUoQe2xR5hr/bnhP2S1JriOPb9E5mKyHExljxO0LCpQdJIy BKAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812594; x=1770417394; 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=zyhzdc6roNohqktXVF46V+5k877QRUEUXl/CXU7Oa7c=; b=VnWTYQS/f1XLsp25IQ8LFuiWVllPb3oHGWHahiR8huPojqJLuSqO7LgV3GLLHVAk0T 4NkVde5nm+oWe76alSrQ72HZRXcqkN/ddjje2pk4fwdwmfunNONMfTaR7+tI9ANaLsZw V1Y4DnCw7yEi5rxa50A++5U8P4ENPQdsE+2XIZMJK5dDTOqi14gB7TeiHo+lNYdkuZmZ Tci5zpIz8yZDrikG/7q9D2cCvGd93NwbtpJpcT4i/gkd82fBVnG70tkOlAMHWr6PeKdI Gcd6C9Il1zh/2aLLHI52aCSafFTDBHFGo61vS8G8w/Cv/bUIQQ6TB5OiU4BnnBVstoAG rUrg== X-Forwarded-Encrypted: i=1; AJvYcCX0x5vl3YzeGSH/fhiJFVon9riaK4biCLS66hJRVrqoEJF/y2sKpp88fihw6DFV5l9JEG+HN+AeChZ5Z5Y=@vger.kernel.org X-Gm-Message-State: AOJu0Yw4SBnNU+zpbkRou2Ou4Vr+z3WtG3vXt++RToMTJfdTyPPlVIv9 CMxHqcfOEOgdbLtjjkWLpKo/h8Cz/+K+tatnbaDokyCGb4WeoH+T3Cc+E0dBdv18SnM= X-Gm-Gg: AZuq6aL2PotLS5JyyuD7zaCfpzq/C5RMQoSrksKJ+0HoExdIHVTqP9WJj6N6/Gpsy8x Z2aOks/QCaj1gf2n4uXP3RXtQeFJHNGSCxLvkTggBSU6EmQuvNIO1hty9B3YAMbQ3nZOESkvyxG u9dcrXE3OW0BkzzViw+tVYLpgvgmHlCHOmL9kI3gG0yoFIV19D8o9zRpytTRIqrG104/KiCOgCj QGeogJrk7pJQe9rpzpWvNK1u3YHqytZ24OeOVvFOZJ9eo6WiIUOdLSWp20OPcQctCW3MnRXMobB +4MukU7IlidulGO7C7miCjGZk8BPy1c2mlnLhGYce/nwrE+oLCyRmcSk7qYrHRsJNqeYj+28P/A jUYAzTH7H90rWIh8fKuBg9W14qtzqDnGj7onEg2ePKlMLPVPtsRCPbM8YgdtwWvxx5iuInBgdI2 unhGHoNLsEq0vLnXChp6POAClv/bJyYJtTKA== X-Received: by 2002:a05:7300:7306:b0:2b7:2fff:ed1f with SMTP id 5a478bee46e88-2b7c86657admr2320612eec.17.1769812593797; Fri, 30 Jan 2026 14:36:33 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:33 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 11/14] nvme-rdma: Use CCR to recover controller that hits an error Date: Fri, 30 Jan 2026 14:34:15 -0800 Message-ID: <20260130223531.2478849-12-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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. If CCR succeeds, switch to FENCED -> RESETTING and continue error recovery as usual. If CCR fails, the behavior depends on whether the subsystem supports CQT or not. If CQT is not supported then reset the controller immediately as if CCR succeeded in order to maintain the current behavior. If CQT is supported switch to time-based recovery. Schedule ctrl->fenced_work resets the controller when time based recovery finishes. Either ctrl->err_work or ctrl->reset_work can run after a controller is fenced. Flush fencing work when either work run. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/rdma.c | 62 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 35c0822edb2d..da45c9ea4f32 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -106,6 +106,8 @@ struct nvme_rdma_ctrl { =20 /* other member variables */ struct blk_mq_tag_set tag_set; + struct work_struct fencing_work; + struct delayed_work fenced_work; struct work_struct err_work; =20 struct nvme_rdma_qe async_event_sqe; @@ -1120,11 +1122,58 @@ static void nvme_rdma_reconnect_ctrl_work(struct wo= rk_struct *work) nvme_rdma_reconnect_or_remove(ctrl, ret); } =20 +static void nvme_rdma_fenced_work(struct work_struct *work) +{ + struct nvme_rdma_ctrl *rdma_ctrl =3D container_of(to_delayed_work(work), + struct nvme_rdma_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &rdma_ctrl->ctrl; + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &rdma_ctrl->err_work); +} + +static void nvme_rdma_fencing_work(struct work_struct *work) +{ + struct nvme_rdma_ctrl *rdma_ctrl =3D container_of(work, + struct nvme_rdma_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &rdma_ctrl->ctrl; + unsigned long rem; + + rem =3D nvme_fence_ctrl(ctrl); + if (!rem) + goto done; + + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } + + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &rdma_ctrl->fenced_work, rem); + return; + +done: + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &rdma_ctrl->err_work); +} + +static void nvme_rdma_flush_fencing_work(struct nvme_rdma_ctrl *ctrl) +{ + flush_work(&ctrl->fencing_work); + flush_delayed_work(&ctrl->fenced_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 + nvme_rdma_flush_fencing_work(ctrl); nvme_stop_keep_alive(&ctrl->ctrl); flush_work(&ctrl->ctrl.async_event_work); nvme_rdma_teardown_io_queues(ctrl, false); @@ -1147,6 +1196,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 +2012,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 +2226,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 + nvme_rdma_flush_fencing_work(ctrl); nvme_stop_ctrl(&ctrl->ctrl); nvme_rdma_shutdown_ctrl(ctrl, false); =20 @@ -2281,6 +2339,8 @@ 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_DELAYED_WORK(&ctrl->fenced_work, nvme_rdma_fenced_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 Sat Feb 7 07:24:33 2026 Received: from mail-dy1-f178.google.com (mail-dy1-f178.google.com [74.125.82.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 BDAA238A9B5 for ; Fri, 30 Jan 2026 22:36:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; cv=none; b=JJmbJ8ihXyhvTXsjl83eKD/eQLAmtJ8SMAQKYDxmXZkkg8L+RLNTo2o21gHf2vgTEnwlJfEOeO32rJNwk3CJzFn1FtOaeaodJpu5W3SPcJCqQIXj4IR0z4guXNvGalc8jN3vDxmEkWVWzKenNmcFKowXpyQGYNvvTo0m2fDrT94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; c=relaxed/simple; bh=MSBKnlqsIu+BRlrhe2SCDcuIWTpy8vl/QfWB/3Ujhkc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uKr5tiU7B7JCgDYt+aYfrX1qoBFl3NgaVSCfhO+vleETiBdsysVLuSfSlx/NeeAcarHRczNb3Ar6jRlvWb/NYUGXHq9gQH7Kc8gu8c5a/7Ky+FO8tCDuyqFt8GPU30SRTMd2z0EOZMdU2hQzNhMkuGx1GaVWgDP8uiUVapQuHQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=c5Bozk3i; arc=none smtp.client-ip=74.125.82.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="c5Bozk3i" Received: by mail-dy1-f178.google.com with SMTP id 5a478bee46e88-2b74f839bdfso2712590eec.1 for ; Fri, 30 Jan 2026 14:36:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812595; x=1770417395; 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=/D5ucSFT3TCGsev1HjV6na9ZT2ASzYHwLoVd/attJt0=; b=c5Bozk3i0UeGajuBnOLnslG76sEo9ogDNtX9ao6lbnNqHM4YsUaZd10Ya1fQnDjg3j M1XuDBKR/6rvOzYZ3zNuDIw8X0XD/x3kAE7VvBZaXPIWm13WPESnTupEOhwz4GfedfYS PGyyMV8bHG7eg8WciOapfe6hf/1jh/fzqhWgsriXIDwx1wD2Eq5TimNqpt4d8Ay8SQB/ JNKNfNIO6FaTAcI4IGvk/yuIrY+N9tZYG0BIqpxuNZaQtqgLmw/K+GGvacmxmPnbkLMm Fw9E6KRSMqKjhEv+PWKy0tb6NuiLeyrOI5XHDKQMUHt2w95GNVeI/nTQxfbstku1qP1J EyNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812595; x=1770417395; 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=/D5ucSFT3TCGsev1HjV6na9ZT2ASzYHwLoVd/attJt0=; b=sK14OcTJqz94osOv12hqevfaW7DdkzRAqLV+WGOScYnCJz+RsWm0rBgVnwtkKIlZ6a FQK/r5lUb7de9G/r0joZH7f7ya2G5enHj+46nfJZmGNbbvH/phKXVe6gpBzZeAC20YvX 66HRaTpver6X8efabrCOn0TBVrWip/zXJGR7wUBTthvtyBKyqI1ZdYwLswFnIT8wJ6+T IuWLHDRdaBt9VfBPprbi04H//00AvE8F8xwbGfTW36NfN+WsYhzCK8ObNoXRvFUV9nUC xxPtaKiE47gtGJorNcnKYZ5ujMT76CtSbuQq5FUaUZk7cu0th4/Ae/Ck8Ca7qZZbCKSC Varw== X-Forwarded-Encrypted: i=1; AJvYcCUKpPqg31O89Fh7EpeRoY1/Sjj4ARXvKJbwmCgsU3m1ij2c3dpoZ518VkKB/I3JahV+mL6E6qqI2XdV9YE=@vger.kernel.org X-Gm-Message-State: AOJu0YzRq7w6w43sOjdUgg7hlSjMILKrhyJXMjLA7CtSw6i2tRDEiS3+ /1DuQqwagi3IWehOTpWskOZp1KZOZVKhemBb36NQ1pvPkRaeUckab1M0WjgOBlaGP8M= X-Gm-Gg: AZuq6aLOOJt+gm8DpOB73E5nF3EEpqrv34obcIBD+jBAkurSFEEwurjs72bNd7Fq+B5 Hl3OBpRsymg60NRC2vSGplbV1mXIzubJV1CLDcOgKcQR59dHBrgSZRWfg7nmnuyW166m1TmGJW7 Umg8BY9WlBKHItq2oEQKZq5oDqsOeXJVt54PNFMgWu38k0h4XVSfFHYrou6ZOcRlbj0BOUWFJGL nJcX2Jy84K18WhBHeosKyY3ZguUpsJ0diECDWdwVKFzknGCMNww57v0vGeePQ5T4uFZuShuCNsy rUHvYa4+1GWb+T4xC8Q7Fpje77sCIqrPdZj/CUq77O5CSgUthwVixxuan5myxTj1uynfKDmgVJL cSTcJZbqdzTQhWwLarDIfKIgDAEUyL0xNuEi6vKMx8wifQ99q1M4+v4MJh0ItuUtOdDYmjpwoZS l/zFL2t/A2omtYk9n1TyxzGDu6ueUVpGfSXw== X-Received: by 2002:a05:7300:a890:b0:2ab:9d23:f0b1 with SMTP id 5a478bee46e88-2b7b1848daemr3392185eec.13.1769812594644; Fri, 30 Jan 2026 14:36:34 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:34 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 12/14] nvme-fc: Decouple error recovery from controller reset Date: Fri, 30 Jan 2026 14:34:16 -0800 Message-ID: <20260130223531.2478849-13-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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" nvme_fc_error_recovery() called from nvme_fc_timeout() while controller in CONNECTING state results in deadlock reported in link below. Update nvme_fc_timeout() to schedule error recovery to avoid the deadlock. Previous to this change if controller was LIVE error recovery resets the controller and this does not match nvme-tcp and nvme-rdma. Decouple error recovery from controller reset to match other fabric transports. Link: https://lore.kernel.org/all/20250529214928.2112990-1-mkhalfella@pures= torage.com/ Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 94 ++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 6948de3f438a..f8f6071b78ed 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -227,6 +227,8 @@ static DEFINE_IDA(nvme_fc_ctrl_cnt); static struct device *fc_udev_device; =20 static void nvme_fc_complete_rq(struct request *rq); +static void nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ctrl, + char *errmsg); =20 /* *********************** FC-NVME Port Management ***********************= * */ =20 @@ -788,7 +790,7 @@ nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctr= l) "Reconnect", ctrl->cnum); =20 set_bit(ASSOC_FAILED, &ctrl->flags); - nvme_reset_ctrl(&ctrl->ctrl); + nvme_fc_start_ioerr_recovery(ctrl, "Connectivity Loss"); } =20 /** @@ -985,7 +987,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 +1569,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 +1872,7 @@ 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"); + nvme_fc_error_recovery(ctrl); } =20 /* @@ -1892,6 +1893,17 @@ 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) +{ + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) + return; + + 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 +2061,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 +2506,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 +2514,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 +3320,26 @@ 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); + + /* 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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f42.google.com (mail-dl1-f42.google.com [74.125.82.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98C8D38A9A0 for ; Fri, 30 Jan 2026 22:36:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; cv=none; b=luAjg8/OJsusJHQpOLRQiJr/GlKYbcJaKPhzmxqr8kZjIKcq8aWuyOlT+1g+VQY+5dY0pFipIg3+i9+rfGKfJb606yp40LJtWIXAkn/vCqqiDn+L39sFOMTUZfodd6jBYds3t43rrcEIwZZX0Mqk4tiHw60Ms+gXwG7YGhARpkc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812599; c=relaxed/simple; bh=4dLf+jpbwji2Sni15TR/T4gZJ9NUyvzCAm7JwtBULB4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XjRmYsclbpM0VlhgTbeoQFVa8L6jJI3ZeNhOMuoUd6VzxjHZNrB/87tIN4x4AhVO3IE9zbnK0CIVrvTMqTWOfWUPhNn81TSKC7TdL4cbUxQOVU3o8QrWOwsat7emGGYzWMDjAZ4nPlxlBTHx9EGootfxJuBtpIgxbn9lohJCd68= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=YD7JBndt; arc=none smtp.client-ip=74.125.82.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="YD7JBndt" Received: by mail-dl1-f42.google.com with SMTP id a92af1059eb24-124566b6693so2426887c88.0 for ; Fri, 30 Jan 2026 14:36:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812596; x=1770417396; 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=LdJVqXRIK4MPnW0UBX/tzXNFanNilVzCHZaDiU6kEj8=; b=YD7JBndtNVQbebZ+s6dnlF5AvI9BLgy7165csYc788AQ9UxZCKqLzrR20J1jH/Ug/N yOIHtH3wNjo76GQpQsBmelArpWH2TcE5+2a8RMGR1/KCfgon1ydj/lZqQTqYHm+1VH5l tZ9sAXLAE9bNWBtWOyrND+uEq6XEa2UuWoLK7IcRnxGkZ+vndx7bMGSxAnxaEKSjyxri pUi7YRQlfbCg+BGLNEHIJGgMje8Zmlph1akbz/T+fAGy9SGgoJTFaLd5+/pxTFKfCcLO zYhaOXCvDJJUHm0vVgqb4fgdGSxFqHPffJRet60KwzQ9bBK3R+BfJq5Gvg9xrgSuq0aQ EyHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812596; x=1770417396; 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=LdJVqXRIK4MPnW0UBX/tzXNFanNilVzCHZaDiU6kEj8=; b=WuEazQmpQQDeI6d7wbGkL5mHl/M2Ut/jQXZGxe9IIJftyj0vvcBCnDA75Bv0j7u4PA OBfWN+ZKqw8RRHSzp5+PL/+R8ZazM51l5AP59l6dId4wo8ZUY7aR8rfp0ptD/AUIYYGZ cuyvC+jiqr8jbV8/a42RAmyQdub/v++DPmt5LZRpPN8CE+enAJy9hAtY6R21n30hDMc1 Pj1nVAjccUpGOjr04noaDsTnm5YbwwQvhNwUIyRU8AXh1ntowKYbr2RGZWwp71ub9Bts kWvPsdpSCnUopGZrtt41L5jDrowH3EyO+HQonHe8W//0amVvDkbN+M46VmP4yk10Wi/Y XizA== X-Forwarded-Encrypted: i=1; AJvYcCX13zNq49khefjT4EX1CE8izeFAri9nRmB2WfMmRL2Ht4chCuBLNRWvCIpHb/wQqb7OV7VOl7qQKQKgjfs=@vger.kernel.org X-Gm-Message-State: AOJu0YziI3zyMry+T1y2jaj8htk1lzsylhON1gi1YoofS4iYgGJ/g1Sf lS5Scvbij8QWBA3kyTIdseCgeXv62Z8sx3s+iivdXSJJnOji3gQXmuUo/HuxZcZLOfg= X-Gm-Gg: AZuq6aIQyLiitsxqNTfXGrsjFmenZGM8nrTcgA2js8ES6APAeGfFsaf7AIY+lAWXX0V 5VF7an4vAcQcCghekgN4lUmrYAqkB/QPouiG+3S3DcZW5tqoQ1avwreqUBnnyMNLESQrJ7hVuWt EoDPADEvL/TgpcYQfKLWt1kG7F2irZJRpHqMEQFBGyURY5qoFSESbdR9sLhxEvWyuVbod26FEQc fnuCSflwPA1GqdinqGftXCqTpfSkV5OgPhHCCuNda363cC1PK6J5Z+NNlm+80O1q01LebPhvbMl 0g/gDy3tzTKfPH1ahZhqnillDKSiKAr3Rriz4bBDeT5U486ZQ9DscophPtTTU5GMLhc3Vdnri8z aGszGyHPsBEPGAjaNvuJwL1VPznZzv+O5f7Y5m2KLjK0yN3ZxYDKbAY9mCeEHCgCzzLOdkuD5xD RGQEUP/F9Zl4jZRn/n8xUzQZU/ecupjbVzbw== X-Received: by 2002:a05:7022:606:b0:11b:d4a8:d24d with SMTP id a92af1059eb24-125c0fbc90emr2380277c88.12.1769812595440; Fri, 30 Jan 2026 14:36:35 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:35 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 13/14] nvme-fc: Use CCR to recover controller that hits an error Date: Fri, 30 Jan 2026 14:34:17 -0800 Message-ID: <20260130223531.2478849-14-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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. If CCR succeeds, switch to FENCED -> RESETTING and continue error recovery as usual. If CCR fails, the behavior depends on whether the subsystem supports CQT or not. If CQT is not supported then reset the controller immediately as if CCR succeeded in order to maintain the current behavior. If CQT is supported switch to time-based recovery. Schedule ctrl->fenced_work resets the controller when time based recovery finishes. Either ctrl->err_work or ctrl->reset_work can run after a controller is fenced. Flush fencing work when either work run. Signed-off-by: Mohamed Khalfella --- drivers/nvme/host/fc.c | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index f8f6071b78ed..3a01aeb39081 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -166,6 +166,8 @@ 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 delayed_work fenced_work; struct work_struct ioerr_work; struct delayed_work connect_work; =20 @@ -1866,12 +1868,59 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *= ctrl, } } =20 +static void nvme_fc_fenced_work(struct work_struct *work) +{ + struct nvme_fc_ctrl *fc_ctrl =3D container_of(to_delayed_work(work), + struct nvme_fc_ctrl, fenced_work); + struct nvme_ctrl *ctrl =3D &fc_ctrl->ctrl; + + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &fc_ctrl->ioerr_work); +} + +static void nvme_fc_fencing_work(struct work_struct *work) +{ + struct nvme_fc_ctrl *fc_ctrl =3D + container_of(work, struct nvme_fc_ctrl, fencing_work); + struct nvme_ctrl *ctrl =3D &fc_ctrl->ctrl; + unsigned long rem; + + rem =3D nvme_fence_ctrl(ctrl); + if (!rem) + goto done; + + if (!ctrl->cqt) { + dev_info(ctrl->device, + "CCR failed, CQT not supported, skip time-based recovery\n"); + goto done; + } + + dev_info(ctrl->device, + "CCR failed, switch to time-based recovery, timeout =3D %ums\n", + jiffies_to_msecs(rem)); + queue_delayed_work(nvme_wq, &fc_ctrl->fenced_work, rem); + return; + +done: + nvme_change_ctrl_state(ctrl, NVME_CTRL_FENCED); + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_reset_wq, &fc_ctrl->ioerr_work); +} + +static void nvme_fc_flush_fencing_work(struct nvme_fc_ctrl *ctrl) +{ + flush_work(&ctrl->fencing_work); + flush_delayed_work(&ctrl->fenced_work); +} + static void 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_flush_fencing_work(ctrl); nvme_fc_error_recovery(ctrl); } =20 @@ -1896,6 +1945,14 @@ EXPORT_SYMBOL_GPL(nvme_fc_io_getuuid); static void nvme_fc_start_ioerr_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) { + 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)) return; =20 @@ -3297,6 +3354,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 + nvme_fc_flush_fencing_work(ctrl); nvme_stop_ctrl(&ctrl->ctrl); =20 /* will block will waiting for io to terminate */ @@ -3471,6 +3529,8 @@ 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_DELAYED_WORK(&ctrl->fenced_work, nvme_fc_fenced_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 Sat Feb 7 07:24:33 2026 Received: from mail-dl1-f43.google.com (mail-dl1-f43.google.com [74.125.82.43]) (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 96C6138A728 for ; Fri, 30 Jan 2026 22:36:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812602; cv=none; b=p8MCADw2APqsGMvliD3+ssi8HVaaIp2s1IuXcyx25b69jbd5ZFzJhcFH2Jc58KJs86CJ4MoMkka/oh99An/UbYBeaG1KiA41X5QIaNruq97CDm6nlQxMfEqGiQEI2Yk6ifm/829jgDpkTOdJTer3qhNJ1C02ezzQo44alcCdlyE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769812602; c=relaxed/simple; bh=A3a9+lNSV5q/BViqrvDsILGTGgIv9R2feUK05w7o6HI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=imXpWh1eOnEIlAqRpsZ84ci4k53RMTlyOrVMN66v0GN/QlSLZFtLAWxqnYddOc01ewuV1BIlIOCPNvFfI0bmNu0bf3TEpPXaQm2F9WWdhFfr0yCsqHoXxoV+kfkD2T+SAWRMdM6yt97HkHfgbExNvMSgQj9nuTNmmaWfUhU0wKM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject 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=fnsrmpXd; arc=none smtp.client-ip=74.125.82.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="fnsrmpXd" Received: by mail-dl1-f43.google.com with SMTP id a92af1059eb24-1233b953bebso3581380c88.1 for ; Fri, 30 Jan 2026 14:36:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1769812597; x=1770417397; 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=uTBUoAOZYxgVE0n+ViXy9ucpXp3tnYCH0vZJ2uE2fAg=; b=fnsrmpXdcHvDTI7kcoxNTkY6VznpnBfOZzMduadPjpLphUP99OX+Ab1Fi6h/lSiJiQ q0KwFzUpetTsXT4Muq5lPDr8b3rRmTTMHgqwcNw0grLjX8Tf+Pta60ZY8nbjrWlUtbdT UTGqdW+Nv2z4M7UDVVBjYjNPw+E2zzOOUYNewsLeqC1TjzyOczx3H77dgSSmFmmzXosw VbJF3hsv+xBf9tm4Y1kJq6DmwdcFgnk/Jk5wOywlWFlgXR8/e2o+G1ulT7AlBI1arErH KXaw1Gl6HsQM8B7c+2FzX48xZJQ6zCRrCIABAJwPS4CMH9RMnNv+dZyT2WQth+l75fVJ zanw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769812597; x=1770417397; 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=uTBUoAOZYxgVE0n+ViXy9ucpXp3tnYCH0vZJ2uE2fAg=; b=V7I0bYKn37DXeCQ2G57olM+bq2jmNirCcBDf+PzwUWQyA5xFouVRrMU0j+jZ118Crp mt2jTQZ6i0fLZg94N2fbcOg7KgcQWSsnak0f97OAt1ycFWK+/h144YBGeLLcf69X/B3m Tzm0QUTHZC3AQurho7DJeUwVEHP4cogU6T9jQ3pR7QE2KdVdaTS26js6R0+thF92hppM CtphXIay7lqt0btwT8IfWnPiqCoBY4bWXnFBR9UewSh6eeFVleJjw+IYErd9AFn3qKM8 /gqzNTd1jKceYANNcutX8ltmSV139DRiBcjJuZ1g0r0Y4jXRdFOlIjbo+ObVMMPAqvhC M3pA== X-Forwarded-Encrypted: i=1; AJvYcCVZ1UBYFLoCABDvw0s9tvaDtOxGhPgfuEFtYJ4tMC8rGumCkW7E+9lh3aC89zwQMfM9/8mkm3LwQ/AoKTk=@vger.kernel.org X-Gm-Message-State: AOJu0Yyw/QqeoYNxd9MwXsvphvZ00LvOhX2k3lvq87zPB8FXbZFszu89 TiCNIoWKzVcrtSThLaxpsUFADZkLEJkiZXwOW6PDY3VxneZVRgnwBSwgzZgAXlsYo/Y= X-Gm-Gg: AZuq6aLDZgOkuEPzF5xqHzglxasmfldg65AMaelnVCmU7vk+XkUmtF1iP5fg+1tHdLB Q/aJidErboIbLOLBqkSuwqWzPlsuYCMSfMgXyO7sr0CKsu4NXVqmJ6RIWnur8uCs+gb9Zr4PADh MFEhjpeAiNZlBsFTkW9tsOFhqXv5eMm4/GCxWkeTHNe1zlSA+QS2bppfYHwC8TTmnptl0r8V6Uw GLR03Ef/vHhYYNuy1ImMUhHwEoj075w70aIVWV8Q6lLYjErBvWVnF56Ev0V7+mqSNSlfjz4XyHg r2qfzMkvjnZ9VpkCSTcBEiYbdVKBctA2eB2nzSq3j8gtdbq+eFs3didHQSFclOyFCYbjTkLYPV2 NsUt3y9eBJNmdFFTDcWiXGf7jqz1K9T/2JwcRCzjTIOKKJZFl6aCxuIHpecmaD54vWuJm0qMcvd /fCt5qc975d634HCxktyj8LF8jkTTpZq2U0A== X-Received: by 2002:a05:7022:6709:b0:11b:9386:7ed3 with SMTP id a92af1059eb24-125c10298e3mr2035531c88.48.1769812596583; Fri, 30 Jan 2026 14:36:36 -0800 (PST) Received: from apollo.purestorage.com ([208.88.152.253]) by smtp.googlemail.com with ESMTPSA id a92af1059eb24-124a9d6b906sm13161717c88.4.2026.01.30.14.36.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jan 2026 14:36:36 -0800 (PST) From: Mohamed Khalfella To: Justin Tee , Naresh Gottumukkala , Paul Ely , Chaitanya Kulkarni , Christoph Hellwig , Jens Axboe , Keith Busch , Sagi Grimberg Cc: Aaron Dailey , Randy Jennings , Dhaval Giani , Hannes Reinecke , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Mohamed Khalfella Subject: [PATCH v2 14/14] nvme-fc: Hold inflight requests while in FENCING state Date: Fri, 30 Jan 2026 14:34:18 -0800 Message-ID: <20260130223531.2478849-15-mkhalfella@purestorage.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130223531.2478849-1-mkhalfella@purestorage.com> References: <20260130223531.2478849-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 --- 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 3a01aeb39081..122ebd7085b1 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -173,7 +173,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]; @@ -1822,7 +1822,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 @@ -1852,20 +1852,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_fenced_work(struct work_struct *work) @@ -1973,7 +1982,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 /* @@ -2106,16 +2116,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) @@ -2754,7 +2786,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); @@ -3223,7 +3256,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); @@ -3232,11 +3265,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