Skip to content

Commit

Permalink
[SCSI] attribute container final klist fixes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Bottomley authored and James Bottomley committed Aug 31, 2005
1 parent 53c165e commit 2b7d6a8
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions drivers/base/attribute_container.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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; )


Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 2b7d6a8

Please sign in to comment.