Re: parallel nvme format

Keith Busch
2023-12-14T23:08:49Z

On Thu, Dec 14, 2023 at 02:49:54PM -0800, Keith Busch wrote:
> On Thu, Dec 14, 2023 at 09:21:28PM +0000, Niklas Cassel wrote:
> > Perhaps we could introduce a new bit, NVME_CTRL_NEEDS_SCAN or similar?
> > (That gets cleared by nvme_scan_work(), after a scan has been performed.)
>
> Good point. Updated patch below.
>
> > I guess for format command specifically, we already have
> > NVME_AER_NOTICE_NS_CHANGED, but that seems to be cleared before by
> > nvme_scan_work() before the mutex is acquired.
>
> The clearing should just re-arm the controller to send the AER again if
> any other namespace changes. But we can't really depend on the AER
> anyway.
>
> > And I'm not sure if all command that have
> > effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)
> > set will trigger a NVME_AER_NOTICE_NS_CHANGED AEN.
>
> We have the "known_effects" for the format command to ensure the driver
> will always request a rescan on a format no matter what a controller
> reports, but yeah, the format could be followed up by another command
> with NVME_CMD_EFFECTS_CSE_MASK set without NIC/NCC, so definitely need
> to retain the need to restart the scan.

The previous diff missed the header update:

diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 39a90b7cb1254..79a71b6ae64fe 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -251,6 +251,7 @@ enum nvme_ctrl_flags {
NVME_CTRL_STOPPED = 3,
NVME_CTRL_SKIP_ID_CNS_CS = 4,
NVME_CTRL_DIRTY_CAPABILITY = 5,
+ NVME_CTRL_NEEDS_RESCAN = 6,
};

struct nvme_ctrl {

> ---
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 590cd4f097c22..0b062a2268447 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -1120,6 +1120,8 @@ u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
> nvme_start_freeze(ctrl);
> nvme_wait_freeze(ctrl);
> }
> + if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
> + set_bit(NVME_CTRL_NEEDS_RESCAN, &ctrl->flags);
> return effects;
> }
> EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, NVME_TARGET_PASSTHRU);
> @@ -1140,7 +1142,7 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
> "controller capabilities changed, reset may be required to take effect.\n");
> }
> }
> - if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)) {
> + if (test_bit(NVME_CTRL_NEEDS_RESCAN, &ctrl->flags)) {
> nvme_queue_scan(ctrl);
> flush_work(&ctrl->scan_work);
> }
> @@ -3945,7 +3947,14 @@ static void nvme_scan_work(struct work_struct *work)
> nvme_clear_changed_ns_log(ctrl);
> }
>
> - mutex_lock(&ctrl->scan_lock);
> + /*
> + * Failure to acquire scan_lock means another thread will requeue this
> + * work shortly
> + */
> + if (!mutex_trylock(&ctrl->scan_lock))
> + return;
> +
> + clear_bit(NVME_CTRL_NEEDS_RESCAN, &ctrl->flags);
> if (nvme_ctrl_limited_cns(ctrl)) {
> nvme_scan_ns_sequential(ctrl);
> } else {
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index 39a90b7cb1254..79a71b6ae64fe 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -251,6 +251,7 @@ enum nvme_ctrl_flags {
> NVME_CTRL_STOPPED = 3,
> NVME_CTRL_SKIP_ID_CNS_CS = 4,
> NVME_CTRL_DIRTY_CAPABILITY = 5,
> + NVME_CTRL_NEEDS_RESCAN = 6,
> };
>
> struct nvme_ctrl {
> --
>