[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