summaryrefslogtreecommitdiff
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c8
-rw-r--r--fs/nfsd/nfs4xdr_gen.c589
-rw-r--r--fs/nfsd/nfs4xdr_gen.h5
-rw-r--r--fs/nfsd/nfsd.h9
-rw-r--r--fs/nfsd/trace.h1
5 files changed, 601 insertions, 11 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6180f6dc8995..258621750eb7 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1276,9 +1276,9 @@ out_dec:
void
nfs4_put_stid(struct nfs4_stid *s)
{
- struct svc_export *exp = s->sc_export;
struct nfs4_file *fp = s->sc_file;
struct nfs4_client *clp = s->sc_client;
+ struct svc_export *exp;
might_lock(&clp->cl_lock);
@@ -1289,6 +1289,8 @@ nfs4_put_stid(struct nfs4_stid *s)
idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id);
if (s->sc_status & SC_STATUS_ADMIN_REVOKED)
atomic_dec(&s->sc_client->cl_admin_revoked);
+ /* Read under cl_lock to serialize with drop_stid_export(). */
+ exp = s->sc_export;
nfs4_free_cpntf_statelist(clp->net, s);
spin_unlock(&clp->cl_lock);
s->sc_free(s);
@@ -1745,6 +1747,7 @@ static void
free_ol_stateid_reaplist(struct list_head *reaplist)
{
struct nfs4_ol_stateid *stp;
+ struct svc_export *exp;
struct nfs4_file *fp;
might_sleep();
@@ -1754,7 +1757,10 @@ free_ol_stateid_reaplist(struct list_head *reaplist)
st_locks);
list_del(&stp->st_locks);
fp = stp->st_stid.sc_file;
+ exp = stp->st_stid.sc_export;
stp->st_stid.sc_free(&stp->st_stid);
+ if (exp)
+ exp_put(exp);
if (fp)
put_nfs4_file(fp);
}
diff --git a/fs/nfsd/nfs4xdr_gen.c b/fs/nfsd/nfs4xdr_gen.c
index 824497051b87..d92dbae5db0f 100644
--- a/fs/nfsd/nfs4xdr_gen.c
+++ b/fs/nfsd/nfs4xdr_gen.c
@@ -1,16 +1,16 @@
// 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:12:07 2026
+// XDR specification modification time: Tue Jun 30 11:57:21 2026
#include <linux/sunrpc/svc.h>
#include "nfs4xdr_gen.h"
static bool __maybe_unused
-xdrgen_decode_int64_t(struct xdr_stream *xdr, int64_t *ptr)
+xdrgen_decode_int32_t(struct xdr_stream *xdr, int32_t *ptr)
{
- return xdrgen_decode_hyper(xdr, ptr);
+ return xdrgen_decode_int(xdr, ptr);
}
static bool __maybe_unused
@@ -20,6 +20,154 @@ xdrgen_decode_uint32_t(struct xdr_stream *xdr, uint32_t *ptr)
}
static bool __maybe_unused
+xdrgen_decode_int64_t(struct xdr_stream *xdr, int64_t *ptr)
+{
+ return xdrgen_decode_hyper(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_uint64_t(struct xdr_stream *xdr, uint64_t *ptr)
+{
+ return xdrgen_decode_unsigned_hyper(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfsstat4(struct xdr_stream *xdr, nfsstat4 *ptr)
+{
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case NFS4_OK:
+ case NFS4ERR_PERM:
+ case NFS4ERR_NOENT:
+ case NFS4ERR_IO:
+ case NFS4ERR_NXIO:
+ case NFS4ERR_ACCESS:
+ case NFS4ERR_EXIST:
+ case NFS4ERR_XDEV:
+ case NFS4ERR_NOTDIR:
+ case NFS4ERR_ISDIR:
+ case NFS4ERR_INVAL:
+ case NFS4ERR_FBIG:
+ case NFS4ERR_NOSPC:
+ case NFS4ERR_ROFS:
+ case NFS4ERR_MLINK:
+ case NFS4ERR_NAMETOOLONG:
+ case NFS4ERR_NOTEMPTY:
+ case NFS4ERR_DQUOT:
+ case NFS4ERR_STALE:
+ case NFS4ERR_BADHANDLE:
+ case NFS4ERR_BAD_COOKIE:
+ case NFS4ERR_NOTSUPP:
+ case NFS4ERR_TOOSMALL:
+ case NFS4ERR_SERVERFAULT:
+ case NFS4ERR_BADTYPE:
+ case NFS4ERR_DELAY:
+ case NFS4ERR_SAME:
+ case NFS4ERR_DENIED:
+ case NFS4ERR_EXPIRED:
+ case NFS4ERR_LOCKED:
+ case NFS4ERR_GRACE:
+ case NFS4ERR_FHEXPIRED:
+ case NFS4ERR_SHARE_DENIED:
+ case NFS4ERR_WRONGSEC:
+ case NFS4ERR_CLID_INUSE:
+ case NFS4ERR_RESOURCE:
+ case NFS4ERR_MOVED:
+ case NFS4ERR_NOFILEHANDLE:
+ case NFS4ERR_MINOR_VERS_MISMATCH:
+ case NFS4ERR_STALE_CLIENTID:
+ case NFS4ERR_STALE_STATEID:
+ case NFS4ERR_OLD_STATEID:
+ case NFS4ERR_BAD_STATEID:
+ case NFS4ERR_BAD_SEQID:
+ case NFS4ERR_NOT_SAME:
+ case NFS4ERR_LOCK_RANGE:
+ case NFS4ERR_SYMLINK:
+ case NFS4ERR_RESTOREFH:
+ case NFS4ERR_LEASE_MOVED:
+ case NFS4ERR_ATTRNOTSUPP:
+ case NFS4ERR_NO_GRACE:
+ case NFS4ERR_RECLAIM_BAD:
+ case NFS4ERR_RECLAIM_CONFLICT:
+ case NFS4ERR_BADXDR:
+ case NFS4ERR_LOCKS_HELD:
+ case NFS4ERR_OPENMODE:
+ case NFS4ERR_BADOWNER:
+ case NFS4ERR_BADCHAR:
+ case NFS4ERR_BADNAME:
+ case NFS4ERR_BAD_RANGE:
+ case NFS4ERR_LOCK_NOTSUPP:
+ case NFS4ERR_OP_ILLEGAL:
+ case NFS4ERR_DEADLOCK:
+ case NFS4ERR_FILE_OPEN:
+ case NFS4ERR_ADMIN_REVOKED:
+ case NFS4ERR_CB_PATH_DOWN:
+ case NFS4ERR_BADIOMODE:
+ case NFS4ERR_BADLAYOUT:
+ case NFS4ERR_BAD_SESSION_DIGEST:
+ case NFS4ERR_BADSESSION:
+ case NFS4ERR_BADSLOT:
+ case NFS4ERR_COMPLETE_ALREADY:
+ case NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case NFS4ERR_DELEG_ALREADY_WANTED:
+ case NFS4ERR_BACK_CHAN_BUSY:
+ case NFS4ERR_LAYOUTTRYLATER:
+ case NFS4ERR_LAYOUTUNAVAILABLE:
+ case NFS4ERR_NOMATCHING_LAYOUT:
+ case NFS4ERR_RECALLCONFLICT:
+ case NFS4ERR_UNKNOWN_LAYOUTTYPE:
+ case NFS4ERR_SEQ_MISORDERED:
+ case NFS4ERR_SEQUENCE_POS:
+ case NFS4ERR_REQ_TOO_BIG:
+ case NFS4ERR_REP_TOO_BIG:
+ case NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case NFS4ERR_RETRY_UNCACHED_REP:
+ case NFS4ERR_UNSAFE_COMPOUND:
+ case NFS4ERR_TOO_MANY_OPS:
+ case NFS4ERR_OP_NOT_IN_SESSION:
+ case NFS4ERR_HASH_ALG_UNSUPP:
+ case NFS4ERR_CLIENTID_BUSY:
+ case NFS4ERR_PNFS_IO_HOLE:
+ case NFS4ERR_SEQ_FALSE_RETRY:
+ case NFS4ERR_BAD_HIGH_SLOT:
+ case NFS4ERR_DEADSESSION:
+ case NFS4ERR_ENCR_ALG_UNSUPP:
+ case NFS4ERR_PNFS_NO_LAYOUT:
+ case NFS4ERR_NOT_ONLY_OP:
+ case NFS4ERR_WRONG_CRED:
+ case NFS4ERR_WRONG_TYPE:
+ case NFS4ERR_DIRDELEG_UNAVAIL:
+ case NFS4ERR_REJECT_DELEG:
+ case NFS4ERR_RETURNCONFLICT:
+ case NFS4ERR_DELEG_REVOKED:
+ case NFS4ERR_PARTNER_NOTSUPP:
+ case NFS4ERR_PARTNER_NO_AUTH:
+ case NFS4ERR_UNION_NOTSUPP:
+ case NFS4ERR_OFFLOAD_DENIED:
+ case NFS4ERR_WRONG_LFS:
+ case NFS4ERR_BADLABEL:
+ case NFS4ERR_OFFLOAD_NO_REQS:
+ case NFS4ERR_NOXATTR:
+ case NFS4ERR_XATTR2BIG:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_attrlist4(struct xdr_stream *xdr, attrlist4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, 0);
+}
+
+static bool __maybe_unused
xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr)
{
if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
@@ -31,6 +179,24 @@ xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr)
}
static bool __maybe_unused
+xdrgen_decode_verifier4(struct xdr_stream *xdr, verifier4 *ptr)
+{
+ return xdr_stream_decode_opaque_fixed(xdr, ptr, NFS4_VERIFIER_SIZE) == 0;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfs_cookie4(struct xdr_stream *xdr, nfs_cookie4 *ptr)
+{
+ return xdrgen_decode_uint64_t(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfs_fh4(struct xdr_stream *xdr, nfs_fh4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, NFS4_FHSIZE);
+}
+
+static bool __maybe_unused
xdrgen_decode_utf8string(struct xdr_stream *xdr, utf8string *ptr)
{
return xdrgen_decode_opaque(xdr, ptr, 0);
@@ -55,6 +221,29 @@ xdrgen_decode_utf8str_mixed(struct xdr_stream *xdr, utf8str_mixed *ptr)
}
static bool __maybe_unused
+xdrgen_decode_component4(struct xdr_stream *xdr, component4 *ptr)
+{
+ return xdrgen_decode_utf8str_cs(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_linktext4(struct xdr_stream *xdr, linktext4 *ptr)
+{
+ return xdrgen_decode_utf8str_cs(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_pathname4(struct xdr_stream *xdr, pathname4 *ptr)
+{
+ if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
+ return false;
+ for (u32 i = 0; i < ptr->count; i++)
+ if (!xdrgen_decode_component4(xdr, &ptr->element[i]))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr)
{
if (!xdrgen_decode_int64_t(xdr, &ptr->seconds))
@@ -65,6 +254,26 @@ xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr)
}
static bool __maybe_unused
+xdrgen_decode_fattr4(struct xdr_stream *xdr, struct fattr4 *ptr)
+{
+ if (!xdrgen_decode_bitmap4(xdr, &ptr->attrmask))
+ return false;
+ if (!xdrgen_decode_attrlist4(xdr, &ptr->attr_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_stateid4(struct xdr_stream *xdr, struct stateid4 *ptr)
+{
+ if (!xdrgen_decode_uint32_t(xdr, &ptr->seqid))
+ return false;
+ if (xdr_stream_decode_opaque_fixed(xdr, ptr->other, 12) < 0)
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
xdrgen_decode_fattr4_offline(struct xdr_stream *xdr, fattr4_offline *ptr)
{
return xdrgen_decode_bool(xdr, ptr);
@@ -366,9 +575,160 @@ xdrgen_decode_fattr4_posix_access_acl(struct xdr_stream *xdr, fattr4_posix_acces
*/
static bool __maybe_unused
-xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value)
+xdrgen_decode_notify_type4(struct xdr_stream *xdr, notify_type4 *ptr)
{
- return xdrgen_encode_hyper(xdr, value);
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case NOTIFY4_CHANGE_CHILD_ATTRS:
+ case NOTIFY4_CHANGE_DIR_ATTRS:
+ case NOTIFY4_REMOVE_ENTRY:
+ case NOTIFY4_ADD_ENTRY:
+ case NOTIFY4_RENAME_ENTRY:
+ case NOTIFY4_CHANGE_COOKIE_VERIFIER:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_entry4(struct xdr_stream *xdr, struct notify_entry4 *ptr)
+{
+ if (!xdrgen_decode_component4(xdr, &ptr->ne_file))
+ return false;
+ if (!xdrgen_decode_fattr4(xdr, &ptr->ne_attrs))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_prev_entry4(struct xdr_stream *xdr, struct prev_entry4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->pe_prev_entry))
+ return false;
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->pe_prev_entry_cookie))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_remove4(struct xdr_stream *xdr, struct notify_remove4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->nrm_old_entry))
+ return false;
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->nrm_old_entry_cookie))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_add4(struct xdr_stream *xdr, struct notify_add4 *ptr)
+{
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_old_entry.count) < 0)
+ return false;
+ if (ptr->nad_old_entry.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_old_entry.count; i++)
+ if (!xdrgen_decode_notify_remove4(xdr, &ptr->nad_old_entry.element[i]))
+ return false;
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->nad_new_entry))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_new_entry_cookie.count) < 0)
+ return false;
+ if (ptr->nad_new_entry_cookie.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_new_entry_cookie.count; i++)
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->nad_new_entry_cookie.element[i]))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_prev_entry.count) < 0)
+ return false;
+ if (ptr->nad_prev_entry.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_prev_entry.count; i++)
+ if (!xdrgen_decode_prev_entry4(xdr, &ptr->nad_prev_entry.element[i]))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->nad_last_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_attr4(struct xdr_stream *xdr, struct notify_attr4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->na_changed_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_rename4(struct xdr_stream *xdr, struct notify_rename4 *ptr)
+{
+ if (!xdrgen_decode_notify_remove4(xdr, &ptr->nrn_old_entry))
+ return false;
+ if (!xdrgen_decode_notify_add4(xdr, &ptr->nrn_new_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_verifier4(struct xdr_stream *xdr, struct notify_verifier4 *ptr)
+{
+ if (!xdrgen_decode_verifier4(xdr, &ptr->nv_old_cookieverf))
+ return false;
+ if (!xdrgen_decode_verifier4(xdr, &ptr->nv_new_cookieverf))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notifylist4(struct xdr_stream *xdr, notifylist4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, 0);
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify4(struct xdr_stream *xdr, struct notify4 *ptr)
+{
+ if (!xdrgen_decode_bitmap4(xdr, &ptr->notify_mask))
+ return false;
+ if (!xdrgen_decode_notifylist4(xdr, &ptr->notify_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_CB_NOTIFY4args(struct xdr_stream *xdr, struct CB_NOTIFY4args *ptr)
+{
+ if (!xdrgen_decode_stateid4(xdr, &ptr->cna_stateid))
+ return false;
+ if (!xdrgen_decode_nfs_fh4(xdr, &ptr->cna_fh))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->cna_changes.count) < 0)
+ return false;
+ for (u32 i = 0; i < ptr->cna_changes.count; i++)
+ if (!xdrgen_decode_notify4(xdr, &ptr->cna_changes.element[i]))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_CB_NOTIFY4res(struct xdr_stream *xdr, struct CB_NOTIFY4res *ptr)
+{
+ if (!xdrgen_decode_nfsstat4(xdr, &ptr->cnr_status))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_int32_t(struct xdr_stream *xdr, const int32_t value)
+{
+ return xdrgen_encode_int(xdr, value);
}
static bool __maybe_unused
@@ -378,6 +738,30 @@ xdrgen_encode_uint32_t(struct xdr_stream *xdr, const uint32_t value)
}
static bool __maybe_unused
+xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value)
+{
+ return xdrgen_encode_hyper(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_uint64_t(struct xdr_stream *xdr, const uint64_t value)
+{
+ return xdrgen_encode_unsigned_hyper(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfsstat4(struct xdr_stream *xdr, nfsstat4 value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_attrlist4(struct xdr_stream *xdr, const attrlist4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value)
{
if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
@@ -389,6 +773,24 @@ xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value)
}
static bool __maybe_unused
+xdrgen_encode_verifier4(struct xdr_stream *xdr, const verifier4 value)
+{
+ return xdr_stream_encode_opaque_fixed(xdr, value, NFS4_VERIFIER_SIZE) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfs_cookie4(struct xdr_stream *xdr, const nfs_cookie4 value)
+{
+ return xdrgen_encode_uint64_t(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfs_fh4(struct xdr_stream *xdr, const nfs_fh4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
xdrgen_encode_utf8string(struct xdr_stream *xdr, const utf8string value)
{
return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
@@ -413,6 +815,29 @@ xdrgen_encode_utf8str_mixed(struct xdr_stream *xdr, const utf8str_mixed value)
}
static bool __maybe_unused
+xdrgen_encode_component4(struct xdr_stream *xdr, const component4 value)
+{
+ return xdrgen_encode_utf8str_cs(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_linktext4(struct xdr_stream *xdr, const linktext4 value)
+{
+ return xdrgen_encode_utf8str_cs(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_pathname4(struct xdr_stream *xdr, const pathname4 value)
+{
+ if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value.count; i++)
+ if (!xdrgen_encode_component4(xdr, value.element[i]))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value)
{
if (!xdrgen_encode_int64_t(xdr, value->seconds))
@@ -423,6 +848,26 @@ xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value)
}
static bool __maybe_unused
+xdrgen_encode_fattr4(struct xdr_stream *xdr, const struct fattr4 *value)
+{
+ if (!xdrgen_encode_bitmap4(xdr, value->attrmask))
+ return false;
+ if (!xdrgen_encode_attrlist4(xdr, value->attr_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_stateid4(struct xdr_stream *xdr, const struct stateid4 *value)
+{
+ if (!xdrgen_encode_uint32_t(xdr, value->seqid))
+ return false;
+ if (xdr_stream_encode_opaque_fixed(xdr, value->other, 12) < 0)
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
xdrgen_encode_fattr4_offline(struct xdr_stream *xdr, const fattr4_offline value)
{
return xdrgen_encode_bool(xdr, value);
@@ -567,3 +1012,137 @@ xdrgen_encode_fattr4_posix_access_acl(struct xdr_stream *xdr, const fattr4_posix
return false;
return true;
}
+
+static bool __maybe_unused
+xdrgen_encode_notify_type4(struct xdr_stream *xdr, notify_type4 value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_entry4(struct xdr_stream *xdr, const struct notify_entry4 *value)
+{
+ if (!xdrgen_encode_component4(xdr, value->ne_file))
+ return false;
+ if (!xdrgen_encode_fattr4(xdr, &value->ne_attrs))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_prev_entry4(struct xdr_stream *xdr, const struct prev_entry4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->pe_prev_entry))
+ return false;
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->pe_prev_entry_cookie))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_remove4(struct xdr_stream *xdr, const struct notify_remove4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->nrm_old_entry))
+ return false;
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->nrm_old_entry_cookie))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_add4(struct xdr_stream *xdr, const struct notify_add4 *value)
+{
+ if (value->nad_old_entry.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_old_entry.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_old_entry.count; i++)
+ if (!xdrgen_encode_notify_remove4(xdr, &value->nad_old_entry.element[i]))
+ return false;
+ if (!xdrgen_encode_notify_entry4(xdr, &value->nad_new_entry))
+ return false;
+ if (value->nad_new_entry_cookie.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_new_entry_cookie.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_new_entry_cookie.count; i++)
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->nad_new_entry_cookie.element[i]))
+ return false;
+ if (value->nad_prev_entry.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_prev_entry.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_prev_entry.count; i++)
+ if (!xdrgen_encode_prev_entry4(xdr, &value->nad_prev_entry.element[i]))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->nad_last_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_attr4(struct xdr_stream *xdr, const struct notify_attr4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->na_changed_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_rename4(struct xdr_stream *xdr, const struct notify_rename4 *value)
+{
+ if (!xdrgen_encode_notify_remove4(xdr, &value->nrn_old_entry))
+ return false;
+ if (!xdrgen_encode_notify_add4(xdr, &value->nrn_new_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_verifier4(struct xdr_stream *xdr, const struct notify_verifier4 *value)
+{
+ if (!xdrgen_encode_verifier4(xdr, value->nv_old_cookieverf))
+ return false;
+ if (!xdrgen_encode_verifier4(xdr, value->nv_new_cookieverf))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notifylist4(struct xdr_stream *xdr, const notifylist4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify4(struct xdr_stream *xdr, const struct notify4 *value)
+{
+ if (!xdrgen_encode_bitmap4(xdr, value->notify_mask))
+ return false;
+ if (!xdrgen_encode_notifylist4(xdr, value->notify_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_CB_NOTIFY4args(struct xdr_stream *xdr, const struct CB_NOTIFY4args *value)
+{
+ if (!xdrgen_encode_stateid4(xdr, &value->cna_stateid))
+ return false;
+ if (!xdrgen_encode_nfs_fh4(xdr, value->cna_fh))
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->cna_changes.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->cna_changes.count; i++)
+ if (!xdrgen_encode_notify4(xdr, &value->cna_changes.element[i]))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_CB_NOTIFY4res(struct xdr_stream *xdr, const struct CB_NOTIFY4res *value)
+{
+ if (!xdrgen_encode_nfsstat4(xdr, value->cnr_status))
+ return false;
+ return true;
+}
diff --git a/fs/nfsd/nfs4xdr_gen.h b/fs/nfsd/nfs4xdr_gen.h
index 1c487f1a11ab..d7725bd5648a 100644
--- a/fs/nfsd/nfs4xdr_gen.h
+++ b/fs/nfsd/nfs4xdr_gen.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:12:07 2026 */
+/* XDR specification modification time: Tue Jun 30 11:57:21 2026 */
#ifndef _LINUX_XDRGEN_NFS4_1_DECL_H
#define _LINUX_XDRGEN_NFS4_1_DECL_H
@@ -21,10 +21,13 @@ bool xdrgen_encode_fattr4_time_deleg_access(struct xdr_stream *xdr, const fattr4
bool xdrgen_decode_fattr4_time_deleg_modify(struct xdr_stream *xdr, fattr4_time_deleg_modify *ptr);
bool xdrgen_encode_fattr4_time_deleg_modify(struct xdr_stream *xdr, const fattr4_time_deleg_modify *value);
+
bool xdrgen_decode_aclmodel4(struct xdr_stream *xdr, aclmodel4 *ptr);
bool xdrgen_encode_aclmodel4(struct xdr_stream *xdr, aclmodel4 value);
+
bool xdrgen_decode_aclscope4(struct xdr_stream *xdr, aclscope4 *ptr);
bool xdrgen_encode_aclscope4(struct xdr_stream *xdr, aclscope4 value);
+
bool xdrgen_decode_posixacetag4(struct xdr_stream *xdr, posixacetag4 *ptr);
bool xdrgen_encode_posixacetag4(struct xdr_stream *xdr, posixacetag4 value);
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 11bce03b9031..d33d49b61e6a 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -332,13 +332,14 @@ void nfsd_lockd_shutdown(void);
#define nfserr_noxattr cpu_to_be32(NFS4ERR_NOXATTR)
/*
- * Error codes for internal use. We use enum to choose numbers that are
- * not already assigned, then covert to be32 resulting in a number that
- * cannot conflict with any existing be32 nfserr value.
+ * Error codes for internal use. These are based at an impossible
+ * nfsstat4 value so that, once converted to be32, they cannot conflict
+ * with any value defined by the protocol (compare the nlm__int__* codes
+ * in fs/lockd/lockd.h).
*/
enum {
/* end-of-file indicator in readdir */
- NFSERR_EOF = NFS4ERR_FIRST_FREE,
+ NFSERR_EOF = 30000,
#define nfserr_eof cpu_to_be32(NFSERR_EOF)
/* replay detected */
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index 33953d38314e..171e8fdbafb6 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -1677,6 +1677,7 @@ TRACE_EVENT(nfsd_cb_setup_err,
{ OP_CB_RECALL, "CB_RECALL" }, \
{ OP_CB_LAYOUTRECALL, "CB_LAYOUTRECALL" }, \
{ OP_CB_RECALL_ANY, "CB_RECALL_ANY" }, \
+ { OP_CB_NOTIFY, "CB_NOTIFY" }, \
{ OP_CB_NOTIFY_LOCK, "CB_NOTIFY_LOCK" }, \
{ OP_CB_OFFLOAD, "CB_OFFLOAD" })