Linux NFS development
 help / color / mirror / Atom feed
From: Chuck Lever <cel@kernel.org>
To: Calum Mackay <calum.mackay@oracle.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH v1 3/8] pynfs: add test for a delegation request after a recall
Date: Thu,  8 Oct 2026 11:47:24 -0400	[thread overview]
Message-ID: <20261008154729.77787-4-cel@kernel.org> (raw)
In-Reply-To: <20261008154729.77787-1-cel@kernel.org>

RFC 8881 Section 10.4.7 names re-establishing a recalled delegation
as a use for a delegation want. No test asks for a delegation again
once the conflicting open is gone, so a server that never grants one
on that file again, or that misreports why, goes unnoticed.

Add DELEG29. It has a second client recall a read delegation and
then close its open. The first client then sends OPEN(CLAIM_FH) with
WANT_READ_DELEG three times, at 0, 65, and 100 seconds, and the
failure message gives the outcome of each. The test accepts a
delegation or OPEN_DELEGATE_NONE_EXT with WND4_CONTENTION. A reply
that names another reason, or that is a bare OPEN_DELEGATE_NONE,
fails it. The delays separate a refusal that ends from one that does
not. NFSD, for one, blocks a recalled file for at least 30 seconds
and ages the block only when a delegation request arrives, so the
block can outlast the second request.

Signed-off-by: Chuck Lever <cel@kernel.org>
---
 nfs4.1/server41tests/st_delegation.py | 73 +++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/nfs4.1/server41tests/st_delegation.py b/nfs4.1/server41tests/st_delegation.py
index 56d227127a15..8addde6c4fbf 100644
--- a/nfs4.1/server41tests/st_delegation.py
+++ b/nfs4.1/server41tests/st_delegation.py
@@ -727,3 +727,76 @@ def testClaimFHUpgradeReadDeleg(t, env):
     check(res)
     res = close_file(sess1, fh, stateid=upgraded)
     check(res)
+
+def testClaimFHAfterRecall(t, env):
+    """OPEN(CLAIM_FH) with WANT_READ_DELEG after the delegation was
+       recalled and the conflicting open has been closed
+
+    The request is made three times: right after the conflicting open
+    is closed, 65 seconds later, and 100 seconds later. A server can
+    refuse a delegation on a recently recalled file for a while, and
+    it can age that refusal only when a request arrives. The last
+    request shows whether the refusal ever ends. Any reply may carry
+    a delegation or WND4_CONTENTION.
+
+    FLAGS: open deleg
+    CODE: DELEG30
+    """
+    recall = threading.Event()
+    def pre_hook(arg, env):
+        env.notify = recall.set
+    def post_hook(arg, env, res):
+        return res
+    name = env.testname(t)
+    sess1 = env.c1.new_client_session(b"%s_1" % name)
+    sess1.client.cb_pre_hook(OP_CB_RECALL, pre_hook)
+    sess1.client.cb_post_hook(OP_CB_RECALL, post_hook)
+    access = OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG
+    fh, stateid, deleg = __create_file_with_deleg(sess1, name, access)
+
+    sess2 = env.c1.new_client_session(b"%s_2" % name)
+    open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE,
+                      open_owner4(0, b"My Open Owner 2"),
+                      openflag4(OPEN4_NOCREATE), open_claim4(CLAIM_NULL, name))
+    slot = sess2.compound_async(env.home + [open_op])
+    completed = recall.wait(2)
+    env.sleep(.1)
+    res = sess1.compound([op.putfh(fh), op.delegreturn(deleg.read.stateid)])
+    check(res)
+    res = sess2.listen(slot)
+    if not completed:
+        fail("delegation break not received")
+    for i in range(5):
+        if res.status != NFS4ERR_DELAY:
+            break
+        env.sleep(1)
+        res = sess2.compound(env.home + [open_op])
+    check(res)
+    res = close_file(sess2, fh, stateid=res.resarray[-1].stateid)
+    check(res)
+
+    passed = True
+    results = []
+    elapsed = 0
+    for delay in (0, 65, 100):
+        # Sleep in short steps so that the lease does not expire
+        while elapsed < delay:
+            env.sleep(5)
+            elapsed += 5
+            check(sess1.compound([]))
+        res = _open_claim_fh(sess1, fh, name, access)
+        check(res)
+        stateid = res.resarray[-1].stateid
+        deleg = res.resarray[-1].delegation
+        _delegreturn(sess1, fh, deleg)
+        if (not _got_deleg(deleg) and
+            (deleg.delegation_type != OPEN_DELEGATE_NONE_EXT or
+             deleg.ond_why != WND4_CONTENTION)):
+            passed = False
+        results.append("after %i seconds: %s" % (delay, _deleg_desc(deleg)))
+    results = "; ".join(results)
+    res = close_file(sess1, fh, stateid=stateid)
+    check(res)
+    if not passed:
+        fail(results)
+    print(results)
-- 
2.55.0


  parent reply	other threads:[~2026-10-08 15:47 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08 15:47 [PATCH v1 0/8] Test the WANT_*_DELEG OPEN flags Chuck Lever
2026-10-08 15:47 ` [PATCH v1 1/8] pynfs: add test for OPEN(CLAIM_FH) with WANT_READ_DELEG Chuck Lever
2026-10-09  7:58   ` Substituting WANT_DELEGATION with OPEN(CLAIM_FH)? " Lionel Cons
2026-10-08 15:47 ` [PATCH v1 2/8] pynfs: add test for OPEN(CLAIM_FH) delegation request on an open file Chuck Lever
2026-10-08 15:47 ` Chuck Lever [this message]
2026-10-08 15:47 ` [PATCH v1 4/8] pynfs: add tests for SETATTR by a delegation holder Chuck Lever
2026-10-08 15:47 ` [PATCH v1 5/8] pynfs: add test for WANT_OPEN_XOR_DELEGATION through CLAIM_FH Chuck Lever
2026-10-08 15:47 ` [PATCH v1 6/8] pynfs: add test for a CLAIM_FH delegation that outlives its open Chuck Lever
2026-10-08 15:47 ` [PATCH v1 7/8] pynfs: add tests for delegation upgrade and downgrade wants Chuck Lever
2026-10-08 15:47 ` [PATCH v1 8/8] pynfs: add test for OPEN with WANT_CANCEL 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=20261008154729.77787-4-cel@kernel.org \
    --to=cel@kernel.org \
    --cc=calum.mackay@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    /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