> >The bus that the device is on should prevent this, why isn't that >working for you? What type of device/bus do you see this problem on?
The device is a firmware class device on a virtual bus. >> Signed-off-by: eun.taik.lee > >We need a "real" name here, I don't think your name has '.' in it, >right? Right. It should've been Eun Taik Lee. >Your email client turned all tabs to spaces and made the patch unable to >be applied. I think I pasted the patch on HTML mode and then switched to text mode. Below patch should be okay. From: "Eun Taik Lee" <[email protected]> There is a possible race condition when a device is added while another device with the same parent , with ref count of one, is deleted. CPU0 CPU1 device_add() device_del() get_device_parent() put_device(parent); kobj = kobject_get(k) kobject_put() kref_put() refcount=0 refcount is 0 WARNS it was 0 but return kobj frees kobj uses the freed parent kobj The race condition exists because kref_put() and the release function is not atomic. Using kobject_get_unless_zero() instead of kobject_get() in get_device_parent() will prevent this race condition. Signed-off-by: Eun Taik Lee <[email protected]> --- drivers/base/core.c | 2 +- include/linux/kobject.h | 2 ++ lib/kobject.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 07304a3..ec2f211 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -761,7 +761,7 @@ static struct kobject *get_device_parent(struct device *dev, spin_lock(&dev->class->p->glue_dirs.list_lock); list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry) if (k->parent == parent_kobj) { - kobj = kobject_get(k); + kobj = kobject_get_unless_zero(k); break; } spin_unlock(&dev->class->p->glue_dirs.list_lock); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 2d61b90..3032744 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -107,6 +107,8 @@ extern int __must_check kobject_rename(struct kobject *, const char *new_name); extern int __must_check kobject_move(struct kobject *, struct kobject *); extern struct kobject *kobject_get(struct kobject *kobj); +extern struct kobject * __must_check kobject_get_unless_zero( + struct kobject *kobj); extern void kobject_put(struct kobject *kobj); extern const void *kobject_namespace(struct kobject *kobj); diff --git a/lib/kobject.c b/lib/kobject.c index 03d4ab3..ff0ce681 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -581,7 +581,7 @@ struct kobject *kobject_get(struct kobject *kobj) return kobj; } -static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj) +struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj) { if (!kref_get_unless_zero(&kobj->kref)) kobj = NULL; -- 1.7.9.5 thanks Eun Taik LeeN�����r��y����b�X��ǧv�^�){.n�+����{����zX����ܨ}���Ơz�&j:+v�������zZ+��+zf���h���~����i���z��w���?�����&�)ߢf��^jǫy�m��@A�a��� 0��h���i

