From 09b92f2ea59cb282de5889d5706507ecac004ce6 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Thu, 3 Aug 2023 14:37:30 +0200 Subject: [PATCH] target support for cancel commands Signed-off-by: Maurizio Lombardi --- drivers/nvme/target/Makefile | 2 +- drivers/nvme/target/admin-cmd.c | 4 ++++ drivers/nvme/target/core.c | 36 +++++++++++++++++++++++++++++ drivers/nvme/target/io-cmd-cancel.c | 17 ++++++++++++++ drivers/nvme/target/nvmet.h | 4 ++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 drivers/nvme/target/io-cmd-cancel.c diff --git a/drivers/nvme/target/Makefile b/drivers/nvme/target/Makefile index c66820102493..6541808579ae 100644 --- a/drivers/nvme/target/Makefile +++ b/drivers/nvme/target/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_NVME_TARGET_FCLOOP) += nvme-fcloop.o obj-$(CONFIG_NVME_TARGET_TCP) += nvmet-tcp.o nvmet-y += core.o configfs.o admin-cmd.o fabrics-cmd.o \ - discovery.o io-cmd-file.o io-cmd-bdev.o + discovery.o io-cmd-file.o io-cmd-bdev.o io-cmd-cancel.o nvmet-$(CONFIG_NVME_TARGET_PASSTHRU) += passthru.o nvmet-$(CONFIG_BLK_DEV_ZONED) += zns.o nvmet-$(CONFIG_NVME_TARGET_AUTH) += fabrics-cmd-auth.o auth.o diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index f5b7054a4a05..3c2062cf4632 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -177,6 +177,10 @@ static void nvmet_get_cmd_effects_nvm(struct nvme_effects_log *log) log->iocs[nvme_cmd_flush] = log->iocs[nvme_cmd_dsm] = cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); + if (emulate_cancel_cmd) { + log->iocs[nvme_cmd_cancel] = + cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); + } log->iocs[nvme_cmd_write] = log->iocs[nvme_cmd_write_zeroes] = cpu_to_le32(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC); diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index e06013c5dace..0d03e9937789 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -26,6 +26,36 @@ static DEFINE_IDA(cntlid_ida); struct workqueue_struct *nvmet_wq; EXPORT_SYMBOL_GPL(nvmet_wq); +static int param_store_val(const char *str, int *val, int min, int max) +{ + int ret, new_val; + + ret = kstrtoint(str, 10, &new_val); + if (ret) + return -EINVAL; + + if (new_val < min || new_val > max) + return -EINVAL; + + *val = new_val; + return 0; +} + +static int set_params(const char *str, const struct kernel_param *kp) +{ + return param_store_val(str, kp->arg, 0, INT_MAX); +} + +static const struct kernel_param_ops set_param_ops = { + .set = set_params, + .get = param_get_int, +}; + + +int emulate_cancel_cmd; +device_param_cb(emulate_cancel_cmd, &set_param_ops, &emulate_cancel_cmd, 0644); +MODULE_PARM_DESC(emulate_cancel_cmd, "Emulate the cancel command. Default = 0"); + /* * This read/write semaphore is used to synchronize access to configuration * information on a target system that will result in discovery log page @@ -904,6 +934,12 @@ static u16 nvmet_parse_io_cmd(struct nvmet_req *req) if (nvmet_is_passthru_req(req)) return nvmet_parse_passthru_io_cmd(req); + if (emulate_cancel_cmd && req->cmd->common.opcode == nvme_cmd_cancel) { + req->execute = nvmet_execute_cancel; + if (req->cmd->cancel.nsid == NVME_NSID_ALL) + return 0; + } + ret = nvmet_req_find_ns(req); if (unlikely(ret)) return ret; diff --git a/drivers/nvme/target/io-cmd-cancel.c b/drivers/nvme/target/io-cmd-cancel.c new file mode 100644 index 000000000000..d19a6126c9c8 --- /dev/null +++ b/drivers/nvme/target/io-cmd-cancel.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NVMe I/O cancel command implementation. + * Copyright (c) 2023 Red Hat + */ + +#include "nvmet.h" + +void nvmet_execute_cancel(struct nvmet_req *req) +{ + if (!nvmet_check_transfer_len(req, 0)) + return; + + nvmet_set_result(req, (1 << 16)); + nvmet_req_complete(req, 0); +} + diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index c1306de1f4dd..f4fe7956aa43 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -31,6 +31,8 @@ #define NVMET_SN_MAX_SIZE 20 #define NVMET_FR_MAX_SIZE 8 +extern int emulate_cancel_cmd; + /* * Supported optional AENs: */ @@ -602,6 +604,8 @@ void nvmet_bdev_execute_zone_mgmt_recv(struct nvmet_req *req); void nvmet_bdev_execute_zone_mgmt_send(struct nvmet_req *req); void nvmet_bdev_execute_zone_append(struct nvmet_req *req); +void nvmet_execute_cancel(struct nvmet_req *req); + static inline u32 nvmet_rw_data_len(struct nvmet_req *req) { return ((u32)le16_to_cpu(req->cmd->rw.length) + 1) << -- 2.43.0