nfs41: renewd sequence operations should take/put client reference
authorAlexandros Batsakis <batsakis@netapp.com>
Fri, 5 Feb 2010 11:45:05 +0000 (03:45 -0800)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 2 Mar 2010 17:54:30 +0000 (12:54 -0500)
renewd sends SEQUENCE requests to the NFS server in order to renew state.
As the request is asynchronous, renewd should take a reference to the
nfs_client to prevent concurrent umounts from freeing the session/client

Signed-off-by: Alexandros Batsakis <batsakis@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c

index 726bc19..663ae0c 100644 (file)
@@ -419,7 +419,8 @@ static void nfs41_sequence_done(struct nfs_client *clp,
                        clp->cl_last_renewal = timestamp;
                spin_unlock(&clp->cl_lock);
                /* Check sequence flags */
-               nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
+               if (atomic_read(&clp->cl_count) > 1)
+                       nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
        }
 out:
        /* The session may be reset by one of the error handlers. */
@@ -5035,7 +5036,9 @@ static void nfs41_sequence_release(void *data)
 {
        struct nfs_client *clp = (struct nfs_client *)data;
 
-       nfs4_schedule_state_renewal(clp);
+       if (atomic_read(&clp->cl_count) > 1)
+               nfs4_schedule_state_renewal(clp);
+       nfs_put_client(clp);
 }
 
 static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
@@ -5046,6 +5049,8 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 
        if (task->tk_status < 0) {
                dprintk("%s ERROR %d\n", __func__, task->tk_status);
+               if (atomic_read(&clp->cl_count) == 1)
+                       goto out;
 
                if (_nfs4_async_handle_error(task, NULL, clp, NULL)
                                                                == -EAGAIN) {
@@ -5054,7 +5059,7 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
                }
        }
        dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
-
+out:
        kfree(task->tk_msg.rpc_argp);
        kfree(task->tk_msg.rpc_resp);
 
@@ -5092,12 +5097,13 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
                .rpc_cred = cred,
        };
 
+       if (!atomic_inc_not_zero(&clp->cl_count))
+               return -EIO;
        args = kzalloc(sizeof(*args), GFP_KERNEL);
-       if (!args)
-               return -ENOMEM;
        res = kzalloc(sizeof(*res), GFP_KERNEL);
-       if (!res) {
+       if (!args || !res) {
                kfree(args);
+               nfs_put_client(clp);
                return -ENOMEM;
        }
        res->sr_slotid = NFS4_MAX_SLOT_TABLE;