NFSv4: Make locku use the new RPC "wait on completion" interface.
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Jan 2006 08:55:07 +0000 (09:55 +0100)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 6 Jan 2006 19:58:40 +0000 (14:58 -0500)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c

index 368b75b3bcba6070c340eefc9f18efc1a3d230ff..c7bec4319236b63a76201c1cb38cee3368122b36 100644 (file)
@@ -206,6 +206,17 @@ static int nfs4_call_async(struct rpc_clnt *clnt,
        return 0;
 }
 
+static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
+{
+       sigset_t oldset;
+       int ret;
+
+       rpc_clnt_sigmask(task->tk_client, &oldset);
+       ret = rpc_wait_for_completion_task(task);
+       rpc_clnt_sigunmask(task->tk_client, &oldset);
+       return ret;
+}
+
 static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
 {
        struct inode *inode = state->inode;
@@ -2867,31 +2878,23 @@ struct nfs4_unlockdata {
        struct nfs_lockres res;
        struct nfs4_lock_state *lsp;
        struct nfs_open_context *ctx;
-       atomic_t refcount;
-       struct completion completion;
 };
 
-static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
-{
-       if (atomic_dec_and_test(&calldata->refcount)) {
-               nfs_free_seqid(calldata->luargs.seqid);
-               nfs4_put_lock_state(calldata->lsp);
-               put_nfs_open_context(calldata->ctx);
-               kfree(calldata);
-       }
-}
-
-static void nfs4_locku_complete(void *data)
+static void nfs4_locku_release_calldata(void *data)
 {
        struct nfs4_unlockdata *calldata = data;
-       complete(&calldata->completion);
-       nfs4_locku_release_calldata(calldata);
+       nfs_free_seqid(calldata->luargs.seqid);
+       nfs4_put_lock_state(calldata->lsp);
+       put_nfs_open_context(calldata->ctx);
+       kfree(calldata);
 }
 
 static void nfs4_locku_done(struct rpc_task *task, void *data)
 {
        struct nfs4_unlockdata *calldata = data;
 
+       if (RPC_ASSASSINATED(task))
+               return;
        nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
        switch (task->tk_status) {
                case 0:
@@ -2935,7 +2938,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 static const struct rpc_call_ops nfs4_locku_ops = {
        .rpc_call_prepare = nfs4_locku_prepare,
        .rpc_call_done = nfs4_locku_done,
-       .rpc_release = nfs4_locku_complete,
+       .rpc_release = nfs4_locku_release_calldata,
 };
 
 static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2944,26 +2947,28 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        struct inode *inode = state->inode;
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_lock_state *lsp;
-       int status;
+       struct rpc_task *task;
+       int status = 0;
 
        /* Is this a delegated lock? */
        if (test_bit(NFS_DELEGATED_STATE, &state->flags))
-               return do_vfs_lock(request->fl_file, request);
+               goto out;
 
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
-               return status;
+               goto out;
        lsp = request->fl_u.nfs4_fl.owner;
        /* We might have lost the locks! */
        if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
-               return 0;
+               goto out;
+       status = -ENOMEM;
        calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
        if (calldata == NULL)
-               return -ENOMEM;
+               goto out;
        calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
        if (calldata->luargs.seqid == NULL) {
                kfree(calldata);
-               return -ENOMEM;
+               goto out;
        }
        calldata->luargs.stateid = &lsp->ls_stateid;
        calldata->arg.fh = NFS_FH(inode);
@@ -2978,14 +2983,16 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        /* Ensure we don't close file until we're done freeing locks! */
        calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);
 
-       atomic_set(&calldata->refcount, 2);
-       init_completion(&calldata->completion);
-
-       status = nfs4_call_async(NFS_SERVER(inode)->client, &nfs4_locku_ops, calldata);
-       if (status == 0)
-               wait_for_completion_interruptible(&calldata->completion);
+       task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_locku_ops, calldata);
+       if (!IS_ERR(task)) {
+               status = nfs4_wait_for_completion_rpc_task(task);
+               rpc_release_task(task);
+       } else {
+               status = PTR_ERR(task);
+               nfs4_locku_release_calldata(calldata);
+       }
+out:
        do_vfs_lock(request->fl_file, request);
-       nfs4_locku_release_calldata(calldata);
        return status;
 }