static int nvme_submit_user_cmd(struct request_queue *q,
                struct nvme_command *cmd, void __user *ubuffer,
                unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
-               u32 meta_seed, u64 *result, unsigned timeout)
+               u32 meta_seed, u64 *result, unsigned timeout, bool vec)
 {
        bool write = nvme_is_write(cmd);
        struct nvme_ns *ns = q->queuedata;
        nvme_req(req)->flags |= NVME_REQ_USERCMD;
 
        if (ubuffer && bufflen) {
-               ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
+               if (!vec)
+                       ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
                                GFP_KERNEL);
+               else {
+                       struct iovec fast_iov[UIO_FASTIOV];
+                       struct iovec *iov = fast_iov;
+                       struct iov_iter iter;
+
+                       ret = import_iovec(rq_data_dir(req), ubuffer, bufflen,
+                                       UIO_FASTIOV, &iov, &iter);
+                       if (ret < 0)
+                               goto out;
+                       ret = blk_rq_map_user_iov(q, req, NULL, &iter,
+                                       GFP_KERNEL);
+                       kfree(iov);
+               }
                if (ret)
                        goto out;
                bio = req->bio;
 
        return nvme_submit_user_cmd(ns->queue, &c,
                        nvme_to_user_ptr(io.addr), length,
-                       metadata, meta_len, lower_32_bits(io.slba), NULL, 0);
+                       metadata, meta_len, lower_32_bits(io.slba), NULL, 0,
+                       false);
 }
 
 static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
        status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
                        nvme_to_user_ptr(cmd.addr), cmd.data_len,
                        nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
-                       0, &result, timeout);
+                       0, &result, timeout, false);
 
        if (status >= 0) {
                if (put_user(result, &ucmd->result))
 }
 
 static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-                       struct nvme_passthru_cmd64 __user *ucmd)
+                       struct nvme_passthru_cmd64 __user *ucmd, bool vec)
 {
        struct nvme_passthru_cmd64 cmd;
        struct nvme_command c;
        status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
                        nvme_to_user_ptr(cmd.addr), cmd.data_len,
                        nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
-                       0, &cmd.result, timeout);
+                       0, &cmd.result, timeout, vec);
 
        if (status >= 0) {
                if (put_user(cmd.result, &ucmd->result))
        case NVME_IOCTL_ADMIN_CMD:
                return nvme_user_cmd(ctrl, NULL, argp);
        case NVME_IOCTL_ADMIN64_CMD:
-               return nvme_user_cmd64(ctrl, NULL, argp);
+               return nvme_user_cmd64(ctrl, NULL, argp, false);
        default:
                return sed_ioctl(ctrl->opal_dev, cmd, argp);
        }
        case NVME_IOCTL_SUBMIT_IO:
                return nvme_submit_io(ns, argp);
        case NVME_IOCTL_IO64_CMD:
-               return nvme_user_cmd64(ns->ctrl, ns, argp);
+               return nvme_user_cmd64(ns->ctrl, ns, argp, false);
+       case NVME_IOCTL_IO64_CMD_VEC:
+               return nvme_user_cmd64(ns->ctrl, ns, argp, true);
        default:
                return -ENOTTY;
        }
        case NVME_IOCTL_ADMIN_CMD:
                return nvme_user_cmd(ctrl, NULL, argp);
        case NVME_IOCTL_ADMIN64_CMD:
-               return nvme_user_cmd64(ctrl, NULL, argp);
+               return nvme_user_cmd64(ctrl, NULL, argp, false);
        case NVME_IOCTL_IO_CMD:
                return nvme_dev_user_cmd(ctrl, argp);
        case NVME_IOCTL_RESET: