diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-13 12:34:28 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-13 12:34:28 +0100 |
| commit | 2c09d2499aecd278bc6a2973b79b2a58ea380815 (patch) | |
| tree | 7da45e627e39b769b3f536cd10f54f497c39aae1 /include | |
| parent | ffc09a9362e9811ccfc0b9e8eeafd7f25c59bbfc (diff) | |
| parent | eafb6de800781f0a1be5cdd98d150620041d8b27 (diff) | |
| download | linux-next-2c09d2499aecd278bc6a2973b79b2a58ea380815.tar.gz linux-next-2c09d2499aecd278bc6a2973b79b2a58ea380815.zip | |
Merge branch 'nfsd-next' of https://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/nfs.h | 55 | ||||
| -rw-r--r-- | include/linux/nfs3.h | 43 | ||||
| -rw-r--r-- | include/linux/nfs4.h | 6 | ||||
| -rw-r--r-- | include/linux/nfs_common.h | 4 | ||||
| -rw-r--r-- | include/linux/nfs_fh.h | 63 | ||||
| -rw-r--r-- | include/linux/nfs_ssc.h | 69 | ||||
| -rw-r--r-- | include/linux/nfsd_ssc.h | 38 | ||||
| -rw-r--r-- | include/linux/nfslocalio.h | 11 | ||||
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 3 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc.h | 95 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc_rdma.h | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 5 | ||||
| -rw-r--r-- | include/linux/sunrpc/xdr.h | 1 | ||||
| -rw-r--r-- | include/linux/sunrpc/xdrgen/_defs.h | 34 | ||||
| -rw-r--r-- | include/linux/sunrpc/xdrgen/nfs2.h | 298 | ||||
| -rw-r--r-- | include/trace/misc/nfs.h | 13 | ||||
| -rw-r--r-- | include/uapi/linux/nfsd_netlink.h | 20 |
17 files changed, 629 insertions, 131 deletions
diff --git a/include/linux/nfs.h b/include/linux/nfs.h index 0906a0b40c6a..8c2818db43c5 100644 --- a/include/linux/nfs.h +++ b/include/linux/nfs.h @@ -11,59 +11,8 @@ #include <linux/cred.h> #include <linux/sunrpc/auth.h> #include <linux/sunrpc/msg_prot.h> -#include <linux/string.h> -#include <linux/crc32.h> -#include <uapi/linux/nfs.h> - -/* The LOCALIO program is entirely private to Linux and is - * NOT part of the uapi. - */ -#define NFS_LOCALIO_PROGRAM 400122 -#define LOCALIOPROC_NULL 0 -#define LOCALIOPROC_UUID_IS_LOCAL 1 - -/* - * This is the kernel NFS client file handle representation - */ -#define NFS_MAXFHSIZE 128 -struct nfs_fh { - unsigned short size; - unsigned char data[NFS_MAXFHSIZE]; -}; - -/* - * Returns a zero iff the size and data fields match. - * Checks only "size" bytes in the data field. - */ -static inline int nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b) -{ - return a->size != b->size || memcmp(a->data, b->data, a->size) != 0; -} - -static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source) -{ - target->size = source->size; - memcpy(target->data, source->data, source->size); -} - -enum nfs3_stable_how { - NFS_UNSTABLE = 0, - NFS_DATA_SYNC = 1, - NFS_FILE_SYNC = 2, +#include <linux/nfs_fh.h> - /* used by direct.c to mark verf as invalid */ - NFS_INVALID_STABLE_HOW = -1 -}; +#include <uapi/linux/nfs.h> -/** - * nfs_fhandle_hash - calculate the crc32 hash for the filehandle - * @fh - pointer to filehandle - * - * returns a crc32 hash for the filehandle that is compatible with - * the one displayed by "wireshark". - */ -static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) -{ - return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); -} #endif /* _LINUX_NFS_H */ diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h index 404b8f724fc9..b6539a75edea 100644 --- a/include/linux/nfs3.h +++ b/include/linux/nfs3.h @@ -7,6 +7,49 @@ #include <uapi/linux/nfs3.h> +/* + * NFSv3 error status values. + * See RFC 1813 Section 2.5 + */ +enum { + NFS3ERR_PERM = 1, + NFS3ERR_NOENT = 2, + NFS3ERR_IO = 5, + NFS3ERR_NXIO = 6, + NFS3ERR_ACCES = 13, + NFS3ERR_EXIST = 17, + NFS3ERR_XDEV = 18, + NFS3ERR_NODEV = 19, + NFS3ERR_NOTDIR = 20, + NFS3ERR_ISDIR = 21, + NFS3ERR_INVAL = 22, + NFS3ERR_FBIG = 27, + NFS3ERR_NOSPC = 28, + NFS3ERR_ROFS = 30, + NFS3ERR_MLINK = 31, + NFS3ERR_NAMETOOLONG = 63, + NFS3ERR_NOTEMPTY = 66, + NFS3ERR_DQUOT = 69, + NFS3ERR_STALE = 70, + NFS3ERR_REMOTE = 71, + NFS3ERR_BADHANDLE = 10001, + NFS3ERR_NOT_SYNC = 10002, + NFS3ERR_BAD_COOKIE = 10003, + NFS3ERR_NOTSUPP = 10004, + NFS3ERR_TOOSMALL = 10005, + NFS3ERR_SERVERFAULT = 10006, + NFS3ERR_BADTYPE = 10007, + NFS3ERR_JUKEBOX = 10008, +}; + +enum nfs3_stable_how { + NFS_UNSTABLE = 0, + NFS_DATA_SYNC = 1, + NFS_FILE_SYNC = 2, + + /* used to mark verf as invalid */ + NFS_INVALID_STABLE_HOW = -1 +}; /* Number of 32bit words in post_op_attr */ #define NFS3_POST_OP_ATTR_WORDS 22 diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 1a3981c26b23..41b7cdcc674f 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -263,6 +263,12 @@ enum why_no_delegation4 { /* new to v4.1 */ WND4_IS_DIR = 8, }; +enum stable_how4 { + UNSTABLE4 = 0, + DATA_SYNC4 = 1, + FILE_SYNC4 = 2, +}; + enum lock_type4 { NFS4_UNLOCK_LT = 0, NFS4_READ_LT = 1, diff --git a/include/linux/nfs_common.h b/include/linux/nfs_common.h index a541c3a02887..88dccd8564cf 100644 --- a/include/linux/nfs_common.h +++ b/include/linux/nfs_common.h @@ -6,11 +6,11 @@ #define _LINUX_NFS_COMMON_H #include <linux/errno.h> -#include <uapi/linux/nfs.h> +#include <linux/types.h> /* Mapping from NFS error code to "errno" error code. */ -int nfs_stat_to_errno(enum nfs_stat status); +int nfs_stat_to_errno(int status); int nfs4_stat_to_errno(int stat); __u32 nfs_localio_errno_to_nfs4_stat(int errno); diff --git a/include/linux/nfs_fh.h b/include/linux/nfs_fh.h new file mode 100644 index 000000000000..49dfc5ec60fe --- /dev/null +++ b/include/linux/nfs_fh.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * struct nfs_fh is an NFS version-agnostic data structure that + * stores an NFS file handle. It is also commonly used in NFS + * related APIs. + */ +#ifndef _LINUX_NFS_FH_H +#define _LINUX_NFS_FH_H + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/crc32.h> + +/* + * The largest file handle size today is an NFSv4 file handle, + * which can be up to 128 octets long. + */ +#define NFS_MAXFHSIZE 128 +struct nfs_fh { + unsigned short size; + unsigned char data[NFS_MAXFHSIZE]; +}; + +/** + * nfs_compare_fh - Compare two NFS file handles + * @a: An NFS file handle to be compared + * @b: An NFS file handle to be compared + * + * Checks only "size" bytes in each data field. + * + * Return: %false if the two file handles are equal, otherwise %true + */ +static inline bool nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b) +{ + return a->size != b->size || memcmp(a->data, b->data, a->size) != 0; +} + +/** + * nfs_copy_fh - Copy an NFS file handle + * @target: Destination file handle + * @source: Source file handle + * + * Copies source->size bytes of file handle data into target. + */ +static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source) +{ + target->size = source->size; + memcpy(target->data, source->data, source->size); +} + +/** + * nfs_fhandle_hash - Calculate the crc32 hash for the filehandle + * @fh: An NFS file handle to hash + * + * Return: a crc32 hash for the filehandle that is compatible with + * the one displayed by "wireshark" + */ +static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) +{ + return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); +} + +#endif /* _LINUX_NFS_FH_H */ diff --git a/include/linux/nfs_ssc.h b/include/linux/nfs_ssc.h index 22265b1ff080..c199ea23e7eb 100644 --- a/include/linux/nfs_ssc.h +++ b/include/linux/nfs_ssc.h @@ -2,80 +2,33 @@ /* * include/linux/nfs_ssc.h * + * NFSv4.2 server-to-server copy, NFS client side APIs + * * Author: Dai Ngo <dai.ngo@oracle.com> * * Copyright (c) 2020, Oracle and/or its affiliates. */ -#include <linux/nfs_fs.h> -#include <linux/sunrpc/svc.h> +#ifndef _LINUX_NFS_SSC_H +#define _LINUX_NFS_SSC_H -extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl; +#include <linux/nfs_fh.h> +#include <linux/nfs4.h> + +struct file; +struct vfsmount; -/* - * NFS_V4 - */ struct nfs4_ssc_client_ops { + struct module *owner; struct file *(*sco_open)(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, nfs4_stateid *stateid); void (*sco_close)(struct file *filep); }; -/* - * NFS_FS - */ -struct nfs_ssc_client_ops { - void (*sco_sb_deactive)(struct super_block *sb); -}; - -struct nfs_ssc_client_ops_tbl { - const struct nfs4_ssc_client_ops *ssc_nfs4_ops; - const struct nfs_ssc_client_ops *ssc_nfs_ops; -}; - extern void nfs42_ssc_register_ops(void); extern void nfs42_ssc_unregister_ops(void); extern void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops); extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops); -#ifdef CONFIG_NFSD_V4_2_INTER_SSC -static inline struct file *nfs42_ssc_open(struct vfsmount *ss_mnt, - struct nfs_fh *src_fh, nfs4_stateid *stateid) -{ - if (nfs_ssc_client_tbl.ssc_nfs4_ops) - return (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_open)(ss_mnt, src_fh, stateid); - return ERR_PTR(-EIO); -} - -static inline void nfs42_ssc_close(struct file *filep) -{ - if (nfs_ssc_client_tbl.ssc_nfs4_ops) - (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep); -} -#endif - -struct nfsd4_ssc_umount_item { - struct list_head nsui_list; - bool nsui_busy; - /* - * nsui_refcnt inited to 2, 1 on list and 1 for consumer. Entry - * is removed when refcnt drops to 1 and nsui_expire expires. - */ - refcount_t nsui_refcnt; - unsigned long nsui_expire; - struct vfsmount *nsui_vfsmount; - char nsui_ipaddr[RPC_MAX_ADDRBUFLEN + 1]; -}; - -/* - * NFS_FS - */ -extern void nfs_ssc_register(const struct nfs_ssc_client_ops *ops); -extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops); - -static inline void nfs_do_sb_deactive(struct super_block *sb) -{ - if (nfs_ssc_client_tbl.ssc_nfs_ops) - (*nfs_ssc_client_tbl.ssc_nfs_ops->sco_sb_deactive)(sb); -} +#endif /* _LINUX_NFS_SSC_H */ diff --git a/include/linux/nfsd_ssc.h b/include/linux/nfsd_ssc.h new file mode 100644 index 000000000000..7001410f01c2 --- /dev/null +++ b/include/linux/nfsd_ssc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * include/linux/nfsd_ssc.h + * + * NFSv4.2 server-to-server copy, NFS server side APIs + * + * Author: Dai Ngo <dai.ngo@oracle.com> + * + * Copyright (c) 2020, Oracle and/or its affiliates. + */ + +#ifndef _LINUX_NFSD_SSC_H +#define _LINUX_NFSD_SSC_H + +#include <linux/nfs_fh.h> +#include <linux/nfs4.h> + +struct file; +struct vfsmount; + +#if IS_ENABLED(CONFIG_NFS_V4_2_SSC_HELPER) +struct file *nfsd42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, + nfs4_stateid *stateid); +void nfsd42_ssc_close(struct file *filp); +#else +static inline struct file *nfsd42_ssc_open(struct vfsmount *ss_mnt, + struct nfs_fh *src_fh, + nfs4_stateid *stateid) +{ + return ERR_PTR(-EIO); +} + +static inline void nfsd42_ssc_close(struct file *filp) +{ +} +#endif + +#endif /* _LINUX_NFSD_SSC_H */ diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index 3d91043254e6..8ce4d978a636 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -13,9 +13,18 @@ #include <linux/uuid.h> #include <linux/sunrpc/clnt.h> #include <linux/sunrpc/svcauth.h> -#include <linux/nfs.h> +#include <linux/nfs_fh.h> + #include <net/net_namespace.h> +/* + * The LOCALIO program is entirely private to Linux and is NOT part of + * the uapi. + */ +#define NFS_LOCALIO_PROGRAM 400122 +#define LOCALIOPROC_NULL 0 +#define LOCALIOPROC_UUID_IS_LOCAL 1 + struct nfs_client; struct nfs_file_localio; diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 3c2b8c355ab3..30344c0d6a9d 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -199,7 +199,8 @@ struct rpc_xprt *rpc_task_get_xprt(struct rpc_clnt *clnt, int rpcb_create_local(struct net *); void rpcb_put_local(struct net *); -int rpcb_register(struct net *, u32, u32, int, unsigned short); +int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, + unsigned short port); int rpcb_v4_register(struct net *net, const u32 program, const u32 version, const struct sockaddr *address, diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 2db1b9ec5658..cfb5ab17dabd 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -78,6 +78,7 @@ struct svc_serv { 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 */ + atomic_t sv_rpcb_failures; /* unanswered rpcbind calls */ struct list_head sv_permsocks; /* all permanent sockets */ struct list_head sv_tempsocks; /* all temporary sockets */ int sv_tmpcnt; /* count of temporary "valid" sockets */ @@ -86,6 +87,8 @@ struct svc_serv { char * sv_name; /* service name */ bool sv_is_pooled; /* is this a pooled service? */ + /* Caller registers with rpcbind itself. Set before svc_bind(). */ + bool sv_no_rpcbind; struct svc_pool * sv_pools; /* array of thread pools */ int (*sv_threadfn)(void *data); @@ -451,6 +454,7 @@ int sunrpc_set_pool_mode(const char *val); int sunrpc_get_pool_mode(char *val, size_t size); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); int svc_bind(struct svc_serv *serv, struct net *net); +unsigned int svc_rpcb_failure_count(struct svc_serv *serv); struct svc_serv *svc_create(struct svc_program *, unsigned int, int (*threadfn)(void *data)); bool svc_rqst_replace_page(struct svc_rqst *rqstp, @@ -471,8 +475,9 @@ unsigned int svc_serv_maxthreads(const struct svc_serv *serv); 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); -int svc_register(const struct svc_serv *, struct net *, const int, - const unsigned short, const unsigned short); +int svc_register(struct svc_serv *serv, struct net *net, + const int family, const unsigned short proto, + const unsigned short port); void svc_wake_up(struct svc_serv *); void svc_reserve(struct svc_rqst *rqstp, int space); @@ -529,6 +534,8 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space) * svcxdr_init_decode - Prepare an xdr_stream for Call decoding * @rqstp: controlling server RPC transaction context * + * The stream records @rqstp, so a codec running on it reaches the + * transaction with svcxdr_rqst(). */ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) { @@ -541,12 +548,15 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) xdr_init_decode(xdr, buf, argv->iov_base, NULL); xdr_set_scratch_folio(xdr, rqstp->rq_scratch_folio); + xdr->xdrgen_ctx = rqstp; } /** * svcxdr_init_encode - Prepare an xdr_stream for svc Reply encoding * @rqstp: controlling server RPC transaction context * + * The stream records @rqstp, so a codec running on it reaches the + * transaction with svcxdr_rqst(). */ static inline void svcxdr_init_encode(struct svc_rqst *rqstp) { @@ -564,6 +574,19 @@ static inline void svcxdr_init_encode(struct svc_rqst *rqstp) xdr->page_ptr = buf->pages - 1; buf->buflen = PAGE_SIZE * (rqstp->rq_page_end - buf->pages); xdr->rqst = NULL; + xdr->xdrgen_ctx = rqstp; +} + +/** + * svcxdr_rqst - Retrieve the transaction bound to an xdr_stream + * @xdr: stream to query + * + * Return: the controlling svc_rqst when @xdr was initialized by + * svcxdr_init_decode() or svcxdr_init_encode(), otherwise NULL. + */ +static inline struct svc_rqst *svcxdr_rqst(struct xdr_stream *xdr) +{ + return xdr->xdrgen_ctx; } /** @@ -588,6 +611,74 @@ static inline void svcxdr_encode_opaque_pages(struct svc_rqst *rqstp, } /** + * svcxdr_encode_opaque_payload - Encode a page-resident opaque data item + * @xdr: xdr_stream to be updated + * @len: number of octets of content in the data item + * + * Context: Process context. @xdr must have been initialized by + * svcxdr_init_encode() and still be positioned in the reply + * head. + * + * Return: + * %true: Success + * %false: The reply head cannot hold the length prefix and XDR + * padding, or the transport could not accommodate the result payload + */ +static inline bool svcxdr_encode_opaque_payload(struct xdr_stream *xdr, u32 len) +{ + struct svc_rqst *rqstp = svcxdr_rqst(xdr); + struct xdr_buf *buf = xdr->buf; + + /* + * The length prefix and any pad word must land in the reply + * head. A prefix that spills into the first Reply page lands + * on the payload itself, and xdr_write_pages() BUGs when the + * pad word does not fit. + */ + if ((xdr->end - xdr->p) * XDR_UNIT < XDR_UNIT + xdr_pad_size(len)) + return false; + if (xdr_stream_encode_u32(xdr, len) < 0) + return false; + svcxdr_encode_opaque_pages(rqstp, xdr, buf->pages, buf->page_base, len); + if (svc_encode_result_payload(rqstp, buf->head->iov_len, len) < 0) + return false; + return true; +} + +/** + * svcxdr_decode_opaque_payload - Decode a page-resident opaque data item + * @xdr: xdr_stream to be decoded + * @payload: on success, describes the octets of the data item's content + * @maxlen: largest data item length the caller will accept, or zero for + * no limit + * + * A bulk payload such as the content of an NFS WRITE request resides in + * the pages of the Receive buffer. Rather than copy it, set @payload to + * describe the item's content in place. + * + * Context: Process context. @xdr must have been initialized by + * svcxdr_init_decode(). + * + * Return: + * %true: @payload describes the item in place and @xdr has advanced + * past it + * %false: a bounds error occurred, or the length prefix exceeds + * @maxlen; @payload is undefined + */ +static inline bool svcxdr_decode_opaque_payload(struct xdr_stream *xdr, + struct xdr_buf *payload, + u32 maxlen) +{ + u32 len; + + if (xdr_stream_decode_u32(xdr, &len) < 0) + return false; + if (maxlen && len > maxlen) + return false; + return xdr_stream_subsegment(xdr, payload, len); +} + +/** * svcxdr_set_auth_slack - * @rqstp: RPC transaction * @slack: buffer space to reserve for the transaction's security flavor diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 76aa5ec4ab40..5ccb13bf906f 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -142,7 +142,7 @@ enum { #define RPCSVC_MAXPAYLOAD_RDMA RPCSVC_MAXPAYLOAD /** - * svc_rdma_send_cid_init - Initialize a Receive Queue completion ID + * svc_rdma_recv_cid_init - Initialize a Receive Queue completion ID * @rdma: controlling transport * @cid: completion ID to initialize */ diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h index da2a2531e110..2af222f3ea2c 100644 --- a/include/linux/sunrpc/svc_xprt.h +++ b/include/linux/sunrpc/svc_xprt.h @@ -37,6 +37,9 @@ struct svc_xprt_class { struct list_head xcl_list; u32 xcl_max_payload; int xcl_ident; + u32 xcl_flags; +/* Set only on classes whose xpo_has_wspace() reads xpt_reserved */ +#define SVC_XPRT_FLAG_WSPACE_RESERVE BIT(0) }; /* @@ -59,7 +62,7 @@ struct svc_xprt { unsigned long xpt_flags; struct svc_serv *xpt_server; /* service for transport */ - atomic_t xpt_reserved; /* space on outq that is rsvd */ + atomic_t xpt_reserved; /* outq space rsvd, UDP only */ atomic_t xpt_nr_rqsts; /* Number of requests */ struct mutex xpt_mutex; /* to serialize sending data */ spinlock_t xpt_lock; /* protects sk_deferred diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index b102b4f21e6b..2b33fc64be17 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -244,6 +244,7 @@ struct xdr_stream { unsigned int nwords; /* Remaining decode buffer length */ struct rpc_rqst *rqst; /* For debugging */ + void *xdrgen_ctx; /* Context for generated codecs */ }; /* diff --git a/include/linux/sunrpc/xdrgen/_defs.h b/include/linux/sunrpc/xdrgen/_defs.h index 8f3776ef3229..d767206feea4 100644 --- a/include/linux/sunrpc/xdrgen/_defs.h +++ b/include/linux/sunrpc/xdrgen/_defs.h @@ -5,11 +5,17 @@ * This header defines XDR data type primitives specified in * Section 4 of RFC 4506, used by RPC programs implemented * in the Linux kernel. + * + * A generated definition can also embed a struct xdr_buf, which + * carries a page-resident payload captured by reference, so this + * header pulls in the kernel's XDR types as well. */ #ifndef _SUNRPC_XDRGEN__DEFS_H_ #define _SUNRPC_XDRGEN__DEFS_H_ +#include <linux/sunrpc/xdr.h> + #define TRUE (true) #define FALSE (false) @@ -23,6 +29,34 @@ typedef struct { u8 *data; } opaque; +/* + * Cursor a hook-driven aggregate codec hands to its begin/item/end + * hooks, one element at a time, in place of a materialized C array. + * The generated framing owns it. @xdr is the RPC layer's stream and + * @ctx its xdrgen_ctx, the svc_rqst on the server. @index is the + * current element; @member_id selects among a type's marked members. + * For a counted array @count is the wire length: a decoder fills it + * before the begin hook runs, an encoder's begin hook sets it. The + * hook contract is under "Pragma aggregate" in + * tools/net/sunrpc/xdrgen/README. + * + * An optional-data list ("type *name") carries no count. Its encoder + * pulls elements until the item hook returns false. False ends the + * list rather than failing the encode: the framing writes the + * value-follows terminator, so a producer that stops early leaves a + * valid truncated list on the wire. A producer that stops for a + * mid-list error records it in the application state @ctx reaches, + * and either returns false from the end hook, which fails the + * encode, or reports it in the procedure status. + */ +struct xdrgen_aggregate_cursor { + struct xdr_stream *xdr; + u32 index; + u32 count; + unsigned int member_id; + void *ctx; +}; + #define XDR_void (0) #define XDR_bool (1) #define XDR_short (1) diff --git a/include/linux/sunrpc/xdrgen/nfs2.h b/include/linux/sunrpc/xdrgen/nfs2.h new file mode 100644 index 000000000000..1d26de39ac69 --- /dev/null +++ b/include/linux/sunrpc/xdrgen/nfs2.h @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Generated by xdrgen. Manual edits will be lost. */ +/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs2.x */ +/* XDR specification modification time: Tue Sep 8 11:26:28 2026 */ + +#ifndef _LINUX_XDRGEN_NFS2_DEF_H +#define _LINUX_XDRGEN_NFS2_DEF_H + +#include <linux/types.h> +#include <linux/sunrpc/xdrgen/_defs.h> + +enum { NFS_MAXDATA = 8192 }; + +enum { NFS_MAXPATHLEN = 1024 }; + +enum { NFS_MAXNAMLEN = 255 }; + +enum { NFS_COOKIESIZE = 4 }; + +enum { NFS_FHSIZE = 32 }; + +enum nfsstat { + NFS_OK = 0, + NFSERR_PERM = 1, + NFSERR_NOENT = 2, + NFSERR_IO = 5, + NFSERR_NXIO = 6, + NFSERR_ACCES = 13, + NFSERR_EXIST = 17, + NFSERR_NODEV = 19, + NFSERR_NOTDIR = 20, + NFSERR_ISDIR = 21, + NFSERR_FBIG = 27, + NFSERR_NOSPC = 28, + NFSERR_ROFS = 30, + NFSERR_NAMETOOLONG = 63, + NFSERR_NOTEMPTY = 66, + NFSERR_DQUOT = 69, + NFSERR_STALE = 70, + NFSERR_WFLUSH = 99, +}; + +typedef __be32 nfsstat; + +enum ftype { + NFNON = 0, + NFREG = 1, + NFDIR = 2, + NFBLK = 3, + NFCHR = 4, + NFLNK = 5, +}; + +typedef enum ftype ftype; + +typedef u8 fhandle[NFS_FHSIZE]; + +typedef u8 nfscookie[NFS_COOKIESIZE]; + +struct timeval { + u32 seconds; + u32 useconds; +}; + +struct fattr { + ftype type; + u32 mode; + u32 nlink; + u32 uid; + u32 gid; + u32 size; + u32 blocksize; + u32 rdev; + u32 blocks; + u32 fsid; + u32 fileid; + struct timeval atime; + struct timeval mtime; + struct timeval ctime; +}; + +struct sattr { + u32 mode; + u32 uid; + u32 gid; + u32 size; + struct timeval atime; + struct timeval mtime; +}; + +typedef string filename; + +typedef string path; + +struct attrstat { + nfsstat status; + union { + struct fattr attributes; + } u; +}; + +struct diropargs { + fhandle dir; + filename name; +}; + +struct diropok { + fhandle file; + struct fattr attributes; +}; + +struct diropres { + nfsstat status; + union { + struct diropok diropok; + } u; +}; + +struct sattrargs { + fhandle file; + struct sattr attributes; +}; + +struct readlinkres { + nfsstat status; + union { + path data; + } u; +}; + +struct readargs { + fhandle file; + u32 offset; + u32 count; + u32 totalcount; +}; + +struct readresok { + struct fattr attributes; + opaque data; +}; + +struct readres { + nfsstat status; + union { + struct readresok readresok; + } u; +}; + +struct writeargs { + fhandle file; + u32 beginoffset; + u32 offset; + u32 totalcount; + struct xdr_buf data; +}; + +struct createargs { + struct diropargs where; + struct sattr attributes; +}; + +struct renameargs { + struct diropargs from; + struct diropargs to; +}; + +struct linkargs { + fhandle from; + struct diropargs to; +}; + +struct symlinkargs { + struct diropargs from; + struct xdr_buf to; + struct sattr attributes; +}; + +struct readdirargs { + fhandle dir; + nfscookie cookie; + u32 count; +}; + +struct entry { + u32 fileid; + filename name; + nfscookie cookie; +}; + +struct readdirok { + struct entry *entries; + bool eof; +}; + +struct readdirres { + nfsstat status; + union { + struct readdirok readdirok; + } u; +}; + +struct info { + u32 tsize; + u32 bsize; + u32 blocks; + u32 bfree; + u32 bavail; +}; + +struct statfsres { + nfsstat status; + union { + struct info info; + } u; +}; + +enum { + NFSPROC_NULL = 0, + NFSPROC_GETATTR = 1, + NFSPROC_SETATTR = 2, + NFSPROC_ROOT = 3, + NFSPROC_LOOKUP = 4, + NFSPROC_READLINK = 5, + NFSPROC_READ = 6, + NFSPROC_WRITECACHE = 7, + NFSPROC_WRITE = 8, + NFSPROC_CREATE = 9, + NFSPROC_REMOVE = 10, + NFSPROC_RENAME = 11, + NFSPROC_LINK = 12, + NFSPROC_SYMLINK = 13, + NFSPROC_MKDIR = 14, + NFSPROC_RMDIR = 15, + NFSPROC_READDIR = 16, + NFSPROC_STATFS = 17, +}; + +#ifndef NFS_PROGRAM +#define NFS_PROGRAM (100003) +#endif + +#define NFS2_nfsstat_sz (XDR_int) +#define NFS2_ftype_sz (XDR_int) +#define NFS2_fhandle_sz (XDR_QUADLEN(NFS_FHSIZE)) +#define NFS2_nfscookie_sz (XDR_QUADLEN(NFS_COOKIESIZE)) +#define NFS2_timeval_sz \ + (XDR_unsigned_int + XDR_unsigned_int) +#define NFS2_fattr_sz \ + (NFS2_ftype_sz + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + NFS2_timeval_sz + NFS2_timeval_sz + NFS2_timeval_sz) +#define NFS2_sattr_sz \ + (XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + NFS2_timeval_sz + NFS2_timeval_sz) +#define NFS2_filename_sz (XDR_unsigned_int + XDR_QUADLEN(NFS_MAXNAMLEN)) +#define NFS2_path_sz (XDR_unsigned_int + XDR_QUADLEN(NFS_MAXPATHLEN)) +#define NFS2_attrstat_sz \ + (NFS2_nfsstat_sz + NFS2_fattr_sz) +#define NFS2_diropargs_sz \ + (NFS2_fhandle_sz + NFS2_filename_sz) +#define NFS2_diropok_sz \ + (NFS2_fhandle_sz + NFS2_fattr_sz) +#define NFS2_diropres_sz \ + (NFS2_nfsstat_sz + NFS2_diropok_sz) +#define NFS2_sattrargs_sz \ + (NFS2_fhandle_sz + NFS2_sattr_sz) +#define NFS2_readlinkres_sz \ + (NFS2_nfsstat_sz + NFS2_path_sz) +#define NFS2_readargs_sz \ + (NFS2_fhandle_sz + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int) +#define NFS2_readresok_sz \ + (NFS2_fattr_sz + XDR_unsigned_int + XDR_QUADLEN(NFS_MAXDATA)) +#define NFS2_readres_sz \ + (NFS2_nfsstat_sz + NFS2_readresok_sz) +#define NFS2_writeargs_sz \ + (NFS2_fhandle_sz + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_QUADLEN(NFS_MAXDATA)) +#define NFS2_createargs_sz \ + (NFS2_diropargs_sz + NFS2_sattr_sz) +#define NFS2_renameargs_sz \ + (NFS2_diropargs_sz + NFS2_diropargs_sz) +#define NFS2_linkargs_sz \ + (NFS2_fhandle_sz + NFS2_diropargs_sz) +#define NFS2_symlinkargs_sz \ + (NFS2_diropargs_sz + NFS2_path_sz + NFS2_sattr_sz) +#define NFS2_readdirargs_sz \ + (NFS2_fhandle_sz + NFS2_nfscookie_sz + XDR_unsigned_int) +#define NFS2_entry_sz \ + (XDR_bool + XDR_unsigned_int + NFS2_filename_sz + NFS2_nfscookie_sz) +#define NFS2_readdirok_sz \ + (XDR_bool + XDR_bool) +#define NFS2_readdirres_sz \ + (NFS2_nfsstat_sz + NFS2_readdirok_sz) +#define NFS2_info_sz \ + (XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int + XDR_unsigned_int) +#define NFS2_statfsres_sz \ + (NFS2_nfsstat_sz + NFS2_info_sz) +#define NFS2_MAX_ARGS_SZ \ + (NFS2_writeargs_sz) + +#endif /* _LINUX_XDRGEN_NFS2_DEF_H */ diff --git a/include/trace/misc/nfs.h b/include/trace/misc/nfs.h index a394b4d38e18..3146813fc4fe 100644 --- a/include/trace/misc/nfs.h +++ b/include/trace/misc/nfs.h @@ -8,6 +8,7 @@ */ #include <linux/nfs.h> +#include <linux/nfs3.h> #include <linux/nfs4.h> #include <uapi/linux/nfs.h> @@ -358,18 +359,6 @@ TRACE_DEFINE_ENUM(IOMODE_ANY); { IOMODE_RW, "RW" }, \ { IOMODE_ANY, "ANY" }) -#define show_rca_mask(x) \ - __print_flags(x, "|", \ - { BIT(RCA4_TYPE_MASK_RDATA_DLG), "RDATA_DLG" }, \ - { BIT(RCA4_TYPE_MASK_WDATA_DLG), "WDATA_DLG" }, \ - { BIT(RCA4_TYPE_MASK_DIR_DLG), "DIR_DLG" }, \ - { BIT(RCA4_TYPE_MASK_FILE_LAYOUT), "FILE_LAYOUT" }, \ - { BIT(RCA4_TYPE_MASK_BLK_LAYOUT), "BLK_LAYOUT" }, \ - { BIT(RCA4_TYPE_MASK_OBJ_LAYOUT_MIN), "OBJ_LAYOUT_MIN" }, \ - { BIT(RCA4_TYPE_MASK_OBJ_LAYOUT_MAX), "OBJ_LAYOUT_MAX" }, \ - { BIT(RCA4_TYPE_MASK_OTHER_LAYOUT_MIN), "OTHER_LAYOUT_MIN" }, \ - { BIT(RCA4_TYPE_MASK_OTHER_LAYOUT_MAX), "OTHER_LAYOUT_MAX" }) - #define show_nfs4_seq4_status(x) \ __print_flags(x, "|", \ { SEQ4_STATUS_CB_PATH_DOWN, "CB_PATH_DOWN" }, \ diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_netlink.h index 87da1d0bb21e..c125af0cc6a5 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -50,6 +50,15 @@ enum nfsd_xprtsec_mode { NFSD_XPRTSEC_MODE_MTLS = 4, }; +/* + * Constraints that apply to an rpcbind registration. no-udp means the kernel + * would not have registered this program and version over UDP, so the caller + * must skip the udp and udp6 netids for it. + */ +enum nfsd_rpcbind_flags { + NFSD_RPCBIND_FLAGS_NO_UDP = 1, +}; + enum { NFSD_A_CACHE_NOTIFY_CACHE_TYPE = 1, @@ -114,7 +123,18 @@ enum { }; enum { + NFSD_A_RPCBIND_PROGRAM = 1, + NFSD_A_RPCBIND_VERSION, + NFSD_A_RPCBIND_FLAGS, + + __NFSD_A_RPCBIND_MAX, + NFSD_A_RPCBIND_MAX = (__NFSD_A_RPCBIND_MAX - 1) +}; + +enum { NFSD_A_SERVER_SOCK_ADDR = 1, + NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND, + NFSD_A_SERVER_SOCK_RPCBIND, __NFSD_A_SERVER_SOCK_MAX, NFSD_A_SERVER_SOCK_MAX = (__NFSD_A_SERVER_SOCK_MAX - 1) |
