[PATCH 2/2] NVMe: Implement WRITE_ZEROS support

Keith Busch keith.busch at intel.com
Tue Jul 8 10:42:39 PDT 2014


Adds WRITE_ZEROS block device command support if the NVMe device supports
this optional command.

Signed-off-by: Keith Busch <keith.busch at intel.com>
---
 drivers/block/nvme-core.c |   24 ++++++++++++++++++++++++
 include/uapi/linux/nvme.h |    2 ++
 2 files changed, 26 insertions(+)

diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 28aec2d..5d8664c 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -668,6 +668,26 @@ static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns,
 	return 0;
 }
 
+static int nvme_submit_write_zeros(struct nvme_queue *nvmeq, struct nvme_ns *ns,
+						struct bio * bio, int cmdid)
+{
+	struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+
+	memset(cmnd, 0, sizeof(*cmnd));
+	cmnd->rw.opcode = nvme_cmd_write_zeros;
+	cmnd->rw.command_id = cmdid;
+	cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
+	cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_iter.bi_sector));
+	cmnd->rw.length =
+		cpu_to_le16((bio->bi_iter.bi_size >> ns->lba_shift) - 1);
+
+	if (++nvmeq->sq_tail == nvmeq->q_depth)
+		nvmeq->sq_tail = 0;
+	writel(nvmeq->sq_tail, nvmeq->q_db);
+
+	return 0;
+}
+
 static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod)
 {
 	struct bio *bio = iod->private;
@@ -685,6 +705,8 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod)
 		return nvme_submit_discard(nvmeq, ns, bio, iod, cmdid);
 	if (bio->bi_rw & REQ_FLUSH)
 		return nvme_submit_flush(nvmeq, ns, cmdid);
+	if (bio->bi_rw & REQ_WRITE_ZEROS)
+		return nvme_submit_write_zeros(nvmeq, ns, bio, cmdid);
 
 	control = 0;
 	if (bio->bi_rw & REQ_FUA)
@@ -2011,6 +2033,8 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
 
 	if (dev->oncs & NVME_CTRL_ONCS_DSM)
 		nvme_config_discard(ns);
+	if (dev->oncs & NVME_CTRL_ONCS_WRITE_ZEROS)
+		blk_queue_max_write_zeros_sectors(ns->queue, 0xffffffff);
 
 	return ns;
 
diff --git a/include/uapi/linux/nvme.h b/include/uapi/linux/nvme.h
index 134518b..16040b7 100644
--- a/include/uapi/linux/nvme.h
+++ b/include/uapi/linux/nvme.h
@@ -89,6 +89,7 @@ enum {
 	NVME_CTRL_ONCS_COMPARE			= 1 << 0,
 	NVME_CTRL_ONCS_WRITE_UNCORRECTABLE	= 1 << 1,
 	NVME_CTRL_ONCS_DSM			= 1 << 2,
+	NVME_CTRL_ONCS_WRITE_ZEROS		= 1 << 3,
 	NVME_CTRL_VWC_PRESENT			= 1 << 0,
 };
 
@@ -189,6 +190,7 @@ enum nvme_opcode {
 	nvme_cmd_read		= 0x02,
 	nvme_cmd_write_uncor	= 0x04,
 	nvme_cmd_compare	= 0x05,
+	nvme_cmd_write_zeros	= 0x08,
 	nvme_cmd_dsm		= 0x09,
 };
 
-- 
1.7.10.4




More information about the Linux-nvme mailing list