This patch moves create/destroy of laundry_wq from nfs4_state_start and nfs4_state_shutdown_net to init_nfsd and exit_nfsd to prevent the laundromat from being freed while a thread is processing a conflicting lock. Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> --- fs/nfsd/nfs4state.c | 15 ++------------- fs/nfsd/nfsctl.c | 6 ++++++ fs/nfsd/nfsd.h | 1 + 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b08c132648b9..b70ba2eb5665 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -125,7 +125,7 @@ static void free_session(struct nfsd4_session *); static const struct nfsd4_callback_ops nfsd4_cb_recall_ops; static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops; -static struct workqueue_struct *laundry_wq; +struct workqueue_struct *laundry_wq; static bool is_session_dead(struct nfsd4_session *ses) { @@ -7798,22 +7798,12 @@ nfs4_state_start(void) { int ret; - laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4"); - if (laundry_wq == NULL) { - ret = -ENOMEM; - goto out; - } ret = nfsd4_create_callback_queue(); if (ret) - goto out_free_laundry; + return ret; set_max_delegations(); return 0; - -out_free_laundry: - destroy_workqueue(laundry_wq); -out: - return ret; } void @@ -7850,7 +7840,6 @@ nfs4_state_shutdown_net(struct net *net) void nfs4_state_shutdown(void) { - destroy_workqueue(laundry_wq); nfsd4_destroy_callback_queue(); } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 16920e4512bd..884e873b46ad 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1544,6 +1544,11 @@ static int __init init_nfsd(void) retval = register_cld_notifier(); if (retval) goto out_free_all; + laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4"); + if (laundry_wq == NULL) { + retval = -ENOMEM; + goto out_free_all; + } return 0; out_free_all: unregister_pernet_subsys(&nfsd_net_ops); @@ -1566,6 +1571,7 @@ static int __init init_nfsd(void) static void __exit exit_nfsd(void) { + destroy_workqueue(laundry_wq); unregister_cld_notifier(); unregister_pernet_subsys(&nfsd_net_ops); nfsd_drc_slab_free(); diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 23996c6ca75e..d41dcf1c4312 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -72,6 +72,7 @@ extern unsigned long nfsd_drc_max_mem; extern unsigned long nfsd_drc_mem_used; extern const struct seq_operations nfs_exports_op; +extern struct workqueue_struct *laundry_wq; /* * Common void argument and result helpers -- 2.9.5