From: Cornelia Huck <cornelia.huck@de.ibm.com> Make setup_parent() void as get_device_parent() will always return either a valid kobject or NULL. Introduce cleanup_glue_dir() to drop reference grabbed on "glue" directory by get_device_parent(). Use it for cleanup in device_move() and device_add() on errors. This should fix the refcounting problem reported in http://marc.info/?l=linux-kernel&m=120052487909200&w=2 Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Cc: Dave Young <hidave.darkstar@gmail.com> Cc: Gabor Gombas <gombasg@sztaki.hu> Cc: Tejun Heo <htejun@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Marcel Holtmann <marcel@holtmann.org> Cc: David Miller <davem@davemloft.net> Cc: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/base/core.c | 29 ++++++++++++++--------------- 1 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index d5d542d..f09dde3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -552,6 +552,8 @@ static struct kobject *get_device_parent(struct device *dev, } static inline void cleanup_device_parent(struct device *dev) {} +static inline void cleanup_glue_dir(struct device *dev, + struct kobject *glue_dir) {} #else static struct kobject *virtual_device_parent(struct device *dev) { @@ -616,27 +618,27 @@ static struct kobject *get_device_parent(struct device *dev, return NULL; } -static void cleanup_device_parent(struct device *dev) +static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) { - struct kobject *glue_dir = dev->kobj.parent; - /* see if we live in a "glue" directory */ if (!dev->class || glue_dir->kset != &dev->class->class_dirs) return; kobject_put(glue_dir); } + +static void cleanup_device_parent(struct device *dev) +{ + cleanup_glue_dir(dev, dev->kobj.parent); +} #endif -static int setup_parent(struct device *dev, struct device *parent) +static void setup_parent(struct device *dev, struct device *parent) { struct kobject *kobj; kobj = get_device_parent(dev, parent); - if (IS_ERR(kobj)) - return PTR_ERR(kobj); if (kobj) dev->kobj.parent = kobj; - return 0; } static int device_add_class_symlinks(struct device *dev) @@ -784,9 +786,7 @@ int device_add(struct device *dev) pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__); parent = get_device(dev->parent); - error = setup_parent(dev, parent); - if (error) - goto Error; + setup_parent(dev, parent); /* first, register with generic layer. */ error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id); @@ -864,6 +864,7 @@ int device_add(struct device *dev) kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: + cleanup_device_parent(dev); if (parent) put_device(parent); goto Done; @@ -1344,15 +1345,12 @@ int device_move(struct device *dev, struct device *new_parent) new_parent = get_device(new_parent); new_parent_kobj = get_device_parent (dev, new_parent); - if (IS_ERR(new_parent_kobj)) { - error = PTR_ERR(new_parent_kobj); - put_device(new_parent); - goto out; - } + pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id, __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>"); error = kobject_move(&dev->kobj, new_parent_kobj); if (error) { + cleanup_glue_dir(dev, new_parent_kobj); put_device(new_parent); goto out; } @@ -1375,6 +1373,7 @@ int device_move(struct device *dev, struct device *new_parent) klist_add_tail(&dev->knode_parent, &old_parent->klist_children); } + cleanup_glue_dir(dev, new_parent_kobj); put_device(new_parent); goto out; } -- 1.5.3.8 --
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Stoyan Gaydarov | From 2.4 to 2.6 to 2.7? |
| David Miller | Slow DOWN, please!!! |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
git: | |
| Joe Fiorini | Undo git-rm without commit? |
| Linus Torvalds | Re: VCS comparison table |
| Linus Torvalds | People unaware of the importance of "git gc"? |
| Luke Lu | git-svn questions: how to clone/init non-standard layout branches/tags? |
| Richard Stallman | Real men don't attack straw men |
| Juan Miscaro | When will OpenBSD support UTF8? |
| Daniel Ouellet | Bottleneck in httpd. I need help to address capacity issues on max parallel and ra... |
| Kevin Neff | Patching a SSH 'Weakness' |
| Jarek Poplawski | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Jiri Olsa | [PATCH] net: fix race in the receive/select |
| Arnaldo Carvalho de Melo | Re: [PATCH 03/37] dccp: List management for new feature negotiation |
| Eric Dumazet | Re: [PATCH] tcp: splice as many packets as possible at once |
