Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Guixin Liu" <kanie@linux.alibaba.com>
Cc: linux-nvme@lists.infradead.org
Subject: Re: [PATCH 07/11] nvmet: implement the FDP feature
Date: Fri, 23 Oct 2026 08:26:15 +0000	[thread overview]
Message-ID: <sashiko-outbox-182513@kernel.org> (raw)
In-Reply-To: <20261023080251.2606443-8-kanie@linux.alibaba.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] nvmet: fdp: nvmet_fdp_lookup_ns() checks ns->enabled instead of NVMET_NS_IO_LIVE
- [Medium] nvmet: nvmet_get_feat_fdp() fails on non-FDP namespaces in mixed subsystems
--

commit 306dfd499967efa07a30c35673d8c81562928443
Author: Guixin Liu <kanie@linux.alibaba.com>

nvmet: implement the FDP feature

This commit implements Set Features and Get Features for the Flexible Data
Placement feature (FID 1Dh) and advertises it in the Supported Features log
page when FDP is configured on the subsystem.

> diff --git a/drivers/nvme/target/fdp.c b/drivers/nvme/target/fdp.c
> index 17949e3665293..5008294984885 100644
> --- a/drivers/nvme/target/fdp.c
> +++ b/drivers/nvme/target/fdp.c

[ ... ]

> @@ -83,3 +87,82 @@ void nvmet_fdp_exit_ns(struct nvmet_ns *ns)
>  	ns->fdp.backend_q = NULL;
>  	ns->fdp.backend_ctrl = NULL;
>  }
> +
> +
> +/*
> + * Each namespace is its own endurance group, so the Endurance Group
> + * Identifier in Command Dword 11, and in the Log Specific Identifier
> + * of the FDP log pages, directly names the namespace.  Returns the
> + * namespace with a reference held.
> + */
> +static struct nvmet_ns *nvmet_fdp_lookup_ns(struct nvmet_req *req, u32 endgid)
> +{
> +	struct nvmet_subsys *subsys = nvmet_req_subsys(req);
> +	struct nvmet_ns *ns;
> +
> +	rcu_read_lock();
> +	ns = xa_load(&subsys->namespaces, endgid);
> +	if (!ns || !ns->enabled || !nvmet_fdp_enabled(ns))
> +		goto out_unlock;
> +
> +	if (!percpu_ref_tryget_live(&ns->ref))
> +		goto out_unlock;

[Severity: High]
Can checking ns->enabled instead of test_bit(NVMET_NS_IO_LIVE, &ns->flags)
here race with nvmet_ns_disable() and nvmet_ns_enable()?

After commits 42b0f5196dc2 ("nvmet: defer setting ns->enabled to false in
nvmet_ns_disable()") and 3fdd281e0a04 ("nvmet: don't allow I/O admission
after percpu ns reference is killed"), nvmet_ns_disable() clears
NVMET_NS_IO_LIVE and tears down ns->ref before setting ns->enabled to false:

drivers/nvme/target/core.c:nvmet_ns_disable() {
	if (!test_and_clear_bit(NVMET_NS_IO_LIVE, &ns->flags))
		return;
	...
	percpu_ref_kill(&ns->ref);
	synchronize_rcu();
	wait_for_completion(&ns->disable_done);
	percpu_ref_exit(&ns->ref);
	...
	mutex_lock(&subsys->lock);
	nvmet_ns_changed(subsys, ns->nsid);
	nvmet_ns_dev_disable(ns);
	ns->enabled = false;
	mutex_unlock(&subsys->lock);
}

Because ns->enabled remains true across percpu_ref_kill(&ns->ref),
synchronize_rcu(), and percpu_ref_exit(&ns->ref), a concurrent
nvmet_set_feat_fdp() or nvmet_get_feat_fdp() calling nvmet_fdp_lookup_ns()
can still observe ns->enabled == true and call percpu_ref_tryget_live(&ns->ref)
while or after percpu_ref_exit(&ns->ref) frees the per-CPU counter.

Similarly, in nvmet_ns_enable(), ns->enabled = true is a plain store with no
release barrier after percpu_ref_init(&ns->ref, ...), whereas NVMET_NS_IO_LIVE
is set after xa_set_mark():

drivers/nvme/target/core.c:nvmet_ns_enable() {
	ret = percpu_ref_init(&ns->ref, nvmet_destroy_namespace, 0, GFP_KERNEL);
	if (ret)
		goto out_fdp_exit;

	nvmet_ns_changed(subsys, ns->nsid);
	ns->enabled = true;
	xa_set_mark(&subsys->namespaces, ns->nsid, NVMET_NS_ENABLED);
	nvmet_debugfs_ns_setup(ns);
	set_bit(NVMET_NS_IO_LIVE, &ns->flags);
}

Should nvmet_fdp_lookup_ns() check test_bit(NVMET_NS_IO_LIVE, &ns->flags) and
use percpu_ref_tryget_live_rcu(&ns->ref), matching nvmet_req_find_ns()?

> +
> +	rcu_read_unlock();
> +	return ns;
> +
> +out_unlock:
> +	rcu_read_unlock();
> +	return NULL;
> +}

[ ... ]

> +u16 nvmet_get_feat_fdp(struct nvmet_req *req)
> +{
> +	struct nvmet_ns *ns;
> +
> +	ns = nvmet_fdp_lookup_ns(req,
> +				 le32_to_cpu(req->cmd->features.dword11));
> +	if (!ns)
> +		return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;

[Severity: Medium]
What happens in a subsystem that contains both FDP-enabled and non-FDP
namespaces?

When at least one namespace in the subsystem has FDP enabled,
nvmet_fdp_subsys_configured() returns true, so the controller advertises
NVME_CTRL_ATTR_FDPS in ctratt and NVME_FEAT_FDP in the Supported Features log
page. Every enabled namespace is exposed as its own endurance group
(endgid = nsid).

When the Linux NVMe host scans namespaces on a controller with
NVME_CTRL_ATTR_FDPS set, nvme_alloc_ns_head() -> nvme_query_fdp_info() issues
Get Features (NVME_FEAT_FDP) for each namespace's endgid and checks whether
FDPCFG_FDPE is set in the result:

drivers/nvme/host/core.c:nvme_query_fdp_info() {
	ret = nvme_get_features(ctrl, NVME_FEAT_FDP, info->endgid, NULL, 0,
				&fdp);
	if (ret) {
		dev_warn(ctrl->device, "FDP get feature status:0x%x\n", ret);
		return ret;
	}

	if (!(fdp.flags & FDPCFG_FDPE))
		return 0;
}

Because nvmet_get_feat_fdp() uses nvmet_fdp_lookup_ns(), which rejects
namespaces where !nvmet_fdp_enabled(ns), won't Get Features fail with
NVME_SC_INVALID_FIELD | NVME_STATUS_DNR on valid non-FDP namespaces instead
of succeeding with result 0 (FDPE cleared) when nvmet_fdp_subsys_configured()
is true?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023080251.2606443-1-kanie@linux.alibaba.com?part=7


  reply	other threads:[~2026-10-23  8:26 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23  8:02 [PATCH v2 0/11] nvmet: FDP bridge for NVMe-oF targets Guixin Liu
2026-10-23  8:02 ` [PATCH 01/11] nvme: add the FDP wire structures for the I/O management send command Guixin Liu
2026-10-23  8:02 ` [PATCH 02/11] block: add bdev_write_stream_granularity() Guixin Liu
2026-10-23  8:02 ` [PATCH 03/11] nvme: export nvme_bdev_ops Guixin Liu
2026-10-23  8:14   ` sashiko-bot
2026-10-23  8:02 ` [PATCH 04/11] nvmet: add per-namespace FDP bridge state and configuration Guixin Liu
2026-10-23  8:02 ` [PATCH 05/11] nvmet: report the Endurance Group Identifier in the CS-INDEP identify data Guixin Liu
2026-10-23  8:02 ` [PATCH 06/11] nvmet: advertise the FDP capability Guixin Liu
2026-10-23  8:02 ` [PATCH 07/11] nvmet: implement the FDP feature Guixin Liu
2026-10-23  8:26   ` sashiko-bot [this message]
2026-10-23  8:02 ` [PATCH 08/11] nvmet: forward the FDP I/O management commands to the backing device Guixin Liu
2026-10-23  8:37   ` sashiko-bot
2026-10-23  8:02 ` [PATCH 09/11] nvmet: serve the FDP log pages Guixin Liu
2026-10-23  8:37   ` sashiko-bot
2026-10-23  8:02 ` [PATCH 10/11] nvmet: translate placement identifiers of writes to write streams Guixin Liu
2026-10-23  8:02 ` [PATCH 11/11] nvmet: add an FDP write translation tracepoint Guixin Liu
  -- strict thread matches above, loose matches on Subject: below --
2026-10-19  3:36 [PATCH RESEND 0/11] nvmet: FDP bridge for NVMe-oF targets Guixin Liu
2026-10-19  3:36 ` [PATCH 07/11] nvmet: implement the FDP feature Guixin Liu
2026-10-19  3:45   ` sashiko-bot
2026-10-19  8:30     ` Guixin Liu
2026-10-13  2:20 [PATCH 0/11] nvmet: FDP bridge for NVMe-oF targets Guixin Liu
2026-10-13  2:21 ` [PATCH 07/11] nvmet: implement the FDP feature Guixin Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-182513@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=kanie@linux.alibaba.com \
    --cc=linux-nvme@lists.infradead.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox