Commit cdd4e68b5f0ed12c64b3e2be83655d2a47588a74
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
fs/nfs/nfs4proc.c
... | ... | @@ -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 | } |
fs/nfs/nfs4xdr.c
... | ... | @@ -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); |