Linux NFS development
 help / color / mirror / Atom feed
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)

  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