@@ -107,6 +107,9 @@ static void __net_exit tipc_exit_net(str
tipc_bcast_stop(net);
tipc_nametbl_stop(net);
tipc_sk_rht_destroy(net);
+
+ while (atomic_read(&tn->wq_count))
+ cond_resched();
}
static struct pernet_operations tipc_net_ops = {
@@ -143,6 +143,8 @@ struct tipc_net {
/* Work item for net finalize */
struct tipc_net_work final_work;
+ /* The numbers of work queues in schedule */
+ atomic_t wq_count;
};
static inline struct tipc_net *tipc_net(struct net *net)
@@ -802,6 +802,7 @@ static void cleanup_bearer(struct work_s
kfree_rcu(rcast, rcu);
}
+ atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
dst_cache_destroy(&ub->rcast.dst_cache);
udp_tunnel_sock_release(ub->ubsock);
synchronize_net();
@@ -822,6 +823,7 @@ static void tipc_udp_disable(struct tipc
RCU_INIT_POINTER(ub->bearer, NULL);
/* sock_release need to be done outside of rtnl lock */
+ atomic_inc(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
INIT_WORK(&ub->work, cleanup_bearer);
schedule_work(&ub->work);
}