NFS: Pull covers off IPv6 address parsing
[linux-2.6-block.git] / fs / nfs / nfs4proc.c
index cb99fd90a9acc5147135bb70846517ad8e79165e..5e8c4cf7959e323ac7fca51d19061fa5fda3cc64 100644 (file)
@@ -210,7 +210,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
        spin_lock(&dir->i_lock);
        nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
        if (!cinfo->atomic || cinfo->before != nfsi->change_attr)
-               nfsi->cache_change_attribute = jiffies;
+               nfs_force_lookup_revalidate(dir);
        nfsi->change_attr = cinfo->after;
        spin_unlock(&dir->i_lock);
 }
@@ -718,19 +718,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
        return err;
 }
 
-static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
-{
-       struct nfs4_opendata *data = calldata;
-       struct  rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
-               .rpc_argp = &data->c_arg,
-               .rpc_resp = &data->c_res,
-               .rpc_cred = data->owner->so_cred,
-       };
-       data->timestamp = jiffies;
-       rpc_call_setup(task, &msg, 0);
-}
-
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
@@ -741,10 +728,10 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
        if (data->rpc_status == 0) {
                memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
                                sizeof(data->o_res.stateid.data));
+               nfs_confirm_seqid(&data->owner->so_seqid, 0);
                renew_lease(data->o_res.server, data->timestamp);
                data->rpc_done = 1;
        }
-       nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
        nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 }
 
@@ -759,7 +746,6 @@ static void nfs4_open_confirm_release(void *calldata)
        /* In case of error, no cleanup! */
        if (!data->rpc_done)
                goto out_free;
-       nfs_confirm_seqid(&data->owner->so_seqid, 0);
        state = nfs4_opendata_to_nfs4_state(data);
        if (!IS_ERR(state))
                nfs4_close_state(&data->path, state, data->o_arg.open_flags);
@@ -768,7 +754,6 @@ out_free:
 }
 
 static const struct rpc_call_ops nfs4_open_confirm_ops = {
-       .rpc_call_prepare = nfs4_open_confirm_prepare,
        .rpc_call_done = nfs4_open_confirm_done,
        .rpc_release = nfs4_open_confirm_release,
 };
@@ -780,12 +765,26 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
 {
        struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
        struct rpc_task *task;
+       struct  rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
+               .rpc_argp = &data->c_arg,
+               .rpc_resp = &data->c_res,
+               .rpc_cred = data->owner->so_cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_open_confirm_ops,
+               .callback_data = data,
+               .flags = RPC_TASK_ASYNC,
+       };
        int status;
 
        kref_get(&data->kref);
        data->rpc_done = 0;
        data->rpc_status = 0;
-       task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
+       data->timestamp = jiffies;
+       task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
        status = nfs4_wait_for_completion_rpc_task(task);
@@ -802,13 +801,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
        struct nfs4_state_owner *sp = data->owner;
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
-               .rpc_argp = &data->o_arg,
-               .rpc_resp = &data->o_res,
-               .rpc_cred = sp->so_cred,
-       };
-       
+
        if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
                return;
        /*
@@ -833,11 +826,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        data->o_arg.id = sp->so_owner_id.id;
        data->o_arg.clientid = sp->so_client->cl_clientid;
        if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
-               msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
+               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
                nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
        }
        data->timestamp = jiffies;
-       rpc_call_setup(task, &msg, 0);
+       rpc_call_start(task);
        return;
 out_no_action:
        task->tk_action = NULL;
@@ -886,7 +879,6 @@ static void nfs4_open_release(void *calldata)
        /* In case we need an open_confirm, no cleanup! */
        if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
                goto out_free;
-       nfs_confirm_seqid(&data->owner->so_seqid, 0);
        state = nfs4_opendata_to_nfs4_state(data);
        if (!IS_ERR(state))
                nfs4_close_state(&data->path, state, data->o_arg.open_flags);
@@ -910,13 +902,26 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
        struct nfs_openargs *o_arg = &data->o_arg;
        struct nfs_openres *o_res = &data->o_res;
        struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+               .rpc_argp = o_arg,
