diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-02-12 17:38:27 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-02-12 17:38:27 -0500 |
commit | 7c7a9bccd2ba9f17e4b588461f140578a0a7b073 (patch) | |
tree | 97a8a5e88339a5defa770c19466190b8a20c0943 /drivers/infiniband | |
parent | ab64b960673250518e748f8b4f1545447136b68b (diff) |
IB/cm: Fix infiniband_cm class kobject ref counting
Commit 9af57b7a ("IB/cm: Add basic performance counters") introduced a
bug in how the reference count for cm_class.subsys.kobj was handled:
the path that released a device did a kobject_put() on that kobject, but
there was no kobject_get() in the path the handles adding a device. So
the reference count ended up too low, which leads to bad things. Fix up
and simplify the reference counting to avoid this.
(Actually, I introduced the bug when fixing the patch up to match some
of Greg's kobject changes, but who's counting)
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/cm.c | 22 |
1 files changed, 8 insertions, 14 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 435e2767a183..b10ade92efed 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -3612,18 +3612,12 @@ struct class cm_class = { | |||
3612 | }; | 3612 | }; |
3613 | EXPORT_SYMBOL(cm_class); | 3613 | EXPORT_SYMBOL(cm_class); |
3614 | 3614 | ||
3615 | static void cm_remove_fs_obj(struct kobject *obj) | ||
3616 | { | ||
3617 | kobject_put(obj->parent); | ||
3618 | kobject_put(obj); | ||
3619 | } | ||
3620 | |||
3621 | static int cm_create_port_fs(struct cm_port *port) | 3615 | static int cm_create_port_fs(struct cm_port *port) |
3622 | { | 3616 | { |
3623 | int i, ret; | 3617 | int i, ret; |
3624 | 3618 | ||
3625 | ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type, | 3619 | ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type, |
3626 | kobject_get(&port->cm_dev->dev_obj), | 3620 | &port->cm_dev->dev_obj, |
3627 | "%d", port->port_num); | 3621 | "%d", port->port_num); |
3628 | if (ret) { | 3622 | if (ret) { |
3629 | kfree(port); | 3623 | kfree(port); |
@@ -3633,7 +3627,7 @@ static int cm_create_port_fs(struct cm_port *port) | |||
3633 | for (i = 0; i < CM_COUNTER_GROUPS; i++) { | 3627 | for (i = 0; i < CM_COUNTER_GROUPS; i++) { |
3634 | ret = kobject_init_and_add(&port->counter_group[i].obj, | 3628 | ret = kobject_init_and_add(&port->counter_group[i].obj, |
3635 | &cm_counter_obj_type, | 3629 | &cm_counter_obj_type, |
3636 | kobject_get(&port->port_obj), | 3630 | &port->port_obj, |
3637 | "%s", counter_group_names[i]); | 3631 | "%s", counter_group_names[i]); |
3638 | if (ret) | 3632 | if (ret) |
3639 | goto error; | 3633 | goto error; |
@@ -3643,8 +3637,8 @@ static int cm_create_port_fs(struct cm_port *port) | |||
3643 | 3637 | ||
3644 | error: | 3638 | error: |
3645 | while (i--) | 3639 | while (i--) |
3646 | cm_remove_fs_obj(&port->counter_group[i].obj); | 3640 | kobject_put(&port->counter_group[i].obj); |
3647 | cm_remove_fs_obj(&port->port_obj); | 3641 | kobject_put(&port->port_obj); |
3648 | return ret; | 3642 | return ret; |
3649 | 3643 | ||
3650 | } | 3644 | } |
@@ -3654,9 +3648,9 @@ static void cm_remove_port_fs(struct cm_port *port) | |||
3654 | int i; | 3648 | int i; |
3655 | 3649 | ||
3656 | for (i = 0; i < CM_COUNTER_GROUPS; i++) | 3650 | for (i = 0; i < CM_COUNTER_GROUPS; i++) |
3657 | cm_remove_fs_obj(&port->counter_group[i].obj); | 3651 | kobject_put(&port->counter_group[i].obj); |
3658 | 3652 | ||
3659 | cm_remove_fs_obj(&port->port_obj); | 3653 | kobject_put(&port->port_obj); |
3660 | } | 3654 | } |
3661 | 3655 | ||
3662 | static void cm_add_one(struct ib_device *device) | 3656 | static void cm_add_one(struct ib_device *device) |
@@ -3740,7 +3734,7 @@ error1: | |||
3740 | ib_unregister_mad_agent(port->mad_agent); | 3734 | ib_unregister_mad_agent(port->mad_agent); |
3741 | cm_remove_port_fs(port); | 3735 | cm_remove_port_fs(port); |
3742 | } | 3736 | } |
3743 | cm_remove_fs_obj(&cm_dev->dev_obj); | 3737 | kobject_put(&cm_dev->dev_obj); |
3744 | } | 3738 | } |
3745 | 3739 | ||
3746 | static void cm_remove_one(struct ib_device *device) | 3740 | static void cm_remove_one(struct ib_device *device) |
@@ -3767,7 +3761,7 @@ static void cm_remove_one(struct ib_device *device) | |||
3767 | ib_unregister_mad_agent(port->mad_agent); | 3761 | ib_unregister_mad_agent(port->mad_agent); |
3768 | cm_remove_port_fs(port); | 3762 | cm_remove_port_fs(port); |
3769 | } | 3763 | } |
3770 | cm_remove_fs_obj(&cm_dev->dev_obj); | 3764 | kobject_put(&cm_dev->dev_obj); |
3771 | } | 3765 | } |
3772 | 3766 | ||
3773 | static int __init ib_cm_init(void) | 3767 | static int __init ib_cm_init(void) |