[PATCH 08/14] nvmet: use nvme write cmd group setting op_flag

Chaitanya Kulkarni chaitanya.kulkarni at wdc.com
Mon Aug 10 14:54:50 EDT 2020


The function nvme_is_write() only checks the last bit of the opcode to
determine if command is a write command or not based on that it sets
the bio->bi_opf for passthru bio with REQ_SYNC | REQ_IDLE.

The condition is true for nvme_cmd_write (opcode 0x01), but there are
commands present in the NVMe command set and are part for NVM Write
Command Group that doesn't have a last bit set. e.g.
nvme_cmd_write_zeroes 0x08. With current implementation for these
commands we will never set the REQ_SYNC for bio->bi_opf even though
command is from NVMe write command set.

For passthru backend introduce nvmet_write_cmd_group() and use the
commands from NVMe 1.4 spec write command group to set the REQ_SYNC
flag for passthru bio and update nvmet_passthru_map_sg accordingly.
Since these are low frequency commands annotate condition with
unlikely respectively.

Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni at wdc.com>
---
 drivers/nvme/target/passthru.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 0b18038c44bb..5f06f4290c52 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -176,6 +176,29 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
 	nvmet_passthru_req_done(rq, 0 /* this value is not used for request */);
 }
 
+static inline bool nvmet_write_cmd_group(__u8 opcode)
+{
+	bool ret;
+
+	/* NVM Express Revision 1.4 Figure 462. */
+	switch (opcode) {
+	case nvme_admin_format_nvm:
+	case nvme_admin_ns_attach:
+	case nvme_admin_ns_mgmt:
+	case nvme_admin_sanitize_nvm:
+	case nvme_admin_security_send:
+	case nvme_cmd_write_zeroes:
+	case nvme_cmd_write_uncor:
+		ret = true;
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	return ret;
+}
+
 static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq)
 {
 	unsigned int op_flags = 0;
@@ -184,10 +207,12 @@ static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq)
 	struct bio *bio;
 	int i, ret;
 
-	if (req->cmd->common.opcode == nvme_cmd_flush)
-		op_flags = REQ_FUA;
-	else if (nvme_is_write(req->cmd))
+	if (nvme_is_write(req->cmd))
 		op_flags = REQ_SYNC | REQ_IDLE;
+	else if (unlikely(nvmet_write_cmd_group(req->cmd->common.opcode)))
+		op_flags = REQ_SYNC;
+	else if (unlikely(req->cmd->common.opcode == nvme_cmd_flush))
+		op_flags = REQ_FUA;
 
 	bio = bio_alloc(GFP_KERNEL, min(sg_cnt, BIO_MAX_PAGES));
 	bio->bi_end_io = bio_put;
-- 
2.22.1




More information about the Linux-nvme mailing list