Commit cdd4e68b5f0ed12c64b3e2be83655d2a47588a74

Authored by Trond Myklebust
1 parent 24ac23ab88

NFSv4: Make open_confirm() asynchronous too

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 3 changed files with 81 additions and 29 deletions Side-by-side Diff

... ... @@ -57,7 +57,8 @@
57 57 #define NFS4_POLL_RETRY_MIN (1*HZ)
58 58 #define NFS4_POLL_RETRY_MAX (15*HZ)
59 59  
60   -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);
  60 +struct nfs4_opendata;
  61 +static int _nfs4_proc_open_confirm(struct nfs4_opendata *data);
61 62 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
62 63 static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
63 64 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
... ... @@ -198,6 +199,8 @@
198 199 atomic_t count;
199 200 struct nfs_openargs o_arg;
200 201 struct nfs_openres o_res;
  202 + struct nfs_open_confirmargs c_arg;
  203 + struct nfs_open_confirmres c_res;
201 204 struct nfs_fattr f_attr;
202 205 struct nfs_fattr dir_attr;
203 206 struct dentry *dentry;
... ... @@ -249,6 +252,9 @@
249 252 p->o_arg.u.attrs = &p->attrs;
250 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 258 return p;
253 259 err_free:
254 260 kfree(p);
... ... @@ -433,8 +439,7 @@
433 439 if (status != 0)
434 440 goto out_free;
435 441 if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
436   - status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
437   - sp, &opendata->o_res.stateid, opendata->o_arg.seqid);
  442 + status = _nfs4_proc_open_confirm(opendata);
438 443 if (status != 0)
439 444 goto out_free;
440 445 }
441 446  
442 447  
443 448  
... ... @@ -472,28 +477,79 @@
472 477 return err;
473 478 }
474 479  
475   -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)
  480 +static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
476 481 {
477   - struct nfs_open_confirmargs arg = {
478   - .fh = fh,
479   - .seqid = seqid,
480   - .stateid = *stateid,
  482 + struct nfs4_opendata *data = calldata;
  483 + struct rpc_message msg = {
  484 + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
  485 + .rpc_argp = &data->c_arg,
  486 + .rpc_resp = &data->c_res,
  487 + .rpc_cred = data->owner->so_cred,
481 488 };
482   - struct nfs_open_confirmres res;
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   - };
  489 + rpc_call_setup(task, &msg, 0);
  490 +}
  491 +
  492 +static 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 +
  506 +static 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);
  521 +out_free:
  522 + nfs4_opendata_free(data);
  523 +}
  524 +
  525 +static 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 + */
  534 +static 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 538 int status;
490 539  
491   - status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
492   - /* Confirm the sequence as being established */
493   - nfs_confirm_seqid(&sp->so_seqid, status);
494   - nfs_increment_open_seqid(status, seqid);
495   - if (status >= 0)
496   - memcpy(stateid, &res.stateid, sizeof(*stateid));
  540 + atomic_inc(&data->count);
  541 + task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
  542 + if (IS_ERR(task)) {
  543 + nfs4_opendata_free(data);
  544 + return PTR_ERR(task);
  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 553 return status;
498 554 }
499 555  
... ... @@ -602,8 +658,7 @@
602 658 } else
603 659 nfs_refresh_inode(dir, o_res->dir_attr);
604 660 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
605   - status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
606   - data->owner, &o_res->stateid, o_arg->seqid);
  661 + status = _nfs4_proc_open_confirm(data);
607 662 if (status != 0)
608 663 return status;
609 664 }
... ... @@ -964,9 +964,9 @@
964 964 {
965 965 uint32_t *p;
966 966  
967   - RESERVE_SPACE(8+sizeof(arg->stateid.data));
  967 + RESERVE_SPACE(8+sizeof(arg->stateid->data));
968 968 WRITE32(OP_OPEN_CONFIRM);
969   - WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
  969 + WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
970 970 WRITE32(arg->seqid->sequence->counter);
971 971  
972 972 return 0;
... ... @@ -1535,9 +1535,6 @@
1535 1535 };
1536 1536 int status;
1537 1537  
1538   - status = nfs_wait_on_sequence(args->seqid, req->rq_task);
1539   - if (status != 0)
1540   - goto out;
1541 1538 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1542 1539 encode_compound_hdr(&xdr, &hdr);
1543 1540 status = encode_putfh(&xdr, args->fh);
include/linux/nfs_xdr.h
... ... @@ -137,7 +137,7 @@
137 137 */
138 138 struct nfs_open_confirmargs {
139 139 const struct nfs_fh * fh;
140   - nfs4_stateid stateid;
  140 + nfs4_stateid * stateid;
141 141 struct nfs_seqid * seqid;
142 142 };
143 143