diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/inet_fragment.c | 19 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 14 |
2 files changed, 16 insertions, 17 deletions
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 5c25727d491e..d666756be5f1 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -145,10 +145,9 @@ static void inet_frags_free_cb(void *ptr, void *arg) inet_frag_destroy(fq); } -static void fqdir_rwork_fn(struct work_struct *work) +static void fqdir_work_fn(struct work_struct *work) { - struct fqdir *fqdir = container_of(to_rcu_work(work), - struct fqdir, destroy_rwork); + struct fqdir *fqdir = container_of(work, struct fqdir, destroy_work); struct inet_frags *f = fqdir->f; rhashtable_free_and_destroy(&fqdir->rhashtable, inet_frags_free_cb, NULL); @@ -187,18 +186,8 @@ EXPORT_SYMBOL(fqdir_init); void fqdir_exit(struct fqdir *fqdir) { - fqdir->high_thresh = 0; /* prevent creation of new frags */ - - fqdir->dead = true; - - /* call_rcu is supposed to provide memory barrier semantics, - * separating the setting of fqdir->dead with the destruction - * work. This implicit barrier is paired with inet_frag_kill(). - */ - - INIT_RCU_WORK(&fqdir->destroy_rwork, fqdir_rwork_fn); - queue_rcu_work(system_wq, &fqdir->destroy_rwork); - + INIT_WORK(&fqdir->destroy_work, fqdir_work_fn); + queue_work(system_wq, &fqdir->destroy_work); } EXPORT_SYMBOL(fqdir_exit); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 1ffaec056821..4385eb9e781f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -143,6 +143,10 @@ static void ip_expire(struct timer_list *t) net = qp->q.fqdir->net; rcu_read_lock(); + + if (qp->q.fqdir->dead) + goto out_rcu_unlock; + spin_lock(&qp->q.lock); if (qp->q.flags & INET_FRAG_COMPLETE) @@ -676,6 +680,11 @@ static int __net_init ipv4_frags_init_net(struct net *net) return res; } +static void __net_exit ipv4_frags_pre_exit_net(struct net *net) +{ + fqdir_pre_exit(net->ipv4.fqdir); +} + static void __net_exit ipv4_frags_exit_net(struct net *net) { ip4_frags_ns_ctl_unregister(net); @@ -683,8 +692,9 @@ static void __net_exit ipv4_frags_exit_net(struct net *net) } static struct pernet_operations ip4_frags_ops = { - .init = ipv4_frags_init_net, - .exit = ipv4_frags_exit_net, + .init = ipv4_frags_init_net, + .pre_exit = ipv4_frags_pre_exit_net, + .exit = ipv4_frags_exit_net, }; |