aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/rds/ib.c1
-rw-r--r--net/rds/ib_rdma.c24
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)
116static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) 117static 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
131int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr) 139int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)