NFSD: move create/destroy of laundry_wq to init_nfsd and exit_nfsd
authorDai Ngo <dai.ngo@oracle.com>
Mon, 2 May 2022 21:19:23 +0000 (14:19 -0700)
committerChuck Lever <chuck.lever@oracle.com>
Thu, 19 May 2022 16:25:39 +0000 (12:25 -0400)
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.

Reviewed-by: J. Bruce Fields <bfields@fieldses.org>
Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h

index fe7949683c01befd716d38902ff7091e6befa1dc..76c98ab7991b5066a43fc67bc43fad53995883c8 100644 (file)
@@ -127,6 +127,21 @@ static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
 
 static struct workqueue_struct *laundry_wq;
 
+int nfsd4_create_laundry_wq(void)
+{
+       int rc = 0;
+
+       laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
+       if (laundry_wq == NULL)
+               rc = -ENOMEM;
+       return rc;
+}
+
+void nfsd4_destroy_laundry_wq(void)
+{
+       destroy_workqueue(laundry_wq);
+}
+
 static bool is_session_dead(struct nfsd4_session *ses)
 {
        return ses->se_flags & NFS4_SESSION_DEAD;
@@ -7747,22 +7762,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
@@ -7799,7 +7804,6 @@ nfs4_state_shutdown_net(struct net *net)
 void
 nfs4_state_shutdown(void)
 {
-       destroy_workqueue(laundry_wq);
        nfsd4_destroy_callback_queue();
 }
 
index 16920e4512bde9446c97bcbedc3167063ec0cc92..322a208878f2c23f306bb60ce38e756a19890494 100644 (file)
@@ -1542,6 +1542,9 @@ static int __init init_nfsd(void)
        if (retval < 0)
                goto out_free_filesystem;
        retval = register_cld_notifier();
+       if (retval)
+               goto out_free_all;
+       retval = nfsd4_create_laundry_wq();
        if (retval)
                goto out_free_all;
        return 0;
@@ -1566,6 +1569,7 @@ out_free_slabs:
 
 static void __exit exit_nfsd(void)
 {
+       nfsd4_destroy_laundry_wq();
        unregister_cld_notifier();
        unregister_pernet_subsys(&nfsd_net_ops);
        nfsd_drc_slab_free();
index 23996c6ca75e3b01ea6f75dff0b32df3576876ca..847b482155ae97cfdaa5e7eaaccb3d87741c152d 100644 (file)
@@ -162,6 +162,8 @@ void nfs4_state_shutdown_net(struct net *net);
 int nfs4_reset_recoverydir(char *recdir);
 char * nfs4_recoverydir(void);
 bool nfsd4_spo_must_allow(struct svc_rqst *rqstp);
+int nfsd4_create_laundry_wq(void);
+void nfsd4_destroy_laundry_wq(void);
 #else
 static inline int nfsd4_init_slabs(void) { return 0; }
 static inline void nfsd4_free_slabs(void) { }
@@ -175,6 +177,8 @@ static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
 {
        return false;
 }
+static inline int nfsd4_create_laundry_wq(void) { return 0; };
+static inline void nfsd4_destroy_laundry_wq(void) {};
 #endif
 
 /*