diff options
-rw-r--r-- | net/rds/ib.c | 1 | ||||
-rw-r--r-- | net/rds/ib_rdma.c | 24 |
2 files changed, 17 insertions, 8 deletions
diff --git a/net/rds/ib.c b/net/rds/ib.c index 927c481b5245..7a2131d37dfb 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c | |||
@@ -137,6 +137,7 @@ void rds_ib_remove_one(struct ib_device *device) | |||
137 | if (!rds_ibdev) | 137 | if (!rds_ibdev) |
138 | return; | 138 | return; |
139 | 139 | ||
140 | synchronize_rcu(); | ||
140 | list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) { | 141 | list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) { |
141 | list_del(&i_ipaddr->list); | 142 | list_del(&i_ipaddr->list); |
142 | kfree(i_ipaddr); | 143 | kfree(i_ipaddr); |
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 242231f09464..7240e583ee58 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/rculist.h> | ||
35 | 36 | ||
36 | #include "rds.h" | 37 | #include "rds.h" |
37 | #include "ib.h" | 38 | #include "ib.h" |
@@ -83,14 +84,14 @@ static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr) | |||
83 | struct rds_ib_ipaddr *i_ipaddr; | 84 | struct rds_ib_ipaddr *i_ipaddr; |
84 | 85 | ||
85 | list_for_each_entry(rds_ibdev, &rds_ib_devices, list) { | 86 | list_for_each_entry(rds_ibdev, &rds_ib_devices, list) { |
86 | spin_lock_irq(&rds_ibdev->spinlock); | 87 | rcu_read_lock(); |
87 | list_for_each_entry(i_ipaddr, &rds_ibdev->ipaddr_list, list) { | 88 | list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) { |
88 | if (i_ipaddr->ipaddr == ipaddr) { | 89 | if (i_ipaddr->ipaddr == ipaddr) { |
89 | spin_unlock_irq(&rds_ibdev->spinlock); | 90 | rcu_read_unlock(); |
90 | return rds_ibdev; | 91 | return rds_ibdev; |
91 | } | 92 | } |
92 | } | 93 | } |
93 | spin_unlock_irq(&rds_ibdev->spinlock); | 94 | rcu_read_unlock(); |
94 | } | 95 | } |
95 | 96 | ||
96 | return NULL; | 97 | return NULL; |
@@ -107,7 +108,7 @@ static int rds_ib_add_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) | |||
107 | i_ipaddr->ipaddr = ipaddr; | 108 | i_ipaddr->ipaddr = ipaddr; |
108 | 109 | ||
109 | spin_lock_irq(&rds_ibdev->spinlock); | 110 | spin_lock_irq(&rds_ibdev->spinlock); |
110 | list_add_tail(&i_ipaddr->list, &rds_ibdev->ipaddr_list); | 111 | list_add_tail_rcu(&i_ipaddr->list, &rds_ibdev->ipaddr_list); |
111 | spin_unlock_irq(&rds_ibdev->spinlock); | 112 | spin_unlock_irq(&rds_ibdev->spinlock); |
112 | 113 | ||
113 | return 0; | 114 | return 0; |
@@ -116,16 +117,23 @@ static int rds_ib_add_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) | |||
116 | static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) | 117 | static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) |
117 | { | 118 | { |
118 | struct rds_ib_ipaddr *i_ipaddr, *next; | 119 | struct rds_ib_ipaddr *i_ipaddr, *next; |
120 | struct rds_ib_ipaddr *to_free = NULL; | ||
121 | |||
119 | 122 | ||
120 | spin_lock_irq(&rds_ibdev->spinlock); | 123 | spin_lock_irq(&rds_ibdev->spinlock); |
121 | list_for_each_entry_safe(i_ipaddr, next, &rds_ibdev->ipaddr_list, list) { | 124 | list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) { |
122 | if (i_ipaddr->ipaddr == ipaddr) { | 125 | if (i_ipaddr->ipaddr == ipaddr) { |
123 | list_del(&i_ipaddr->list); | 126 | list_del_rcu(&i_ipaddr->list); |
124 | kfree(i_ipaddr); | 127 | to_free = i_ipaddr; |
125 | break; | 128 | break; |
126 | } | 129 | } |
127 | } | 130 | } |
128 | spin_unlock_irq(&rds_ibdev->spinlock); | 131 | spin_unlock_irq(&rds_ibdev->spinlock); |
132 | |||
133 | if (to_free) { | ||
134 | synchronize_rcu(); | ||
135 | kfree(to_free); | ||
136 | } | ||
129 | } | 137 | } |
130 | 138 | ||
131 | int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) | 139 | int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) |