NFSv4.x: Fix up the global tracking of the callback server
authorTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 30 Aug 2016 00:03:50 +0000 (20:03 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 19 Sep 2016 17:08:36 +0000 (13:08 -0400)
Ensure that the nfs_callback_info[] array correctly tracks the
struct svc_serv.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/callback.c

index 08e16f9b333363a884a626485226a9c63566412f..b125f02ddf8bbade22d762d88855682ce84261fb 100644 (file)
@@ -201,7 +201,6 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
 
        svc_sock_update_bufs(serv);
 
-       cb_info->serv = serv;
        cb_info->rqst = rqstp;
        cb_info->task = kthread_create(serv->sv_ops->svo_function,
                                    cb_info->rqst,
@@ -300,7 +299,7 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)
        /*
         * Check whether we're already up and running.
         */
-       if (cb_info->task) {
+       if (cb_info->serv) {
                /*
                 * Note: increase service usage, because later in case of error
                 * svc_destroy() will be called.
@@ -333,6 +332,7 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)
                printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
                return ERR_PTR(-ENOMEM);
        }
+       cb_info->serv = serv;
        /* As there is only one thread we need to over-ride the
         * default maximum of 80 connections
         */
@@ -375,6 +375,8 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
         * thread exits.
         */
 err_net:
+       if (!cb_info->users)
+               cb_info->serv = NULL;
        svc_destroy(serv);
 err_create:
        mutex_unlock(&nfs_callback_mutex);
@@ -396,9 +398,11 @@ void nfs_callback_down(int minorversion, struct net *net)
        mutex_lock(&nfs_callback_mutex);
        nfs_callback_down_net(minorversion, cb_info->serv, net);
        cb_info->users--;
-       if (cb_info->users == 0 && cb_info->task != NULL) {
-               kthread_stop(cb_info->task);
-               dprintk("nfs_callback_down: service stopped\n");
+       if (cb_info->users == 0) {
+               if (cb_info->task != NULL) {
+                       kthread_stop(cb_info->task);
+                       dprintk("nfs_callback_down: service stopped\n");
+               }
                svc_exit_thread(cb_info->rqst);
                dprintk("nfs_callback_down: service destroyed\n");
                cb_info->serv = NULL;