Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFS: Implement NFSv4.2's OFFLOAD_STATUS operation

Enable the Linux NFS client to observe the progress of an offloaded
asynchronous COPY operation. This new operation will be put to use
in a subsequent patch.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Link: https://lore.kernel.org/r/20250113153235.48706-14-cel@kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

authored by

Chuck Lever and committed by
Trond Myklebust
77dd8a30 8955e7ce

+106 -1
+103
fs/nfs/nfs42proc.c
··· 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 { ··· 581 579 if (status == -ENOTSUPP) 582 580 dst_server->caps &= ~NFS_CAP_OFFLOAD_CANCEL; 583 581 rpc_put_task(task); 582 + return status; 583 + } 584 + 585 + static int 586 + _nfs42_proc_offload_status(struct nfs_server *server, struct file *file, 587 + struct nfs42_offload_data *data) 588 + { 589 + struct nfs_open_context *ctx = nfs_file_open_context(file); 590 + struct rpc_message msg = { 591 + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OFFLOAD_STATUS], 592 + .rpc_argp = &data->args, 593 + .rpc_resp = &data->res, 594 + .rpc_cred = ctx->cred, 595 + }; 596 + int status; 597 + 598 + status = nfs4_call_sync(server->client, server, &msg, 599 + &data->args.osa_seq_args, 600 + &data->res.osr_seq_res, 1); 601 + switch (status) { 602 + case 0: 603 + break; 604 + 605 + case -NFS4ERR_ADMIN_REVOKED: 606 + case -NFS4ERR_BAD_STATEID: 607 + case -NFS4ERR_OLD_STATEID: 608 + /* 609 + * Server does not recognize the COPY stateid. CB_OFFLOAD 610 + * could have purged it, or server might have rebooted. 611 + * Since COPY stateids don't have an associated inode, 612 + * avoid triggering state recovery. 613 + */ 614 + status = -EBADF; 615 + break; 616 + case -NFS4ERR_NOTSUPP: 617 + case -ENOTSUPP: 618 + case -EOPNOTSUPP: 619 + server->caps &= ~NFS_CAP_OFFLOAD_STATUS; 620 + status = -EOPNOTSUPP; 621 + break; 622 + } 623 + 624 + return status; 625 + } 626 + 627 + /** 628 + * nfs42_proc_offload_status - Poll completion status of an async copy operation 629 + * @dst: handle of file being copied into 630 + * @stateid: copy stateid (from async COPY result) 631 + * @copied: OUT: number of bytes copied so far 632 + * 633 + * Return values: 634 + * %0: Server returned an NFS4_OK completion status 635 + * %-EINPROGRESS: Server returned no completion status 636 + * %-EREMOTEIO: Server returned an error completion status 637 + * %-EBADF: Server did not recognize the copy stateid 638 + * %-EOPNOTSUPP: Server does not support OFFLOAD_STATUS 639 + * %-ERESTARTSYS: Wait interrupted by signal 640 + * 641 + * Other negative errnos indicate the client could not complete the 642 + * request. 643 + */ 644 + static int __maybe_unused 645 + nfs42_proc_offload_status(struct file *dst, nfs4_stateid *stateid, u64 *copied) 646 + { 647 + struct inode *inode = file_inode(dst); 648 + struct nfs_server *server = NFS_SERVER(inode); 649 + struct nfs4_exception exception = { 650 + .inode = inode, 651 + }; 652 + struct nfs42_offload_data *data; 653 + int status; 654 + 655 + if (!(server->caps & NFS_CAP_OFFLOAD_STATUS)) 656 + return -EOPNOTSUPP; 657 + 658 + data = kzalloc(sizeof(*data), GFP_KERNEL); 659 + if (!data) 660 + return -ENOMEM; 661 + data->seq_server = server; 662 + data->args.osa_src_fh = NFS_FH(inode); 663 + memcpy(&data->args.osa_stateid, stateid, 664 + sizeof(data->args.osa_stateid)); 665 + exception.stateid = &data->args.osa_stateid; 666 + do { 667 + status = _nfs42_proc_offload_status(server, dst, data); 668 + if (status == -EOPNOTSUPP) 669 + goto out; 670 + status = nfs4_handle_exception(server, status, &exception); 671 + } while (exception.retry); 672 + if (status) 673 + goto out; 674 + 675 + *copied = data->res.osr_count; 676 + if (!data->res.complete_count) 677 + status = -EINPROGRESS; 678 + else if (data->res.osr_complete != NFS_OK) 679 + status = -EREMOTEIO; 680 + 681 + out: 682 + kfree(data); 584 683 return status; 585 684 } 586 685
+2 -1
fs/nfs/nfs4proc.c
··· 10781 10781 | NFS_CAP_CLONE 10782 10782 | NFS_CAP_LAYOUTERROR 10783 10783 | NFS_CAP_READ_PLUS 10784 - | NFS_CAP_MOVEABLE, 10784 + | NFS_CAP_MOVEABLE 10785 + | NFS_CAP_OFFLOAD_STATUS, 10785 10786 .init_client = nfs41_init_client, 10786 10787 .shutdown_client = nfs41_shutdown_client, 10787 10788 .match_stateid = nfs41_match_stateid,
+1
include/linux/nfs_fs_sb.h
··· 293 293 #define NFS_CAP_CASE_INSENSITIVE (1U << 6) 294 294 #define NFS_CAP_CASE_PRESERVING (1U << 7) 295 295 #define NFS_CAP_REBOOT_LAYOUTRETURN (1U << 8) 296 + #define NFS_CAP_OFFLOAD_STATUS (1U << 9) 296 297 #define NFS_CAP_OPEN_XOR (1U << 12) 297 298 #define NFS_CAP_DELEGTIME (1U << 13) 298 299 #define NFS_CAP_POSIX_LOCK (1U << 14)