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 5/8] pynfs: add test for WANT_OPEN_XOR_DELEGATION through CLAIM_FH
Date: Thu,  8 Oct 2026 11:47:26 -0400	[thread overview]
Message-ID: <20261008154729.77787-6-cel@kernel.org> (raw)
In-Reply-To: <20261008154729.77787-1-cel@kernel.org>

An OPEN(CLAIM_FH) from the open-owner that already has the file open
bumps the seqid of that owner's open stateid, even when the client
only wants a delegation. RFC 9754 gives the client a way around
that: send the OPEN from a second open-owner with
OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION, and the server returns
the delegation alone. No test exercises XOR.

Add DELEG32. It holds the file open under one open-owner and sends
the XOR request from another. The reply has to carry a read
delegation and OPEN4_RESULT_NO_OPEN_STATEID, and the first owner's
open stateid has to keep its seqid. The test reports UNSUPPORTED
when the open_arguments attribute does not advertise XOR.

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

diff --git a/nfs4.1/server41tests/st_delegation.py b/nfs4.1/server41tests/st_delegation.py
index 198555ce9b9d..a8b7ea54a772 100644
--- a/nfs4.1/server41tests/st_delegation.py
+++ b/nfs4.1/server41tests/st_delegation.py
@@ -859,3 +859,62 @@ def testReadDelegHolderSetattr(t, env):
     _testHolderSetattr(t, env, OPEN4_SHARE_ACCESS_READ |
                        OPEN4_SHARE_ACCESS_WANT_READ_DELEG,
                        OPEN_DELEGATE_READ)
+
+def testClaimFHXorDeleg(t, env):
+    """OPEN(CLAIM_FH) with WANT_OPEN_XOR_DELEGATION from a second
+       open-owner returns a delegation and no open stateid
+
+    FLAGS: open deleg all
+    CODE: DELEG33
+    """
+    name = env.testname(t)
+    sess1 = env.c1.new_client_session(b"%s_1" % name)
+    res = sess1.compound([op.putrootfh(),
+                          op.getattr(nfs4lib.list2bitmap([FATTR4_OPEN_ARGUMENTS]))])
+    check(res)
+    caps = res.resarray[-1].obj_attributes
+    xor = 1 << OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION
+    if (FATTR4_OPEN_ARGUMENTS not in caps or
+        not caps[FATTR4_OPEN_ARGUMENTS].oa_share_access_want & xor):
+        t.fail_support("Server does not advertise WANT_OPEN_XOR_DELEGATION")
+
+    res = create_file(sess1, name, access=OPEN4_SHARE_ACCESS_READ |
+                      OPEN4_SHARE_ACCESS_WANT_NO_DELEG)
+    check(res)
+    fh = res.resarray[-1].object
+    stateid = res.resarray[-2].stateid
+
+    owner2 = b"%s_2" % name
+    access = (OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG |
+              OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION)
+    res = _open_claim_fh(sess1, fh, owner2, access)
+    check(res)
+    if not _got_deleg(res.resarray[-1].delegation):
+        # Close first, so that the retry is not an upgrade of this open
+        res = close_file(sess1, fh, stateid=res.resarray[-1].stateid)
+        check(res)
+        res = _open_claim_fh(sess1, fh, owner2, access)
+        check(res)
+    deleg = res.resarray[-1].delegation
+    if deleg.delegation_type != OPEN_DELEGATE_READ:
+        fail("Expected a read delegation, got %s" % _deleg_desc(deleg))
+    if not res.resarray[-1].rflags & OPEN4_RESULT_NO_OPEN_STATEID:
+        _delegreturn(sess1, fh, deleg)
+        fail("Got a delegation, but OPEN4_RESULT_NO_OPEN_STATEID is not set")
+
+    # An OPEN by the first open-owner bumps its seqid once. Any other
+    # seqid means the second open-owner's OPEN changed that stateid.
+    res = _open_claim_fh(sess1, fh, name, OPEN4_SHARE_ACCESS_READ |
+                         OPEN4_SHARE_ACCESS_WANT_NO_DELEG)
+    check(res)
+    upgraded = res.resarray[-1].stateid
+    if upgraded.other != stateid.other:
+        fail("OPEN by the same open-owner returned a different stateid")
+    if upgraded.seqid != stateid.seqid + 1:
+        fail("Expected open stateid seqid %i, got %i" %
+             (stateid.seqid + 1, upgraded.seqid))
+
+    res = sess1.compound([op.putfh(fh), op.delegreturn(deleg.read.stateid)])
+    check(res)
+    res = close_file(sess1, fh, stateid=upgraded)
+    check(res)
-- 
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 ` [PATCH v1 3/8] pynfs: add test for a delegation request after a recall Chuck Lever
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 ` Chuck Lever [this message]
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-6-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