All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add some tests for unsupported fattr4 attributes
@ 2025-09-29 20:16 Chuck Lever
  2025-09-29 21:14 ` Calum Mackay
  2025-09-30 11:34 ` Jeff Layton
  0 siblings, 2 replies; 5+ messages in thread
From: Chuck Lever @ 2025-09-29 20:16 UTC (permalink / raw)
  To: Calum Mackay; +Cc: linux-nfs, Chuck Lever

From: Chuck Lever <chuck.lever@oracle.com>

Linux NFSD does not implement a handful of these NFSv4.0 fattr4
attributes. Ensure that NFSD's fattr4 result encoder is correctly
clearing the result mask and returning NFS4_OK.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 nfs4.0/servertests/st_getattr.py | 149 +++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/nfs4.0/servertests/st_getattr.py b/nfs4.0/servertests/st_getattr.py
index 1c47ebf60571..d423aa1df46d 100644
--- a/nfs4.0/servertests/st_getattr.py
+++ b/nfs4.0/servertests/st_getattr.py
@@ -521,6 +521,155 @@ def testOwnerName(t, env):
         t.fail_support("owner not a supported attribute")
     # print(res.resarray[-1].obj_attributes)
 
+def testArchive(t, env):
+    """GETATTR on "archive" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11a
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_ARCHIVE])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(archive)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("archive not a supported attribute")
+
+def testHidden(t, env):
+    """GETATTR on "hidden" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11b
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_HIDDEN])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(hidden)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("hidden not a supported attribute")
+
+def testMimetype(t, env):
+    """GETATTR on "mimetype" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11c
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_MIMETYPE])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(mimetype)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("mimetype not a supported attribute")
+
+def testQuotaAvailHard(t, env):
+    """GETATTR on "quota avail hard" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11d
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_QUOTA_AVAIL_HARD])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_hard)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("quota_avail_hard not a supported attribute")
+
+def testQuotaAvailSoft(t, env):
+    """GETATTR on "quota avail soft" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11e
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_QUOTA_AVAIL_SOFT])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_soft)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("quota_avail_soft not a supported attribute")
+
+def testQuotaUsed(t, env):
+    """GETATTR on "quota used" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11f
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_QUOTA_USED])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_used)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("quota_used not a supported attribute")
+
+def testSystem(t, env):
+    """GETATTR on "system" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11g
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_SYSTEM])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(system)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("system not a supported attribute")
+
+def testTimeBackup(t, env):
+    """GETATTR on "time backup" attribute
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11h
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_TIME_BACKUP])]
+    res = c.compound(ops)
+    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_backup)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("time_backup not a supported attribute")
+
+def testTimeAccessSet(t, env):
+    """GETATTR on "time access set" attribute (write-only)
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11i
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_TIME_ACCESS_SET])]
+    res = c.compound(ops)
+    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_access_set)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("time_access_set not a supported attribute")
+
+def testTimeModifySet(t, env):
+    """GETATTR on "time modify set" attribute (write-only)
+
+    FLAGS: getattr all
+    DEPEND: LOOKFILE
+    CODE: GATT11j
+    """
+    c = env.c1
+    ops = c.use_obj(env.opts.usefile)
+    ops += [c.getattr([FATTR4_TIME_MODIFY_SET])]
+    res = c.compound(ops)
+    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_modify_set)")
+    if res.status == NFS4ERR_ATTRNOTSUPP:
+        t.fail_support("time_modify_set not a supported attribute")
 
 ####################################################
 
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add some tests for unsupported fattr4 attributes
  2025-09-29 20:16 [PATCH] Add some tests for unsupported fattr4 attributes Chuck Lever
@ 2025-09-29 21:14 ` Calum Mackay
  2025-09-29 21:16   ` Chuck Lever
  2025-09-30 11:34 ` Jeff Layton
  1 sibling, 1 reply; 5+ messages in thread
From: Calum Mackay @ 2025-09-29 21:14 UTC (permalink / raw)
  To: Chuck Lever; +Cc: Calum Mackay, linux-nfs, Chuck Lever

thanks Chuck,

I'm still catching up with pynfs patches; I'll get this (and the others 
queued up) in asap.

cheers,
c.


On 29/09/2025 9:16 pm, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
> 
> Linux NFSD does not implement a handful of these NFSv4.0 fattr4
> attributes. Ensure that NFSD's fattr4 result encoder is correctly
> clearing the result mask and returning NFS4_OK.
> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>   nfs4.0/servertests/st_getattr.py | 149 +++++++++++++++++++++++++++++++
>   1 file changed, 149 insertions(+)
> 
> diff --git a/nfs4.0/servertests/st_getattr.py b/nfs4.0/servertests/st_getattr.py
> index 1c47ebf60571..d423aa1df46d 100644
> --- a/nfs4.0/servertests/st_getattr.py
> +++ b/nfs4.0/servertests/st_getattr.py
> @@ -521,6 +521,155 @@ def testOwnerName(t, env):
>           t.fail_support("owner not a supported attribute")
>       # print(res.resarray[-1].obj_attributes)
>   
> +def testArchive(t, env):
> +    """GETATTR on "archive" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11a
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_ARCHIVE])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(archive)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("archive not a supported attribute")
> +
> +def testHidden(t, env):
> +    """GETATTR on "hidden" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11b
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_HIDDEN])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(hidden)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("hidden not a supported attribute")
> +
> +def testMimetype(t, env):
> +    """GETATTR on "mimetype" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11c
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_MIMETYPE])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(mimetype)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("mimetype not a supported attribute")
> +
> +def testQuotaAvailHard(t, env):
> +    """GETATTR on "quota avail hard" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11d
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_HARD])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_hard)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_avail_hard not a supported attribute")
> +
> +def testQuotaAvailSoft(t, env):
> +    """GETATTR on "quota avail soft" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11e
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_SOFT])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_soft)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_avail_soft not a supported attribute")
> +
> +def testQuotaUsed(t, env):
> +    """GETATTR on "quota used" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11f
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_USED])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_used)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_used not a supported attribute")
> +
> +def testSystem(t, env):
> +    """GETATTR on "system" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11g
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_SYSTEM])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(system)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("system not a supported attribute")
> +
> +def testTimeBackup(t, env):
> +    """GETATTR on "time backup" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11h
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_BACKUP])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_backup)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_backup not a supported attribute")
> +
> +def testTimeAccessSet(t, env):
> +    """GETATTR on "time access set" attribute (write-only)
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11i
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_ACCESS_SET])]
> +    res = c.compound(ops)
> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_access_set)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_access_set not a supported attribute")
> +
> +def testTimeModifySet(t, env):
> +    """GETATTR on "time modify set" attribute (write-only)
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11j
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_MODIFY_SET])]
> +    res = c.compound(ops)
> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_modify_set)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_modify_set not a supported attribute")
>   
>   ####################################################
>   

-- 
Calum Mackay
Linux Kernel Engineering
Oracle Linux and Virtualisation


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add some tests for unsupported fattr4 attributes
  2025-09-29 21:14 ` Calum Mackay
@ 2025-09-29 21:16   ` Chuck Lever
  2025-09-29 22:10     ` Calum Mackay
  0 siblings, 1 reply; 5+ messages in thread
From: Chuck Lever @ 2025-09-29 21:16 UTC (permalink / raw)
  To: Calum Mackay; +Cc: linux-nfs, Chuck Lever

On 9/29/25 2:14 PM, Calum Mackay wrote:
> thanks Chuck,
> 
> I'm still catching up with pynfs patches; I'll get this (and the others
> queued up) in asap.

My patch deserves a smell test first, of course. I'm not at all sure
this is reasonable or proper Python.


> cheers,
> c.
> 
> 
> On 29/09/2025 9:16 pm, Chuck Lever wrote:
>> From: Chuck Lever <chuck.lever@oracle.com>
>>
>> Linux NFSD does not implement a handful of these NFSv4.0 fattr4
>> attributes. Ensure that NFSD's fattr4 result encoder is correctly
>> clearing the result mask and returning NFS4_OK.
>>
>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>> ---
>>   nfs4.0/servertests/st_getattr.py | 149 +++++++++++++++++++++++++++++++
>>   1 file changed, 149 insertions(+)
>>
>> diff --git a/nfs4.0/servertests/st_getattr.py b/nfs4.0/servertests/
>> st_getattr.py
>> index 1c47ebf60571..d423aa1df46d 100644
>> --- a/nfs4.0/servertests/st_getattr.py
>> +++ b/nfs4.0/servertests/st_getattr.py
>> @@ -521,6 +521,155 @@ def testOwnerName(t, env):
>>           t.fail_support("owner not a supported attribute")
>>       # print(res.resarray[-1].obj_attributes)
>>   +def testArchive(t, env):
>> +    """GETATTR on "archive" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11a
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_ARCHIVE])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(archive)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("archive not a supported attribute")
>> +
>> +def testHidden(t, env):
>> +    """GETATTR on "hidden" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11b
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_HIDDEN])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(hidden)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("hidden not a supported attribute")
>> +
>> +def testMimetype(t, env):
>> +    """GETATTR on "mimetype" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11c
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_MIMETYPE])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(mimetype)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("mimetype not a supported attribute")
>> +
>> +def testQuotaAvailHard(t, env):
>> +    """GETATTR on "quota avail hard" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11d
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_HARD])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP],
>> "GETATTR(quota_avail_hard)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("quota_avail_hard not a supported attribute")
>> +
>> +def testQuotaAvailSoft(t, env):
>> +    """GETATTR on "quota avail soft" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11e
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_SOFT])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP],
>> "GETATTR(quota_avail_soft)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("quota_avail_soft not a supported attribute")
>> +
>> +def testQuotaUsed(t, env):
>> +    """GETATTR on "quota used" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11f
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_QUOTA_USED])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_used)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("quota_used not a supported attribute")
>> +
>> +def testSystem(t, env):
>> +    """GETATTR on "system" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11g
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_SYSTEM])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(system)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("system not a supported attribute")
>> +
>> +def testTimeBackup(t, env):
>> +    """GETATTR on "time backup" attribute
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11h
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_TIME_BACKUP])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_backup)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("time_backup not a supported attribute")
>> +
>> +def testTimeAccessSet(t, env):
>> +    """GETATTR on "time access set" attribute (write-only)
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11i
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_TIME_ACCESS_SET])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP],
>> "GETATTR(time_access_set)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("time_access_set not a supported attribute")
>> +
>> +def testTimeModifySet(t, env):
>> +    """GETATTR on "time modify set" attribute (write-only)
>> +
>> +    FLAGS: getattr all
>> +    DEPEND: LOOKFILE
>> +    CODE: GATT11j
>> +    """
>> +    c = env.c1
>> +    ops = c.use_obj(env.opts.usefile)
>> +    ops += [c.getattr([FATTR4_TIME_MODIFY_SET])]
>> +    res = c.compound(ops)
>> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP],
>> "GETATTR(time_modify_set)")
>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>> +        t.fail_support("time_modify_set not a supported attribute")
>>     ####################################################
>>   
> 


