[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 55/56] hw/block/nvme: fix zone boundary check for append
From: |
Klaus Jensen |
Subject: |
[PULL 55/56] hw/block/nvme: fix zone boundary check for append |
Date: |
Tue, 9 Feb 2021 08:31:00 +0100 |
From: Klaus Jensen <k.jensen@samsung.com>
When a zone append is processed the controller checks that validity of
the write before assigning the LBA to the append command. This causes
the boundary check to be wrong.
Fix this by checking the write *after* assigning the LBA. Remove the
append special case from the nvme_check_zone_write and open code it in
nvme_do_write, assigning the slba when basic sanity checks have been
performed. Then check the validity of the resulting write like any other
write command.
In the process, also fix a missing endianness conversion for the zone
append ALBA.
Reported-by: Niklas Cassel <Niklas.Cassel@wdc.com>
Cc: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Tested-by: Niklas Cassel <niklas.cassel@wdc.com>
Tested-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
hw/block/nvme.c | 46 ++++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index e562d7467b3b..cedb4ad9ffd3 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1188,7 +1188,7 @@ static uint16_t nvme_check_zone_state_for_write(NvmeZone
*zone)
static uint16_t nvme_check_zone_write(NvmeCtrl *n, NvmeNamespace *ns,
NvmeZone *zone, uint64_t slba,
- uint32_t nlb, bool append)
+ uint32_t nlb)
{
uint16_t status;
@@ -1202,16 +1202,8 @@ static uint16_t nvme_check_zone_write(NvmeCtrl *n,
NvmeNamespace *ns,
trace_pci_nvme_err_zone_write_not_ok(slba, nlb, status);
} else {
assert(nvme_wp_is_valid(zone));
- if (append) {
- if (unlikely(slba != zone->d.zslba)) {
- trace_pci_nvme_err_append_not_at_start(slba, zone->d.zslba);
- status = NVME_INVALID_FIELD;
- }
- if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
- trace_pci_nvme_err_append_too_large(slba, nlb, n->zasl);
- status = NVME_INVALID_FIELD;
- }
- } else if (unlikely(slba != zone->w_ptr)) {
+
+ if (unlikely(slba != zone->w_ptr)) {
trace_pci_nvme_err_write_not_at_wp(slba, zone->d.zslba,
zone->w_ptr);
status = NVME_ZONE_INVALID_WRITE;
@@ -1349,10 +1341,9 @@ static void nvme_finalize_zoned_write(NvmeNamespace *ns,
NvmeRequest *req,
}
}
-static uint64_t nvme_advance_zone_wp(NvmeNamespace *ns, NvmeZone *zone,
- uint32_t nlb)
+static void nvme_advance_zone_wp(NvmeNamespace *ns, NvmeZone *zone,
+ uint32_t nlb)
{
- uint64_t result = zone->w_ptr;
uint8_t zs;
zone->w_ptr += nlb;
@@ -1368,8 +1359,6 @@ static uint64_t nvme_advance_zone_wp(NvmeNamespace *ns,
NvmeZone *zone,
nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_IMPLICITLY_OPEN);
}
}
-
- return result;
}
static inline bool nvme_is_write(NvmeRequest *req)
@@ -1747,7 +1736,24 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest
*req, bool append,
if (ns->params.zoned) {
zone = nvme_get_zone_by_slba(ns, slba);
- status = nvme_check_zone_write(n, ns, zone, slba, nlb, append);
+ if (append) {
+ if (unlikely(slba != zone->d.zslba)) {
+ trace_pci_nvme_err_append_not_at_start(slba, zone->d.zslba);
+ status = NVME_INVALID_FIELD;
+ goto invalid;
+ }
+
+ if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
+ trace_pci_nvme_err_append_too_large(slba, nlb, n->zasl);
+ status = NVME_INVALID_FIELD;
+ goto invalid;
+ }
+
+ slba = zone->w_ptr;
+ res->slba = cpu_to_le64(slba);
+ }
+
+ status = nvme_check_zone_write(n, ns, zone, slba, nlb);
if (status) {
goto invalid;
}
@@ -1757,11 +1763,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest
*req, bool append,
goto invalid;
}
- if (append) {
- slba = zone->w_ptr;
- }
-
- res->slba = nvme_advance_zone_wp(ns, zone, nlb);
+ nvme_advance_zone_wp(ns, zone, nlb);
}
data_offset = nvme_l2b(ns, slba);
--
2.30.0
- [PULL 47/56] hw/block/nvme: move cmb logic to v1.4, (continued)
- [PULL 47/56] hw/block/nvme: move cmb logic to v1.4, Klaus Jensen, 2021/02/09
- [PULL 54/56] hw/block/nvme: fix wrong parameter name 'cross_read', Klaus Jensen, 2021/02/09
- [PULL 56/56] hw/block/nvme: refactor the logic for zone write checks, Klaus Jensen, 2021/02/09
- [PULL 43/56] hw/block/nvme: rename PMR/CMB shift/mask fields, Klaus Jensen, 2021/02/09
- [PULL 36/56] hw/block/nvme: add smart_critical_warning property, Klaus Jensen, 2021/02/09
- [PULL 34/56] hw/block/nvme: fix zone write finalize, Klaus Jensen, 2021/02/09
- [PULL 51/56] hw/block/nvme: fix set feature for error recovery, Klaus Jensen, 2021/02/09
- [PULL 44/56] hw/block/nvme: remove redundant zeroing of PMR registers, Klaus Jensen, 2021/02/09
- [PULL 49/56] hw/block/nvme: lift cmb restrictions, Klaus Jensen, 2021/02/09
- [PULL 53/56] hw/block/nvme: align with existing style, Klaus Jensen, 2021/02/09
- [PULL 55/56] hw/block/nvme: fix zone boundary check for append,
Klaus Jensen <=
- [PULL 52/56] hw/block/nvme: fix set feature save field check, Klaus Jensen, 2021/02/09
- Re: [PULL 00/56] emulated nvme patches, Peter Maydell, 2021/02/09