aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2005-09-06 19:56:51 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 21:26:54 -0400
commit34bb61f9ddabd7a7f909cbfb05592eb775f6662a (patch)
tree06232f6fc975bd279236fd8005c7d5528220ec68 /drivers/base/core.c
parentdf4edad1787bbfa3c9c10824e4f11e9f4a7ec5c6 (diff)
[PATCH] fix klist semantics for lists which have elements removed on traversal
The problem is that klists claim to provide semantics for safe traversal of lists which are being modified. The failure case is when traversal of a list causes element removal (a fairly common case). The issue is that although the list node is refcounted, if it is embedded in an object (which is universally the case), then the object will be freed regardless of the klist refcount leading to slab corruption because the klist iterator refers to the prior element to get the next. The solution is to make the klist take and release references to the embedding object meaning that the embedding object won't be released until the list relinquishes the reference to it. (akpm: fast-track this because it's needed for the 2.6.13 scsi merge) Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index c8a33df0076..6ab73f5c799 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -191,6 +191,20 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
191 } 191 }
192} 192}
193 193
194static void klist_children_get(struct klist_node *n)
195{
196 struct device *dev = container_of(n, struct device, knode_parent);
197
198 get_device(dev);
199}
200
201static void klist_children_put(struct klist_node *n)
202{
203 struct device *dev = container_of(n, struct device, knode_parent);
204
205 put_device(dev);
206}
207
194 208
195/** 209/**
196 * device_initialize - init device structure. 210 * device_initialize - init device structure.
@@ -207,7 +221,8 @@ void device_initialize(struct device *dev)
207{ 221{
208 kobj_set_kset_s(dev, devices_subsys); 222 kobj_set_kset_s(dev, devices_subsys);
209 kobject_init(&dev->kobj); 223 kobject_init(&dev->kobj);
210 klist_init(&dev->klist_children); 224 klist_init(&dev->klist_children, klist_children_get,
225 klist_children_put);
211 INIT_LIST_HEAD(&dev->dma_pools); 226 INIT_LIST_HEAD(&dev->dma_pools);
212 init_MUTEX(&dev->sem); 227 init_MUTEX(&dev->sem);
213} 228}