From: "Chuck Lever" <cel@kernel.org>
To: "Jeff Layton" <jlayton@kernel.org>,
"Calum Mackay" <calum.mackay@oracle.com>
Cc: "Chuck Lever" <chuck.lever@vger.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
Subject: Re: [PATCH pynfs] RPLY14: reconnect before retransmitting the call
Date: Thu, 24 Sep 2026 09:14:42 -0400 [thread overview]
Message-ID: <32c54d0b-0760-45ba-8ecb-edbbe0ff1210@app.fastmail.com> (raw)
In-Reply-To: <20260923-rply14-v1-1-f653557909af@kernel.org>
On Wed, Sep 23, 2026, at 1:43 PM, Jeff Layton wrote:
> This test recently started failing with a change to the Linux kernel,
> but we believe that the test is wrong. This test replays the same call
> with the same XID over the same socket without reconnecting in between.
>
> There is language in RFC1813 that implies that a reconnect is necessary
> on a retransmit on a reliable transport like TCP.
I'd like to see a specific Section number and maybe even a block
quote.
But RFC 1813 is not normative for NFSv4.0. Does RFC 7530 have
anything to say about retransmission of NFS requests on
connection-oriented RPC transports?
One more below.
> Change the test to
> reconnect the socket before retransmitting.
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> nfs4.0/lib/rpc/rpc.py | 25 +++++++++++++++++++++++++
> nfs4.0/servertests/st_replay.py | 10 ++++++++--
> 2 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/nfs4.0/lib/rpc/rpc.py b/nfs4.0/lib/rpc/rpc.py
> index 7a80241aa127..c530847a46d9 100644
> --- a/nfs4.0/lib/rpc/rpc.py
> +++ b/nfs4.0/lib/rpc/rpc.py
> @@ -315,6 +315,31 @@ class RPCClient(object):
> out.settimeout(self.timeout)
> self.lock.release()
> return out
> +
> + def reconnect_same_port(self):
> + """Drop the current connection and reconnect from the same local
> + port, so the server sees a new transport with an unchanged
> + (address, port) cache key. Used to test duplicate reply cache
> + behavior across connections.
> +
> + The old socket is reset (RST) rather than closed gracefully: a
> + graceful close leaves the 4-tuple unusable until the server
> + also closes, while an RST frees the source port immediately.
> + """
> + t = threading.currentThread()
> + self.lock.acquire()
> + old = self._socket[t]
> + saddr = old.getsockname()
> + old.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
> + struct.pack('ii', 1, 0))
> + old.close()
> + out = self._socket[t] = socket.socket(self.af, socket.SOCK_STREAM)
> + out.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
> + out.bind(saddr)
> + out.connect((self.remotehost, self.remoteport))
> + out.settimeout(self.timeout)
> + self.lock.release()
> + return out
>
> def send(self, procedure, data=b'', program=None, version=None):
> """Send an RPC call to the server
> diff --git a/nfs4.0/servertests/st_replay.py b/nfs4.0/servertests/st_replay.py
> index 48e5363432ec..fc8282151909 100644
> --- a/nfs4.0/servertests/st_replay.py
> +++ b/nfs4.0/servertests/st_replay.py
> @@ -4,7 +4,7 @@ from xdrdef.nfs4_type import *
> import nfs_ops
> op = nfs_ops.NFS4ops()
>
> -def _replay(env, c, ops, error=NFS4_OK):
> +def _replay(env, c, ops, error=NFS4_OK, newconn=False):
> # Can send in an error list, but replays must return same error as orig
> if type(error) is list:
> check_funct = check
> @@ -18,6 +18,12 @@ def _replay(env, c, ops, error=NFS4_OK):
> try:
> c.get_new_xid = lambda : xid
>
> + if newconn:
> + # Reconnect from the same source port before replaying:
> + # servers may drop a retransmit that arrives on the same
> + # connection as the original call.
This comment echoes the documenting comment in front of reconnect_same_port
and can be dropped.
> + c.reconnect_same_port()
> +
> # note: this is really cheesy: we happen to know the current
> # Linux server implementation will drop a replay if it comes
> # "too quickly" (<.02 seconds).
> @@ -260,4 +266,4 @@ def testMkdirReplay(t, env):
> c = env.c1
> c.init_connection()
> ops = c.go_home() + [op.create(createtype4(NF4DIR), t.word(), {})]
> - _replay(env, c, ops)
> + _replay(env, c, ops, newconn=True)
>
> ---
> base-commit: cd4701827a8261fedbfb4c6e39029fb9671321a6
> change-id: 20260923-rply14-d24b334cd6fa
>
> Best regards,
> --
> Jeff Layton <jlayton@kernel.org>
--
Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)
next prev parent reply other threads:[~2026-09-24 13:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 17:43 [PATCH pynfs] RPLY14: reconnect before retransmitting the call Jeff Layton
2026-09-24 13:14 ` Chuck Lever [this message]
2026-09-24 21:46 ` NeilBrown
2026-09-25 14:04 ` Chuck Lever
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=32c54d0b-0760-45ba-8ecb-edbbe0ff1210@app.fastmail.com \
--to=cel@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=calum.mackay@oracle.com \
--cc=chuck.lever@vger.kernel.org \
--cc=jlayton@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox