diff options
author | Bart Van Assche | 2019-06-28 09:53:30 -0700 |
---|---|---|
committer | Christoph Hellwig | 2019-07-09 14:15:37 -0700 |
commit | 9d05a96e298aadb36e3ec971fab8d416e6fb7331 (patch) | |
tree | 9c504202160ee7cf018a6e5ef3b0f3973c3c1752 /drivers/nvme | |
parent | 4c0181bf6cc81716102308dc47779ad1f5aeded2 (diff) |
nvmet: export I/O characteristics attributes in Identify
Make the NVMe NAWUN, NAWUPF, NACWU, NPWG, NPWA, NPDG and NOWS attributes
available to initator systems for the block backend.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/nvme')
-rw-r--r-- | drivers/nvme/target/admin-cmd.c | 3 | ||||
-rw-r--r-- | drivers/nvme/target/io-cmd-bdev.c | 39 | ||||
-rw-r--r-- | drivers/nvme/target/nvmet.h | 8 |
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index 9f72d515fc4b..4dc12ea52f23 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -442,6 +442,9 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req) break; } + if (ns->bdev) + nvmet_bdev_set_limits(ns->bdev, id); + /* * We just provide a single LBA format that matches what the * underlying device reports. diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 7a1cf6437a6a..de0bff70ebb6 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -8,6 +8,45 @@ #include <linux/module.h> #include "nvmet.h" +void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id) +{ + const struct queue_limits *ql = &bdev_get_queue(bdev)->limits; + /* Number of physical blocks per logical block. */ + const u32 ppl = ql->physical_block_size / ql->logical_block_size; + /* Physical blocks per logical block, 0's based. */ + const __le16 ppl0b = to0based(ppl); + + /* + * For NVMe 1.2 and later, bit 1 indicates that the fields NAWUN, + * NAWUPF, and NACWU are defined for this namespace and should be + * used by the host for this namespace instead of the AWUN, AWUPF, + * and ACWU fields in the Identify Controller data structure. If + * any of these fields are zero that means that the corresponding + * field from the identify controller data structure should be used. + */ + id->nsfeat |= 1 << 1; + id->nawun = ppl0b; + id->nawupf = ppl0b; + id->nacwu = ppl0b; + + /* + * Bit 4 indicates that the fields NPWG, NPWA, NPDG, NPDA, and + * NOWS are defined for this namespace and should be used by + * the host for I/O optimization. + */ + id->nsfeat |= 1 << 4; + /* NPWG = Namespace Preferred Write Granularity. 0's based */ + id->npwg = ppl0b; + /* NPWA = Namespace Preferred Write Alignment. 0's based */ + id->npwa = id->npwg; + /* NPDG = Namespace Preferred Deallocate Granularity. 0's based */ + id->npdg = to0based(ql->discard_granularity / ql->logical_block_size); + /* NPDG = Namespace Preferred Deallocate Alignment */ + id->npda = id->npdg; + /* NOWS = Namespace Optimal Write Size */ + id->nows = to0based(ql->io_opt / ql->logical_block_size); +} + int nvmet_bdev_ns_enable(struct nvmet_ns *ns) { int ret; diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index dc270944bb25..6ee66c610739 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -365,6 +365,7 @@ u16 nvmet_set_feat_async_event(struct nvmet_req *req, u32 mask); void nvmet_execute_async_event(struct nvmet_req *req); u16 nvmet_parse_connect_cmd(struct nvmet_req *req); +void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id); u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req); u16 nvmet_file_parse_io_cmd(struct nvmet_req *req); u16 nvmet_parse_admin_cmd(struct nvmet_req *req); @@ -492,4 +493,11 @@ static inline u32 nvmet_rw_len(struct nvmet_req *req) } u16 errno_to_nvme_status(struct nvmet_req *req, int errno); + +/* Convert a 32-bit number to a 16-bit 0's based number */ +static inline __le16 to0based(u32 a) +{ + return cpu_to_le16(max(1U, min(1U << 16, a)) - 1); +} + #endif /* _NVMET_H */ |