Skip to content

Commit 8695f06

Browse files
alanpeteradChristoph Hellwig
authored andcommitted
nvme: all namespaces in a subsystem must adhere to a common atomic write size
The first namespace configured in a subsystem sets the subsystem's atomic write size based on its AWUPF or NAWUPF. Subsequent namespaces must have an atomic write size (per their AWUPF or NAWUPF) less than or equal to the subsystem's atomic write size, or their probing will be rejected. Signed-off-by: Alan Adamson <alan.adamson@oracle.com> [hch: fold in review comments from John Garry] Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: John Garry <john.g.garry@oracle.com>
1 parent a21675e commit 8695f06

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

drivers/nvme/host/core.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,7 +2059,21 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
20592059
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf)
20602060
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
20612061
else
2062-
atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
2062+
atomic_bs = (1 + ns->ctrl->awupf) * bs;
2063+
2064+
/*
2065+
* Set subsystem atomic bs.
2066+
*/
2067+
if (ns->ctrl->subsys->atomic_bs) {
2068+
if (atomic_bs != ns->ctrl->subsys->atomic_bs) {
2069+
dev_err_ratelimited(ns->ctrl->device,
2070+
"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n",
2071+
ns->disk ? ns->disk->disk_name : "?",
2072+
ns->ctrl->subsys->atomic_bs,
2073+
atomic_bs);
2074+
}
2075+
} else
2076+
ns->ctrl->subsys->atomic_bs = atomic_bs;
20632077

20642078
nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs);
20652079
}
@@ -2201,6 +2215,17 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
22012215
nvme_set_chunk_sectors(ns, id, &lim);
22022216
if (!nvme_update_disk_info(ns, id, &lim))
22032217
capacity = 0;
2218+
2219+
/*
2220+
* Validate the max atomic write size fits within the subsystem's
2221+
* atomic write capabilities.
2222+
*/
2223+
if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) {
2224+
blk_mq_unfreeze_queue(ns->disk->queue, memflags);
2225+
ret = -ENXIO;
2226+
goto out;
2227+
}
2228+
22042229
nvme_config_discard(ns, &lim);
22052230
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
22062231
ns->head->ids.csi == NVME_CSI_ZNS)
@@ -3031,7 +3056,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
30313056
kfree(subsys);
30323057
return -EINVAL;
30333058
}
3034-
subsys->awupf = le16_to_cpu(id->awupf);
30353059
nvme_mpath_default_iopolicy(subsys);
30363060

30373061
subsys->dev.class = &nvme_subsys_class;
@@ -3441,7 +3465,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
34413465
dev_pm_qos_expose_latency_tolerance(ctrl->device);
34423466
else if (!ctrl->apst_enabled && prev_apst_enabled)
34433467
dev_pm_qos_hide_latency_tolerance(ctrl->device);
3444-
3468+
ctrl->awupf = le16_to_cpu(id->awupf);
34453469
out_free:
34463470
kfree(id);
34473471
return ret;

drivers/nvme/host/nvme.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ struct nvme_ctrl {
410410

411411
enum nvme_ctrl_type cntrltype;
412412
enum nvme_dctype dctype;
413+
u16 awupf; /* 0's based value. */
413414
};
414415

415416
static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
@@ -442,11 +443,11 @@ struct nvme_subsystem {
442443
u8 cmic;
443444
enum nvme_subsys_type subtype;
444445
u16 vendor_id;
445-
u16 awupf; /* 0's based awupf value. */
446446
struct ida ns_ida;
447447
#ifdef CONFIG_NVME_MULTIPATH
448448
enum nvme_iopolicy iopolicy;
449449
#endif
450+
u32 atomic_bs;
450451
};
451452

452453
/*

0 commit comments

Comments
 (0)