SUNRPC: Further cleanups
[linux-2.6-microblaze.git] / fs / nfs / nfs4proc.c
index 21482b2..368b75b 100644 (file)
@@ -195,16 +195,13 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
 }
 
 /* Helper for asynchronous RPC calls */
-static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
-               rpc_action tk_exit, void *calldata)
+static int nfs4_call_async(struct rpc_clnt *clnt,
+               const struct rpc_call_ops *tk_ops, void *calldata)
 {
        struct rpc_task *task;
 
-       if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC)))
+       if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
                return -ENOMEM;
-
-       task->tk_calldata = calldata;
-       task->tk_action = tk_begin;
        rpc_execute(task);
        return 0;
 }
@@ -867,10 +864,10 @@ struct nfs4_closedata {
        struct nfs_fattr fattr;
 };
 
-static void nfs4_free_closedata(struct nfs4_closedata *calldata)
+static void nfs4_free_closedata(void *data)
 {
-       struct nfs4_state *state = calldata->state;
-       struct nfs4_state_owner *sp = state->owner;
+       struct nfs4_closedata *calldata = data;
+       struct nfs4_state_owner *sp = calldata->state->owner;
 
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
@@ -878,12 +875,14 @@ static void nfs4_free_closedata(struct nfs4_closedata *calldata)
        kfree(calldata);
 }
 
-static void nfs4_close_done(struct rpc_task *task)
+static void nfs4_close_done(struct rpc_task *task, void *data)
 {
-       struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+       struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
        struct nfs_server *server = NFS_SERVER(calldata->inode);
 
+       if (RPC_ASSASSINATED(task))
+               return;
         /* hmm. we are done with the inode, and in the process of freeing
         * the state_owner. we keep this around to process errors
         */
@@ -904,12 +903,11 @@ static void nfs4_close_done(struct rpc_task *task)
                        }
        }
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
-       nfs4_free_closedata(calldata);
 }
 
-static void nfs4_close_begin(struct rpc_task *task)
+static void nfs4_close_prepare(struct rpc_task *task, void *data)
 {
-       struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+       struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
@@ -918,10 +916,8 @@ static void nfs4_close_begin(struct rpc_task *task)
                .rpc_cred = state->owner->so_cred,
        };
        int mode = 0, old_mode;
-       int status;
 
-       status = nfs_wait_on_sequence(calldata->arg.seqid, task);
-       if (status != 0)
+       if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                return;
        /* Recalculate the new open mode in case someone reopened the file
         * while we were waiting in line to be scheduled.
@@ -937,9 +933,8 @@ static void nfs4_close_begin(struct rpc_task *task)
        spin_unlock(&calldata->inode->i_lock);
        spin_unlock(&state->owner->so_lock);
        if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-               nfs4_free_closedata(calldata);
-               task->tk_exit = NULL;
-               rpc_exit(task, 0);
+               /* Note: exit _without_ calling nfs4_close_done */
+               task->tk_action = NULL;
                return;
        }
        nfs_fattr_init(calldata->res.fattr);
@@ -949,6 +944,12 @@ static void nfs4_close_begin(struct rpc_task *task)
        rpc_call_setup(task, &msg, 0);
 }
 
+static const struct rpc_call_ops nfs4_close_ops = {
+       .rpc_call_prepare = nfs4_close_prepare,
+       .rpc_call_done = nfs4_close_done,
+       .rpc_release = nfs4_free_closedata,
+};
+
 /* 
  * It is possible for data to be read/written from a mem-mapped file 
  * after the sys_close call (which hits the vfs layer as a flush).
@@ -981,8 +982,7 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
        calldata->res.fattr = &calldata->fattr;
        calldata->res.server = server;
 
-       status = nfs4_call_async(server->client, nfs4_close_begin,
-                       nfs4_close_done, calldata);
+       status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
        if (status == 0)
                goto out;
 
@@ -1506,10 +1506,15 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata)
        dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
                        (long long) wdata->args.offset);
 
+       wdata->args.bitmask = server->attr_bitmask;
+       wdata->res.server = server;
        nfs_fattr_init(fattr);
        status = rpc_call_sync(server->client, &msg, rpcflags);
        dprintk("NFS reply write: %d\n", status);
-       return status;
+       if (status < 0)
+               return status;
+       nfs_post_op_update_inode(inode, fattr);
+       return wdata->res.count;
 }
 
 static int nfs4_proc_write(struct nfs_write_data *wdata)
@@ -1540,9 +1545,13 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata)
        dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
                        (long long) cdata->args.offset);
 
+       cdata->args.bitmask = server->attr_bitmask;
+       cdata->res.server = server;
        nfs_fattr_init(fattr);
        status = rpc_call_sync(server->client, &msg, 0);
        dprintk("NFS reply commit: %d\n", status);
+       if (status >= 0)
+               nfs_post_op_update_inode(inode, fattr);
        return status;
 }
 
@@ -2116,10 +2125,9 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
        return err;
 }
 
-static void
-nfs4_read_done(struct rpc_task *task)
+static void nfs4_read_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
+       struct nfs_read_data *data = calldata;
        struct inode *inode = data->inode;
 
        if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2129,9 +2137,14 @@ nfs4_read_done(struct rpc_task *task)
        if (task->tk_status > 0)
                renew_lease(NFS_SERVER(inode), data->timestamp);
        /* Call back common NFS readpage processing */
-       nfs_readpage_result(task);
+       nfs_readpage_result(task, calldata);
 }
 
+static const struct rpc_call_ops nfs4_read_ops = {
+       .rpc_call_done = nfs4_read_done,
+       .rpc_release = nfs_readdata_release,
+};
+
 static void
 nfs4_proc_read_setup(struct nfs_read_data *data)
 {
@@ -2151,14 +2164,13 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
        flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 
        /* Finalize the task. */
-       rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags);
+       rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data);
        rpc_call_setup(task, &msg, 0);
 }
 
