]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
block: fix kobject double initialization in add_disk
authorZheng Qixing <zhengqixing@huawei.com>
Fri, 8 Aug 2025 05:36:09 +0000 (13:36 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Aug 2025 16:41:33 +0000 (18:41 +0200)
[ Upstream commit 343dc5423bfe876c12bb80c56f5e44286e442a07 ]

Device-mapper can call add_disk() multiple times for the same gendisk
due to its two-phase creation process (dm create + dm load). This leads
to kobject double initialization errors when the underlying iSCSI devices
become temporarily unavailable and then reappear.

However, if the first add_disk() call fails and is retried, the queue_kobj
gets initialized twice, causing:

kobject: kobject (ffff88810c27bb90): tried to init an initialized object,
something is seriously wrong.
 Call Trace:
  <TASK>
  dump_stack_lvl+0x5b/0x80
  kobject_init.cold+0x43/0x51
  blk_register_queue+0x46/0x280
  add_disk_fwnode+0xb5/0x280
  dm_setup_md_queue+0x194/0x1c0
  table_load+0x297/0x2d0
  ctl_ioctl+0x2a2/0x480
  dm_ctl_ioctl+0xe/0x20
  __x64_sys_ioctl+0xc7/0x110
  do_syscall_64+0x72/0x390
  entry_SYSCALL_64_after_hwframe+0x76/0x7e

Fix this by separating kobject initialization from sysfs registration:
 - Initialize queue_kobj early during gendisk allocation
 - add_disk() only adds the already-initialized kobject to sysfs
 - del_gendisk() removes from sysfs but doesn't destroy the kobject
 - Final cleanup happens when the disk is released

Fixes: 2bd85221a625 ("block: untangle request_queue refcounting from sysfs")
Reported-by: Li Lingfeng <lilingfeng3@huawei.com>
Closes: https://lore.kernel.org/all/83591d0b-2467-433c-bce0-5581298eb161@huawei.com/
Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Link: https://lore.kernel.org/r/20250808053609.3237836-1-zhengqixing@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
block/blk-sysfs.c
block/blk.h
block/genhd.c

index c611444480b320bb04d0b2259ac6330b688bdcb3..de39746de18b48e8443381ed095a459b23f97455 100644 (file)
@@ -821,7 +821,7 @@ static void blk_queue_release(struct kobject *kobj)
        /* nothing to do here, all data is associated with the parent gendisk */
 }
 
-static const struct kobj_type blk_queue_ktype = {
+const struct kobj_type blk_queue_ktype = {
        .default_groups = blk_queue_attr_groups,
        .sysfs_ops      = &queue_sysfs_ops,
        .release        = blk_queue_release,
@@ -849,15 +849,14 @@ int blk_register_queue(struct gendisk *disk)
        struct request_queue *q = disk->queue;
        int ret;
 
-       kobject_init(&disk->queue_kobj, &blk_queue_ktype);
        ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue");
        if (ret < 0)
-               goto out_put_queue_kobj;
+               return ret;
 
        if (queue_is_mq(q)) {
                ret = blk_mq_sysfs_register(disk);
                if (ret)
-                       goto out_put_queue_kobj;
+                       goto out_del_queue_kobj;
        }
        mutex_lock(&q->sysfs_lock);
 
@@ -908,8 +907,8 @@ out_debugfs_remove:
        mutex_unlock(&q->sysfs_lock);
        if (queue_is_mq(q))
                blk_mq_sysfs_unregister(disk);
-out_put_queue_kobj:
-       kobject_put(&disk->queue_kobj);
+out_del_queue_kobj:
+       kobject_del(&disk->queue_kobj);
        return ret;
 }
 
@@ -960,5 +959,4 @@ void blk_unregister_queue(struct gendisk *disk)
                elevator_set_none(q);
 
        blk_debugfs_remove(disk);
-       kobject_put(&disk->queue_kobj);
 }
index fae7653a941f5a0294132576ea8d5eeb1aea4d4f..4746a7704856af4a9a16b3886c76cfd77996b48c 100644 (file)
@@ -19,6 +19,7 @@ struct elevator_type;
 /* Max future timer expiry for timeouts */
 #define BLK_MAX_TIMEOUT                (5 * HZ)
 
+extern const struct kobj_type blk_queue_ktype;
 extern struct dentry *blk_debugfs_root;
 
 struct blk_flush_queue {
index c26733f6324b250be7510631341478ac61c42214..9bbc38d127926605f8a05929f91a7abe0c8265e6 100644 (file)
@@ -1303,6 +1303,7 @@ static void disk_release(struct device *dev)
        disk_free_zone_resources(disk);
        xa_destroy(&disk->part_tbl);
 
+       kobject_put(&disk->queue_kobj);
        disk->queue->disk = NULL;
        blk_put_queue(disk->queue);
 
@@ -1486,6 +1487,7 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
        INIT_LIST_HEAD(&disk->slave_bdevs);
 #endif
        mutex_init(&disk->rqos_state_mutex);
+       kobject_init(&disk->queue_kobj, &blk_queue_ktype);
        return disk;
 
 out_erase_part0: