[PATCH] nvme: freeze IO accesses around format
Christoph Hellwig
hch at infradead.org
Wed Nov 1 08:56:03 PDT 2017
> If the controller does not support the command effects log page, the
> driver will define the effects for known opcodes. The nvme format is
> the only such command in this patch with known effects.
Sanitize is another one. Also Format might either affect a single
namespace or the whole controller depending on what it advertises in
FNA.
> +static void nvme_get_admin_effects(struct nvme_ctrl *ctrl, u8 opcode, u32 *effects)
Overly long line.
> +{
> + if (ctrl->effects)
> + *effects = le32_to_cpu(ctrl->effects->acs[opcode]);
> +
> + if (*effects != 0)
> + return;
> +
> + /*
> + * Set known effects for opcodes if the controller doesn't support
> + * reporting the command's effects.
> + */
> + switch (opcode) {
> + case nvme_admin_format_nvm:
> + *effects = NVME_CMD_FX_CSUPP | NVME_CMD_FX_LBCC |
> + NVME_CMD_FX_CSE_MASK;
> + break;
> + default:
> + break;
> + }
> +}
Hmm. I'd expect it to be something like:
static u32 nvme_get_admin_effects((struct nvme_ctrl *ctrl, u8 opcode)
{
if (ctrl->effects)
return le32_to_cpu(ctrl->effects->acs[opcode]);
switch (opcode) {
...
}
}
That is: a) return the value instead of pass by reference, and
b) if the controller supports the log page rely on it.
Also don't we need to also handle this for I/O commands? While
non of the currently defined I/O commands would need anything, the
spec defines the mechanismş and it might be useful for vendor
specific commands.
> +static void nvme_passthru_start(struct nvme_ctrl *ctrl, u32 effects)
> +{
> + if (effects & (NVME_CMD_FX_LBCC | NVME_CMD_FX_CSE_MASK)) {
> + nvme_start_freeze(ctrl);
> + nvme_wait_freeze(ctrl);
> + }
> +}
I'd move the nvme_get_admin_effects call into this, and return the
value from this function to keep the caller a little more uncluttered.
> + if (effects & NVME_CMD_FX_LBCC) {
> + struct nvme_ns *ns;
> +
> + mutex_lock(&ctrl->namespaces_mutex);
> + list_for_each_entry(ns, &ctrl->namespaces, list) {
> + if (ns->disk && nvme_revalidate_disk(ns->disk))
> + nvme_ns_remove(ns);
> + }
> + mutex_unlock(&ctrl->namespaces_mutex);
> + }
Split the code above into a helper?
> +static int nvme_get_log(struct nvme_ctrl *ctrl, u8 log_page, void *log, size_t size)
To loong line again. Also I think adding this helper should probably
be a preparation patch.
> +{
> + struct nvme_command c = { };
> +
> +
> + c.common.opcode = nvme_admin_get_log_page;
Double empty line.
> +static void nvme_scan(struct nvme_ctrl *ctrl)
> {
> - struct nvme_ctrl *ctrl =
> - container_of(work, struct nvme_ctrl, scan_work);
> struct nvme_id_ctrl *id;
> unsigned nn;
>
> @@ -2549,6 +2650,14 @@ static void nvme_scan_work(struct work_struct *work)
> kfree(id);
> }
>
> +static void nvme_scan_work(struct work_struct *work)
> +{
> + struct nvme_ctrl *ctrl =
> + container_of(work, struct nvme_ctrl, scan_work);
> +
> + nvme_scan(ctrl);
> +}
Why do we do the scan inline here, but not in any other place?
> @@ -267,6 +267,7 @@ enum {
> NVME_CTRL_OACS_SEC_SUPP = 1 << 0,
> NVME_CTRL_OACS_DIRECTIVES = 1 << 5,
> NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8,
> + NVME_CTRL_LPA_CMD_FX_LOG = 1 << 1,
I'd just use the bit directly, given that it doesn't have a name
in the spec either.
> enum {
> + NVME_CMD_FX_CSUPP = 1 << 0,
> + NVME_CMD_FX_LBCC = 1 << 1,
> + NVME_CMD_FX_NCC = 1 << 2,
> + NVME_CMD_FX_NIC = 1 << 3,
> + NVME_CMD_FX_CCC = 1 << 4,
> + NVME_CMD_FX_CSE_MASK = 3 << 16,
s/NVME_CMD_FX/NVME_CMD_EFFECTS/g ?
> + NVME_LOG_CMD_FX = 0x05,
same here.
More information about the Linux-nvme
mailing list