Commit cdd4e68b authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Make open_confirm() asynchronous too

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 24ac23ab
...@@ -57,7 +57,8 @@ ...@@ -57,7 +57,8 @@
#define NFS4_POLL_RETRY_MIN (1*HZ) #define NFS4_POLL_RETRY_MIN (1*HZ)
#define NFS4_POLL_RETRY_MAX (15*HZ) #define NFS4_POLL_RETRY_MAX (15*HZ)
static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid); struct nfs4_opendata;
static int _nfs4_proc_open_confirm(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
...@@ -198,6 +199,8 @@ struct nfs4_opendata { ...@@ -198,6 +199,8 @@ struct nfs4_opendata {
atomic_t count; atomic_t count;
struct nfs_openargs o_arg; struct nfs_openargs o_arg;
struct nfs_openres o_res; struct nfs_openres o_res;
struct nfs_open_confirmargs c_arg;
struct nfs_open_confirmres c_res;
struct nfs_fattr f_attr; struct nfs_fattr f_attr;
struct nfs_fattr dir_attr; struct nfs_fattr dir_attr;
struct dentry *dentry; struct dentry *dentry;
...@@ -249,6 +252,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, ...@@ -249,6 +252,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p->o_arg.u.attrs = &p->attrs; p->o_arg.u.attrs = &p->attrs;
memcpy(&p->attrs, attrs, sizeof(p->attrs)); memcpy(&p->attrs, attrs, sizeof(p->attrs));
} }
p->c_arg.fh = &p->o_res.fh;
p->c_arg.stateid = &p->o_res.stateid;
p->c_arg.seqid = p->o_arg.seqid;
return p; return p;
err_free: err_free:
kfree(p); kfree(p);
...@@ -433,8 +439,7 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state ...@@ -433,8 +439,7 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state
if (status != 0) if (status != 0)
goto out_free; goto out_free;
if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) { if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), status = _nfs4_proc_open_confirm(opendata);
sp, &opendata->o_res.stateid, opendata->o_arg.seqid);
if (status != 0) if (status != 0)
goto out_free; goto out_free;
} }
...@@ -472,28 +477,79 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) ...@@ -472,28 +477,79 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
return err; return err;
} }
static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid) static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
{ {
struct nfs_open_confirmargs arg = { struct nfs4_opendata *data = calldata;
.fh = fh,
.seqid = seqid,
.stateid = *stateid,
};
struct nfs_open_confirmres res;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
.rpc_argp = &arg, .rpc_argp = &data->c_arg,
.rpc_resp = &res, .rpc_resp = &data->c_res,
.rpc_cred = sp->so_cred, .rpc_cred = data->owner->so_cred,
}; };
rpc_call_setup(task, &msg, 0);
}
static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
{
struct nfs4_opendata *data = calldata;
data->rpc_status = task->tk_status;
if (RPC_ASSASSINATED(task))
return;
if (data->rpc_status == 0)
memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
sizeof(data->o_res.stateid.data));
nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
}
static void nfs4_open_confirm_release(void *calldata)
{
struct nfs4_opendata *data = calldata;
struct nfs4_state *state = NULL;
/* If this request hasn't been cancelled, do nothing */
if (data->cancelled == 0)
goto out_free;
/* In case of error, no cleanup! */
if (data->rpc_status != 0)
goto out_free;
nfs_confirm_seqid(&data->owner->so_seqid, 0);
state = nfs4_opendata_to_nfs4_state(data);
if (state != NULL)
nfs4_close_state(state, data->o_arg.open_flags);
out_free:
nfs4_opendata_free(data);
}
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,
};
/*
* Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata
*/
static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
{
struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
struct rpc_task *task;
int status; int status;
status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); atomic_inc(&data->count);
/* Confirm the sequence as being established */ task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
nfs_confirm_seqid(&sp->so_seqid, status); if (IS_ERR(task)) {
nfs_increment_open_seqid(status, seqid); nfs4_opendata_free(data);
if (status >= 0) return PTR_ERR(task);
memcpy(stateid, &res.stateid, sizeof(*stateid)); }
status = nfs4_wait_for_completion_rpc_task(task);
if (status != 0) {
data->cancelled = 1;
smp_wmb();
} else
status = data->rpc_status;
rpc_release_task(task);
return status; return status;
} }
...@@ -602,8 +658,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) ...@@ -602,8 +658,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
} else } else
nfs_refresh_inode(dir, o_res->dir_attr); nfs_refresh_inode(dir, o_res->dir_attr);
if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
status = _nfs4_proc_open_confirm(server->client, &o_res->fh, status = _nfs4_proc_open_confirm(data);
data->owner, &o_res->stateid, o_arg->seqid);
if (status != 0) if (status != 0)
return status; return status;
} }
......
...@@ -964,9 +964,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con ...@@ -964,9 +964,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8+sizeof(arg->stateid.data)); RESERVE_SPACE(8+sizeof(arg->stateid->data));
WRITE32(OP_OPEN_CONFIRM); WRITE32(OP_OPEN_CONFIRM);
WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
WRITE32(arg->seqid->sequence->counter); WRITE32(arg->seqid->sequence->counter);
return 0; return 0;
...@@ -1535,9 +1535,6 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n ...@@ -1535,9 +1535,6 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n
}; };
int status; int status;
status = nfs_wait_on_sequence(args->seqid, req->rq_task);
if (status != 0)
goto out;
xdr_init_encode(&xdr, &req->rq_snd_buf, p); xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr); encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh); status = encode_putfh(&xdr, args->fh);
......
...@@ -137,7 +137,7 @@ struct nfs_openres { ...@@ -137,7 +137,7 @@ struct nfs_openres {
*/ */
struct nfs_open_confirmargs { struct nfs_open_confirmargs {
const struct nfs_fh * fh; const struct nfs_fh * fh;
nfs4_stateid stateid; nfs4_stateid * stateid;
struct nfs_seqid * seqid; struct nfs_seqid * seqid;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment