diff options
author | Keith Busch <keith.busch@intel.com> | 2015-06-19 19:07:30 +0200 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-06-19 21:16:26 +0200 |
commit | 71feb364e7faadc681e714f7fdc2bede208ba26c (patch) | |
tree | f55db156d34c3b60cf2101c78d6f693efe67d6c7 /drivers/block | |
parent | nvme: don't overwrite req->cmd_flags on sync cmd (diff) | |
download | linux-71feb364e7faadc681e714f7fdc2bede208ba26c.tar.xz linux-71feb364e7faadc681e714f7fdc2bede208ba26c.zip |
NVMe: Fix IO for extended metadata formats
This fixes io submit ioctl handling when using extended metadata
formats. When these formats are used, the user provides a single virtually
contiguous buffer containing both the block and metadata interleaved,
so the metadata size needs to be added to the total length and not mapped
as a separate transfer.
The command is also driver generated, so this patch does not enforce
blk-integrity extensions provide the metadata buffer.
Reported-by: Marcin Dziegielewski <marcin.dziegielewski@intel.com>
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nvme-core.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 12d5b7b03f9b..a501d3e6ac92 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -852,7 +852,8 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, * stripped/generated by the controller with PRACT=1. */ if (ns && ns->ms && !blk_integrity_rq(req)) { - if (!(ns->pi_type && ns->ms == 8)) { + if (!(ns->pi_type && ns->ms == 8) && + req->cmd_type != REQ_TYPE_DRV_PRIV) { req->errors = -EFAULT; blk_mq_complete_request(req); return BLK_MQ_RQ_QUEUE_OK; @@ -1747,15 +1748,14 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) meta_len = (io.nblocks + 1) * ns->ms; write = io.opcode & 1; + if (ns->ext) { + length += meta_len; + meta_len = 0; + } if (meta_len) { if (((io.metadata & 3) || !io.metadata) && !ns->ext) return -EINVAL; - if (ns->ext) { - length += meta_len; - meta_len = 0; - } - meta = dma_alloc_coherent(dev->dev, meta_len, &meta_dma, GFP_KERNEL); if (!meta) { |