aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/attribute_container.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-08-28 10:13:17 -0400
committerJames Bottomley <jejb@titanic.(none)>2005-08-30 23:44:32 -0400
commit2b7d6a8cb9718fc1d9e826201b64909c44a915f4 (patch)
treead08bea9651332c41192cd7e019692a1e1e103bf /drivers/base/attribute_container.c
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>
Diffstat (limited to 'drivers/base/attribute_container.c')
-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 6c0f49340eb2..373e7b728fa7 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -27,6 +27,21 @@ struct internal_container {
27 struct class_device classdev; 27 struct class_device classdev;
28}; 28};
29 29
30static void internal_container_klist_get(struct klist_node *n)
31{
32 struct internal_container *ic =
33 container_of(n, struct internal_container, node);
34 class_device_get(&ic->classdev);
35}
36
37static void internal_container_klist_put(struct klist_node *n)
38{
39 struct internal_container *ic =
40 container_of(n, struct internal_container, node);
41 class_device_put(&ic->classdev);
42}
43
44
30/** 45/**
31 * attribute_container_classdev_to_container - given a classdev, return the container 46 * attribute_container_classdev_to_container - given a classdev, return the container
32 * 47 *
@@ -57,7 +72,8 @@ int
57attribute_container_register(struct attribute_container *cont) 72attribute_container_register(struct attribute_container *cont)
58{ 73{
59 INIT_LIST_HEAD(&cont->node); 74 INIT_LIST_HEAD(&cont->node);
60 klist_init(&cont->containers); 75 klist_init(&cont->containers,internal_container_klist_get,
76 internal_container_klist_put);
61 77
62 down(&attribute_container_mutex); 78 down(&attribute_container_mutex);
63 list_add_tail(&cont->node, &attribute_container_list); 79 list_add_tail(&cont->node, &attribute_container_list);
@@ -163,8 +179,8 @@ attribute_container_add_device(struct device *dev,
163#define klist_for_each_entry(pos, head, member, iter) \ 179#define klist_for_each_entry(pos, head, member, iter) \
164 for (klist_iter_init(head, iter); (pos = ({ \ 180 for (klist_iter_init(head, iter); (pos = ({ \
165 struct klist_node *n = klist_next(iter); \ 181 struct klist_node *n = klist_next(iter); \
166 n ? ({ klist_iter_exit(iter) ; NULL; }) : \ 182 n ? container_of(n, typeof(*pos), member) : \
167 container_of(n, typeof(*pos), member);\ 183 ({ klist_iter_exit(iter) ; NULL; }); \
168 }) ) != NULL; ) 184 }) ) != NULL; )
169 185
170 186
@@ -206,7 +222,7 @@ attribute_container_remove_device(struct device *dev,
206 klist_for_each_entry(ic, &cont->containers, node, &iter) { 222 klist_for_each_entry(ic, &cont->containers, node, &iter) {
207 if (dev != ic->classdev.dev) 223 if (dev != ic->classdev.dev)
208 continue; 224 continue;
209 klist_remove(&ic->node); 225 klist_del(&ic->node);
210 if (fn) 226 if (fn)
211 fn(cont, dev, &ic->classdev); 227 fn(cont, dev, &ic->classdev);
212 else { 228 else {