Skip to content

Commit 707693c

Browse files
herbertxdavem330
authored andcommitted
netlink: Call cb->done from a worker thread
The cb->done interface expects to be called in process context. This was broken by the netlink RCU conversion. This patch fixes it by adding a worker struct to make the cb->done call where necessary. Fixes: 21e4902 ("netlink: Lockless lookup with RCU grace...") Reported-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 95c2027 commit 707693c

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

net/netlink/af_netlink.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,11 @@ static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
322322
sk_mem_charge(sk, skb->truesize);
323323
}
324324

325-
static void netlink_sock_destruct(struct sock *sk)
325+
static void __netlink_sock_destruct(struct sock *sk)
326326
{
327327
struct netlink_sock *nlk = nlk_sk(sk);
328328

329329
if (nlk->cb_running) {
330-
if (nlk->cb.done)
331-
nlk->cb.done(&nlk->cb);
332-
333330
module_put(nlk->cb.module);
334331
kfree_skb(nlk->cb.skb);
335332
}
@@ -346,6 +343,28 @@ static void netlink_sock_destruct(struct sock *sk)
346343
WARN_ON(nlk_sk(sk)->groups);
347344
}
348345

346+
static void netlink_sock_destruct_work(struct work_struct *work)
347+
{
348+
struct netlink_sock *nlk = container_of(work, struct netlink_sock,
349+
work);
350+
351+
nlk->cb.done(&nlk->cb);
352+
__netlink_sock_destruct(&nlk->sk);
353+
}
354+
355+
static void netlink_sock_destruct(struct sock *sk)
356+
{
357+
struct netlink_sock *nlk = nlk_sk(sk);
358+
359+
if (nlk->cb_running && nlk->cb.done) {
360+
INIT_WORK(&nlk->work, netlink_sock_destruct_work);
361+
schedule_work(&nlk->work);
362+
return;
363+
}
364+
365+
__netlink_sock_destruct(sk);
366+
}
367+
349368
/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
350369
* SMP. Look, when several writers sleep and reader wakes them up, all but one
351370
* immediately hit write lock and grab all the cpus. Exclusive sleep solves

net/netlink/af_netlink.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <linux/rhashtable.h>
55
#include <linux/atomic.h>
6+
#include <linux/workqueue.h>
67
#include <net/sock.h>
78

89
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
@@ -33,6 +34,7 @@ struct netlink_sock {
3334

3435
struct rhash_head node;
3536
struct rcu_head rcu;
37+
struct work_struct work;
3638
};
3739

3840
static inline struct netlink_sock *nlk_sk(struct sock *sk)

0 commit comments

Comments
 (0)