-- 
Chuck Lever

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add some tests for unsupported fattr4 attributes
  2025-09-29 21:16   ` Chuck Lever
@ 2025-09-29 22:10     ` Calum Mackay
  0 siblings, 0 replies; 5+ messages in thread
From: Calum Mackay @ 2025-09-29 22:10 UTC (permalink / raw)
  To: Chuck Lever; +Cc: Calum Mackay, linux-nfs, Chuck Lever

On 29/09/2025 10:16 pm, Chuck Lever wrote:
> On 9/29/25 2:14 PM, Calum Mackay wrote:
>> thanks Chuck,
>>
>> I'm still catching up with pynfs patches; I'll get this (and the others
>> queued up) in asap.
> 
> My patch deserves a smell test first, of course. I'm not at all sure
> this is reasonable or proper Python.

Yes, of course :)

ta,
c.



> 
> 
>> cheers,
>> c.
>>
>>
>> On 29/09/2025 9:16 pm, Chuck Lever wrote:
>>> From: Chuck Lever <chuck.lever@oracle.com>
>>>
>>> Linux NFSD does not implement a handful of these NFSv4.0 fattr4
>>> attributes. Ensure that NFSD's fattr4 result encoder is correctly
>>> clearing the result mask and returning NFS4_OK.
>>>
>>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>>> ---
>>>    nfs4.0/servertests/st_getattr.py | 149 +++++++++++++++++++++++++++++++
>>>    1 file changed, 149 insertions(+)
>>>
>>> diff --git a/nfs4.0/servertests/st_getattr.py b/nfs4.0/servertests/
>>> st_getattr.py
>>> index 1c47ebf60571..d423aa1df46d 100644
>>> --- a/nfs4.0/servertests/st_getattr.py
>>> +++ b/nfs4.0/servertests/st_getattr.py
>>> @@ -521,6 +521,155 @@ def testOwnerName(t, env):
>>>            t.fail_support("owner not a supported attribute")
>>>        # print(res.resarray[-1].obj_attributes)
>>>    +def testArchive(t, env):
>>> +    """GETATTR on "archive" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11a
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_ARCHIVE])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(archive)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("archive not a supported attribute")
>>> +
>>> +def testHidden(t, env):
>>> +    """GETATTR on "hidden" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11b
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_HIDDEN])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(hidden)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("hidden not a supported attribute")
>>> +
>>> +def testMimetype(t, env):
>>> +    """GETATTR on "mimetype" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11c
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_MIMETYPE])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(mimetype)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("mimetype not a supported attribute")
>>> +
>>> +def testQuotaAvailHard(t, env):
>>> +    """GETATTR on "quota avail hard" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11d
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_HARD])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP],
>>> "GETATTR(quota_avail_hard)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("quota_avail_hard not a supported attribute")
>>> +
>>> +def testQuotaAvailSoft(t, env):
>>> +    """GETATTR on "quota avail soft" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11e
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_SOFT])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP],
>>> "GETATTR(quota_avail_soft)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("quota_avail_soft not a supported attribute")
>>> +
>>> +def testQuotaUsed(t, env):
>>> +    """GETATTR on "quota used" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11f
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_QUOTA_USED])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_used)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("quota_used not a supported attribute")
>>> +
>>> +def testSystem(t, env):
>>> +    """GETATTR on "system" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11g
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_SYSTEM])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(system)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("system not a supported attribute")
>>> +
>>> +def testTimeBackup(t, env):
>>> +    """GETATTR on "time backup" attribute
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11h
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_TIME_BACKUP])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_backup)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("time_backup not a supported attribute")
>>> +
>>> +def testTimeAccessSet(t, env):
>>> +    """GETATTR on "time access set" attribute (write-only)
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11i
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_TIME_ACCESS_SET])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP],
>>> "GETATTR(time_access_set)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("time_access_set not a supported attribute")
>>> +
>>> +def testTimeModifySet(t, env):
>>> +    """GETATTR on "time modify set" attribute (write-only)
>>> +
>>> +    FLAGS: getattr all
>>> +    DEPEND: LOOKFILE
>>> +    CODE: GATT11j
>>> +    """
>>> +    c = env.c1
>>> +    ops = c.use_obj(env.opts.usefile)
>>> +    ops += [c.getattr([FATTR4_TIME_MODIFY_SET])]
>>> +    res = c.compound(ops)
>>> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP],
>>> "GETATTR(time_modify_set)")
>>> +    if res.status == NFS4ERR_ATTRNOTSUPP:
>>> +        t.fail_support("time_modify_set not a supported attribute")
>>>      ####################################################
>>>    
>>
> 
> 

-- 
Calum Mackay
Linux Kernel Engineering
Oracle Linux and Virtualisation


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add some tests for unsupported fattr4 attributes
  2025-09-29 20:16 [PATCH] Add some tests for unsupported fattr4 attributes Chuck Lever
  2025-09-29 21:14 ` Calum Mackay
@ 2025-09-30 11:34 ` Jeff Layton
  1 sibling, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2025-09-30 11:34 UTC (permalink / raw)
  To: Chuck Lever, Calum Mackay; +Cc: linux-nfs, Chuck Lever

On Mon, 2025-09-29 at 16:16 -0400, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
> 
> Linux NFSD does not implement a handful of these NFSv4.0 fattr4
> attributes. Ensure that NFSD's fattr4 result encoder is correctly
> clearing the result mask and returning NFS4_OK.
> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>  nfs4.0/servertests/st_getattr.py | 149 +++++++++++++++++++++++++++++++
>  1 file changed, 149 insertions(+)
> 
> diff --git a/nfs4.0/servertests/st_getattr.py b/nfs4.0/servertests/st_getattr.py
> index 1c47ebf60571..d423aa1df46d 100644
> --- a/nfs4.0/servertests/st_getattr.py
> +++ b/nfs4.0/servertests/st_getattr.py
> @@ -521,6 +521,155 @@ def testOwnerName(t, env):
>          t.fail_support("owner not a supported attribute")
>      # print(res.resarray[-1].obj_attributes)
>  
> +def testArchive(t, env):
> +    """GETATTR on "archive" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11a
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_ARCHIVE])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(archive)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("archive not a supported attribute")
> +
> +def testHidden(t, env):
> +    """GETATTR on "hidden" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11b
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_HIDDEN])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(hidden)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("hidden not a supported attribute")
> +
> +def testMimetype(t, env):
> +    """GETATTR on "mimetype" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11c
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_MIMETYPE])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(mimetype)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("mimetype not a supported attribute")
> +
> +def testQuotaAvailHard(t, env):
> +    """GETATTR on "quota avail hard" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11d
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_HARD])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_hard)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_avail_hard not a supported attribute")
> +
> +def testQuotaAvailSoft(t, env):
> +    """GETATTR on "quota avail soft" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11e
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_AVAIL_SOFT])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_avail_soft)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_avail_soft not a supported attribute")
> +
> +def testQuotaUsed(t, env):
> +    """GETATTR on "quota used" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11f
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_QUOTA_USED])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(quota_used)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("quota_used not a supported attribute")
> +
> +def testSystem(t, env):
> +    """GETATTR on "system" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11g
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_SYSTEM])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(system)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("system not a supported attribute")
> +
> +def testTimeBackup(t, env):
> +    """GETATTR on "time backup" attribute
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11h
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_BACKUP])]
> +    res = c.compound(ops)
> +    check(res, [NFS4_OK, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_backup)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_backup not a supported attribute")
> +
> +def testTimeAccessSet(t, env):
> +    """GETATTR on "time access set" attribute (write-only)
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11i
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_ACCESS_SET])]
> +    res = c.compound(ops)
> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_access_set)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_access_set not a supported attribute")
> +
> +def testTimeModifySet(t, env):
> +    """GETATTR on "time modify set" attribute (write-only)
> +
> +    FLAGS: getattr all
> +    DEPEND: LOOKFILE
> +    CODE: GATT11j
> +    """
> +    c = env.c1
> +    ops = c.use_obj(env.opts.usefile)
> +    ops += [c.getattr([FATTR4_TIME_MODIFY_SET])]
> +    res = c.compound(ops)
> +    check(res, [NFS4ERR_INVAL, NFS4ERR_ATTRNOTSUPP], "GETATTR(time_modify_set)")
> +    if res.status == NFS4ERR_ATTRNOTSUPP:
> +        t.fail_support("time_modify_set not a supported attribute")
>  
>  ####################################################
>  

Reviewed-by: Jeff Layton <jlayton@kernel.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-09-30 11:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-29 20:16 [PATCH] Add some tests for unsupported fattr4 attributes Chuck Lever
2025-09-29 21:14 ` Calum Mackay
2025-09-29 21:16   ` Chuck Lever
2025-09-29 22:10     ` Calum Mackay
2025-09-30 11:34 ` Jeff Layton

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.