Skip to content

Commit c1fef73

Browse files
lsgunthChristoph Hellwig
authored andcommitted
nvmet: add passthru code to process commands
Add passthru command handling capability for the NVMeOF target and export passthru APIs which are used to integrate passthru code with nvmet-core. The new file passthru.c handles passthru cmd parsing and execution. In the passthru mode, we create a block layer request from the nvmet request and map the data on to the block layer request. Admin commands and features are on an allow list as there are a number of each that don't make too much sense with passthrough. We use an allow list such that new commands can be considered before being blindly passed through. In both cases, vendor specific commands are always allowed. We also reject reservation IO commands as the underlying device cannot differentiate between multiple hosts behind a fabric. Based-on-a-patch-by: Chaitanya Kulkarni <[email protected]> Signed-off-by: Logan Gunthorpe <[email protected]> Reviewed-by: Keith Busch <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 24493b8 commit c1fef73

File tree

6 files changed

+510
-2
lines changed

6 files changed

+510
-2
lines changed

drivers/nvme/target/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ obj-$(CONFIG_NVME_TARGET_TCP) += nvmet-tcp.o
1111

1212
nvmet-y += core.o configfs.o admin-cmd.o fabrics-cmd.o \
1313
discovery.o io-cmd-file.o io-cmd-bdev.o
14+
nvmet-$(CONFIG_NVME_TARGET_PASSTHRU) += passthru.o
1415
nvme-loop-y += loop.o
1516
nvmet-rdma-y += rdma.o
1617
nvmet-fc-y += fc.o

drivers/nvme/target/admin-cmd.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ u16 nvmet_set_feat_async_event(struct nvmet_req *req, u32 mask)
749749
return 0;
750750
}
751751

752-
static void nvmet_execute_set_features(struct nvmet_req *req)
752+
void nvmet_execute_set_features(struct nvmet_req *req)
753753
{
754754
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
755755
u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
@@ -824,7 +824,7 @@ void nvmet_get_feat_async_event(struct nvmet_req *req)
824824
nvmet_set_result(req, READ_ONCE(req->sq->ctrl->aen_enabled));
825825
}
826826

827-
static void nvmet_execute_get_features(struct nvmet_req *req)
827+
void nvmet_execute_get_features(struct nvmet_req *req)
828828
{
829829
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
830830
u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
@@ -940,6 +940,9 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
940940
if (unlikely(ret))
941941
return ret;
942942

943+
if (nvmet_req_passthru_ctrl(req))
944+
return nvmet_parse_passthru_admin_cmd(req);
945+
943946
switch (cmd->common.opcode) {
944947
case nvme_admin_get_log_page:
945948
req->execute = nvmet_execute_get_log_page;

drivers/nvme/target/core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,9 @@ static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
849849
if (unlikely(ret))
850850
return ret;
851851

852+
if (nvmet_req_passthru_ctrl(req))
853+
return nvmet_parse_passthru_io_cmd(req);
854+
852855
req->ns = nvmet_find_namespace(req->sq->ctrl, cmd->rw.nsid);
853856
if (unlikely(!req->ns)) {
854857
req->error_loc = offsetof(struct nvme_common_command, nsid);

drivers/nvme/target/nvmet.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ struct nvmet_subsys {
242242
struct config_group allowed_hosts_group;
243243

244244
struct nvmet_subsys_model __rcu *model;
245+
246+
#ifdef CONFIG_NVME_TARGET_PASSTHRU
247+
struct nvme_ctrl *passthru_ctrl;
248+
#endif /* CONFIG_NVME_TARGET_PASSTHRU */
245249
};
246250

247251
static inline struct nvmet_subsys *to_subsys(struct config_item *item)
@@ -321,6 +325,11 @@ struct nvmet_req {
321325
struct bio_vec *bvec;
322326
struct work_struct work;
323327
} f;
328+
struct {
329+
struct request *rq;
330+
struct work_struct work;
331+
bool use_workqueue;
332+
} p;
324333
};
325334
int sg_cnt;
326335
int metadata_sg_cnt;
@@ -400,6 +409,8 @@ void nvmet_req_complete(struct nvmet_req *req, u16 status);
400409
int nvmet_req_alloc_sgls(struct nvmet_req *req);
401410
void nvmet_req_free_sgls(struct nvmet_req *req);
402411

412+
void nvmet_execute_set_features(struct nvmet_req *req);
413+
void nvmet_execute_get_features(struct nvmet_req *req);
403414
void nvmet_execute_keep_alive(struct nvmet_req *req);
404415

405416
void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid,
@@ -532,6 +543,34 @@ static inline u32 nvmet_dsm_len(struct nvmet_req *req)
532543
sizeof(struct nvme_dsm_range);
533544
}
534545

546+
#ifdef CONFIG_NVME_TARGET_PASSTHRU
547+
u16 nvmet_parse_passthru_admin_cmd(struct nvmet_req *req);
548+
u16 nvmet_parse_passthru_io_cmd(struct nvmet_req *req);
549+
static inline struct nvme_ctrl *nvmet_passthru_ctrl(struct nvmet_subsys *subsys)
550+
{
551+
return subsys->passthru_ctrl;
552+
}
553+
#else /* CONFIG_NVME_TARGET_PASSTHRU */
554+
static inline u16 nvmet_parse_passthru_admin_cmd(struct nvmet_req *req)
555+
{
556+
return 0;
557+
}
558+
static inline u16 nvmet_parse_passthru_io_cmd(struct nvmet_req *req)
559+
{
560+
return 0;
561+
}
562+
static inline struct nvme_ctrl *nvmet_passthru_ctrl(struct nvmet_subsys *subsys)
563+
{
564+
return NULL;
565+
}
566+
#endif /* CONFIG_NVME_TARGET_PASSTHRU */
567+
568+
static inline struct nvme_ctrl *
569+
nvmet_req_passthru_ctrl(struct nvmet_req *req)
570+
{
571+
return nvmet_passthru_ctrl(req->sq->ctrl->subsys);
572+
}
573+
535574
u16 errno_to_nvme_status(struct nvmet_req *req, int errno);
536575

537576
/* Convert a 32-bit number to a 16-bit 0's based number */

0 commit comments

Comments
 (0)