summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-08-28 09:13:17 -0500
committerJames Bottomley <jejb@titanic.(none)>2005-08-30 22:44:32 -0500
commit2b7d6a8cb9718fc1d9e826201b64909c44a915f4 (patch)
treead08bea9651332c41192cd7e019692a1e1e103bf
parent53c165e0a6c8a4ff7df316557528fa7a52d20711 (diff)
[SCSI] attribute container final klist fixes
Since the attribute container deletes from a klist while it's walking it, it is vulnerable to the problem (and fix) here: http://marc.theaimsgroup.com/?l=linux-scsi&m=112485448830217 The attached fixes this (but won't compile without the above). It also fixes the logical reversal in the traversal loop which meant that we were never actually traversing the loop to hit this bug in the first place. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/base/attribute_container.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 6c0f49340eb..373e7b728fa 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -27,6 +27,21 @@ struct internal_container {
struct class_device classdev;
};
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
/**
* attribute_container_classdev_to_container - given a classdev, return the container
*
@@ -57,7 +72,8 @@ int
attribute_container_register(struct attribute_container *cont)
{
INIT_LIST_HEAD(&cont->node);
- klist_init(&cont->containers);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
down(&attribute_container_mutex);
list_add_tail(&cont->node, &attribute_container_list);
@@ -163,8 +179,8 @@ attribute_container_add_device(struct device *dev,
#define klist_for_each_entry(pos, head, member, iter) \
for (klist_iter_init(head, iter); (pos = ({ \
struct klist_node *n = klist_next(iter); \
- n ? ({ klist_iter_exit(iter) ; NULL; }) : \
- container_of(n, typeof(*pos), member);\
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
}) ) != NULL; )
@@ -206,7 +222,7 @@ attribute_container_remove_device(struct device *dev,
klist_for_each_entry(ic, &cont->containers, node, &iter) {
if (dev != ic->classdev.dev)
continue;
- klist_remove(&ic->node);
+ klist_del(&ic->node);
if (fn)
fn(cont, dev, &ic->classdev);
else {