Skip to content

Commit 91cc3bb

Browse files
Eric Dumazetdavem330
authored andcommitted
xfrm6_tunnel: RCU conversion
xfrm6_tunnels use one rwlock to protect their hash tables. Plain and straightforward conversion to RCU locking to permit better SMP performance. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4543c10 commit 91cc3bb

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

net/ipv6/xfrm6_tunnel.c

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
#include <linux/module.h>
2525
#include <linux/xfrm.h>
26-
#include <linux/list.h>
26+
#include <linux/rculist.h>
2727
#include <net/ip.h>
2828
#include <net/xfrm.h>
2929
#include <net/ipv6.h>
@@ -36,14 +36,15 @@
3636
* per xfrm_address_t.
3737
*/
3838
struct xfrm6_tunnel_spi {
39-
struct hlist_node list_byaddr;
40-
struct hlist_node list_byspi;
41-
xfrm_address_t addr;
42-
u32 spi;
43-
atomic_t refcnt;
39+
struct hlist_node list_byaddr;
40+
struct hlist_node list_byspi;
41+
xfrm_address_t addr;
42+
u32 spi;
43+
atomic_t refcnt;
44+
struct rcu_head rcu_head;
4445
};
4546

46-
static DEFINE_RWLOCK(xfrm6_tunnel_spi_lock);
47+
static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock);
4748

4849
static u32 xfrm6_tunnel_spi;
4950

@@ -107,6 +108,7 @@ static void xfrm6_tunnel_spi_fini(void)
107108
if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i]))
108109
return;
109110
}
111+
rcu_barrier();
110112
kmem_cache_destroy(xfrm6_tunnel_spi_kmem);
111113
xfrm6_tunnel_spi_kmem = NULL;
112114
}
@@ -116,7 +118,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
116118
struct xfrm6_tunnel_spi *x6spi;
117119
struct hlist_node *pos;
118120

119-
hlist_for_each_entry(x6spi, pos,
121+
hlist_for_each_entry_rcu(x6spi, pos,
120122
&xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
121123
list_byaddr) {
122124
if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0)
@@ -131,10 +133,10 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
131133
struct xfrm6_tunnel_spi *x6spi;
132134
u32 spi;
133135

134-
read_lock_bh(&xfrm6_tunnel_spi_lock);
136+
rcu_read_lock_bh();
135137
x6spi = __xfrm6_tunnel_spi_lookup(saddr);
136138
spi = x6spi ? x6spi->spi : 0;
137-
read_unlock_bh(&xfrm6_tunnel_spi_lock);
139+
rcu_read_unlock_bh();
138140
return htonl(spi);
139141
}
140142

@@ -185,14 +187,15 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
185187
if (!x6spi)
186188
goto out;
187189

190+
INIT_RCU_HEAD(&x6spi->rcu_head);
188191
memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
189192
x6spi->spi = spi;
190193
atomic_set(&x6spi->refcnt, 1);
191194

192-
hlist_add_head(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]);
195+
hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]);
193196

194197
index = xfrm6_tunnel_spi_hash_byaddr(saddr);
195-
hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]);
198+
hlist_add_head_rcu(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]);
196199
out:
197200
return spi;
198201
}
@@ -202,41 +205,47 @@ __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
202205
struct xfrm6_tunnel_spi *x6spi;
203206
u32 spi;
204207

205-
write_lock_bh(&xfrm6_tunnel_spi_lock);
208+
spin_lock_bh(&xfrm6_tunnel_spi_lock);
206209
x6spi = __xfrm6_tunnel_spi_lookup(saddr);
207210
if (x6spi) {
208211
atomic_inc(&x6spi->refcnt);
209212
spi = x6spi->spi;
210213
} else
211214
spi = __xfrm6_tunnel_alloc_spi(saddr);
212-
write_unlock_bh(&xfrm6_tunnel_spi_lock);
215+
spin_unlock_bh(&xfrm6_tunnel_spi_lock);
213216

214217
return htonl(spi);
215218
}
216219

217220
EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);
218221

222+
static void x6spi_destroy_rcu(struct rcu_head *head)
223+
{
224+
kmem_cache_free(xfrm6_tunnel_spi_kmem,
225+
container_of(head, struct xfrm6_tunnel_spi, rcu_head));
226+
}
227+
219228
void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
220229
{
221230
struct xfrm6_tunnel_spi *x6spi;
222231
struct hlist_node *pos, *n;
223232

224-
write_lock_bh(&xfrm6_tunnel_spi_lock);
233+
spin_lock_bh(&xfrm6_tunnel_spi_lock);
225234

226235
hlist_for_each_entry_safe(x6spi, pos, n,
227236
&xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
228237
list_byaddr)
229238
{
230239
if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
231240
if (atomic_dec_and_test(&x6spi->refcnt)) {
232-
hlist_del(&x6spi->list_byaddr);
233-
hlist_del(&x6spi->list_byspi);
234-
kmem_cache_free(xfrm6_tunnel_spi_kmem, x6spi);
241+
hlist_del_rcu(&x6spi->list_byaddr);
242+
hlist_del_rcu(&x6spi->list_byspi);
243+
call_rcu(&x6spi->rcu_head, x6spi_destroy_rcu);
235244
break;
236245
}
237246
}
238247
}
239-
write_unlock_bh(&xfrm6_tunnel_spi_lock);
248+
spin_unlock_bh(&xfrm6_tunnel_spi_lock);
240249
}
241250

242251
EXPORT_SYMBOL(xfrm6_tunnel_free_spi);

0 commit comments

Comments
 (0)