Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

block: fix kobject double initialization in add_disk

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>

authored by

Zheng Qixing and committed by
Jens Axboe
343dc542 196447c7

+8 -7
+5 -7
block/blk-sysfs.c
··· 847 847 /* nothing to do here, all data is associated with the parent gendisk */ 848 848 } 849 849 850 - static const struct kobj_type blk_queue_ktype = { 850 + const struct kobj_type blk_queue_ktype = { 851 851 .default_groups = blk_queue_attr_groups, 852 852 .sysfs_ops = &queue_sysfs_ops, 853 853 .release = blk_queue_release, ··· 875 875 struct request_queue *q = disk->queue; 876 876 int ret; 877 877 878 - kobject_init(&disk->queue_kobj, &blk_queue_ktype); 879 878 ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue"); 880 879 if (ret < 0) 881 - goto out_put_queue_kobj; 880 + return ret; 882 881 883 882 if (queue_is_mq(q)) { 884 883 ret = blk_mq_sysfs_register(disk); 885 884 if (ret) 886 - goto out_put_queue_kobj; 885 + goto out_del_queue_kobj; 887 886 } 888 887 mutex_lock(&q->sysfs_lock); 889 888 ··· 933 934 mutex_unlock(&q->sysfs_lock); 934 935 if (queue_is_mq(q)) 935 936 blk_mq_sysfs_unregister(disk); 936 - out_put_queue_kobj: 937 - kobject_put(&disk->queue_kobj); 937 + out_del_queue_kobj: 938 + kobject_del(&disk->queue_kobj); 938 939 return ret; 939 940 } 940 941 ··· 985 986 elevator_set_none(q); 986 987 987 988 blk_debugfs_remove(disk); 988 - kobject_put(&disk->queue_kobj); 989 989 }
+1
block/blk.h
··· 29 29 /* Max future timer expiry for timeouts */ 30 30 #define BLK_MAX_TIMEOUT (5 * HZ) 31 31 32 + extern const struct kobj_type blk_queue_ktype; 32 33 extern struct dentry *blk_debugfs_root; 33 34 34 35 struct blk_flush_queue {
+2
block/genhd.c
··· 1303 1303 disk_free_zone_resources(disk); 1304 1304 xa_destroy(&disk->part_tbl); 1305 1305 1306 + kobject_put(&disk->queue_kobj); 1306 1307 disk->queue->disk = NULL; 1307 1308 blk_put_queue(disk->queue); 1308 1309 ··· 1487 1486 INIT_LIST_HEAD(&disk->slave_bdevs); 1488 1487 #endif 1489 1488 mutex_init(&disk->rqos_state_mutex); 1489 + kobject_init(&disk->queue_kobj, &blk_queue_ktype); 1490 1490 return disk; 1491 1491 1492 1492 out_erase_part0: