aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c101
-rw-r--r--fs/nfs/nfs4xdr.c7
2 files changed, 80 insertions, 28 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index aed8701c1a36..8154f2579469 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -57,7 +57,8 @@
57#define NFS4_POLL_RETRY_MIN (1*HZ) 57#define NFS4_POLL_RETRY_MIN (1*HZ)
58#define NFS4_POLL_RETRY_MAX (15*HZ) 58#define NFS4_POLL_RETRY_MAX (15*HZ)
59 59
60static 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); 60struct nfs4_opendata;
61static int _nfs4_proc_open_confirm(struct nfs4_opendata *data);
61static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 62static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
62static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); 63static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
63static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); 64static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
@@ -198,6 +199,8 @@ struct nfs4_opendata {
198 atomic_t count; 199 atomic_t count;
199 struct nfs_openargs o_arg; 200 struct nfs_openargs o_arg;
200 struct nfs_openres o_res; 201 struct nfs_openres o_res;
202 struct nfs_open_confirmargs c_arg;
203 struct nfs_open_confirmres c_res;
201 struct nfs_fattr f_attr; 204 struct nfs_fattr f_attr;
202 struct nfs_fattr dir_attr; 205 struct nfs_fattr dir_attr;
203 struct dentry *dentry; 206 struct dentry *dentry;
@@ -249,6 +252,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
249 p->o_arg.u.attrs = &p->attrs; 252 p->o_arg.u.attrs = &p->attrs;
250 memcpy(&p->attrs, attrs, sizeof(p->attrs)); 253 memcpy(&p->attrs, attrs, sizeof(p->attrs));
251 } 254 }
255 p->c_arg.fh = &p->o_res.fh;
256 p->c_arg.stateid = &p->o_res.stateid;
257 p->c_arg.seqid = p->o_arg.seqid;
252 return p; 258 return p;
253err_free: 259err_free:
254 kfree(p); 260 kfree(p);
@@ -433,8 +439,7 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state
433 if (status != 0) 439 if (status != 0)
434 goto out_free; 440 goto out_free;
435 if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) { 441 if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
436 status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), 442 status = _nfs4_proc_open_confirm(opendata);
437 sp, &opendata->o_res.stateid, opendata->o_arg.seqid);
438 if (status != 0) 443 if (status != 0)
439 goto out_free; 444 goto out_free;
440 } 445 }
@@ -472,28 +477,79 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
472 return err; 477 return err;
473} 478}
474 479
475static 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) 480static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
476{ 481{
477 struct nfs_open_confirmargs arg = { 482 struct nfs4_opendata *data = calldata;
478 .fh = fh, 483 struct rpc_message msg = {
479 .seqid = seqid, 484 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
480 .stateid = *stateid, 485 .rpc_argp = &data->c_arg,
481 }; 486 .rpc_resp = &data->c_res,
482 struct nfs_open_confirmres res; 487 .rpc_cred = data->owner->so_cred,
483 struct rpc_message msg = {
484 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
485 .rpc_argp = &arg,
486 .rpc_resp = &res,
487 .rpc_cred = sp->so_cred,
488 }; 488 };
489 rpc_call_setup(task, &msg, 0);
490}
491
492static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
493{
494 struct nfs4_opendata *data = calldata;
495
496 data->rpc_status = task->tk_status;
497 if (RPC_ASSASSINATED(task))
498 return;
499 if (data->rpc_status == 0)
500 memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
501 sizeof(data->o_res.stateid.data));
502 nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
503 nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
504}
505
506static void nfs4_open_confirm_release(void *calldata)
507{
508 struct nfs4_opendata *data = calldata;
509 struct nfs4_state *state = NULL;
510
511 /* If this request hasn't been cancelled, do nothing */
512 if (data->cancelled == 0)
513 goto out_free;
514 /* In case of error, no cleanup! */
515 if (data->rpc_status != 0)
516 goto out_free;
517 nfs_confirm_seqid(&data->owner->so_seqid, 0);
518 state = nfs4_opendata_to_nfs4_state(data);
519 if (state != NULL)
520 nfs4_close_state(state, data->o_arg.open_flags);
521out_free:
522 nfs4_opendata_free(data);
523}
524
525static const struct rpc_call_ops nfs4_open_confirm_ops = {
526 .rpc_call_prepare = nfs4_open_confirm_prepare,
527 .rpc_call_done = nfs4_open_confirm_done,
528 .rpc_release = nfs4_open_confirm_release,
529};
530
531/*
532 * Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata
533 */
534static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
535{
536 struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
537 struct rpc_task *task;
489 int status; 538 int status;
490 539
491 status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); 540 atomic_inc(&data->count);
492 /* Confirm the sequence as being established */ 541 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
493 nfs_confirm_seqid(&sp->so_seqid, status); 542 if (IS_ERR(task)) {
494 nfs_increment_open_seqid(status, seqid); 543 nfs4_opendata_free(data);
495 if (status >= 0) 544 return PTR_ERR(task);
496 memcpy(stateid, &res.stateid, sizeof(*stateid)); 545 }
546 status = nfs4_wait_for_completion_rpc_task(task);
547 if (status != 0) {
548 data->cancelled = 1;
549 smp_wmb();
550 } else
551 status = data->rpc_status;
552 rpc_release_task(task);
497 return status; 553 return status;
498} 554}
499 555
@@ -602,8 +658,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
602 } else 658 } else
603 nfs_refresh_inode(dir, o_res->dir_attr); 659 nfs_refresh_inode(dir, o_res->dir_attr);
604 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { 660 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
605 status = _nfs4_proc_open_confirm(server->client, &o_res->fh, 661 status = _nfs4_proc_open_confirm(data);
606 data->owner, &o_res->stateid, o_arg->seqid);
607 if (status != 0) 662 if (status != 0)
608 return status; 663 return status;
609 } 664 }
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index db2bcf722f91..2ba9906f2a51 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -964,9 +964,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
964{ 964{
965 uint32_t *p; 965 uint32_t *p;
966 966
967 RESERVE_SPACE(8+sizeof(arg->stateid.data)); 967 RESERVE_SPACE(8+sizeof(arg->stateid->data));
968 WRITE32(OP_OPEN_CONFIRM); 968 WRITE32(OP_OPEN_CONFIRM);
969 WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); 969 WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
970 WRITE32(arg->seqid->sequence->counter); 970 WRITE32(arg->seqid->sequence->counter);
971 971
972 return 0; 972 return 0;
@@ -1535,9 +1535,6 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n
1535 }; 1535 };
1536 int status; 1536 int status;
1537 1537
1538 status = nfs_wait_on_sequence(args->seqid, req->rq_task);
1539 if (status != 0)
1540 goto out;
1541 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1538 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1542 encode_compound_hdr(&xdr, &hdr); 1539 encode_compound_hdr(&xdr, &hdr);
1543 status = encode_putfh(&xdr, args->fh); 1540 status = encode_putfh(&xdr, args->fh);