Skip to content

Commit 77dd8a3

Browse files
chuckleverTrond Myklebust
authored andcommitted
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 <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Benjamin Coddington <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Trond Myklebust <[email protected]>
1 parent 8955e7c commit 77dd8a3

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

fs/nfs/nfs42proc.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#define NFSDBG_FACILITY NFSDBG_PROC
2323
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);
2426

2527
static void nfs42_set_netaddr(struct file *filep, struct nfs42_netaddr *naddr)
2628
{
@@ -582,6 +584,107 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
582584
return status;
583585
}
584586

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+
585688
static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
586689
struct nfs42_copy_notify_args *args,
587690
struct nfs42_copy_notify_res *res)

fs/nfs/nfs4proc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10781,7 +10781,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
1078110781
| NFS_CAP_CLONE
1078210782
| NFS_CAP_LAYOUTERROR
1078310783
| NFS_CAP_READ_PLUS
10784-
| NFS_CAP_MOVEABLE,
10784+
| NFS_CAP_MOVEABLE
10785+
| NFS_CAP_OFFLOAD_STATUS,
1078510786
.init_client = nfs41_init_client,
1078610787
.shutdown_client = nfs41_shutdown_client,
1078710788
.match_stateid = nfs41_match_stateid,

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ struct nfs_server {
293293
#define NFS_CAP_CASE_INSENSITIVE (1U << 6)
294294
#define NFS_CAP_CASE_PRESERVING (1U << 7)
295295
#define NFS_CAP_REBOOT_LAYOUTRETURN (1U << 8)
296+
#define NFS_CAP_OFFLOAD_STATUS (1U << 9)
296297
#define NFS_CAP_OPEN_XOR (1U << 12)
297298
#define NFS_CAP_DELEGTIME (1U << 13)
298299
#define NFS_CAP_POSIX_LOCK (1U << 14)

0 commit comments

Comments
 (0)