|
21 | 21 |
|
22 | 22 | #define NFSDBG_FACILITY NFSDBG_PROC
|
23 | 23 | static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std);
|
| 24 | +static int nfs42_proc_offload_status(struct file *file, nfs4_stateid *stateid, |
| 25 | + u64 *copied); |
24 | 26 |
|
25 | 27 | static void nfs42_set_netaddr(struct file *filep, struct nfs42_netaddr *naddr)
|
26 | 28 | {
|
@@ -582,6 +584,107 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
|
582 | 584 | return status;
|
583 | 585 | }
|
584 | 586 |
|
| 587 | +static int |
| 588 | +_nfs42_proc_offload_status(struct nfs_server *server, struct file *file, |
| 589 | + struct nfs42_offload_data *data) |
| 590 | +{ |
| 591 | + struct nfs_open_context *ctx = nfs_file_open_context(file); |
| 592 | + struct rpc_message msg = { |
| 593 | + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OFFLOAD_STATUS], |
| 594 | + .rpc_argp = &data->args, |
| 595 | + .rpc_resp = &data->res, |
| 596 | + .rpc_cred = ctx->cred, |
| 597 | + }; |
| 598 | + int status; |
| 599 | + |
| 600 | + status = nfs4_call_sync(server->client, server, &msg, |
| 601 | + &data->args.osa_seq_args, |
| 602 | + &data->res.osr_seq_res, 1); |
| 603 | + switch (status) { |
| 604 | + case 0: |
| 605 | + break; |
| 606 | + |
| 607 | + case -NFS4ERR_ADMIN_REVOKED: |
| 608 | + case -NFS4ERR_BAD_STATEID: |
| 609 | + case -NFS4ERR_OLD_STATEID: |
| 610 | + /* |
| 611 | + * Server does not recognize the COPY stateid. CB_OFFLOAD |
| 612 | + * could have purged it, or server might have rebooted. |
| 613 | + * Since COPY stateids don't have an associated inode, |
| 614 | + * avoid triggering state recovery. |
| 615 | + */ |
| 616 | + status = -EBADF; |
| 617 | + break; |
| 618 | + case -NFS4ERR_NOTSUPP: |
| 619 | + case -ENOTSUPP: |
| 620 | + case -EOPNOTSUPP: |
| 621 | + server->caps &= ~NFS_CAP_OFFLOAD_STATUS; |
| 622 | + status = -EOPNOTSUPP; |
| 623 | + break; |
| 624 | + } |
| 625 | + |
| 626 | + return status; |
| 627 | +} |
| 628 | + |
| 629 | +/** |
| 630 | + * nfs42_proc_offload_status - Poll completion status of an async copy operation |
| 631 | + * @dst: handle of file being copied into |
| 632 | + * @stateid: copy stateid (from async COPY result) |
| 633 | + * @copied: OUT: number of bytes copied so far |
| 634 | + * |
| 635 | + * Return values: |
| 636 | + * %0: Server returned an NFS4_OK completion status |
| 637 | + * %-EINPROGRESS: Server returned no completion status |
| 638 | + * %-EREMOTEIO: Server returned an error completion status |
| 639 | + * %-EBADF: Server did not recognize the copy stateid |
| 640 | + * %-EOPNOTSUPP: Server does not support OFFLOAD_STATUS |
| 641 | + * %-ERESTARTSYS: Wait interrupted by signal |
| 642 | + * |
| 643 | + * Other negative errnos indicate the client could not complete the |
| 644 | + * request. |
| 645 | + */ |
| 646 | +static int __maybe_unused |
| 647 | +nfs42_proc_offload_status(struct file *dst, nfs4_stateid *stateid, u64 *copied) |
| 648 | +{ |
| 649 | + struct inode *inode = file_inode(dst); |
| 650 | + struct nfs_server *server = NFS_SERVER(inode); |
| 651 | + struct nfs4_exception exception = { |
| 652 | + .inode = inode, |
| 653 | + }; |
| 654 | + struct nfs42_offload_data *data; |
| 655 | + int status; |
| 656 | + |
| 657 | + if (!(server->caps & NFS_CAP_OFFLOAD_STATUS)) |
| 658 | + return -EOPNOTSUPP; |
| 659 | + |
| 660 | + data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 661 | + if (!data) |
| 662 | + return -ENOMEM; |
| 663 | + data->seq_server = server; |
| 664 | + data->args.osa_src_fh = NFS_FH(inode); |
| 665 | + memcpy(&data->args.osa_stateid, stateid, |
| 666 | + sizeof(data->args.osa_stateid)); |
| 667 | + exception.stateid = &data->args.osa_stateid; |
| 668 | + do { |
| 669 | + status = _nfs42_proc_offload_status(server, dst, data); |
| 670 | + if (status == -EOPNOTSUPP) |
| 671 | + goto out; |
| 672 | + status = nfs4_handle_exception(server, status, &exception); |
| 673 | + } while (exception.retry); |
| 674 | + if (status) |
| 675 | + goto out; |
| 676 | + |
| 677 | + *copied = data->res.osr_count; |
| 678 | + if (!data->res.complete_count) |
| 679 | + status = -EINPROGRESS; |
| 680 | + else if (data->res.osr_complete != NFS_OK) |
| 681 | + status = -EREMOTEIO; |
| 682 | + |
| 683 | +out: |
| 684 | + kfree(data); |
| 685 | + return status; |
| 686 | +} |
| 687 | + |
585 | 688 | static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
586 | 689 | struct nfs42_copy_notify_args *args,
|
587 | 690 | struct nfs42_copy_notify_res *res)
|
|
0 commit comments