From: Jeff Layton <jlayton@kernel.org>
To: Calum Mackay <calum.mackay@oracle.com>
Cc: Chuck Lever <cel@kernel.org>, NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
linux-nfs@vger.kernel.org, Jeff Layton <jlayton@kernel.org>
Subject: [PATCH pynfs 13/13] server41tests: test inter-server COPY
Date: Thu, 09 Jul 2026 15:02:41 -0400 [thread overview]
Message-ID: <20260709-copy-v1-13-849bf581d7cb@kernel.org> (raw)
In-Reply-To: <20260709-copy-v1-0-849bf581d7cb@kernel.org>
Add INTERCOPY1, a full NFSv4.2 server-to-server COPY across two servers.
The source file is created on the second server and the destination on
the primary server; the client issues COPY_NOTIFY to the source, then
COPY to the destination naming the source via ca_source_server, and
verifies the copied data.
The test requires --server2 SERVER:/PATH and is reported as unsupported
when no second server is configured or when either server lacks the
inter-server copy operations.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
nfs4.1/server41tests/st_copy.py | 80 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/nfs4.1/server41tests/st_copy.py b/nfs4.1/server41tests/st_copy.py
index 7eb6e2c98c4d..9cb9c199a025 100644
--- a/nfs4.1/server41tests/st_copy.py
+++ b/nfs4.1/server41tests/st_copy.py
@@ -436,3 +436,83 @@ def testCopyNotifyNoFh(t, env):
t.fail_support("Server does not support COPY_NOTIFY "
"(inter-server copy source)")
check(res, NFS4ERR_NOFILEHANDLE, msg="COPY_NOTIFY with no filehandle")
+
+def _inter_copy_ops(src_fh, src_stateid, dst_fh, dst_stateid, source_server,
+ src_offset=0, dst_offset=0, count=0,
+ consecutive=0, synchronous=1):
+ """COMPOUND for an inter-server COPY, sent to the destination server.
+
+ SAVED_FH is the source file's filehandle as known to the source server;
+ the destination server treats it as opaque and forwards it to the source
+ named by source_server (a non-empty ca_source_server list is what marks
+ the copy as inter-server).
+ """
+ return [op.putfh(src_fh), op.savefh(), op.putfh(dst_fh),
+ op.copy(src_stateid, dst_stateid, src_offset, dst_offset,
+ count, consecutive, synchronous, source_server)]
+
+def testInterServerCopy(t, env):
+ """server-to-server (inter-server) COPY across two servers
+
+ Requires a second server: pass --server2 SERVER:/PATH. The source file
+ is created on the second server (env.c2, the copy source) and the
+ destination file on the primary server (env.c1, the copy destination).
+ The client issues COPY_NOTIFY to the source to authorize the destination,
+ then COPY to the destination naming the source via ca_source_server.
+
+ FLAGS: copy
+ CODE: INTERCOPY1
+ VERS: 2-
+ """
+ if env.c2 is None:
+ t.fail_support("No second server configured "
+ "(pass --server2 SERVER:/PATH to enable)")
+
+ # Source file on the second server (the copy source).
+ src_sess = env.c2.new_client_session(env.testname(t) + b"_src")
+ src_fh, src_stateid = _create_and_open(src_sess, env.testname(t))
+ data = b"inter-server copy payload " * 4096
+ _write_data(src_sess, src_fh, src_stateid, data)
+
+ # Ask the source to authorize the primary server as the copy destination.
+ dest_netloc = _server_netloc(env) # names the primary server (env.c1)
+ res = src_sess.compound([op.putfh(src_fh),
+ op.copy_notify(src_stateid, dest_netloc)])
+ check(res, [NFS4_OK, NFS4ERR_NOTSUPP], msg="COPY_NOTIFY on source server")
+ if res.status == NFS4ERR_NOTSUPP:
+ t.fail_support("Source server does not support COPY_NOTIFY")
+ cnr = res.resarray[-1]
+ copy_src_stateid = cnr.cnr_stateid
+ source_server = cnr.cnr_source_server
+ if not source_server:
+ fail("COPY_NOTIFY returned an empty cnr_source_server list")
+
+ # Destination file on the primary server (the copy destination).
+ dst_sess = env.c1.new_client_session(env.testname(t) + b"_dst")
+ dst_fh, dst_stateid = _create_and_open(dst_sess, env.testname(t))
+
+ # COPY to the destination, naming the source via ca_source_server.
+ # Inter-server copy is asynchronous on the Linux server (a synchronous
+ # request returns NFS4ERR_NOTSUPP), so ask for async and poll below.
+ ops = _inter_copy_ops(src_fh, copy_src_stateid, dst_fh, dst_stateid,
+ source_server, count=len(data), synchronous=0)
+ res = dst_sess.compound(ops)
+ check(res, [NFS4_OK, NFS4ERR_NOTSUPP], msg="inter-server COPY")
+ if res.status == NFS4ERR_NOTSUPP:
+ t.fail_support("Destination server does not support inter-server COPY")
+ cr = res.resarray[-1]
+
+ if cr.cr_resok4.cr_requirements.cr_synchronous:
+ if cr.cr_response.wr_count != len(data):
+ fail("Inter-server copy expected %d bytes, got %d" %
+ (len(data), cr.cr_response.wr_count))
+ else:
+ copy_stateid = cr.cr_response.wr_callback_id[0]
+ status = _poll_offload_status(dst_sess, dst_fh, copy_stateid)
+ if status.osr_complete[0] != NFS4_OK:
+ fail("Async inter-server copy error: %d" % status.osr_complete[0])
+ if status.osr_count != len(data):
+ fail("Expected %d bytes copied, got %d" %
+ (len(data), status.osr_count))
+
+ _verify_data(dst_sess, dst_fh, dst_stateid, data)
--
2.55.0
prev parent reply other threads:[~2026-07-09 19:02 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 19:02 [PATCH pynfs 00/13] server41tests: add some tests for copy offload Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 01/13] server41tests: add helpers and basic synchronous COPY test Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 02/13] server41tests: test COPY with non-zero offsets Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 03/13] server41tests: test async COPY with OFFLOAD_STATUS polling Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 04/13] server41tests: test OFFLOAD_STATUS persists after async copy completes Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 05/13] server41tests: test OFFLOAD_CANCEL on async copy Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 06/13] server41tests: test COPY with bad source stateid Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 07/13] server41tests: test COPY with bad destination stateid Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 08/13] server41tests: test OFFLOAD_STATUS with fabricated stateid Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 09/13] server41tests: test COPY within same file Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 10/13] nfs4.1: fix COPY_NOTIFY args union arm name in XDR Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 11/13] server41tests: test COPY_NOTIFY Jeff Layton
2026-07-09 19:02 ` [PATCH pynfs 12/13] server41tests: support a second server for inter-server copy Jeff Layton
2026-07-09 19:02 ` Jeff Layton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260709-copy-v1-13-849bf581d7cb@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=calum.mackay@oracle.com \
--cc=cel@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.