From 0ac903d1bfdce8ff40657c2b7d996947b72b6645 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 9 Dec 2025 19:28:50 -0500 Subject: NFS: NFSERR_INVAL is not defined by NFSv2 A documenting comment in include/uapi/linux/nfs.h claims incorrectly that NFSv2 defines NFSERR_INVAL. There is no such definition in either RFC 1094 or https://pubs.opengroup.org/onlinepubs/9629799/chap7.htm NFS3ERR_INVAL is introduced in RFC 1813. NFSD returns NFSERR_INVAL for PROC_GETACL, which has no specification (yet). However, nfsd_map_status() maps nfserr_symlink and nfserr_wrong_type to nfserr_inval, which does not align with RFC 1094. This logic was introduced only recently by commit 438f81e0e92a ("nfsd: move error choice for incorrect object types to version-specific code."). Given that we have no INVAL or SERVERFAULT status in NFSv2, probably the only choice is NFSERR_IO. Fixes: 438f81e0e92a ("nfsd: move error choice for incorrect object types to version-specific code.") Reviewed-by: NeilBrown Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- include/uapi/linux/nfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/linux/nfs.h b/include/uapi/linux/nfs.h index 71c7196d3281..e629c4953534 100644 --- a/include/uapi/linux/nfs.h +++ b/include/uapi/linux/nfs.h @@ -55,7 +55,7 @@ NFSERR_NODEV = 19, /* v2 v3 v4 */ NFSERR_NOTDIR = 20, /* v2 v3 v4 */ NFSERR_ISDIR = 21, /* v2 v3 v4 */ - NFSERR_INVAL = 22, /* v2 v3 v4 */ + NFSERR_INVAL = 22, /* v3 v4 */ NFSERR_FBIG = 27, /* v2 v3 v4 */ NFSERR_NOSPC = 28, /* v2 v3 v4 */ NFSERR_ROFS = 30, /* v2 v3 v4 */ -- cgit v1.2.3 From ae78eb497868f335919db83b82eb59849c6cf251 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 16 Dec 2025 11:23:09 -0500 Subject: xdrgen: Implement short (16-bit) integer types "short" and "unsigned short" types are not defined in RFC 4506, but are supported by the rpcgen program. An upcoming protocol specification includes at least one "unsigned short" field, so xdrgen needs to implement support for these types. Signed-off-by: Chuck Lever --- include/linux/sunrpc/xdrgen/_builtins.h | 60 +++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'include') diff --git a/include/linux/sunrpc/xdrgen/_builtins.h b/include/linux/sunrpc/xdrgen/_builtins.h index 66ca3ece951a..52ed9a9151c4 100644 --- a/include/linux/sunrpc/xdrgen/_builtins.h +++ b/include/linux/sunrpc/xdrgen/_builtins.h @@ -46,6 +46,66 @@ xdrgen_encode_bool(struct xdr_stream *xdr, bool val) return true; } +/* + * De facto (non-standard but commonly implemented) signed short type: + * - Wire sends sign-extended 32-bit value (e.g., 0xFFFFFFFF) + * - be32_to_cpup() returns u32 (0xFFFFFFFF) + * - Explicit (s16) cast truncates to 16 bits (0xFFFF = -1) + */ +static inline bool +xdrgen_decode_short(struct xdr_stream *xdr, s16 *ptr) +{ + __be32 *p = xdr_inline_decode(xdr, XDR_UNIT); + + if (unlikely(!p)) + return false; + *ptr = (s16)be32_to_cpup(p); + return true; +} + +/* + * De facto (non-standard but commonly implemented) signed short type: + * - C integer promotion sign-extends s16 val to int before passing to + * cpu_to_be32() + * - This is well-defined: -1 as s16 -1 as int 0xFFFFFFFF on wire + */ +static inline bool +xdrgen_encode_short(struct xdr_stream *xdr, s16 val) +{ + __be32 *p = xdr_reserve_space(xdr, XDR_UNIT); + + if (unlikely(!p)) + return false; + *p = cpu_to_be32(val); + return true; +} + +/* + * De facto (non-standard but commonly implemented) unsigned short type: + * 16-bit integer zero-extended to fill one XDR_UNIT. + */ +static inline bool +xdrgen_decode_unsigned_short(struct xdr_stream *xdr, u16 *ptr) +{ + __be32 *p = xdr_inline_decode(xdr, XDR_UNIT); + + if (unlikely(!p)) + return false; + *ptr = (u16)be32_to_cpup(p); + return true; +} + +static inline bool +xdrgen_encode_unsigned_short(struct xdr_stream *xdr, u16 val) +{ + __be32 *p = xdr_reserve_space(xdr, XDR_UNIT); + + if (unlikely(!p)) + return false; + *p = cpu_to_be32(val); + return true; +} + static inline bool xdrgen_decode_int(struct xdr_stream *xdr, s32 *ptr) { -- cgit v1.2.3 From 27b0fcae8f535fb882b1876227a935dcfdf576aa Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 20 Dec 2025 10:41:09 -0500 Subject: xdrgen: Initialize data pointer for zero-length items The xdrgen decoders for strings and opaque data had an optimization that skipped calling xdr_inline_decode() when the item length was zero. This left the data pointer uninitialized, which could lead to unpredictable behavior when callers access it. Remove the zero-length check and always call xdr_inline_decode(). When passed a length of zero, xdr_inline_decode() returns the current buffer position, which is valid and matches the behavior of hand-coded XDR decoders throughout the kernel. Fixes: 4b132aacb076 ("tools: Add xdrgen") Reviewed-by: Jeff Layton Reviewed-by: NeilBrown Signed-off-by: Chuck Lever --- include/linux/sunrpc/xdrgen/_builtins.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/xdrgen/_builtins.h b/include/linux/sunrpc/xdrgen/_builtins.h index 52ed9a9151c4..a723fb1da9c8 100644 --- a/include/linux/sunrpc/xdrgen/_builtins.h +++ b/include/linux/sunrpc/xdrgen/_builtins.h @@ -248,12 +248,10 @@ xdrgen_decode_string(struct xdr_stream *xdr, string *ptr, u32 maxlen) return false; if (unlikely(maxlen && len > maxlen)) return false; - if (len != 0) { - p = xdr_inline_decode(xdr, len); - if (unlikely(!p)) - return false; - ptr->data = (unsigned char *)p; - } + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + return false; + ptr->data = (unsigned char *)p; ptr->len = len; return true; } @@ -279,12 +277,10 @@ xdrgen_decode_opaque(struct xdr_stream *xdr, opaque *ptr, u32 maxlen) return false; if (unlikely(maxlen && len > maxlen)) return false; - if (len != 0) { - p = xdr_inline_decode(xdr, len); - if (unlikely(!p)) - return false; - ptr->data = (u8 *)p; - } + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + return false; + ptr->data = (u8 *)p; ptr->len = len; return true; } -- cgit v1.2.3 From 5288993c4d1a8e59310e007aa68cf9b856551cc6 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 26 Dec 2025 10:19:35 -0500 Subject: xdrgen: Add enum value validation to generated decoders XDR enum decoders generated by xdrgen do not verify that incoming values are valid members of the enum. Incoming out-of-range values from malicious or buggy peers propagate through the system unchecked. Add validation logic to generated enum decoders using a switch statement that explicitly lists valid enumerator values. The compiler optimizes this to a simple range check when enum values are dense (contiguous), while correctly rejecting invalid values for sparse enums with gaps in their value ranges. The --no-enum-validation option on the source subcommand disables this validation when not needed. The minimum and maximum fields in _XdrEnum, which were previously unused placeholders for a range-based validation approach, have been removed since the switch-based validation handles both dense and sparse enums correctly. Because the new mechanism results in substantive changes to generated code, existing .x files are regenerated. Unrelated white space and semicolon changes in the generated code are due to recent commit 1c873a2fd110 ("xdrgen: Don't generate unnecessary semicolon") and commit 38c4df91242b ("xdrgen: Address some checkpatch whitespace complaints"). Reviewed-by: NeilBrown Signed-off-by: Chuck Lever --- include/linux/sunrpc/xdrgen/nfs4_1.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sunrpc/xdrgen/nfs4_1.h b/include/linux/sunrpc/xdrgen/nfs4_1.h index cf21a14aa885..352bffda08f7 100644 --- a/include/linux/sunrpc/xdrgen/nfs4_1.h +++ b/include/linux/sunrpc/xdrgen/nfs4_1.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Generated by xdrgen. Manual edits will be lost. */ /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ -/* XDR specification modification time: Mon Oct 14 09:10:13 2024 */ +/* XDR specification modification time: Thu Dec 25 13:44:43 2025 */ #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H #define _LINUX_XDRGEN_NFS4_1_DEF_H @@ -40,6 +40,7 @@ enum open_args_share_access4 { OPEN_ARGS_SHARE_ACCESS_WRITE = 2, OPEN_ARGS_SHARE_ACCESS_BOTH = 3, }; + typedef enum open_args_share_access4 open_args_share_access4; enum open_args_share_deny4 { @@ -48,6 +49,7 @@ enum open_args_share_deny4 { OPEN_ARGS_SHARE_DENY_WRITE = 2, OPEN_ARGS_SHARE_DENY_BOTH = 3, }; + typedef enum open_args_share_deny4 open_args_share_deny4; enum open_args_share_access_want4 { @@ -59,6 +61,7 @@ enum open_args_share_access_want4 { OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS = 20, OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION = 21, }; + typedef enum open_args_share_access_want4 open_args_share_access_want4; enum open_args_open_claim4 { @@ -70,6 +73,7 @@ enum open_args_open_claim4 { OPEN_ARGS_OPEN_CLAIM_DELEG_CUR_FH = 5, OPEN_ARGS_OPEN_CLAIM_DELEG_PREV_FH = 6, }; + typedef enum open_args_open_claim4 open_args_open_claim4; enum open_args_createmode4 { @@ -78,6 +82,7 @@ enum open_args_createmode4 { OPEN_ARGS_CREATEMODE_EXCLUSIVE4 = 2, OPEN_ARGS_CREATE_MODE_EXCLUSIVE4_1 = 3, }; + typedef enum open_args_createmode4 open_args_createmode4; typedef struct open_arguments4 fattr4_open_arguments; @@ -124,6 +129,7 @@ enum open_delegation_type4 { OPEN_DELEGATE_READ_ATTRS_DELEG = 4, OPEN_DELEGATE_WRITE_ATTRS_DELEG = 5, }; + typedef enum open_delegation_type4 open_delegation_type4; #define NFS4_int64_t_sz \ -- cgit v1.2.3 From e344f872628e769874c8cf30ec9a554bd55c26a3 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:43 -0500 Subject: sunrpc: split svc_set_num_threads() into two functions svc_set_num_threads() will set the number of running threads for a given pool. If the pool argument is set to NULL however, it will distribute the threads among all of the pools evenly. These divergent codepaths complicate the move to dynamic threading. Simplify the API by splitting these two cases into different helpers: Add a new svc_set_pool_threads() function that sets the number of threads in a single, given pool. Modify svc_set_num_threads() to distribute the threads evenly between all of the pools and then call svc_set_pool_threads() for each. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 5506d20857c3..2676bf276d6b 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -446,7 +446,9 @@ struct svc_serv * svc_create_pooled(struct svc_program *prog, struct svc_stat *stats, unsigned int bufsize, int (*threadfn)(void *data)); -int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int); +int svc_set_pool_threads(struct svc_serv *serv, struct svc_pool *pool, + unsigned int nrservs); +int svc_set_num_threads(struct svc_serv *serv, unsigned int nrservs); int svc_pool_stats_open(struct svc_info *si, struct file *file); void svc_process(struct svc_rqst *rqstp); void svc_process_bc(struct rpc_rqst *req, struct svc_rqst *rqstp); -- cgit v1.2.3 From 6cd60f4274b19327ebc5afa0c814b13379c34370 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:45 -0500 Subject: sunrpc: track the max number of requested threads in a pool The kernel currently tracks the number of threads running in a pool in the "sp_nrthreads" field. In the future, where threads are dynamically spun up and down, it'll be necessary to keep track of the maximum number of requested threads separately from the actual number running. Add a pool->sp_nrthrmax parameter to track this. When userland changes the number of threads in a pool, update that value accordingly. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 2676bf276d6b..ec2b6ef54823 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -35,8 +35,9 @@ */ struct svc_pool { unsigned int sp_id; /* pool id; also node id on NUMA */ + unsigned int sp_nrthreads; /* # of threads currently running in pool */ + unsigned int sp_nrthrmax; /* Max requested number of threads in pool */ struct lwq sp_xprts; /* pending transports */ - unsigned int sp_nrthreads; /* # of threads in pool */ struct list_head sp_all_threads; /* all server threads */ struct llist_head sp_idle_threads; /* idle server threads */ -- cgit v1.2.3 From 7ffc7ade2cb1138ea5d4ab55cb42c878d44165fb Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:46 -0500 Subject: sunrpc: introduce the concept of a minimum number of threads per pool Add a new pool->sp_nrthrmin field to track the minimum number of threads in a pool. Add min_threads parameters to both svc_set_num_threads() and svc_set_pool_threads(). If min_threads is non-zero and less than the max, svc_set_num_threads() will ensure that the number of running threads is between the min and the max. If the min is 0 or greater than the max, then it is ignored, and the maximum number of threads will be started, and never spun down. For now, the min_threads is always 0, but a later patch will pass the proper value through from nfsd. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index ec2b6ef54823..8fd511d02f3b 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -36,6 +36,7 @@ struct svc_pool { unsigned int sp_id; /* pool id; also node id on NUMA */ unsigned int sp_nrthreads; /* # of threads currently running in pool */ + unsigned int sp_nrthrmin; /* Min number of threads to run per pool */ unsigned int sp_nrthrmax; /* Max requested number of threads in pool */ struct lwq sp_xprts; /* pending transports */ struct list_head sp_all_threads; /* all server threads */ @@ -72,7 +73,7 @@ struct svc_serv { struct svc_stat * sv_stats; /* RPC statistics */ spinlock_t sv_lock; unsigned int sv_nprogs; /* Number of sv_programs */ - unsigned int sv_nrthreads; /* # of server threads */ + unsigned int sv_nrthreads; /* # of running server threads */ unsigned int sv_max_payload; /* datagram payload size */ unsigned int sv_max_mesg; /* max_payload + 1 page for overheads */ unsigned int sv_xdrsize; /* XDR buffer size */ @@ -448,8 +449,9 @@ struct svc_serv * svc_create_pooled(struct svc_program *prog, unsigned int bufsize, int (*threadfn)(void *data)); int svc_set_pool_threads(struct svc_serv *serv, struct svc_pool *pool, - unsigned int nrservs); -int svc_set_num_threads(struct svc_serv *serv, unsigned int nrservs); + unsigned int min_threads, unsigned int max_threads); +int svc_set_num_threads(struct svc_serv *serv, unsigned int min_threads, + unsigned int nrservs); int svc_pool_stats_open(struct svc_info *si, struct file *file); void svc_process(struct svc_rqst *rqstp); void svc_process_bc(struct rpc_rqst *req, struct svc_rqst *rqstp); -- cgit v1.2.3 From 7f221b340d16558919d963a2afed585d6a145fa4 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:47 -0500 Subject: sunrpc: split new thread creation into a separate function Break out the part of svc_start_kthreads() that creates a thread into svc_new_thread(), as a new exported helper function. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 8fd511d02f3b..b55ed8404a9e 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -442,6 +442,7 @@ struct svc_serv *svc_create(struct svc_program *, unsigned int, bool svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page); void svc_rqst_release_pages(struct svc_rqst *rqstp); +int svc_new_thread(struct svc_serv *serv, struct svc_pool *pool); void svc_exit_thread(struct svc_rqst *); struct svc_serv * svc_create_pooled(struct svc_program *prog, unsigned int nprog, -- cgit v1.2.3 From a0022a38be1017fb302563eaee54ff904be48cea Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:48 -0500 Subject: sunrpc: allow svc_recv() to return -ETIMEDOUT and -EBUSY To dynamically adjust the thread count, nfsd requires some information about how busy things are. Change svc_recv() to take a timeout value, and then allow the wait for work to time out if it's set. If a timeout is not defined, then the schedule will be set to MAX_SCHEDULE_TIMEOUT. If the task waits for the full timeout, then have it return -ETIMEDOUT to the caller. If it wakes up, finds that there is more work and that no threads are available, then attempt to set SP_TASK_STARTING. If wasn't already set, have the task return -EBUSY to cue to the caller that the service could use more threads. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 1 + include/linux/sunrpc/svcsock.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index b55ed8404a9e..4dc14c7a711b 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -55,6 +55,7 @@ enum { SP_TASK_PENDING, /* still work to do even if no xprt is queued */ SP_NEED_VICTIM, /* One thread needs to agree to exit */ SP_VICTIM_REMAINS, /* One thread needs to actually exit */ + SP_TASK_STARTING, /* Task has started but not added to idle yet */ }; diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index de37069aba90..372a00882ca6 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -61,7 +61,7 @@ static inline u32 svc_sock_final_rec(struct svc_sock *svsk) /* * Function prototypes. */ -void svc_recv(struct svc_rqst *rqstp); +int svc_recv(struct svc_rqst *rqstp, long timeo); void svc_send(struct svc_rqst *rqstp); int svc_addsock(struct svc_serv *serv, struct net *net, const int fd, char *name_return, const size_t len, -- cgit v1.2.3 From d8316b837c2ca5f92e781fa1575095c0132ae3c1 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 6 Jan 2026 13:59:50 -0500 Subject: nfsd: add controls to set the minimum number of threads per pool Add a new "min_threads" variable to the nfsd_net, along with the corresponding netlink interface, to set that value from userland. Pass that value to svc_set_pool_threads() and svc_set_num_threads(). Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- include/uapi/linux/nfsd_netlink.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_netlink.h index e157e2009ea8..e9efbc9e63d8 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -35,6 +35,7 @@ enum { NFSD_A_SERVER_GRACETIME, NFSD_A_SERVER_LEASETIME, NFSD_A_SERVER_SCOPE, + NFSD_A_SERVER_MIN_THREADS, __NFSD_A_SERVER_MAX, NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1) -- cgit v1.2.3 From 6bc85baba4b08c787a8c9ba1bb0252a83e5c5603 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 9 Jan 2026 11:21:30 -0500 Subject: xdrgen: Implement pass-through lines in specifications XDR specification files can contain lines prefixed with '%' that pass through unchanged to generated output. Traditional rpcgen removes the '%' and emits the remainder verbatim, allowing direct insertion of C includes, pragma directives, or other language- specific content into the generated code. Until now, xdrgen silently discarded these lines during parsing. This prevented specifications from including necessary headers or preprocessor directives that might be required for the generated code to compile correctly. The grammar now captures pass-through lines instead of ignoring them. A new AST node type represents pass-through content, and the AST transformer strips the leading '%' character. Definition and source generators emit pass-through content in document order, preserving the original placement within the specification. This brings xdrgen closer to feature parity with traditional rpcgen while maintaining the existing document-order processing model. Existing generated xdrgen source code has been regenerated. Signed-off-by: Chuck Lever --- include/linux/sunrpc/xdrgen/nfs4_1.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sunrpc/xdrgen/nfs4_1.h b/include/linux/sunrpc/xdrgen/nfs4_1.h index 352bffda08f7..5283739242c7 100644 --- a/include/linux/sunrpc/xdrgen/nfs4_1.h +++ b/include/linux/sunrpc/xdrgen/nfs4_1.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Generated by xdrgen. Manual edits will be lost. */ /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ -/* XDR specification modification time: Thu Dec 25 13:44:43 2025 */ +/* XDR specification modification time: Thu Jan 8 23:11:48 2026 */ #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H #define _LINUX_XDRGEN_NFS4_1_DEF_H @@ -87,6 +87,10 @@ typedef enum open_args_createmode4 open_args_createmode4; typedef struct open_arguments4 fattr4_open_arguments; +/* + * Determine what OPEN supports. + */ + enum { FATTR4_OPEN_ARGUMENTS = 86 }; enum { OPEN4_RESULT_NO_OPEN_STATEID = 0x00000010 }; @@ -95,6 +99,11 @@ typedef struct nfstime4 fattr4_time_deleg_access; typedef struct nfstime4 fattr4_time_deleg_modify; +/* + * New RECOMMENDED Attribute for + * delegation caching of times + */ + enum { FATTR4_TIME_DELEG_ACCESS = 84 }; enum { FATTR4_TIME_DELEG_MODIFY = 85 }; -- cgit v1.2.3 From 91dc464fbed3a567cbbd12b41b24f89b905ad63d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 9 Jan 2026 11:21:32 -0500 Subject: Add RPC language definition of NFSv4 POSIX ACL extension The language definition was extracted from the new draft-ietf-nfsv4-posix-acls specification. This ensures good constant and type name alignment between the spec and the Linux kernel source code, and brings in some basic XDR utilities for handling NFSv4 POSIX draft ACLs. Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- include/linux/nfs4.h | 4 ++ include/linux/sunrpc/xdrgen/nfs4_1.h | 97 +++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index e947af6a3684..d87be1f25273 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -598,6 +598,10 @@ enum { #define FATTR4_WORD2_TIME_DELEG_ACCESS BIT(FATTR4_TIME_DELEG_ACCESS - 64) #define FATTR4_WORD2_TIME_DELEG_MODIFY BIT(FATTR4_TIME_DELEG_MODIFY - 64) #define FATTR4_WORD2_OPEN_ARGUMENTS BIT(FATTR4_OPEN_ARGUMENTS - 64) +#define FATTR4_WORD2_ACL_TRUEFORM BIT(FATTR4_ACL_TRUEFORM - 64) +#define FATTR4_WORD2_ACL_TRUEFORM_SCOPE BIT(FATTR4_ACL_TRUEFORM_SCOPE - 64) +#define FATTR4_WORD2_POSIX_DEFAULT_ACL BIT(FATTR4_POSIX_DEFAULT_ACL - 64) +#define FATTR4_WORD2_POSIX_ACCESS_ACL BIT(FATTR4_POSIX_ACCESS_ACL - 64) /* MDS threshold bitmap bits */ #define THRESHOLD_RD (1UL << 0) diff --git a/include/linux/sunrpc/xdrgen/nfs4_1.h b/include/linux/sunrpc/xdrgen/nfs4_1.h index 5283739242c7..4ac54bdbd335 100644 --- a/include/linux/sunrpc/xdrgen/nfs4_1.h +++ b/include/linux/sunrpc/xdrgen/nfs4_1.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Generated by xdrgen. Manual edits will be lost. */ /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ -/* XDR specification modification time: Thu Jan 8 23:11:48 2026 */ +/* XDR specification modification time: Thu Jan 8 23:12:07 2026 */ #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H #define _LINUX_XDRGEN_NFS4_1_DEF_H @@ -18,6 +18,14 @@ typedef struct { uint32_t *element; } bitmap4; +typedef opaque utf8string; + +typedef utf8string utf8str_cis; + +typedef utf8string utf8str_cs; + +typedef utf8string utf8str_mixed; + struct nfstime4 { int64_t seconds; uint32_t nseconds; @@ -141,11 +149,85 @@ enum open_delegation_type4 { typedef enum open_delegation_type4 open_delegation_type4; +enum aclmodel4 { + ACL_MODEL_NFS4 = 1, + ACL_MODEL_POSIX_DRAFT = 2, + ACL_MODEL_NONE = 3, +}; + +typedef enum aclmodel4 aclmodel4; + +enum aclscope4 { + ACL_SCOPE_FILE_OBJECT = 1, + ACL_SCOPE_FILE_SYSTEM = 2, + ACL_SCOPE_SERVER = 3, +}; + +typedef enum aclscope4 aclscope4; + +enum posixacetag4 { + POSIXACE4_TAG_USER_OBJ = 1, + POSIXACE4_TAG_USER = 2, + POSIXACE4_TAG_GROUP_OBJ = 3, + POSIXACE4_TAG_GROUP = 4, + POSIXACE4_TAG_MASK = 5, + POSIXACE4_TAG_OTHER = 6, +}; + +typedef enum posixacetag4 posixacetag4; + +typedef uint32_t posixaceperm4; + +enum { POSIXACE4_PERM_EXECUTE = 0x00000001 }; + +enum { POSIXACE4_PERM_WRITE = 0x00000002 }; + +enum { POSIXACE4_PERM_READ = 0x00000004 }; + +struct posixace4 { + posixacetag4 tag; + posixaceperm4 perm; + utf8str_mixed who; +}; + +typedef aclmodel4 fattr4_acl_trueform; + +typedef aclscope4 fattr4_acl_trueform_scope; + +typedef struct { + u32 count; + struct posixace4 *element; +} fattr4_posix_default_acl; + +typedef struct { + u32 count; + struct posixace4 *element; +} fattr4_posix_access_acl; + +/* + * New for POSIX ACL extension + */ + +enum { FATTR4_ACL_TRUEFORM = 89 }; + +enum { FATTR4_ACL_TRUEFORM_SCOPE = 90 }; + +enum { FATTR4_POSIX_DEFAULT_ACL = 91 }; + +enum { FATTR4_POSIX_ACCESS_ACL = 92 }; + #define NFS4_int64_t_sz \ (XDR_hyper) #define NFS4_uint32_t_sz \ (XDR_unsigned_int) #define NFS4_bitmap4_sz (XDR_unsigned_int) +#define NFS4_utf8string_sz (XDR_unsigned_int) +#define NFS4_utf8str_cis_sz \ + (NFS4_utf8string_sz) +#define NFS4_utf8str_cs_sz \ + (NFS4_utf8string_sz) +#define NFS4_utf8str_mixed_sz \ + (NFS4_utf8string_sz) #define NFS4_nfstime4_sz \ (NFS4_int64_t_sz + NFS4_uint32_t_sz) #define NFS4_fattr4_offline_sz \ @@ -164,5 +246,18 @@ typedef enum open_delegation_type4 open_delegation_type4; #define NFS4_fattr4_time_deleg_modify_sz \ (NFS4_nfstime4_sz) #define NFS4_open_delegation_type4_sz (XDR_int) +#define NFS4_aclmodel4_sz (XDR_int) +#define NFS4_aclscope4_sz (XDR_int) +#define NFS4_posixacetag4_sz (XDR_int) +#define NFS4_posixaceperm4_sz \ + (NFS4_uint32_t_sz) +#define NFS4_posixace4_sz \ + (NFS4_posixacetag4_sz + NFS4_posixaceperm4_sz + NFS4_utf8str_mixed_sz) +#define NFS4_fattr4_acl_trueform_sz \ + (NFS4_aclmodel4_sz) +#define NFS4_fattr4_acl_trueform_scope_sz \ + (NFS4_aclscope4_sz) +#define NFS4_fattr4_posix_default_acl_sz (XDR_unsigned_int) +#define NFS4_fattr4_posix_access_acl_sz (XDR_unsigned_int) #endif /* _LINUX_XDRGEN_NFS4_1_DEF_H */ -- cgit v1.2.3