Skip to content

Commit 8b448f0

Browse files
author
Paolo Abeni
committed
Merge branch 'phonet-convert-all-doit-and-dumpit-to-rcu'
Kuniyuki Iwashima says: ==================== phonet: Convert all doit() and dumpit() to RCU. addr_doit() and route_doit() access only phonet_device_list(dev_net(dev)) and phonet_pernet(dev_net(dev))->routes, respectively. Each per-netns struct has its dedicated mutex, and RTNL also protects the structs. __dev_change_net_namespace() has synchronize_net(), so we have two options to convert addr_doit() and route_doit(). 1. Use per-netns RTNL 2. Use RCU and convert each struct mutex to spinlock_t As RCU is preferable, this series converts all PF_PHONET's doit() and dumpit() to RCU. 4 doit()s and 1 dumpit() are now converted to RCU, 70 doit()s and 28 dumpit()s are still under RTNL. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 1bf70e6 + 17a1ac0 commit 8b448f0

File tree

3 files changed

+120
-72
lines changed

3 files changed

+120
-72
lines changed

include/net/phonet/pn_dev.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
#define PN_DEV_H
1212

1313
#include <linux/list.h>
14-
#include <linux/mutex.h>
14+
#include <linux/spinlock.h>
1515

1616
struct net;
1717

1818
struct phonet_device_list {
1919
struct list_head list;
20-
struct mutex lock;
20+
spinlock_t lock;
2121
};
2222

2323
struct phonet_device_list *phonet_device_list(struct net *net);
@@ -38,11 +38,11 @@ int phonet_address_add(struct net_device *dev, u8 addr);
3838
int phonet_address_del(struct net_device *dev, u8 addr);
3939
u8 phonet_address_get(struct net_device *dev, u8 addr);
4040
int phonet_address_lookup(struct net *net, u8 addr);
41-
void phonet_address_notify(int event, struct net_device *dev, u8 addr);
41+
void phonet_address_notify(struct net *net, int event, u32 ifindex, u8 addr);
4242

4343
int phonet_route_add(struct net_device *dev, u8 daddr);
4444
int phonet_route_del(struct net_device *dev, u8 daddr);
45-
void rtm_phonet_notify(int event, struct net_device *dev, u8 dst);
45+
void rtm_phonet_notify(struct net *net, int event, u32 ifindex, u8 dst);
4646
struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr);
4747
struct net_device *phonet_route_output(struct net *net, u8 daddr);
4848

net/phonet/pn_dev.c

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <net/phonet/pn_dev.h>
2323

2424
struct phonet_routes {
25-
struct mutex lock;
25+
spinlock_t lock;
2626
struct net_device __rcu *table[64];
2727
};
2828

@@ -54,7 +54,7 @@ static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
5454
pnd->netdev = dev;
5555
bitmap_zero(pnd->addrs, 64);
5656

57-
BUG_ON(!mutex_is_locked(&pndevs->lock));
57+
lockdep_assert_held(&pndevs->lock);
5858
list_add_rcu(&pnd->list, &pndevs->list);
5959
return pnd;
6060
}
@@ -64,7 +64,8 @@ static struct phonet_device *__phonet_get(struct net_device *dev)
6464
struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
6565
struct phonet_device *pnd;
6666

67-
BUG_ON(!mutex_is_locked(&pndevs->lock));
67+
lockdep_assert_held(&pndevs->lock);
68+
6869
list_for_each_entry(pnd, &pndevs->list, list) {
6970
if (pnd->netdev == dev)
7071
return pnd;
@@ -91,17 +92,22 @@ static void phonet_device_destroy(struct net_device *dev)
9192

9293
ASSERT_RTNL();
9394

94-
mutex_lock(&pndevs->lock);
95+
spin_lock(&pndevs->lock);
96+
9597
pnd = __phonet_get(dev);
9698
if (pnd)
9799
list_del_rcu(&pnd->list);
98-
mutex_unlock(&pndevs->lock);
100+
101+
spin_unlock(&pndevs->lock);
99102

100103
if (pnd) {
104+
struct net *net = dev_net(dev);
105+
u32 ifindex = dev->ifindex;
101106
u8 addr;
102107

103108
for_each_set_bit(addr, pnd->addrs, 64)
104-
phonet_address_notify(RTM_DELADDR, dev, addr);
109+
phonet_address_notify(net, RTM_DELADDR, ifindex, addr);
110+
105111
kfree(pnd);
106112
}
107113
}
@@ -133,7 +139,8 @@ int phonet_address_add(struct net_device *dev, u8 addr)
133139
struct phonet_device *pnd;
134140
int err = 0;
135141

