hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/10302 --------------------------------- A namespace that carries protection information cannot use P2P memory: generating or verifying PI makes the block layer walk the data pages, and P2P pages are not CPU accessible. nvme sets QUEUE_FLAG_PCI_P2PDMA when the namespace is created, but the integrity profile is registered later and can change on every revalidation. A PI namespace therefore keeps advertising P2P, and an I/O that carries P2P pages reaches bio_integrity_prep() and accesses memory the CPU cannot map. The capability has to follow the namespace's integrity state, which is only known after nvme_update_disk_info() has registered or dropped the profile. Clear it on the path queue and on the multipath head disk while the profile is present. Signed-off-by: Zizhi Wo <wozizhi@huawei.com> --- drivers/nvme/host/core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index d049b55efd03..52fc918f7321 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2095,10 +2095,16 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, blk_mq_unfreeze_queue(ns->disk->queue); goto out; } nvme_set_chunk_sectors(ns, id); nvme_update_disk_info(ns->disk, ns, id); + /* P2P pages cannot be used for block layer PI processing. */ + if (blk_get_integrity(ns->disk)) + blk_queue_flag_clear(QUEUE_FLAG_PCI_P2PDMA, ns->queue); + else if (ns->ctrl->ops->supports_pci_p2pdma && + ns->ctrl->ops->supports_pci_p2pdma(ns->ctrl)) + blk_queue_flag_set(QUEUE_FLAG_PCI_P2PDMA, ns->queue); nvme_set_queue_limits(ns->ctrl, ns->queue); if (ns->head->ids.csi == NVME_CSI_ZNS) { ret = nvme_update_zone_info(ns, lbaf); if (ret) { @@ -2130,11 +2136,12 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, nvme_update_disk_info(ns->head->disk, ns, id); set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info)); nvme_mpath_revalidate_paths(ns); blk_stack_limits(&ns->head->disk->queue->limits, &ns->queue->limits, 0); - if (!blk_queue_pci_p2pdma(ns->queue)) + if (!blk_queue_pci_p2pdma(ns->queue) || + blk_get_integrity(ns->head->disk)) blk_queue_flag_clear(QUEUE_FLAG_PCI_P2PDMA, ns->head->disk->queue); disk_update_readahead(ns->head->disk); blk_mq_unfreeze_queue(ns->head->disk->queue); } -- 2.52.0