Skip to content

Commit 6e02318

Browse files
ChaitanayaKulkarniChristoph Hellwig
authored andcommitted
nvme: add support for the Write Zeroes command
Allow write zeroes operations (REQ_OP_WRITE_ZEROES) on the block device, if the device supports an optional command bit set for write zeroes. Add support to setup write zeroes command. Set maximum possible write zeroes sectors in one write zeroes command according to nvme write zeroes command definition. This patch was posted as a part of block-write-zeroes support implementation (https://patchwork.kernel.org/patch/9454859/), but did not make into mainline kernel as it got reverted due to failure on the Linus's machine. In this patch in order to be more cautious, we use NVMe controller's maximum hardware sector size which is calculated based on the controller's MDTS (Maximum Data Transfer Size) field to calculate the maximum sectors for the write zeroes request. Signed-off-by: Chaitanya Kulkarni <[email protected]> Reviewed-by: Martin K. Petersen <[email protected]> [folded a fix from Keith Busch to properly respect NVME_QUIRK_DEALLOCATE_ZEROES] Signed-off-by: Christoph Hellwig <[email protected]>
1 parent bb94aea commit 6e02318

File tree

1 file changed

+50
-2
lines changed

1 file changed

+50
-2
lines changed

drivers/nvme/host/core.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,22 @@ static blk_status_t nvme_setup_discard(struct nvme_ns *ns, struct request *req,
611611
return BLK_STS_OK;
612612
}
613613

614+
static inline blk_status_t nvme_setup_write_zeroes(struct nvme_ns *ns,
615+
struct request *req, struct nvme_command *cmnd)
616+
{
617+
if (ns->ctrl->quirks & NVME_QUIRK_DEALLOCATE_ZEROES)
618+
return nvme_setup_discard(ns, req, cmnd);
619+
620+
cmnd->write_zeroes.opcode = nvme_cmd_write_zeroes;
621+
cmnd->write_zeroes.nsid = cpu_to_le32(ns->head->ns_id);
622+
cmnd->write_zeroes.slba =
623+
cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
624+
cmnd->write_zeroes.length =
625+
cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
626+
cmnd->write_zeroes.control = 0;
627+
return BLK_STS_OK;
628+
}
629+
614630
static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
615631
struct request *req, struct nvme_command *cmnd)
616632
{
@@ -705,7 +721,8 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
705721
nvme_setup_flush(ns, cmd);
706722
break;
707723
case REQ_OP_WRITE_ZEROES:
708-
/* currently only aliased to deallocate for a few ctrls: */
724+
ret = nvme_setup_write_zeroes(ns, req, cmd);
725+
break;
709726
case REQ_OP_DISCARD:
710727
ret = nvme_setup_discard(ns, req, cmd);
711728
break;
@@ -1509,6 +1526,37 @@ static void nvme_config_discard(struct nvme_ns *ns)
15091526
blk_queue_max_write_zeroes_sectors(queue, UINT_MAX);
15101527
}
15111528

1529+
static inline void nvme_config_write_zeroes(struct nvme_ns *ns)
1530+
{
1531+
u32 max_sectors;
1532+
unsigned short bs = 1 << ns->lba_shift;
1533+
1534+
if (!(ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES))
1535+
return;
1536+
/*
1537+
* Even though NVMe spec explicitly states that MDTS is not
1538+
* applicable to the write-zeroes:- "The restriction does not apply to
1539+
* commands that do not transfer data between the host and the
1540+
* controller (e.g., Write Uncorrectable ro Write Zeroes command).".
1541+
* In order to be more cautious use controller's max_hw_sectors value
1542+
* to configure the maximum sectors for the write-zeroes which is
1543+
* configured based on the controller's MDTS field in the
1544+
* nvme_init_identify() if available.
1545+
*/
1546+
if (ns->ctrl->max_hw_sectors == UINT_MAX)
1547+
max_sectors = ((u32)(USHRT_MAX + 1) * bs) >> 9;
1548+
else
1549+
max_sectors = ((u32)(ns->ctrl->max_hw_sectors + 1) * bs) >> 9;
1550+
1551+
blk_queue_max_write_zeroes_sectors(ns->queue, max_sectors);
1552+
}
1553+
1554+
static inline void nvme_ns_config_oncs(struct nvme_ns *ns)
1555+
{
1556+
nvme_config_discard(ns);
1557+
nvme_config_write_zeroes(ns);
1558+
}
1559+
15121560
static void nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid,
15131561
struct nvme_id_ns *id, struct nvme_ns_ids *ids)
15141562
{
@@ -1562,7 +1610,7 @@ static void nvme_update_disk_info(struct gendisk *disk,
15621610
capacity = 0;
15631611

15641612
set_capacity(disk, capacity);
1565-
nvme_config_discard(ns);
1613+
nvme_ns_config_oncs(ns);
15661614

15671615
if (id->nsattr & (1 << 0))
15681616
set_disk_ro(disk, true);

0 commit comments

Comments
 (0)