Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB67YI CVE: CVE-2024-53093
--------------------
Fix kabi broken caused by commit 08d945a8dbe9 ("nvme-multipath: defer partition scanning").
Fixes: 08d945a8dbe9 ("nvme-multipath: defer partition scanning") Signed-off-by: Zheng Qixing zhengqixing@huawei.com --- drivers/nvme/host/core.c | 14 +++++++++----- drivers/nvme/host/multipath.c | 18 +++++++++++++----- drivers/nvme/host/nvme.h | 8 +++++++- 3 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 1db3a80d767f..7533a7484dbe 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -477,12 +477,14 @@ static void nvme_free_ns_head(struct kref *ref) { struct nvme_ns_head *head = container_of(ref, struct nvme_ns_head, ref); + struct nvme_ns_head_wrapper *head_wrapper = + container_of(head, struct nvme_ns_head_wrapper, head);
nvme_mpath_remove_disk(head); ida_simple_remove(&head->subsys->ns_ida, head->instance); cleanup_srcu_struct(&head->srcu); nvme_put_subsystem(head->subsys); - kfree(head); + kfree(head_wrapper); }
static bool nvme_tryget_ns_head(struct nvme_ns_head *head) @@ -3737,17 +3739,19 @@ static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys, static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl, unsigned nsid, struct nvme_ns_ids *ids) { + struct nvme_ns_head_wrapper *head_wrapper; struct nvme_ns_head *head; - size_t size = sizeof(*head); + size_t size = sizeof(*head_wrapper); int ret = -ENOMEM;
#ifdef CONFIG_NVME_MULTIPATH size += num_possible_nodes() * sizeof(struct nvme_ns *); #endif
- head = kzalloc(size, GFP_KERNEL); - if (!head) + head_wrapper = kzalloc(size, GFP_KERNEL); + if (!head_wrapper) goto out; + head = &head_wrapper->head; ret = ida_simple_get(&ctrl->subsys->ns_ida, 1, 0, GFP_KERNEL); if (ret < 0) goto out_free_head; @@ -3789,7 +3793,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl, out_ida_remove: ida_simple_remove(&ctrl->subsys->ns_ida, head->instance); out_free_head: - kfree(head); + kfree(head_wrapper); out: if (ret > 0) ret = blk_status_to_errno(nvme_error_status(ret)); diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index eee881f970f7..c79b67989a22 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -337,8 +337,9 @@ blk_qc_t nvme_ns_head_submit_bio(struct bio *bio)
static void nvme_partition_scan_work(struct work_struct *work) { - struct nvme_ns_head *head = - container_of(work, struct nvme_ns_head, partition_scan_work); + struct nvme_ns_head_wrapper *head_wrapper = + container_of(work, struct nvme_ns_head_wrapper, partition_scan_work); + struct nvme_ns_head *head = &head_wrapper->head; struct block_device *bdev;
if (WARN_ON_ONCE(!test_and_clear_bit(GENHD_FL_NO_PART_SCAN, @@ -381,13 +382,15 @@ static void nvme_requeue_work(struct work_struct *work) int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head) { struct request_queue *q; + struct nvme_ns_head_wrapper *head_wrapper = + container_of(head, struct nvme_ns_head_wrapper, head); bool vwc = false;
mutex_init(&head->lock); bio_list_init(&head->requeue_list); spin_lock_init(&head->requeue_lock); INIT_WORK(&head->requeue_work, nvme_requeue_work); - INIT_WORK(&head->partition_scan_work, nvme_partition_scan_work); + INIT_WORK(&head_wrapper->partition_scan_work, nvme_partition_scan_work);
/* * Add a multipath node if the subsystems supports multiple controllers. @@ -440,6 +443,8 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head) static void nvme_mpath_set_live(struct nvme_ns *ns) { struct nvme_ns_head *head = ns->head; + struct nvme_ns_head_wrapper *head_wrapper = + container_of(head, struct nvme_ns_head_wrapper, head);
if (!head->disk) return; @@ -447,7 +452,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns) if (!test_and_set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) { device_add_disk(&head->subsys->dev, head->disk, nvme_ns_id_attr_groups); - kblockd_schedule_work(&head->partition_scan_work); + kblockd_schedule_work(&head_wrapper->partition_scan_work); }
mutex_lock(&head->lock); @@ -762,13 +767,16 @@ void nvme_mpath_shutdown_disk(struct nvme_ns_head *head)
void nvme_mpath_remove_disk(struct nvme_ns_head *head) { + struct nvme_ns_head_wrapper *head_wrapper = + container_of(head, struct nvme_ns_head_wrapper, head); + if (!head->disk) return; blk_set_queue_dying(head->disk->queue); /* make sure all pending bios are cleaned up */ kblockd_schedule_work(&head->requeue_work); flush_work(&head->requeue_work); - flush_work(&head->partition_scan_work); + flush_work(&head_wrapper->partition_scan_work); blk_cleanup_queue(head->disk->queue); if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) { /* diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 951e1d0f0885..61ce3d4ee64e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -422,7 +422,6 @@ struct nvme_ns_head { struct bio_list requeue_list; spinlock_t requeue_lock; struct work_struct requeue_work; - struct work_struct partition_scan_work; struct mutex lock; unsigned long flags; #define NVME_NSHEAD_DISK_LIVE 0 @@ -430,6 +429,13 @@ struct nvme_ns_head { #endif };
+struct nvme_ns_head_wrapper { +#ifdef CONFIG_NVME_MULTIPATH + struct work_struct partition_scan_work; +#endif + struct nvme_ns_head head; +}; + enum nvme_ns_features { NVME_NS_EXT_LBAS = 1 << 0, /* support extended LBA format */ NVME_NS_METADATA_SUPPORTED = 1 << 1, /* support getting generated md */