On Fri, Dec 17, 2021 at 07:37:43PM +0900, Tetsuo Handa wrote: > I think we can apply this patch as-is... Unfortunately I don't think so, don't we end up still with a race in between the first part of device_add() and the kobject_add() which adds the kobject to generic layer and in return enables the disk_release() call for the disk? I count 5 error paths in between including kobject_add() which can fail as well. If correct then something like the following may be needed: diff --git a/block/genhd.c b/block/genhd.c index 3c139a1b6f04..08ab7ce63e57 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -539,9 +539,10 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, out_device_del: device_del(ddev); out_disk_release_events: - disk_release_events(disk); + if (!kobject_alive(&ddev->kobj)) + disk_release_events(disk); out_free_ext_minor: - if (disk->major == BLOCK_EXT_MAJOR) + if (!kobject_alive(&ddev->kobj) && disk->major == BLOCK_EXT_MAJOR) blk_free_ext_minor(disk->first_minor); return ret; } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c740062b4b1a..4884aedbd4e0 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -117,6 +117,23 @@ extern void kobject_get_ownership(struct kobject *kobj, kuid_t *uid, kgid_t *gid); extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); +/** + * kobject_alive - Returns whether a kobject_add() has succeeded + * @kobj: the object to test + * + * This will return whether a kobject has been successfully added already with + * kobject_add(). It is useful for subsystems which have a kobj_type with its + * own kobj_type release() routine and want to verify that it will be called + * as otherwise if kobject_add() failed the subsystem is in charge of doing that + * cleanup. + */ +static inline bool kobject_alive(struct kobject *kobj) +{ + if (!kobj || kref_read(&kobj->kref) == 0) + return false; + return true; +} + /** * kobject_has_children - Returns whether a kobject has children. * @kobj: the object to test