[PATCH 1/2] nvme: support fused nvme requests
Keith Busch
kbusch at kernel.org
Tue Jan 5 18:52:10 EST 2021
On Tue, Jan 05, 2021 at 02:49:38PM -0800, klayph at gmail.com wrote:
> @@ -157,6 +157,8 @@ struct nvme_request {
> u8 flags;
> u16 status;
> struct nvme_ctrl *ctrl;
> + struct nvme_request *nrq2; /* Points to second fused request */
> + struct nvme_command cmnd; /* Saved fused first cmnd */
This struct is getting a bit large, and we allocate 1000's of them. An
extra 72B (3x its current size) for something that likely never gets
used (and can't be used for fabrics) seems a bit much.
> @@ -918,7 +942,13 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
> }
>
> blk_mq_start_request(req);
> - nvme_submit_cmd(nvmeq, &cmnd, bd->last);
> +
> + if (cmnd.common.flags & NVME_CMD_FUSE_FIRST)
> + memcpy(&nvme_req(req)->nrq2->cmnd, &cmnd, sizeof(cmnd));
> + else if (cmnd.common.flags & NVME_CMD_FUSE_SECOND)
> + nvme_submit_cmd2(nvmeq, &nvme_req(req)->cmnd, &cmnd, bd->last);
> + else
> + nvme_submit_cmd(nvmeq, &cmnd, bd->last);
There's an unlikely scenario where this breaks down, but it'd look
something like this: the FUSE_FIRST is submitted to the driver, then
before the FUSE_SECOND reaches the driver, the controller is reset.
Because you're only using this through the passthrough interface where
the FAILFAST flag is set, the FUSE_FIRST command is ended in failure,
which releases the command ID for reuse. Once the controller is
restarted, the FUSE_SECOND is dispatched to the driver using an invalid
command ID stored in its 'cmnd' field.
More information about the Linux-nvme
mailing list