History

nvme: allow 64-bit results in passthru commands

It is not possible to get 64-bit results from the passthru commands, what prevents from getting for the Capabilities (CAP) property value. As a result, it is not possible to implement IOL's NVMe Conformance test 4.3 Case 1 for Fabrics targets [1] (page 123). This issue has been already discussed [2], but without a solution. This patch solves the problem by adding new ioctls with a new passthru structure, including 64-bit results. The older ioctls stay unchanged. [1] https://www.iol.unh.edu/sites/default/files/testsuites/nvme/UNH-IOL_NVMe_Conformance_Test_Suite_v11.0.pdf [2] http://lists.infradead.org/pipermail/linux-nvme/2018-June/018791.html

Marta Rybczynska committed 7 years ago

Commit 65e68ed1 parent 19ea0252 files · +115 −16Browse files

Unified · Split

2 files
  1. drivers/nvme/host/core.c +92 −16
  2. include/uapi/linux/nvme_ioctl.h +23 −0
drivers/nvme/host/core.c+92−16
@@ -850,7 +850,7 @@ out: · 849 unmodified lines
850850 static int nvme_submit_user_cmd(struct request_queue *q,
851851 struct nvme_command *cmd, void __user *ubuffer,
852852 unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
853− u32 meta_seed, u32 *result, unsigned timeout)
853+ u32 meta_seed, u64 *result, unsigned timeout)
854854 {
855855 bool write = nvme_is_write(cmd);
856856 struct nvme_ns *ns = q->queuedata;
@@ -891,7 +891,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, · 34 unmodified lines
891891 else
892892 ret = nvme_req(req)->status;
893893 if (result)
894− *result = le32_to_cpu(nvme_req(req)->result.u32);
894+ *result = le64_to_cpu(nvme_req(req)->result.u64);
895895 if (meta && !ret && !write) {
896896 if (copy_to_user(meta_buffer, meta, meta_len))
897897 ret = -EFAULT;
@@ -1338,6 +1338,54 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, · 440 unmodified lines
13381338 struct nvme_command c;
13391339 unsigned timeout = 0;
13401340 u32 effects;
1341+ u64 result;
1342+ int status;
1343+
1344+ if (!capable(CAP_SYS_ADMIN))
1345+ return -EACCES;
1346+ if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
1347+ return -EFAULT;
1348+ if (cmd.flags)
1349+ return -EINVAL;
1350+
1351+ memset(&c, 0, sizeof(c));
1352+ c.common.opcode = cmd.opcode;
1353+ c.common.flags = cmd.flags;
1354+ c.common.nsid = cpu_to_le32(cmd.nsid);
1355+ c.common.cdw2[0] = cpu_to_le32(cmd.cdw2);
1356+ c.common.cdw2[1] = cpu_to_le32(cmd.cdw3);
1357+ c.common.cdw10 = cpu_to_le32(cmd.cdw10);
1358+ c.common.cdw11 = cpu_to_le32(cmd.cdw11);
1359+ c.common.cdw12 = cpu_to_le32(cmd.cdw12);
1360+ c.common.cdw13 = cpu_to_le32(cmd.cdw13);
1361+ c.common.cdw14 = cpu_to_le32(cmd.cdw14);
1362+ c.common.cdw15 = cpu_to_le32(cmd.cdw15);
1363+
1364+ if (cmd.timeout_ms)
1365+ timeout = msecs_to_jiffies(cmd.timeout_ms);
1366+
1367+ effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
1368+ status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
1369+ (void __user *)(uintptr_t)cmd.addr, cmd.data_len,
1370+ (void __user *)(uintptr_t)cmd.metadata,
1371+ cmd.metadata_len, 0, &result, timeout);
1372+ nvme_passthru_end(ctrl, effects);
1373+
1374+ if (status >= 0) {
1375+ if (put_user(result, &ucmd->result))
1376+ return -EFAULT;
1377+ }
1378+
1379+ return status;
1380+}
1381+
1382+static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
1383+ struct nvme_passthru_cmd64 __user *ucmd)
1384+{
1385+ struct nvme_passthru_cmd64 cmd;
1386+ struct nvme_command c;
1387+ unsigned timeout = 0;
1388+ u32 effects;
13411389 int status;
13421390
13431391 if (!capable(CAP_SYS_ADMIN))
@@ -1408,6 +1456,41 @@ static void nvme_put_ns_from_disk(struct nvme_ns_head *head, int idx) · 64 unmodified lines
14081456 srcu_read_unlock(&head->srcu, idx);
14091457 }
14101458
1459+static bool is_ctrl_ioctl(unsigned int cmd)
1460+{
1461+ if (cmd == NVME_IOCTL_ADMIN_CMD || cmd == NVME_IOCTL_ADMIN64_CMD)
1462+ return true;
1463+ if (is_sed_ioctl(cmd))
1464+ return true;
1465+ return false;
1466+}
1467+
1468+static int nvme_handle_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd,
1469+ void __user *argp,
1470+ struct nvme_ns_head *head,
1471+ int srcu_idx)
1472+{
1473+ struct nvme_ctrl *ctrl = ns->ctrl;
1474+ int ret;
1475+
1476+ nvme_get_ctrl(ns->ctrl);
1477+ nvme_put_ns_from_disk(head, srcu_idx);
1478+
1479+ switch (cmd) {
1480+ case NVME_IOCTL_ADMIN_CMD:
1481+ ret = nvme_user_cmd(ctrl, NULL, argp);
1482+ break;
1483+ case NVME_IOCTL_ADMIN64_CMD:
1484+ ret = nvme_user_cmd64(ctrl, NULL, argp);
1485+ break;
1486+ default:
1487+ ret = sed_ioctl(ctrl->opal_dev, cmd, argp);
1488+ break;
1489+ }
1490+ nvme_put_ctrl(ctrl);
1491+ return ret;
1492+}
1493+
14111494 static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
14121495 unsigned int cmd, unsigned long arg)
14131496 {
@@ -1425,20 +1508,8 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, · 11 unmodified lines
14251508 * seperately and drop the ns SRCU reference early. This avoids a
14261509 * deadlock when deleting namespaces using the passthrough interface.
14271510 */
1428− if (cmd == NVME_IOCTL_ADMIN_CMD || is_sed_ioctl(cmd)) {
1429− struct nvme_ctrl *ctrl = ns->ctrl;
1430−
1431− nvme_get_ctrl(ns->ctrl);
1432− nvme_put_ns_from_disk(head, srcu_idx);
1433−
1434− if (cmd == NVME_IOCTL_ADMIN_CMD)
1435− ret = nvme_user_cmd(ctrl, NULL, argp);
1436− else
1437− ret = sed_ioctl(ctrl->opal_dev, cmd, argp);
1438−
1439− nvme_put_ctrl(ctrl);
1440− return ret;
1441− }
1511+ if (is_ctrl_ioctl(cmd))
1512+ return nvme_handle_ctrl_ioctl(ns, cmd, argp, head, srcu_idx);
14421513
14431514 switch (cmd) {
14441515 case NVME_IOCTL_ID:
@@ -1451,6 +1522,9 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, · 6 unmodified lines
14511522 case NVME_IOCTL_SUBMIT_IO:
14521523 ret = nvme_submit_io(ns, argp);
14531524 break;
1525+ case NVME_IOCTL_IO64_CMD:
1526+ ret = nvme_user_cmd64(ns->ctrl, ns, argp);
1527+ break;
14541528 default:
14551529 if (ns->ndev)
14561530 ret = nvme_nvm_ioctl(ns, cmd, arg);
@@ -2852,6 +2926,8 @@ static long nvme_dev_ioctl(struct file *file, unsigned int cmd, · 1395 unmodified lines
28522926 switch (cmd) {
28532927 case NVME_IOCTL_ADMIN_CMD:
28542928 return nvme_user_cmd(ctrl, NULL, argp);
2929+ case NVME_IOCTL_ADMIN64_CMD:
2930+ return nvme_user_cmd64(ctrl, NULL, argp);
28552931 case NVME_IOCTL_IO_CMD:
28562932 return nvme_dev_user_cmd(ctrl, argp);
28572933 case NVME_IOCTL_RESET:
include/uapi/linux/nvme_ioctl.h+23−0
@@ -45,6 +45,27 @@ struct nvme_passthru_cmd { · 44 unmodified lines
4545 __u32 result;
4646 };
4747
48+struct nvme_passthru_cmd64 {
49+ __u8 opcode;
50+ __u8 flags;
51+ __u16 rsvd1;
52+ __u32 nsid;
53+ __u32 cdw2;
54+ __u32 cdw3;
55+ __u64 metadata;
56+ __u64 addr;
57+ __u32 metadata_len;
58+ __u32 data_len;
59+ __u32 cdw10;
60+ __u32 cdw11;
61+ __u32 cdw12;
62+ __u32 cdw13;
63+ __u32 cdw14;
64+ __u32 cdw15;
65+ __u32 timeout_ms;
66+ __u64 result;
67+};
68+
4869 #define nvme_admin_cmd nvme_passthru_cmd
4970
5071 #define NVME_IOCTL_ID _IO('N', 0x40)
@@ -54,5 +75,7 @@ struct nvme_passthru_cmd { · 3 unmodified lines
5475 #define NVME_IOCTL_RESET _IO('N', 0x44)
5576 #define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45)
5677 #define NVME_IOCTL_RESCAN _IO('N', 0x46)
78+#define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64)
79+#define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64)
5780
5881 #endif /* _UAPI_LINUX_NVME_IOCTL_H */