+               .rpc_resp = o_res,
+               .rpc_cred = data->owner->so_cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_open_ops,
+               .callback_data = data,
+               .flags = RPC_TASK_ASYNC,
+       };
        int status;
 
        kref_get(&data->kref);
        data->rpc_done = 0;
        data->rpc_status = 0;
        data->cancelled = 0;
-       task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
+       task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
        status = nfs4_wait_for_completion_rpc_task(task);
@@ -1246,12 +1251,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
-               .rpc_argp = &calldata->arg,
-               .rpc_resp = &calldata->res,
-               .rpc_cred = state->owner->so_cred,
-       };
        int clear_rd, clear_wr, clear_rdwr;
 
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
@@ -1278,14 +1277,14 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        }
        nfs_fattr_init(calldata->res.fattr);
        if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
-               msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
+               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
                calldata->arg.open_flags = FMODE_READ;
        } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
-               msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
+               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
                calldata->arg.open_flags = FMODE_WRITE;
        }
        calldata->timestamp = jiffies;
-       rpc_call_setup(task, &msg, 0);
+       rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_close_ops = {
@@ -1305,12 +1304,22 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct path *path, struct nfs4_state *state)
+int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_closedata *calldata;
        struct nfs4_state_owner *sp = state->owner;
        struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
+               .rpc_cred = state->owner->so_cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_close_ops,
+               .flags = RPC_TASK_ASYNC,
+       };
        int status = -ENOMEM;
 
        calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
@@ -1330,11 +1339,17 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
        calldata->path.mnt = mntget(path->mnt);
        calldata->path.dentry = dget(path->dentry);
 
-       task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+       msg.rpc_argp = &calldata->arg,
+       msg.rpc_resp = &calldata->res,
+       task_setup_data.callback_data = calldata;
+       task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
+       status = 0;
+       if (wait)
+               status = rpc_wait_for_completion_task(task);
        rpc_put_task(task);
-       return 0;
+       return status;
 out_free_calldata:
        kfree(calldata);
 out:
@@ -1365,13 +1380,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
        }
        ret = PTR_ERR(filp);
 out_close:
-       nfs4_close_state(path, state, nd->intent.open.flags);
+       nfs4_close_sync(path, state, nd->intent.open.flags);
        return ret;
 }
 
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       struct dentry *parent;
        struct path path = {
                .mnt = nd->mnt,
                .dentry = dentry,
@@ -1394,6 +1410,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return (struct dentry *)cred;
+       parent = dentry->d_parent;
+       /* Protect against concurrent sillydeletes */
+       nfs_block_sillyrename(parent);
        state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
        put_rpccred(cred);
        if (IS_ERR(state)) {
@@ -1401,12 +1420,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
                        d_add(dentry, NULL);
                        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
                }
+               nfs_unblock_sillyrename(parent);
                return (struct dentry *)state;
        }
        res = d_add_unique(dentry, igrab(state->inode));
        if (res != NULL)
                path.dentry = res;
        nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
+       nfs_unblock_sillyrename(parent);
        nfs4_intent_set_file(nd, &path, state);
        return res;
 }
@@ -1444,7 +1465,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
                nfs4_intent_set_file(nd, &path, state);
                return 1;
        }
-       nfs4_close_state(&path, state, openflags);
+       nfs4_close_sync(&path, state, openflags);
 out_drop:
        d_drop(dentry);
        return 0;
@@ -1898,7 +1919,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
                status = nfs4_intent_set_file(nd, &path, state);
        else
-               nfs4_close_state(&path, state, flags);
+               nfs4_close_sync(&path, state, flags);
 out:
        return status;
 }
@@ -2407,18 +2428,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
        return 0;
 }
 
-static void nfs4_proc_read_setup(struct nfs_read_data *data)
+static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
 {
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
-               .rpc_argp = &data->args,
-               .rpc_resp = &data->res,
-               .rpc_cred = data->cred,
-       };
-
        data->timestamp   = jiffies;
-
-       rpc_call_setup(&data->task, &msg, 0);
+       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
 }
 
 static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2436,33 +2449,15 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
        return 0;
 }
 
-static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
 {
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
-               .rpc_argp = &data->args,
-               .rpc_resp = &data->res,
-               .rpc_cred = data->cred,
-       };
-       struct inode *inode = data->inode;
-       struct nfs_server *server = NFS_SERVER(inode);
-       int stable;
-       
-       if (how & FLUSH_STABLE) {
-               if (!NFS_I(inode)->ncommit)
-                       stable = NFS_FILE_SYNC;
-               else
-                       stable = NFS_DATA_SYNC;
-       } else
-               stable = NFS_UNSTABLE;
-       data->args.stable = stable;
+       struct nfs_server *server = NFS_SERVER(data->inode);
+
        data->args.bitmask = server->attr_bitmask;
        data->res.server = server;
-
        data->timestamp   = jiffies;
 
-       /* Finalize the task. */
-       rpc_call_setup(&data->task, &msg, 0);
+       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
 }
 
 static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2477,20 +2472,13 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
        return 0;
 }
 
-static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg)
 {
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
-               .rpc_argp = &data->args,
-               .rpc_resp = &data->res,
-               .rpc_cred = data->cred,
-       };      
        struct nfs_server *server = NFS_SERVER(data->inode);
        
        data->args.bitmask = server->attr_bitmask;
        data->res.server = server;
-
-       rpc_call_setup(&data->task, &msg, 0);
+       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
 }
 
 /*
@@ -2903,14 +2891,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
 
        for(;;) {
                setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-                               sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
-                               clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr),
+                               sizeof(setclientid.sc_name), "%s/%s %s %u",
+                               clp->cl_ipaddr,
+                               rpc_peeraddr2str(clp->cl_rpcclient,
+                                                       RPC_DISPLAY_ADDR),
                                cred->cr_ops->cr_name,
                                clp->cl_id_uniquifier);
                setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
-                               sizeof(setclientid.sc_netid), "tcp");
+                               sizeof(setclientid.sc_netid),
+                               rpc_peeraddr2str(clp->cl_rpcclient,
+                                                       RPC_DISPLAY_NETID));
                setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
-                               sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+                               sizeof(setclientid.sc_uaddr), "%s.%u.%u",
                                clp->cl_ipaddr, port >> 8, port & 255);
 
                status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
@@ -2974,25 +2966,11 @@ struct nfs4_delegreturndata {
        struct nfs4_delegreturnres res;
        struct nfs_fh fh;
        nfs4_stateid stateid;
-       struct rpc_cred *cred;
        unsigned long timestamp;
        struct nfs_fattr fattr;
        int rpc_status;
 };
 
-static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
-{
-       struct nfs4_delegreturndata *data = calldata;
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
-               .rpc_argp = &data->args,
-               .rpc_resp = &data->res,
-               .rpc_cred = data->cred,
-       };
-       nfs_fattr_init(data->res.fattr);
-       rpc_call_setup(task, &msg, 0);
-}
-
 static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_delegreturndata *data = calldata;
@@ -3003,14 +2981,10 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 
 static void nfs4_delegreturn_release(void *calldata)
 {
-       struct nfs4_delegreturndata *data = calldata;
-
-       put_rpccred(data->cred);
        kfree(calldata);
 }
 
 static const struct rpc_call_ops nfs4_delegreturn_ops = {
-       .rpc_call_prepare = nfs4_delegreturn_prepare,
        .rpc_call_done = nfs4_delegreturn_done,
        .rpc_release = nfs4_delegreturn_release,
 };
@@ -3020,6 +2994,16 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
        struct nfs4_delegreturndata *data;
        struct nfs_server *server = NFS_SERVER(inode);
        struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
+               .rpc_cred = cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_delegreturn_ops,
+               .flags = RPC_TASK_ASYNC,
+       };
        int status;
 
        data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -3032,11 +3016,14 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
        memcpy(&data->stateid, stateid, sizeof(data->stateid));
        data->res.fattr = &data->fattr;
        data->res.server = server;
-       data->cred = get_rpccred(cred);
+       nfs_fattr_init(data->res.fattr);
        data->timestamp = jiffies;
        data->rpc_status = 0;
 
-       task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
+       task_setup_data.callback_data = data;
+       msg.rpc_argp = &data->args,
+       msg.rpc_resp = &data->res,
+       task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
        status = nfs4_wait_for_completion_rpc_task(task);
@@ -3223,12 +3210,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_unlockdata *calldata = data;
-       struct rpc_message msg = {
-               .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
-               .rpc_argp       = &calldata->arg,
-               .rpc_resp       = &calldata->res,
-               .rpc_cred       = calldata->lsp->ls_state->owner->so_cred,
-       };
 
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                return;
@@ -3238,7 +3219,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
                return;
        }
        calldata->timestamp = jiffies;
-       rpc_call_setup(task, &msg, 0);
+       rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -3253,6 +3234,16 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
                struct nfs_seqid *seqid)
 {
        struct nfs4_unlockdata *data;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
+               .rpc_cred = ctx->cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = NFS_CLIENT(lsp->ls_state->inode),
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_locku_ops,
+               .flags = RPC_TASK_ASYNC,
+       };
 
        /* Ensure this is an unlock - when canceling a lock, the
         * canceled lock is passed in, and it won't be an unlock.
@@ -3265,7 +3256,10 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
                return ERR_PTR(-ENOMEM);
        }
 
-       return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
+       msg.rpc_argp = &data->arg,
+       msg.rpc_resp = &data->res,
+       task_setup_data.callback_data = data;
+       return rpc_run_task(&task_setup_data);
 }
 
 static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -3324,9 +3318,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
 
        p->arg.fh = NFS_FH(inode);
        p->arg.fl = &p->fl;
+       p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid);
+       if (p->arg.open_seqid == NULL)
+               goto out_free;
        p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
        if (p->arg.lock_seqid == NULL)
-               goto out_free;
+               goto out_free_seqid;
        p->arg.lock_stateid = &lsp->ls_stateid;
        p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
        p->arg.lock_owner.id = lsp->ls_id.id;
@@ -3335,6 +3332,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
        p->ctx = get_nfs_open_context(ctx);
        memcpy(&p->fl, fl, sizeof(p->fl));
        return p;
+out_free_seqid:
+       nfs_free_seqid(p->arg.open_seqid);
 out_free:
        kfree(p);
        return NULL;
@@ -3344,31 +3343,20 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_lockdata *data = calldata;
        struct nfs4_state *state = data->lsp->ls_state;
-       struct nfs4_state_owner *sp = state->owner;
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
-               .rpc_argp = &data->arg,
-               .rpc_resp = &data->res,
-               .rpc_cred = sp->so_cred,
-       };
 
+       dprintk("%s: begin!\n", __FUNCTION__);
        if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
                return;
-       dprintk("%s: begin!\n", __FUNCTION__);
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
-               data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid);
-               if (data->arg.open_seqid == NULL) {
-                       data->rpc_status = -ENOMEM;
-                       task->tk_action = NULL;
-                       goto out;
-               }
+               if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
+                       return;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
-       }
+       } else
+               data->arg.new_lock_owner = 0;
        data->timestamp = jiffies;
-       rpc_call_setup(task, &msg, 0);
-out:
+       rpc_call_start(task);
        dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
 }
 
@@ -3404,8 +3392,7 @@ static void nfs4_lock_release(void *calldata)
        struct nfs4_lockdata *data = calldata;
 
        dprintk("%s: begin!\n", __FUNCTION__);
-       if (data->arg.open_seqid != NULL)
-               nfs_free_seqid(data->arg.open_seqid);
+       nfs_free_seqid(data->arg.open_seqid);
        if (data->cancelled != 0) {
                struct rpc_task *task;
                task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
@@ -3431,6 +3418,16 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
 {
        struct nfs4_lockdata *data;
        struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
+               .rpc_cred = state->owner->so_cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = NFS_CLIENT(state->inode),
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_lock_ops,
+               .flags = RPC_TASK_ASYNC,
+       };
        int ret;
 
        dprintk("%s: begin!\n", __FUNCTION__);
@@ -3442,8 +3439,10 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
                data->arg.block = 1;
        if (reclaim != 0)
                data->arg.reclaim = 1;
-       task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC,
-                       &nfs4_lock_ops, data);
+       msg.rpc_argp = &data->arg,
+       msg.rpc_resp = &data->res,
+       task_setup_data.callback_data = data;
+       task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
        ret = nfs4_wait_for_completion_rpc_task(task);