-static void
-nfs4_write_done(struct rpc_task *task)
+static void nfs4_write_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+       struct nfs_write_data *data = calldata;
        struct inode *inode = data->inode;
        
        if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2170,9 +2182,14 @@ nfs4_write_done(struct rpc_task *task)
                nfs_post_op_update_inode(inode, data->res.fattr);
        }
        /* Call back common NFS writeback processing */
-       nfs_writeback_done(task);
+       nfs_writeback_done(task, calldata);
 }
 
+static const struct rpc_call_ops nfs4_write_ops = {
+       .rpc_call_done = nfs4_write_done,
+       .rpc_release = nfs_writedata_release,
+};
+
 static void
 nfs4_proc_write_setup(struct nfs_write_data *data, int how)
 {
@@ -2205,14 +2222,13 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
        flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
        /* Finalize the task. */
-       rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags);
+       rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data);
        rpc_call_setup(task, &msg, 0);
 }
 
-static void
-nfs4_commit_done(struct rpc_task *task)
+static void nfs4_commit_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+       struct nfs_write_data *data = calldata;
        struct inode *inode = data->inode;
        
        if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2222,9 +2238,14 @@ nfs4_commit_done(struct rpc_task *task)
        if (task->tk_status >= 0)
                nfs_post_op_update_inode(inode, data->res.fattr);
        /* Call back common NFS writeback processing */
-       nfs_commit_done(task);
+       nfs_commit_done(task, calldata);
 }
 
+static const struct rpc_call_ops nfs4_commit_ops = {
+       .rpc_call_done = nfs4_commit_done,
+       .rpc_release = nfs_commit_release,
+};
+
 static void
 nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
 {
@@ -2246,7 +2267,7 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
        flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
        /* Finalize the task. */
-       rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
+       rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
        rpc_call_setup(task, &msg, 0);  
 }
 
@@ -2254,11 +2275,10 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
  * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
  * standalone procedure for queueing an asynchronous RENEW.
  */
-static void
-renew_done(struct rpc_task *task)
+static void nfs4_renew_done(struct rpc_task *task, void *data)
 {
        struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
-       unsigned long timestamp = (unsigned long)task->tk_calldata;
+       unsigned long timestamp = (unsigned long)data;
 
        if (task->tk_status < 0) {
                switch (task->tk_status) {
@@ -2275,6 +2295,10 @@ renew_done(struct rpc_task *task)
        spin_unlock(&clp->cl_lock);
 }
 
+static const struct rpc_call_ops nfs4_renew_ops = {
+       .rpc_call_done = nfs4_renew_done,
+};
+
 int
 nfs4_proc_async_renew(struct nfs4_client *clp)
 {
@@ -2285,7 +2309,7 @@ nfs4_proc_async_renew(struct nfs4_client *clp)
        };
 
        return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
-                       renew_done, (void *)jiffies);
+                       &nfs4_renew_ops, (void *)jiffies);
 }
 
 int
@@ -2857,15 +2881,16 @@ static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
        }
 }
 
-static void nfs4_locku_complete(struct nfs4_unlockdata *calldata)
+static void nfs4_locku_complete(void *data)
 {
+       struct nfs4_unlockdata *calldata = data;
        complete(&calldata->completion);
        nfs4_locku_release_calldata(calldata);
 }
 
-static void nfs4_locku_done(struct rpc_task *task)
+static void nfs4_locku_done(struct rpc_task *task, void *data)
 {
-       struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+       struct nfs4_unlockdata *calldata = data;
 
        nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
        switch (task->tk_status) {
@@ -2881,15 +2906,13 @@ static void nfs4_locku_done(struct rpc_task *task)
                default:
                        if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
                                rpc_restart_call(task);
-                               return;
                        }
        }
-       nfs4_locku_complete(calldata);
 }
 
-static void nfs4_locku_begin(struct rpc_task *task)
+static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 {
-       struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+       struct nfs4_unlockdata *calldata = data;
        struct rpc_message msg = {
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
                .rpc_argp       = &calldata->arg,
@@ -2902,14 +2925,19 @@ static void nfs4_locku_begin(struct rpc_task *task)
        if (status != 0)
                return;
        if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
-               nfs4_locku_complete(calldata);
-               task->tk_exit = NULL;
-               rpc_exit(task, 0);
+               /* Note: exit _without_ running nfs4_locku_done */
+               task->tk_action = NULL;
                return;
        }
        rpc_call_setup(task, &msg, 0);
 }
 
+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,
+};
+
 static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
        struct nfs4_unlockdata *calldata;
@@ -2953,8 +2981,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        atomic_set(&calldata->refcount, 2);
        init_completion(&calldata->completion);
 
-       status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
-                       nfs4_locku_done, calldata);
+       status = nfs4_call_async(NFS_SERVER(inode)->client, &nfs4_locku_ops, calldata);
        if (status == 0)
                wait_for_completion_interruptible(&calldata->completion);
        do_vfs_lock(request->fl_file, request);
@@ -3071,15 +3098,15 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
        struct nfs4_client *clp = state->owner->so_client;
        int status;
 
-       down_read(&clp->cl_sem);
        /* Is this a delegated open? */
-       if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+       if (NFS_I(state->inode)->delegation_state != 0) {
                /* Yes: cache locks! */
                status = do_vfs_lock(request->fl_file, request);
                /* ...but avoid races with delegation recall... */
                if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags))
-                       goto out;
+                       return status;
        }
+       down_read(&clp->cl_sem);
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
                goto out;