136-
mutex_lock(&pndevs->lock);
142+
spin_lock(&pndevs->lock);
143+
137144
/* Find or create Phonet-specific device data */
138145
pnd = __phonet_get(dev);
139146
if (pnd == NULL)
@@ -142,7 +149,9 @@ int phonet_address_add(struct net_device *dev, u8 addr)
142149
err = -ENOMEM;
143150
else if (test_and_set_bit(addr >> 2, pnd->addrs))
144151
err = -EEXIST;
145-
mutex_unlock(&pndevs->lock);
152+
153+
spin_unlock(&pndevs->lock);
154+
146155
return err;
147156
}
148157

@@ -152,7 +161,8 @@ int phonet_address_del(struct net_device *dev, u8 addr)
152161
struct phonet_device *pnd;
153162
int err = 0;
154163

155-
mutex_lock(&pndevs->lock);
164+
spin_lock(&pndevs->lock);
165+
156166
pnd = __phonet_get(dev);
157167
if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) {
158168
err = -EADDRNOTAVAIL;
@@ -161,7 +171,8 @@ int phonet_address_del(struct net_device *dev, u8 addr)
161171
list_del_rcu(&pnd->list);
162172
else
163173
pnd = NULL;
164-
mutex_unlock(&pndevs->lock);
174+
175+
spin_unlock(&pndevs->lock);
165176

166177
if (pnd)
167178
kfree_rcu(pnd, rcu);
@@ -244,32 +255,39 @@ static int phonet_device_autoconf(struct net_device *dev)
244255
ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device);
245256
if (ret)
246257
return ret;
247-
phonet_address_notify(RTM_NEWADDR, dev,
248-
req.ifr_phonet_autoconf.device);
258+
259+
phonet_address_notify(dev_net(dev), RTM_NEWADDR, dev->ifindex,
260+
req.ifr_phonet_autoconf.device);
249261
return 0;
250262
}
251263

252264
static void phonet_route_autodel(struct net_device *dev)
253265
{
254-
struct phonet_net *pnn = phonet_pernet(dev_net(dev));
255-
unsigned int i;
266+
struct net *net = dev_net(dev);
256267
DECLARE_BITMAP(deleted, 64);
268+
u32 ifindex = dev->ifindex;
269+
struct phonet_net *pnn;
270+
unsigned int i;
271+
272+
pnn = phonet_pernet(net);
257273

258274
/* Remove left-over Phonet routes */
259275
bitmap_zero(deleted, 64);
260-
mutex_lock(&pnn->routes.lock);
261-
for (i = 0; i < 64; i++)
276+
277+
spin_lock(&pnn->routes.lock);
278+
for (i = 0; i < 64; i++) {
262279
if (rcu_access_pointer(pnn->routes.table[i]) == dev) {
263280
RCU_INIT_POINTER(pnn->routes.table[i], NULL);
264281
set_bit(i, deleted);
265282
}
266-
mutex_unlock(&pnn->routes.lock);
283+
}
284+
spin_unlock(&pnn->routes.lock);
267285

268286
if (bitmap_empty(deleted, 64))
269287
return; /* short-circuit RCU */
270288
synchronize_rcu();
271289
for_each_set_bit(i, deleted, 64) {
272-
rtm_phonet_notify(RTM_DELROUTE, dev, i);
290+
rtm_phonet_notify(net, RTM_DELROUTE, ifindex, i);
273291
dev_put(dev);
274292
}
275293
}
@@ -309,8 +327,8 @@ static int __net_init phonet_init_net(struct net *net)
309327
return -ENOMEM;
310328

311329
INIT_LIST_HEAD(&pnn->pndevs.list);
312-
mutex_init(&pnn->pndevs.lock);
313-
mutex_init(&pnn->routes.lock);
330+
spin_lock_init(&pnn->pndevs.lock);
331+
spin_lock_init(&pnn->routes.lock);
314332
return 0;
315333
}
316334

@@ -360,13 +378,15 @@ int phonet_route_add(struct net_device *dev, u8 daddr)
360378
int err = -EEXIST;
361379

362380
daddr = daddr >> 2;
363-
mutex_lock(&routes->lock);
381+
382+
spin_lock(&routes->lock);
364383
if (routes->table[daddr] == NULL) {
365384
rcu_assign_pointer(routes->table[daddr], dev);
366385
dev_hold(dev);
367386
err = 0;
368387
}
369-
mutex_unlock(&routes->lock);
388+
spin_unlock(&routes->lock);
389+
370390
return err;
371391
}
372392

@@ -376,12 +396,13 @@ int phonet_route_del(struct net_device *dev, u8 daddr)
376396
struct phonet_routes *routes = &pnn->routes;
377397

378398
daddr = daddr >> 2;
379-
mutex_lock(&routes->lock);
399+
400+
spin_lock(&routes->lock);
380401
if (rcu_access_pointer(routes->table[daddr]) == dev)
381402
RCU_INIT_POINTER(routes->table[daddr], NULL);
382403
else
383404
dev = NULL;
384-
mutex_unlock(&routes->lock);
405+
spin_unlock(&routes->lock);
385406

386407
if (!dev)
387408
return -ENOENT;

0 commit comments

Comments
 (0)