]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
NVMe: Fix IO for extended metadata formats
authorKeith Busch <keith.busch@intel.com>
Sat, 17 Dec 2016 23:33:20 +0000 (15:33 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 1 Jun 2017 20:40:27 +0000 (13:40 -0700)
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>
(cherry picked from commit 71feb364e7faadc681e714f7fdc2bede208ba26c)

Orabug: 25130845
Signed-off-by: Ashok Vairavan <ashok.vairavan@oracle.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/block/nvme-core.c

index 6302216e03032073041ffddf45f340a0dba0c0b8..360526b19569270dfa92b48ea2a87b3c14425606 100644 (file)
@@ -893,7 +893,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;
@@ -1804,15 +1805,14 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
        metadata = (void __user *)(uintptr_t)io.metadata;
        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);