]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Mar 2024 11:34:00 +0000 (12:34 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Mar 2024 11:34:00 +0000 (12:34 +0100)
added patches:
exportfs-use-pr_debug-for-unreachable-debug-statements.patch
filelock-add-a-new-locks_inode_context-accessor-function.patch
lockd-ensure-we-use-the-correct-file-descriptor-when-unlocking.patch
lockd-fix-file-selection-in-nlmsvc_cancel_blocked.patch
lockd-set-missing-fl_flags-field-when-retrieving-args.patch
lockd-use-locks_inode_context-helper.patch
nfsd-add-a-nfsd4_file_hash_remove-helper.patch
nfsd-add-cb_recall_any-tracepoints.patch
nfsd-add-delegation-reaper-to-react-to-low-memory-condition.patch
nfsd-add-support-for-sending-cb_recall_any.patch
nfsd-allow-disabling-nfsv2-at-compile-time.patch
nfsd-avoid-clashing-function-prototypes.patch
nfsd-clean-up-find_or_add_file.patch
nfsd-clean-up-nfs4_preprocess_stateid_op-call-sites.patch
nfsd-clean-up-nfsd4_init_file.patch
nfsd-don-t-destroy-global-nfs4_file-table-in-per-net-shutdown.patch
nfsd-fix-licensing-header-in-filecache.c.patch
nfsd-fix-up-the-filecache-laundrette-scheduling.patch
nfsd-flesh-out-a-documenting-comment-for-filecache.c.patch
nfsd-ignore-requests-to-disable-unsupported-versions.patch
nfsd-move-nfserrno-to-vfs.c.patch
nfsd-refactor-find_file.patch
nfsd-refactoring-courtesy_client_reaper-to-a-generic-low-memory-shrinker.patch
nfsd-register-unregister-of-nfsd-client-shrinker-at-nfsd-startup-shutdown-time.patch
nfsd-remove-redundant-assignment-to-variable-host_err.patch
nfsd-replace-delayed_work-with-work_struct-for-nfsd_client_shrinker.patch
nfsd-simplify-read_plus.patch
nfsd-trace-delegation-revocations.patch
nfsd-trace-stateids-returned-via-delegreturn.patch
nfsd-update-file_hashtbl-helpers.patch
nfsd-use-const-pointers-as-parameters-to-fh_-helpers.patch
nfsd-use-locks_inode_context-helper.patch
nfsd-use-only-rq_dropme-to-signal-the-need-to-drop-a-reply.patch
nfsd-use-rhashtable-for-managing-nfs4_file-objects.patch
nfsd-use-set_bit-rq_dropme.patch
nfsd-use-struct_size-helper-in-alloc_session.patch
trace-relocate-event-helper-files.patch

38 files changed:
queue-6.1/exportfs-use-pr_debug-for-unreachable-debug-statements.patch [new file with mode: 0644]
queue-6.1/filelock-add-a-new-locks_inode_context-accessor-function.patch [new file with mode: 0644]
queue-6.1/lockd-ensure-we-use-the-correct-file-descriptor-when-unlocking.patch [new file with mode: 0644]
queue-6.1/lockd-fix-file-selection-in-nlmsvc_cancel_blocked.patch [new file with mode: 0644]
queue-6.1/lockd-set-missing-fl_flags-field-when-retrieving-args.patch [new file with mode: 0644]
queue-6.1/lockd-use-locks_inode_context-helper.patch [new file with mode: 0644]
queue-6.1/nfsd-add-a-nfsd4_file_hash_remove-helper.patch [new file with mode: 0644]
queue-6.1/nfsd-add-cb_recall_any-tracepoints.patch [new file with mode: 0644]
queue-6.1/nfsd-add-delegation-reaper-to-react-to-low-memory-condition.patch [new file with mode: 0644]
queue-6.1/nfsd-add-support-for-sending-cb_recall_any.patch [new file with mode: 0644]
queue-6.1/nfsd-allow-disabling-nfsv2-at-compile-time.patch [new file with mode: 0644]
queue-6.1/nfsd-avoid-clashing-function-prototypes.patch [new file with mode: 0644]
queue-6.1/nfsd-clean-up-find_or_add_file.patch [new file with mode: 0644]
queue-6.1/nfsd-clean-up-nfs4_preprocess_stateid_op-call-sites.patch [new file with mode: 0644]
queue-6.1/nfsd-clean-up-nfsd4_init_file.patch [new file with mode: 0644]
queue-6.1/nfsd-don-t-destroy-global-nfs4_file-table-in-per-net-shutdown.patch [new file with mode: 0644]
queue-6.1/nfsd-fix-licensing-header-in-filecache.c.patch [new file with mode: 0644]
queue-6.1/nfsd-fix-up-the-filecache-laundrette-scheduling.patch [new file with mode: 0644]
queue-6.1/nfsd-flesh-out-a-documenting-comment-for-filecache.c.patch [new file with mode: 0644]
queue-6.1/nfsd-ignore-requests-to-disable-unsupported-versions.patch [new file with mode: 0644]
queue-6.1/nfsd-move-nfserrno-to-vfs.c.patch [new file with mode: 0644]
queue-6.1/nfsd-refactor-find_file.patch [new file with mode: 0644]
queue-6.1/nfsd-refactoring-courtesy_client_reaper-to-a-generic-low-memory-shrinker.patch [new file with mode: 0644]
queue-6.1/nfsd-register-unregister-of-nfsd-client-shrinker-at-nfsd-startup-shutdown-time.patch [new file with mode: 0644]
queue-6.1/nfsd-remove-redundant-assignment-to-variable-host_err.patch [new file with mode: 0644]
queue-6.1/nfsd-replace-delayed_work-with-work_struct-for-nfsd_client_shrinker.patch [new file with mode: 0644]
queue-6.1/nfsd-simplify-read_plus.patch [new file with mode: 0644]
queue-6.1/nfsd-trace-delegation-revocations.patch [new file with mode: 0644]
queue-6.1/nfsd-trace-stateids-returned-via-delegreturn.patch [new file with mode: 0644]
queue-6.1/nfsd-update-file_hashtbl-helpers.patch [new file with mode: 0644]
queue-6.1/nfsd-use-const-pointers-as-parameters-to-fh_-helpers.patch [new file with mode: 0644]
queue-6.1/nfsd-use-locks_inode_context-helper.patch [new file with mode: 0644]
queue-6.1/nfsd-use-only-rq_dropme-to-signal-the-need-to-drop-a-reply.patch [new file with mode: 0644]
queue-6.1/nfsd-use-rhashtable-for-managing-nfs4_file-objects.patch [new file with mode: 0644]
queue-6.1/nfsd-use-set_bit-rq_dropme.patch [new file with mode: 0644]
queue-6.1/nfsd-use-struct_size-helper-in-alloc_session.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/trace-relocate-event-helper-files.patch [new file with mode: 0644]

diff --git a/queue-6.1/exportfs-use-pr_debug-for-unreachable-debug-statements.patch b/queue-6.1/exportfs-use-pr_debug-for-unreachable-debug-statements.patch
new file mode 100644 (file)
index 0000000..0cc7381
--- /dev/null
@@ -0,0 +1,55 @@
+From db11de653c2fdd198722c6647c23d8ecbf2dc80a Mon Sep 17 00:00:00 2001
+From: David Disseldorp <ddiss@suse.de>
+Date: Fri, 21 Oct 2022 14:24:14 +0200
+Subject: exportfs: use pr_debug for unreachable debug statements
+
+From: David Disseldorp <ddiss@suse.de>
+
+[ Upstream commit 427505ffeaa464f683faba945a88d3e3248f6979 ]
+
+expfs.c has a bunch of dprintk statements which are unusable due to:
+ #define dprintk(fmt, args...) do{}while(0)
+Use pr_debug so that they can be enabled dynamically.
+Also make some minor changes to the debug statements to fix some
+incorrect types, and remove __func__ which can be handled by dynamic
+debug separately.
+
+Signed-off-by: David Disseldorp <ddiss@suse.de>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exportfs/expfs.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/exportfs/expfs.c
++++ b/fs/exportfs/expfs.c
+@@ -18,7 +18,7 @@
+ #include <linux/sched.h>
+ #include <linux/cred.h>
+-#define dprintk(fmt, args...) do{}while(0)
++#define dprintk(fmt, args...) pr_debug(fmt, ##args)
+ static int get_name(const struct path *path, char *name, struct dentry *child);
+@@ -132,8 +132,8 @@ static struct dentry *reconnect_one(stru
+       inode_unlock(dentry->d_inode);
+       if (IS_ERR(parent)) {
+-              dprintk("%s: get_parent of %ld failed, err %d\n",
+-                      __func__, dentry->d_inode->i_ino, PTR_ERR(parent));
++              dprintk("get_parent of %lu failed, err %ld\n",
++                      dentry->d_inode->i_ino, PTR_ERR(parent));
+               return parent;
+       }
+@@ -147,7 +147,7 @@ static struct dentry *reconnect_one(stru
+       dprintk("%s: found name: %s\n", __func__, nbuf);
+       tmp = lookup_one_unlocked(mnt_user_ns(mnt), nbuf, parent, strlen(nbuf));
+       if (IS_ERR(tmp)) {
+-              dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp));
++              dprintk("lookup failed: %ld\n", PTR_ERR(tmp));
+               err = PTR_ERR(tmp);
+               goto out_err;
+       }
diff --git a/queue-6.1/filelock-add-a-new-locks_inode_context-accessor-function.patch b/queue-6.1/filelock-add-a-new-locks_inode_context-accessor-function.patch
new file mode 100644 (file)
index 0000000..48e2b93
--- /dev/null
@@ -0,0 +1,168 @@
+From 5c8dcb0ee71e3d832d3f7b67bcf369fc206fed1a Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 16 Nov 2022 09:02:30 -0500
+Subject: filelock: add a new locks_inode_context accessor function
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 401a8b8fd5acd51582b15238d72a8d0edd580e9f ]
+
+There are a number of places in the kernel that are accessing the
+inode->i_flctx field without smp_load_acquire. This is required to
+ensure that the caller doesn't see a partially-initialized structure.
+
+Add a new accessor function for it to make this clear and convert all of
+the relevant accesses in locks.c to use it. Also, convert
+locks_free_lock_context to use the helper as well instead of just doing
+a "bare" assignment.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 77c67530e1f9 ("nfsd: use locks_inode_context helper")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/locks.c         |   24 ++++++++++++------------
+ include/linux/fs.h |   14 ++++++++++++++
+ 2 files changed, 26 insertions(+), 12 deletions(-)
+
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -175,7 +175,7 @@ locks_get_lock_context(struct inode *ino
+       struct file_lock_context *ctx;
+       /* paired with cmpxchg() below */
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (likely(ctx) || type == F_UNLCK)
+               goto out;
+@@ -194,7 +194,7 @@ locks_get_lock_context(struct inode *ino
+        */
+       if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
+               kmem_cache_free(flctx_cache, ctx);
+-              ctx = smp_load_acquire(&inode->i_flctx);
++              ctx = locks_inode_context(inode);
+       }
+ out:
+       trace_locks_get_lock_context(inode, type, ctx);
+@@ -247,7 +247,7 @@ locks_check_ctx_file_list(struct file *f
+ void
+ locks_free_lock_context(struct inode *inode)
+ {
+-      struct file_lock_context *ctx = inode->i_flctx;
++      struct file_lock_context *ctx = locks_inode_context(inode);
+       if (unlikely(ctx)) {
+               locks_check_ctx_lists(inode);
+@@ -891,7 +891,7 @@ posix_test_lock(struct file *filp, struc
+       void *owner;
+       void (*func)(void);
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx || list_empty_careful(&ctx->flc_posix)) {
+               fl->fl_type = F_UNLCK;
+               return;
+@@ -1483,7 +1483,7 @@ int __break_lease(struct inode *inode, u
+       new_fl->fl_flags = type;
+       /* typically we will check that ctx is non-NULL before calling */
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx) {
+               WARN_ON_ONCE(1);
+               goto free_lock;
+@@ -1588,7 +1588,7 @@ void lease_get_mtime(struct inode *inode
+       struct file_lock_context *ctx;
+       struct file_lock *fl;
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (ctx && !list_empty_careful(&ctx->flc_lease)) {
+               spin_lock(&ctx->flc_lock);
+               fl = list_first_entry_or_null(&ctx->flc_lease,
+@@ -1634,7 +1634,7 @@ int fcntl_getlease(struct file *filp)
+       int type = F_UNLCK;
+       LIST_HEAD(dispose);
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (ctx && !list_empty_careful(&ctx->flc_lease)) {
+               percpu_down_read(&file_rwsem);
+               spin_lock(&ctx->flc_lock);
+@@ -1823,7 +1823,7 @@ static int generic_delete_lease(struct f
+       struct file_lock_context *ctx;
+       LIST_HEAD(dispose);
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx) {
+               trace_generic_delete_lease(inode, NULL);
+               return error;
+@@ -2562,7 +2562,7 @@ void locks_remove_posix(struct file *fil
+        * posix_lock_file().  Another process could be setting a lock on this
+        * file at the same time, but we wouldn't remove that lock anyway.
+        */
+-      ctx =  smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx || list_empty(&ctx->flc_posix))
+               return;
+@@ -2635,7 +2635,7 @@ void locks_remove_file(struct file *filp
+ {
+       struct file_lock_context *ctx;
+-      ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
++      ctx = locks_inode_context(locks_inode(filp));
+       if (!ctx)
+               return;
+@@ -2682,7 +2682,7 @@ bool vfs_inode_has_locks(struct inode *i
+       struct file_lock_context *ctx;
+       bool ret;
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx)
+               return false;
+@@ -2863,7 +2863,7 @@ void show_fd_locks(struct seq_file *f,
+       struct file_lock_context *ctx;
+       int id = 0;
+-      ctx = smp_load_acquire(&inode->i_flctx);
++      ctx = locks_inode_context(inode);
+       if (!ctx)
+               return;
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1189,6 +1189,13 @@ extern void show_fd_locks(struct seq_fil
+                        struct file *filp, struct files_struct *files);
+ extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
+                       fl_owner_t owner);
++
++static inline struct file_lock_context *
++locks_inode_context(const struct inode *inode)
++{
++      return smp_load_acquire(&inode->i_flctx);
++}
++
+ #else /* !CONFIG_FILE_LOCKING */
+ static inline int fcntl_getlk(struct file *file, unsigned int cmd,
+                             struct flock __user *user)
+@@ -1334,6 +1341,13 @@ static inline bool locks_owner_has_block
+ {
+       return false;
+ }
++
++static inline struct file_lock_context *
++locks_inode_context(const struct inode *inode)
++{
++      return NULL;
++}
++
+ #endif /* !CONFIG_FILE_LOCKING */
+ static inline struct inode *file_inode(const struct file *f)
diff --git a/queue-6.1/lockd-ensure-we-use-the-correct-file-descriptor-when-unlocking.patch b/queue-6.1/lockd-ensure-we-use-the-correct-file-descriptor-when-unlocking.patch
new file mode 100644 (file)
index 0000000..b3aff36
--- /dev/null
@@ -0,0 +1,40 @@
+From f9d843598ec499abdb2f040a1c6665cfc7ab1b87 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Fri, 11 Nov 2022 14:36:37 -0500
+Subject: lockd: ensure we use the correct file descriptor when unlocking
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 69efce009f7df888e1fede3cb2913690eb829f52 ]
+
+Shared locks are set on O_RDONLY descriptors and exclusive locks are set
+on O_WRONLY ones. nlmsvc_unlock however calls vfs_lock_file twice, once
+for each descriptor, but it doesn't reset fl_file. Ensure that it does.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svclock.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -659,11 +659,13 @@ nlmsvc_unlock(struct net *net, struct nl
+       nlmsvc_cancel_blocked(net, file, lock);
+       lock->fl.fl_type = F_UNLCK;
+-      if (file->f_file[O_RDONLY])
+-              error = vfs_lock_file(file->f_file[O_RDONLY], F_SETLK,
++      lock->fl.fl_file = file->f_file[O_RDONLY];
++      if (lock->fl.fl_file)
++              error = vfs_lock_file(lock->fl.fl_file, F_SETLK,
+                                       &lock->fl, NULL);
+-      if (file->f_file[O_WRONLY])
+-              error = vfs_lock_file(file->f_file[O_WRONLY], F_SETLK,
++      lock->fl.fl_file = file->f_file[O_WRONLY];
++      if (lock->fl.fl_file)
++              error |= vfs_lock_file(lock->fl.fl_file, F_SETLK,
+                                       &lock->fl, NULL);
+       return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
diff --git a/queue-6.1/lockd-fix-file-selection-in-nlmsvc_cancel_blocked.patch b/queue-6.1/lockd-fix-file-selection-in-nlmsvc_cancel_blocked.patch
new file mode 100644 (file)
index 0000000..3ea46ad
--- /dev/null
@@ -0,0 +1,38 @@
+From fdf4fd6f05ae4659354de48f42dcee40eb4405dd Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Fri, 11 Nov 2022 14:36:38 -0500
+Subject: lockd: fix file selection in nlmsvc_cancel_blocked
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 9f27783b4dd235ef3c8dbf69fc6322777450323c ]
+
+We currently do a lock_to_openmode call based on the arguments from the
+NLM_UNLOCK call, but that will always set the fl_type of the lock to
+F_UNLCK, and the O_RDONLY descriptor is always chosen.
+
+Fix it to use the file_lock from the block instead.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svclock.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -699,9 +699,10 @@ nlmsvc_cancel_blocked(struct net *net, s
+       block = nlmsvc_lookup_block(file, lock);
+       mutex_unlock(&file->f_mutex);
+       if (block != NULL) {
+-              mode = lock_to_openmode(&lock->fl);
+-              vfs_cancel_lock(block->b_file->f_file[mode],
+-                              &block->b_call->a_args.lock.fl);
++              struct file_lock *fl = &block->b_call->a_args.lock.fl;
++
++              mode = lock_to_openmode(fl);
++              vfs_cancel_lock(block->b_file->f_file[mode], fl);
+               status = nlmsvc_unlink_block(block);
+               nlmsvc_release_block(block);
+       }
diff --git a/queue-6.1/lockd-set-missing-fl_flags-field-when-retrieving-args.patch b/queue-6.1/lockd-set-missing-fl_flags-field-when-retrieving-args.patch
new file mode 100644 (file)
index 0000000..ac56a5f
--- /dev/null
@@ -0,0 +1,37 @@
+From c9bb9f1f9a8a13d5c4d8d0dc61826710edfa5ee4 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Fri, 11 Nov 2022 14:36:36 -0500
+Subject: lockd: set missing fl_flags field when retrieving args
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 75c7940d2a86d3f1b60a0a265478cb8fc887b970 ]
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svc4proc.c |    1 +
+ fs/lockd/svcproc.c  |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -52,6 +52,7 @@ nlm4svc_retrieve_args(struct svc_rqst *r
+               *filp = file;
+               /* Set up the missing parts of the file_lock structure */
++              lock->fl.fl_flags = FL_POSIX;
+               lock->fl.fl_file  = file->f_file[mode];
+               lock->fl.fl_pid = current->tgid;
+               lock->fl.fl_start = (loff_t)lock->lock_start;
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -77,6 +77,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rq
+               /* Set up the missing parts of the file_lock structure */
+               mode = lock_to_openmode(&lock->fl);
++              lock->fl.fl_flags = FL_POSIX;
+               lock->fl.fl_file  = file->f_file[mode];
+               lock->fl.fl_pid = current->tgid;
+               lock->fl.fl_lmops = &nlmsvc_lock_operations;
diff --git a/queue-6.1/lockd-use-locks_inode_context-helper.patch b/queue-6.1/lockd-use-locks_inode_context-helper.patch
new file mode 100644 (file)
index 0000000..5c34743
--- /dev/null
@@ -0,0 +1,44 @@
+From 444f52797c77c16ddea5319f53c0d650d775606c Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 16 Nov 2022 09:19:43 -0500
+Subject: lockd: use locks_inode_context helper
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 98b41ffe0afdfeaa1439a5d6bd2db4a94277e31b ]
+
+lockd currently doesn't access i_flctx safely. This requires a
+smp_load_acquire, as the pointer is set via cmpxchg (a release
+operation).
+
+Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
+Cc: Anna Schumaker <anna@kernel.org>
+Cc: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svcsubs.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -210,7 +210,7 @@ nlm_traverse_locks(struct nlm_host *host
+ {
+       struct inode     *inode = nlmsvc_file_inode(file);
+       struct file_lock *fl;
+-      struct file_lock_context *flctx = inode->i_flctx;
++      struct file_lock_context *flctx = locks_inode_context(inode);
+       struct nlm_host  *lockhost;
+       if (!flctx || list_empty_careful(&flctx->flc_posix))
+@@ -265,7 +265,7 @@ nlm_file_inuse(struct nlm_file *file)
+ {
+       struct inode     *inode = nlmsvc_file_inode(file);
+       struct file_lock *fl;
+-      struct file_lock_context *flctx = inode->i_flctx;
++      struct file_lock_context *flctx = locks_inode_context(inode);
+       if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
+               return 1;
diff --git a/queue-6.1/nfsd-add-a-nfsd4_file_hash_remove-helper.patch b/queue-6.1/nfsd-add-a-nfsd4_file_hash_remove-helper.patch
new file mode 100644 (file)
index 0000000..52500cf
--- /dev/null
@@ -0,0 +1,61 @@
+From 29ddbb46d0563b2f0dc15886308b67aa5916965a Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:34 -0400
+Subject: NFSD: Add a nfsd4_file_hash_remove() helper
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 3341678f2fd6106055cead09e513fad6950a0d19 ]
+
+Refactor to relocate hash deletion operation to a helper function
+that is close to most other nfs4_file data structure operations.
+
+The "noinline" annotation will become useful in a moment when the
+hlist_del_rcu() is replaced with a more complex rhash remove
+operation. It also guarantees that hash remove operations can be
+traced with "-p function -l remove_nfs4_file_locked".
+
+This also simplifies the organization of forward declarations: the
+to-be-added rhashtable and its param structure will be defined
+/after/ put_nfs4_file().
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -84,6 +84,7 @@ static bool check_for_locks(struct nfs4_
+ static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
+ void nfsd4_end_grace(struct nfsd_net *nn);
+ static void _free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_state *cps);
++static void nfsd4_file_hash_remove(struct nfs4_file *fi);
+ /* Locking: */
+@@ -591,7 +592,7 @@ put_nfs4_file(struct nfs4_file *fi)
+       might_lock(&state_lock);
+       if (refcount_dec_and_lock(&fi->fi_ref, &state_lock)) {
+-              hlist_del_rcu(&fi->fi_hash);
++              nfsd4_file_hash_remove(fi);
+               spin_unlock(&state_lock);
+               WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
+               WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
+@@ -4750,6 +4751,11 @@ find_or_add_file(struct nfs4_file *new,
+       return insert_file(new, fh, hashval);
+ }
++static noinline_for_stack void nfsd4_file_hash_remove(struct nfs4_file *fi)
++{
++      hlist_del_rcu(&fi->fi_hash);
++}
++
+ /*
+  * Called to check deny when READ with all zero stateid or
+  * WRITE with all zero or all one stateid
diff --git a/queue-6.1/nfsd-add-cb_recall_any-tracepoints.patch b/queue-6.1/nfsd-add-cb_recall_any-tracepoints.patch
new file mode 100644 (file)
index 0000000..93eabee
--- /dev/null
@@ -0,0 +1,136 @@
+From f8705e063165c4cd87f1bbdec9211992c5d434e4 Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 16 Nov 2022 19:44:48 -0800
+Subject: NFSD: add CB_RECALL_ANY tracepoints
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit 638593be55c0b37a1930038460a9918215d5c24b ]
+
+Add tracepoints to trace start and end of CB_RECALL_ANY operation.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+[ cel: added show_rca_mask() macro ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c      |    2 +
+ fs/nfsd/trace.h          |   50 +++++++++++++++++++++++++++++++++++++++++++++++
+ include/trace/misc/nfs.h |   12 +++++++++++
+ 3 files changed, 64 insertions(+)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2877,6 +2877,7 @@ static int
+ nfsd4_cb_recall_any_done(struct nfsd4_callback *cb,
+                               struct rpc_task *task)
+ {
++      trace_nfsd_cb_recall_any_done(cb, task);
+       switch (task->tk_status) {
+       case -NFS4ERR_DELAY:
+               rpc_delay(task, 2 * HZ);
+@@ -6254,6 +6255,7 @@ deleg_reaper(struct nfsd_net *nn)
+               list_del_init(&clp->cl_ra_cblist);
+               clp->cl_ra->ra_keep = 0;
+               clp->cl_ra->ra_bmval[0] = BIT(RCA4_TYPE_MASK_RDATA_DLG);
++              trace_nfsd_cb_recall_any(clp->cl_ra);
+               nfsd4_run_cb(&clp->cl_ra->ra_cb);
+       }
+ }
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -9,9 +9,12 @@
+ #define _NFSD_TRACE_H
+ #include <linux/tracepoint.h>
++#include <linux/sunrpc/xprt.h>
++#include <trace/misc/nfs.h>
+ #include "export.h"
+ #include "nfsfh.h"
++#include "xdr4.h"
+ #define NFSD_TRACE_PROC_RES_FIELDS \
+               __field(unsigned int, netns_ino) \
+@@ -1492,6 +1495,32 @@ TRACE_EVENT(nfsd_cb_offload,
+               __entry->fh_hash, __entry->count, __entry->status)
+ );
++TRACE_EVENT(nfsd_cb_recall_any,
++      TP_PROTO(
++              const struct nfsd4_cb_recall_any *ra
++      ),
++      TP_ARGS(ra),
++      TP_STRUCT__entry(
++              __field(u32, cl_boot)
++              __field(u32, cl_id)
++              __field(u32, keep)
++              __field(unsigned long, bmval0)
++              __sockaddr(addr, ra->ra_cb.cb_clp->cl_cb_conn.cb_addrlen)
++      ),
++      TP_fast_assign(
++              __entry->cl_boot = ra->ra_cb.cb_clp->cl_clientid.cl_boot;
++              __entry->cl_id = ra->ra_cb.cb_clp->cl_clientid.cl_id;
++              __entry->keep = ra->ra_keep;
++              __entry->bmval0 = ra->ra_bmval[0];
++              __assign_sockaddr(addr, &ra->ra_cb.cb_clp->cl_addr,
++                                ra->ra_cb.cb_clp->cl_cb_conn.cb_addrlen);
++      ),
++      TP_printk("addr=%pISpc client %08x:%08x keep=%u bmval0=%s",
++              __get_sockaddr(addr), __entry->cl_boot, __entry->cl_id,
++              __entry->keep, show_rca_mask(__entry->bmval0)
++      )
++);
++
+ DECLARE_EVENT_CLASS(nfsd_cb_done_class,
+       TP_PROTO(
+               const stateid_t *stp,
+@@ -1531,6 +1560,27 @@ DEFINE_NFSD_CB_DONE_EVENT(nfsd_cb_notify
+ DEFINE_NFSD_CB_DONE_EVENT(nfsd_cb_layout_done);
+ DEFINE_NFSD_CB_DONE_EVENT(nfsd_cb_offload_done);
++TRACE_EVENT(nfsd_cb_recall_any_done,
++      TP_PROTO(
++              const struct nfsd4_callback *cb,
++              const struct rpc_task *task
++      ),
++      TP_ARGS(cb, task),
++      TP_STRUCT__entry(
++              __field(u32, cl_boot)
++              __field(u32, cl_id)
++              __field(int, status)
++      ),
++      TP_fast_assign(
++              __entry->status = task->tk_status;
++              __entry->cl_boot = cb->cb_clp->cl_clientid.cl_boot;
++              __entry->cl_id = cb->cb_clp->cl_clientid.cl_id;
++      ),
++      TP_printk("client %08x:%08x status=%d",
++              __entry->cl_boot, __entry->cl_id, __entry->status
++      )
++);
++
+ #endif /* _NFSD_TRACE_H */
+ #undef TRACE_INCLUDE_PATH
+--- a/include/trace/misc/nfs.h
++++ b/include/trace/misc/nfs.h
+@@ -360,6 +360,18 @@ 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/queue-6.1/nfsd-add-delegation-reaper-to-react-to-low-memory-condition.patch b/queue-6.1/nfsd-add-delegation-reaper-to-react-to-low-memory-condition.patch
new file mode 100644 (file)
index 0000000..115391f
--- /dev/null
@@ -0,0 +1,204 @@
+From ae75430dec3ea9b1eeaeefdfc28470352dd00dc5 Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 16 Nov 2022 19:44:47 -0800
+Subject: NFSD: add delegation reaper to react to low memory condition
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit 44df6f439a1790a5f602e3842879efa88f346672 ]
+
+The delegation reaper is called by nfsd memory shrinker's on
+the 'count' callback. It scans the client list and sends the
+courtesy CB_RECALL_ANY to the clients that hold delegations.
+
+To avoid flooding the clients with CB_RECALL_ANY requests, the
+delegation reaper sends only one CB_RECALL_ANY request to each
+client per 5 seconds.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+[ cel: moved definition of RCA4_TYPE_MASK_RDATA_DLG ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c  |   88 ++++++++++++++++++++++++++++++++++++++++++++++++---
+ fs/nfsd/state.h      |    5 ++
+ include/linux/nfs4.h |   13 +++++++
+ 3 files changed, 102 insertions(+), 4 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2145,6 +2145,7 @@ static void __free_client(struct kref *k
+       kfree(clp->cl_nii_domain.data);
+       kfree(clp->cl_nii_name.data);
+       idr_destroy(&clp->cl_stateids);
++      kfree(clp->cl_ra);
+       kmem_cache_free(client_slab, clp);
+ }
+@@ -2872,6 +2873,36 @@ static const struct tree_descr client_fi
+       [3] = {""},
+ };
++static int
++nfsd4_cb_recall_any_done(struct nfsd4_callback *cb,
++                              struct rpc_task *task)
++{
++      switch (task->tk_status) {
++      case -NFS4ERR_DELAY:
++              rpc_delay(task, 2 * HZ);
++              return 0;
++      default:
++              return 1;
++      }
++}
++
++static void
++nfsd4_cb_recall_any_release(struct nfsd4_callback *cb)
++{
++      struct nfs4_client *clp = cb->cb_clp;
++      struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
++
++      spin_lock(&nn->client_lock);
++      clear_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
++      put_client_renew_locked(clp);
++      spin_unlock(&nn->client_lock);
++}
++
++static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
++      .done           = nfsd4_cb_recall_any_done,
++      .release        = nfsd4_cb_recall_any_release,
++};
++
+ static struct nfs4_client *create_client(struct xdr_netobj name,
+               struct svc_rqst *rqstp, nfs4_verifier *verf)
+ {
+@@ -2909,6 +2940,14 @@ static struct nfs4_client *create_client
+               free_client(clp);
+               return NULL;
+       }
++      clp->cl_ra = kzalloc(sizeof(*clp->cl_ra), GFP_KERNEL);
++      if (!clp->cl_ra) {
++              free_client(clp);
++              return NULL;
++      }
++      clp->cl_ra_time = 0;
++      nfsd4_init_cb(&clp->cl_ra->ra_cb, clp, &nfsd4_cb_recall_any_ops,
++                      NFSPROC4_CLNT_CB_RECALL_ANY);
+       return clp;
+ }
+@@ -4364,14 +4403,16 @@ out:
+ static unsigned long
+ nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
+ {
+-      int cnt;
++      int count;
+       struct nfsd_net *nn = container_of(shrink,
+                       struct nfsd_net, nfsd_client_shrinker);
+-      cnt = atomic_read(&nn->nfsd_courtesy_clients);
+-      if (cnt > 0)
++      count = atomic_read(&nn->nfsd_courtesy_clients);
++      if (!count)
++              count = atomic_long_read(&num_delegations);
++      if (count)
+               mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0);
+-      return (unsigned long)cnt;
++      return (unsigned long)count;
+ }
+ static unsigned long
+@@ -6180,6 +6221,44 @@ courtesy_client_reaper(struct nfsd_net *
+ }
+ static void
++deleg_reaper(struct nfsd_net *nn)
++{
++      struct list_head *pos, *next;
++      struct nfs4_client *clp;
++      struct list_head cblist;
++
++      INIT_LIST_HEAD(&cblist);
++      spin_lock(&nn->client_lock);
++      list_for_each_safe(pos, next, &nn->client_lru) {
++              clp = list_entry(pos, struct nfs4_client, cl_lru);
++              if (clp->cl_state != NFSD4_ACTIVE ||
++                      list_empty(&clp->cl_delegations) ||
++                      atomic_read(&clp->cl_delegs_in_recall) ||
++                      test_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags) ||
++                      (ktime_get_boottime_seconds() -
++                              clp->cl_ra_time < 5)) {
++                      continue;
++              }
++              list_add(&clp->cl_ra_cblist, &cblist);
++
++              /* release in nfsd4_cb_recall_any_release */
++              atomic_inc(&clp->cl_rpc_users);
++              set_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
++              clp->cl_ra_time = ktime_get_boottime_seconds();
++      }
++      spin_unlock(&nn->client_lock);
++
++      while (!list_empty(&cblist)) {
++              clp = list_first_entry(&cblist, struct nfs4_client,
++                                      cl_ra_cblist);
++              list_del_init(&clp->cl_ra_cblist);
++              clp->cl_ra->ra_keep = 0;
++              clp->cl_ra->ra_bmval[0] = BIT(RCA4_TYPE_MASK_RDATA_DLG);
++              nfsd4_run_cb(&clp->cl_ra->ra_cb);
++      }
++}
++
++static void
+ nfsd4_state_shrinker_worker(struct work_struct *work)
+ {
+       struct delayed_work *dwork = to_delayed_work(work);
+@@ -6187,6 +6266,7 @@ nfsd4_state_shrinker_worker(struct work_
+                               nfsd_shrinker_work);
+       courtesy_client_reaper(nn);
++      deleg_reaper(nn);
+ }
+ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp)
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -368,6 +368,7 @@ struct nfs4_client {
+ #define NFSD4_CLIENT_UPCALL_LOCK      (5)     /* upcall serialization */
+ #define NFSD4_CLIENT_CB_FLAG_MASK     (1 << NFSD4_CLIENT_CB_UPDATE | \
+                                        1 << NFSD4_CLIENT_CB_KILL)
++#define NFSD4_CLIENT_CB_RECALL_ANY    (6)
+       unsigned long           cl_flags;
+       const struct cred       *cl_cb_cred;
+       struct rpc_clnt         *cl_cb_client;
+@@ -411,6 +412,10 @@ struct nfs4_client {
+       unsigned int            cl_state;
+       atomic_t                cl_delegs_in_recall;
++
++      struct nfsd4_cb_recall_any      *cl_ra;
++      time64_t                cl_ra_time;
++      struct list_head        cl_ra_cblist;
+ };
+ /* struct nfs4_client_reset
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -732,4 +732,17 @@ enum nfs4_setxattr_options {
+       SETXATTR4_CREATE        = 1,
+       SETXATTR4_REPLACE       = 2,
+ };
++
++enum {
++      RCA4_TYPE_MASK_RDATA_DLG        = 0,
++      RCA4_TYPE_MASK_WDATA_DLG        = 1,
++      RCA4_TYPE_MASK_DIR_DLG          = 2,
++      RCA4_TYPE_MASK_FILE_LAYOUT      = 3,
++      RCA4_TYPE_MASK_BLK_LAYOUT       = 4,
++      RCA4_TYPE_MASK_OBJ_LAYOUT_MIN   = 8,
++      RCA4_TYPE_MASK_OBJ_LAYOUT_MAX   = 9,
++      RCA4_TYPE_MASK_OTHER_LAYOUT_MIN = 12,
++      RCA4_TYPE_MASK_OTHER_LAYOUT_MAX = 15,
++};
++
+ #endif
diff --git a/queue-6.1/nfsd-add-support-for-sending-cb_recall_any.patch b/queue-6.1/nfsd-add-support-for-sending-cb_recall_any.patch
new file mode 100644 (file)
index 0000000..25510d5
--- /dev/null
@@ -0,0 +1,165 @@
+From 08607743476ffa171431efaec0d6e7c29bbbed4e Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 16 Nov 2022 19:44:46 -0800
+Subject: NFSD: add support for sending CB_RECALL_ANY
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit 3959066b697b5dfbb7141124ae9665337d4bc638 ]
+
+Add XDR encode and decode function for CB_RECALL_ANY.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4callback.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/nfsd/state.h        |    1 
+ fs/nfsd/xdr4.h         |    5 +++
+ fs/nfsd/xdr4cb.h       |    6 ++++
+ 4 files changed, 84 insertions(+)
+
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -76,6 +76,17 @@ static __be32 *xdr_encode_empty_array(__
+  * 1 Protocol"
+  */
++static void encode_uint32(struct xdr_stream *xdr, u32 n)
++{
++      WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0);
++}
++
++static void encode_bitmap4(struct xdr_stream *xdr, const __u32 *bitmap,
++                         size_t len)
++{
++      WARN_ON_ONCE(xdr_stream_encode_uint32_array(xdr, bitmap, len) < 0);
++}
++
+ /*
+  *    nfs_cb_opnum4
+  *
+@@ -329,6 +340,24 @@ static void encode_cb_recall4args(struct
+ }
+ /*
++ * CB_RECALLANY4args
++ *
++ *    struct CB_RECALLANY4args {
++ *            uint32_t        craa_objects_to_keep;
++ *            bitmap4         craa_type_mask;
++ *    };
++ */
++static void
++encode_cb_recallany4args(struct xdr_stream *xdr,
++      struct nfs4_cb_compound_hdr *hdr, struct nfsd4_cb_recall_any *ra)
++{
++      encode_nfs_cb_opnum4(xdr, OP_CB_RECALL_ANY);
++      encode_uint32(xdr, ra->ra_keep);
++      encode_bitmap4(xdr, ra->ra_bmval, ARRAY_SIZE(ra->ra_bmval));
++      hdr->nops++;
++}
++
++/*
+  * CB_SEQUENCE4args
+  *
+  *    struct CB_SEQUENCE4args {
+@@ -482,6 +511,26 @@ static void nfs4_xdr_enc_cb_recall(struc
+       encode_cb_nops(&hdr);
+ }
++/*
++ * 20.6. Operation 8: CB_RECALL_ANY - Keep Any N Recallable Objects
++ */
++static void
++nfs4_xdr_enc_cb_recall_any(struct rpc_rqst *req,
++              struct xdr_stream *xdr, const void *data)
++{
++      const struct nfsd4_callback *cb = data;
++      struct nfsd4_cb_recall_any *ra;
++      struct nfs4_cb_compound_hdr hdr = {
++              .ident = cb->cb_clp->cl_cb_ident,
++              .minorversion = cb->cb_clp->cl_minorversion,
++      };
++
++      ra = container_of(cb, struct nfsd4_cb_recall_any, ra_cb);
++      encode_cb_compound4args(xdr, &hdr);
++      encode_cb_sequence4args(xdr, cb, &hdr);
++      encode_cb_recallany4args(xdr, &hdr, ra);
++      encode_cb_nops(&hdr);
++}
+ /*
+  * NFSv4.0 and NFSv4.1 XDR decode functions
+@@ -520,6 +569,28 @@ static int nfs4_xdr_dec_cb_recall(struct
+       return decode_cb_op_status(xdr, OP_CB_RECALL, &cb->cb_status);
+ }
++/*
++ * 20.6. Operation 8: CB_RECALL_ANY - Keep Any N Recallable Objects
++ */
++static int
++nfs4_xdr_dec_cb_recall_any(struct rpc_rqst *rqstp,
++                                struct xdr_stream *xdr,
++                                void *data)
++{
++      struct nfsd4_callback *cb = data;
++      struct nfs4_cb_compound_hdr hdr;
++      int status;
++
++      status = decode_cb_compound4res(xdr, &hdr);
++      if (unlikely(status))
++              return status;
++      status = decode_cb_sequence4res(xdr, cb);
++      if (unlikely(status || cb->cb_seq_status))
++              return status;
++      status =  decode_cb_op_status(xdr, OP_CB_RECALL_ANY, &cb->cb_status);
++      return status;
++}
++
+ #ifdef CONFIG_NFSD_PNFS
+ /*
+  * CB_LAYOUTRECALL4args
+@@ -783,6 +854,7 @@ static const struct rpc_procinfo nfs4_cb
+ #endif
+       PROC(CB_NOTIFY_LOCK,    COMPOUND,       cb_notify_lock, cb_notify_lock),
+       PROC(CB_OFFLOAD,        COMPOUND,       cb_offload,     cb_offload),
++      PROC(CB_RECALL_ANY,     COMPOUND,       cb_recall_any,  cb_recall_any),
+ };
+ static unsigned int nfs4_cb_counts[ARRAY_SIZE(nfs4_cb_procedures)];
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -636,6 +636,7 @@ enum nfsd4_cb_op {
+       NFSPROC4_CLNT_CB_OFFLOAD,
+       NFSPROC4_CLNT_CB_SEQUENCE,
+       NFSPROC4_CLNT_CB_NOTIFY_LOCK,
++      NFSPROC4_CLNT_CB_RECALL_ANY,
+ };
+ /* Returns true iff a is later than b: */
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -896,5 +896,10 @@ struct nfsd4_operation {
+                       union nfsd4_op_u *);
+ };
++struct nfsd4_cb_recall_any {
++      struct nfsd4_callback   ra_cb;
++      u32                     ra_keep;
++      u32                     ra_bmval[1];
++};
+ #endif
+--- a/fs/nfsd/xdr4cb.h
++++ b/fs/nfsd/xdr4cb.h
+@@ -48,3 +48,9 @@
+ #define NFS4_dec_cb_offload_sz                (cb_compound_dec_hdr_sz  +      \
+                                       cb_sequence_dec_sz +            \
+                                       op_dec_sz)
++#define NFS4_enc_cb_recall_any_sz     (cb_compound_enc_hdr_sz +       \
++                                      cb_sequence_enc_sz +            \
++                                      1 + 1 + 1)
++#define NFS4_dec_cb_recall_any_sz     (cb_compound_dec_hdr_sz  +      \
++                                      cb_sequence_dec_sz +            \
++                                      op_dec_sz)
diff --git a/queue-6.1/nfsd-allow-disabling-nfsv2-at-compile-time.patch b/queue-6.1/nfsd-allow-disabling-nfsv2-at-compile-time.patch
new file mode 100644 (file)
index 0000000..937c615
--- /dev/null
@@ -0,0 +1,143 @@
+From ca0bebbcc3bee825aa4f8768aca93a41aa076bbb Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 18 Oct 2022 07:47:56 -0400
+Subject: nfsd: allow disabling NFSv2 at compile time
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 2f3a4b2ac2f28b9be78ad21f401f31e263845214 ]
+
+rpc.nfsd stopped supporting NFSv2 a year ago. Take the next logical
+step toward deprecating it and allow NFSv2 support to be compiled out.
+
+Add a new CONFIG_NFSD_V2 option that can be turned off and rework the
+CONFIG_NFSD_V?_ACL option dependencies. Add a description that
+discourages enabling it.
+
+Also, change the description of CONFIG_NFSD to state that the always-on
+version is now 3 instead of 2.
+
+Finally, add an #ifdef around "case 2:" in __write_versions. When NFSv2
+is disabled at compile time, this should make the kernel ignore attempts
+to disable it at runtime, but still error out when trying to enable it.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Tom Talpey <tom@talpey.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/Kconfig  |   19 +++++++++++++++----
+ fs/nfsd/Makefile |    5 +++--
+ fs/nfsd/nfsctl.c |    2 ++
+ fs/nfsd/nfsd.h   |    3 +--
+ fs/nfsd/nfssvc.c |    6 ++++++
+ 5 files changed, 27 insertions(+), 8 deletions(-)
+
+--- a/fs/nfsd/Kconfig
++++ b/fs/nfsd/Kconfig
+@@ -8,6 +8,7 @@ config NFSD
+       select SUNRPC
+       select EXPORTFS
+       select NFS_ACL_SUPPORT if NFSD_V2_ACL
++      select NFS_ACL_SUPPORT if NFSD_V3_ACL
+       depends on MULTIUSER
+       help
+         Choose Y here if you want to allow other computers to access
+@@ -26,19 +27,29 @@ config NFSD
+         Below you can choose which versions of the NFS protocol are
+         available to clients mounting the NFS server on this system.
+-        Support for NFS version 2 (RFC 1094) is always available when
++        Support for NFS version 3 (RFC 1813) is always available when
+         CONFIG_NFSD is selected.
+         If unsure, say N.
+-config NFSD_V2_ACL
+-      bool
++config NFSD_V2
++      bool "NFS server support for NFS version 2 (DEPRECATED)"
+       depends on NFSD
++      default n
++      help
++        NFSv2 (RFC 1094) was the first publicly-released version of NFS.
++        Unless you are hosting ancient (1990's era) NFS clients, you don't
++        need this.
++
++        If unsure, say N.
++
++config NFSD_V2_ACL
++      bool "NFS server support for the NFSv2 ACL protocol extension"
++      depends on NFSD_V2
+ config NFSD_V3_ACL
+       bool "NFS server support for the NFSv3 ACL protocol extension"
+       depends on NFSD
+-      select NFSD_V2_ACL
+       help
+         Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
+         never became an official part of the NFS version 3 protocol.
+--- a/fs/nfsd/Makefile
++++ b/fs/nfsd/Makefile
+@@ -10,9 +10,10 @@ obj-$(CONFIG_NFSD)  += nfsd.o
+ # this one should be compiled first, as the tracing macros can easily blow up
+ nfsd-y                        += trace.o
+-nfsd-y                        += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
+-                         export.o auth.o lockd.o nfscache.o nfsxdr.o \
++nfsd-y                        += nfssvc.o nfsctl.o nfsfh.o vfs.o \
++                         export.o auth.o lockd.o nfscache.o \
+                          stats.o filecache.o nfs3proc.o nfs3xdr.o
++nfsd-$(CONFIG_NFSD_V2) += nfsproc.o nfsxdr.o
+ nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
+ nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
+ nfsd-$(CONFIG_NFSD_V4)        += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -581,7 +581,9 @@ static ssize_t __write_versions(struct f
+                       cmd = sign == '-' ? NFSD_CLEAR : NFSD_SET;
+                       switch(num) {
++#ifdef CONFIG_NFSD_V2
+                       case 2:
++#endif
+                       case 3:
+                               nfsd_vers(nn, num, cmd);
+                               break;
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -64,8 +64,7 @@ struct readdir_cd {
+ extern struct svc_program     nfsd_program;
+-extern const struct svc_version       nfsd_version2, nfsd_version3,
+-                              nfsd_version4;
++extern const struct svc_version       nfsd_version2, nfsd_version3, nfsd_version4;
+ extern struct mutex           nfsd_mutex;
+ extern spinlock_t             nfsd_drc_lock;
+ extern unsigned long          nfsd_drc_max_mem;
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -91,8 +91,12 @@ unsigned long       nfsd_drc_mem_used;
+ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+ static struct svc_stat        nfsd_acl_svcstats;
+ static const struct svc_version *nfsd_acl_version[] = {
++# if defined(CONFIG_NFSD_V2_ACL)
+       [2] = &nfsd_acl_version2,
++# endif
++# if defined(CONFIG_NFSD_V3_ACL)
+       [3] = &nfsd_acl_version3,
++# endif
+ };
+ #define NFSD_ACL_MINVERS            2
+@@ -116,7 +120,9 @@ static struct svc_stat     nfsd_acl_svcstats
+ #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+ static const struct svc_version *nfsd_version[] = {
++#if defined(CONFIG_NFSD_V2)
+       [2] = &nfsd_version2,
++#endif
+       [3] = &nfsd_version3,
+ #if defined(CONFIG_NFSD_V4)
+       [4] = &nfsd_version4,
diff --git a/queue-6.1/nfsd-avoid-clashing-function-prototypes.patch b/queue-6.1/nfsd-avoid-clashing-function-prototypes.patch
new file mode 100644 (file)
index 0000000..b259b1a
--- /dev/null
@@ -0,0 +1,1529 @@
+From deb43baeb013c36694511a8751b59a4c68170a29 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Fri, 2 Dec 2022 12:48:59 -0800
+Subject: NFSD: Avoid clashing function prototypes
+
+From: Kees Cook <keescook@chromium.org>
+
+[ Upstream commit e78e274eb22d966258a3845acc71d3c5b8ee2ea8 ]
+
+When built with Control Flow Integrity, function prototypes between
+caller and function declaration must match. These mismatches are visible
+at compile time with the new -Wcast-function-type-strict in Clang[1].
+
+There were 97 warnings produced by NFS. For example:
+
+fs/nfsd/nfs4xdr.c:2228:17: warning: cast from '__be32 (*)(struct nfsd4_compoundargs *, struct nfsd4_access *)' (aka 'unsigned int (*)(struct nfsd4_compoundargs *, struct nfsd4_access *)') to 'nfsd4_dec' (aka 'unsigned int (*)(struct nfsd4_compoundargs *, void *)') converts to incompatible function type [-Wcast-function-type-strict]
+        [OP_ACCESS]             = (nfsd4_dec)nfsd4_decode_access,
+                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The enc/dec callbacks were defined as passing "void *" as the second
+argument, but were being implicitly cast to a new type. Replace the
+argument with union nfsd4_op_u, and perform explicit member selection
+in the function body. There are no resulting binary differences.
+
+Changes were made mechanically using the following Coccinelle script,
+with minor by-hand fixes for members that didn't already match their
+existing argument name:
+
+@find@
+identifier func;
+type T, opsT;
+identifier ops, N;
+@@
+
+ opsT ops[] = {
+        [N] = (T) func,
+ };
+
+@already_void@
+identifier find.func;
+identifier name;
+@@
+
+ func(...,
+-void
++union nfsd4_op_u
+ *name)
+ {
+        ...
+ }
+
+@proto depends on !already_void@
+identifier find.func;
+type T;
+identifier name;
+position p;
+@@
+
+ func@p(...,
+        T name
+ ) {
+        ...
+   }
+
+@script:python get_member@
+type_name << proto.T;
+member;
+@@
+
+coccinelle.member = cocci.make_ident(type_name.split("_", 1)[1].split(' ',1)[0])
+
+@convert@
+identifier find.func;
+type proto.T;
+identifier proto.name;
+position proto.p;
+identifier get_member.member;
+@@
+
+ func@p(...,
+-       T name
++       union nfsd4_op_u *u
+ ) {
++       T name = &u->member;
+        ...
+   }
+
+@cast@
+identifier find.func;
+type T, opsT;
+identifier ops, N;
+@@
+
+ opsT ops[] = {
+        [N] =
+-       (T)
+        func,
+ };
+
+Cc: Chuck Lever <chuck.lever@oracle.com>
+Cc: Jeff Layton <jlayton@kernel.org>
+Cc: Gustavo A. R. Silva <gustavoars@kernel.org>
+Cc: linux-nfs@vger.kernel.org
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4xdr.c |  632 ++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 377 insertions(+), 255 deletions(-)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -770,16 +770,18 @@ nfsd4_decode_cb_sec(struct nfsd4_compoun
+ static __be32
+ nfsd4_decode_access(struct nfsd4_compoundargs *argp,
+-                  struct nfsd4_access *access)
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_access *access = &u->access;
+       if (xdr_stream_decode_u32(argp->xdr, &access->ac_req_access) < 0)
+               return nfserr_bad_xdr;
+       return nfs_ok;
+ }
+ static __be32
+-nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
++nfsd4_decode_close(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_close *close = &u->close;
+       if (xdr_stream_decode_u32(argp->xdr, &close->cl_seqid) < 0)
+               return nfserr_bad_xdr;
+       return nfsd4_decode_stateid4(argp, &close->cl_stateid);
+@@ -787,8 +789,9 @@ nfsd4_decode_close(struct nfsd4_compound
+ static __be32
+-nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
++nfsd4_decode_commit(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_commit *commit = &u->commit;
+       if (xdr_stream_decode_u64(argp->xdr, &commit->co_offset) < 0)
+               return nfserr_bad_xdr;
+       if (xdr_stream_decode_u32(argp->xdr, &commit->co_count) < 0)
+@@ -798,8 +801,9 @@ nfsd4_decode_commit(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
++nfsd4_decode_create(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_create *create = &u->create;
+       __be32 *p, status;
+       memset(create, 0, sizeof(*create));
+@@ -844,22 +848,25 @@ nfsd4_decode_create(struct nfsd4_compoun
+ }
+ static inline __be32
+-nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
++nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_delegreturn *dr = &u->delegreturn;
+       return nfsd4_decode_stateid4(argp, &dr->dr_stateid);
+ }
+ static inline __be32
+-nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
++nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_getattr *getattr = &u->getattr;
+       memset(getattr, 0, sizeof(*getattr));
+       return nfsd4_decode_bitmap4(argp, getattr->ga_bmval,
+                                   ARRAY_SIZE(getattr->ga_bmval));
+ }
+ static __be32
+-nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
++nfsd4_decode_link(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_link *link = &u->link;
+       memset(link, 0, sizeof(*link));
+       return nfsd4_decode_component4(argp, &link->li_name, &link->li_namelen);
+ }
+@@ -907,8 +914,9 @@ nfsd4_decode_locker4(struct nfsd4_compou
+ }
+ static __be32
+-nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
++nfsd4_decode_lock(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_lock *lock = &u->lock;
+       memset(lock, 0, sizeof(*lock));
+       if (xdr_stream_decode_u32(argp->xdr, &lock->lk_type) < 0)
+               return nfserr_bad_xdr;
+@@ -924,8 +932,9 @@ nfsd4_decode_lock(struct nfsd4_compounda
+ }
+ static __be32
+-nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
++nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_lockt *lockt = &u->lockt;
+       memset(lockt, 0, sizeof(*lockt));
+       if (xdr_stream_decode_u32(argp->xdr, &lockt->lt_type) < 0)
+               return nfserr_bad_xdr;
+@@ -940,8 +949,9 @@ nfsd4_decode_lockt(struct nfsd4_compound
+ }
+ static __be32
+-nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
++nfsd4_decode_locku(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_locku *locku = &u->locku;
+       __be32 status;
+       if (xdr_stream_decode_u32(argp->xdr, &locku->lu_type) < 0)
+@@ -962,8 +972,9 @@ nfsd4_decode_locku(struct nfsd4_compound
+ }
+ static __be32
+-nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
++nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_lookup *lookup = &u->lookup;
+       return nfsd4_decode_component4(argp, &lookup->lo_name, &lookup->lo_len);
+ }
+@@ -1143,8 +1154,9 @@ nfsd4_decode_open_claim4(struct nfsd4_co
+ }
+ static __be32
+-nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
++nfsd4_decode_open(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_open *open = &u->open;
+       __be32 status;
+       u32 dummy;
+@@ -1171,8 +1183,10 @@ nfsd4_decode_open(struct nfsd4_compounda
+ }
+ static __be32
+-nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
++nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp,
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_open_confirm *open_conf = &u->open_confirm;
+       __be32 status;
+       if (argp->minorversion >= 1)
+@@ -1190,8 +1204,10 @@ nfsd4_decode_open_confirm(struct nfsd4_c
+ }
+ static __be32
+-nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
++nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp,
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_open_downgrade *open_down = &u->open_downgrade;
+       __be32 status;
+       memset(open_down, 0, sizeof(*open_down));
+@@ -1209,8 +1225,9 @@ nfsd4_decode_open_downgrade(struct nfsd4
+ }
+ static __be32
+-nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
++nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_putfh *putfh = &u->putfh;
+       __be32 *p;
+       if (xdr_stream_decode_u32(argp->xdr, &putfh->pf_fhlen) < 0)
+@@ -1229,7 +1246,7 @@ nfsd4_decode_putfh(struct nfsd4_compound
+ }
+ static __be32
+-nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p)
++nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, union nfsd4_op_u *p)
+ {
+       if (argp->minorversion == 0)
+               return nfs_ok;
+@@ -1237,8 +1254,9 @@ nfsd4_decode_putpubfh(struct nfsd4_compo
+ }
+ static __be32
+-nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
++nfsd4_decode_read(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_read *read = &u->read;
+       __be32 status;
+       memset(read, 0, sizeof(*read));
+@@ -1254,8 +1272,9 @@ nfsd4_decode_read(struct nfsd4_compounda
+ }
+ static __be32
+-nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
++nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_readdir *readdir = &u->readdir;
+       __be32 status;
+       memset(readdir, 0, sizeof(*readdir));
+@@ -1276,15 +1295,17 @@ nfsd4_decode_readdir(struct nfsd4_compou
+ }
+ static __be32
+-nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
++nfsd4_decode_remove(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_remove *remove = &u->remove;
+       memset(&remove->rm_cinfo, 0, sizeof(remove->rm_cinfo));
+       return nfsd4_decode_component4(argp, &remove->rm_name, &remove->rm_namelen);
+ }
+ static __be32
+-nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
++nfsd4_decode_rename(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_rename *rename = &u->rename;
+       __be32 status;
+       memset(rename, 0, sizeof(*rename));
+@@ -1295,22 +1316,25 @@ nfsd4_decode_rename(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
++nfsd4_decode_renew(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      clientid_t *clientid = &u->renew;
+       return nfsd4_decode_clientid4(argp, clientid);
+ }
+ static __be32
+ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
+-                   struct nfsd4_secinfo *secinfo)
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_secinfo *secinfo = &u->secinfo;
+       secinfo->si_exp = NULL;
+       return nfsd4_decode_component4(argp, &secinfo->si_name, &secinfo->si_namelen);
+ }
+ static __be32
+-nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
++nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_setattr *setattr = &u->setattr;
+       __be32 status;
+       memset(setattr, 0, sizeof(*setattr));
+@@ -1324,8 +1348,9 @@ nfsd4_decode_setattr(struct nfsd4_compou
+ }
+ static __be32
+-nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
++nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_setclientid *setclientid = &u->setclientid;
+       __be32 *p, status;
+       memset(setclientid, 0, sizeof(*setclientid));
+@@ -1367,8 +1392,10 @@ nfsd4_decode_setclientid(struct nfsd4_co
+ }
+ static __be32
+-nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
++nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp,
++                               union nfsd4_op_u *u)
+ {
++      struct nfsd4_setclientid_confirm *scd_c = &u->setclientid_confirm;
+       __be32 status;
+       if (argp->minorversion >= 1)
+@@ -1382,8 +1409,9 @@ nfsd4_decode_setclientid_confirm(struct
+ /* Also used for NVERIFY */
+ static __be32
+-nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
++nfsd4_decode_verify(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_verify *verify = &u->verify;
+       __be32 *p, status;
+       memset(verify, 0, sizeof(*verify));
+@@ -1409,8 +1437,9 @@ nfsd4_decode_verify(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
++nfsd4_decode_write(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_write *write = &u->write;
+       __be32 status;
+       status = nfsd4_decode_stateid4(argp, &write->wr_stateid);
+@@ -1434,8 +1463,10 @@ nfsd4_decode_write(struct nfsd4_compound
+ }
+ static __be32
+-nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
++nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp,
++                             union nfsd4_op_u *u)
+ {
++      struct nfsd4_release_lockowner *rlockowner = &u->release_lockowner;
+       __be32 status;
+       if (argp->minorversion >= 1)
+@@ -1452,16 +1483,20 @@ nfsd4_decode_release_lockowner(struct nf
+       return nfs_ok;
+ }
+-static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
++static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp,
++                                         union nfsd4_op_u *u)
+ {
++      struct nfsd4_backchannel_ctl *bc = &u->backchannel_ctl;
+       memset(bc, 0, sizeof(*bc));
+       if (xdr_stream_decode_u32(argp->xdr, &bc->bc_cb_program) < 0)
+               return nfserr_bad_xdr;
+       return nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
+ }
+-static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
++static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp,
++                                              union nfsd4_op_u *u)
+ {
++      struct nfsd4_bind_conn_to_session *bcts = &u->bind_conn_to_session;
+       u32 use_conn_in_rdma_mode;
+       __be32 status;
+@@ -1603,8 +1638,9 @@ nfsd4_decode_nfs_impl_id4(struct nfsd4_c
+ static __be32
+ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
+-                       struct nfsd4_exchange_id *exid)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_exchange_id *exid = &u->exchange_id;
+       __be32 status;
+       memset(exid, 0, sizeof(*exid));
+@@ -1656,8 +1692,9 @@ nfsd4_decode_channel_attrs4(struct nfsd4
+ static __be32
+ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
+-                          struct nfsd4_create_session *sess)
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_create_session *sess = &u->create_session;
+       __be32 status;
+       memset(sess, 0, sizeof(*sess));
+@@ -1681,23 +1718,26 @@ nfsd4_decode_create_session(struct nfsd4
+ static __be32
+ nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
+-                           struct nfsd4_destroy_session *destroy_session)
++                           union nfsd4_op_u *u)
+ {
++      struct nfsd4_destroy_session *destroy_session = &u->destroy_session;
+       return nfsd4_decode_sessionid4(argp, &destroy_session->sessionid);
+ }
+ static __be32
+ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
+-                        struct nfsd4_free_stateid *free_stateid)
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_free_stateid *free_stateid = &u->free_stateid;
+       return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
+ }
+ #ifdef CONFIG_NFSD_PNFS
+ static __be32
+ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
+-              struct nfsd4_getdeviceinfo *gdev)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_getdeviceinfo *gdev = &u->getdeviceinfo;
+       __be32 status;
+       memset(gdev, 0, sizeof(*gdev));
+@@ -1717,8 +1757,9 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_
+ static __be32
+ nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
+-                        struct nfsd4_layoutcommit *lcp)
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutcommit *lcp = &u->layoutcommit;
+       __be32 *p, status;
+       memset(lcp, 0, sizeof(*lcp));
+@@ -1753,8 +1794,9 @@ nfsd4_decode_layoutcommit(struct nfsd4_c
+ static __be32
+ nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
+-              struct nfsd4_layoutget *lgp)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutget *lgp = &u->layoutget;
+       __be32 status;
+       memset(lgp, 0, sizeof(*lgp));
+@@ -1781,8 +1823,9 @@ nfsd4_decode_layoutget(struct nfsd4_comp
+ static __be32
+ nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
+-              struct nfsd4_layoutreturn *lrp)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutreturn *lrp = &u->layoutreturn;
+       memset(lrp, 0, sizeof(*lrp));
+       if (xdr_stream_decode_bool(argp->xdr, &lrp->lr_reclaim) < 0)
+               return nfserr_bad_xdr;
+@@ -1795,8 +1838,9 @@ nfsd4_decode_layoutreturn(struct nfsd4_c
+ #endif /* CONFIG_NFSD_PNFS */
+ static __be32 nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
+-                                         struct nfsd4_secinfo_no_name *sin)
++                                         union nfsd4_op_u *u)
+ {
++      struct nfsd4_secinfo_no_name *sin = &u->secinfo_no_name;
+       if (xdr_stream_decode_u32(argp->xdr, &sin->sin_style) < 0)
+               return nfserr_bad_xdr;
+@@ -1806,8 +1850,9 @@ static __be32 nfsd4_decode_secinfo_no_na
+ static __be32
+ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
+-                    struct nfsd4_sequence *seq)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_sequence *seq = &u->sequence;
+       __be32 *p, status;
+       status = nfsd4_decode_sessionid4(argp, &seq->sessionid);
+@@ -1826,8 +1871,10 @@ nfsd4_decode_sequence(struct nfsd4_compo
+ }
+ static __be32
+-nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
++nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp,
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_test_stateid *test_stateid = &u->test_stateid;
+       struct nfsd4_test_stateid_id *stateid;
+       __be32 status;
+       u32 i;
+@@ -1852,14 +1899,16 @@ nfsd4_decode_test_stateid(struct nfsd4_c
+ }
+ static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp,
+-                                          struct nfsd4_destroy_clientid *dc)
++                                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_destroy_clientid *dc = &u->destroy_clientid;
+       return nfsd4_decode_clientid4(argp, &dc->clientid);
+ }
+ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp,
+-                                          struct nfsd4_reclaim_complete *rc)
++                                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_reclaim_complete *rc = &u->reclaim_complete;
+       if (xdr_stream_decode_bool(argp->xdr, &rc->rca_one_fs) < 0)
+               return nfserr_bad_xdr;
+       return nfs_ok;
+@@ -1867,8 +1916,9 @@ static __be32 nfsd4_decode_reclaim_compl
+ static __be32
+ nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
+-                     struct nfsd4_fallocate *fallocate)
++                     union nfsd4_op_u *u)
+ {
++      struct nfsd4_fallocate *fallocate = &u->allocate;
+       __be32 status;
+       status = nfsd4_decode_stateid4(argp, &fallocate->falloc_stateid);
+@@ -1924,8 +1974,9 @@ static __be32 nfsd4_decode_nl4_server(st
+ }
+ static __be32
+-nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
++nfsd4_decode_copy(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_copy *copy = &u->copy;
+       u32 consecutive, i, count, sync;
+       struct nl4_server *ns_dummy;
+       __be32 status;
+@@ -1982,8 +2033,9 @@ nfsd4_decode_copy(struct nfsd4_compounda
+ static __be32
+ nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,
+-                       struct nfsd4_copy_notify *cn)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_copy_notify *cn = &u->copy_notify;
+       __be32 status;
+       memset(cn, 0, sizeof(*cn));
+@@ -2002,16 +2054,18 @@ nfsd4_decode_copy_notify(struct nfsd4_co
+ static __be32
+ nfsd4_decode_offload_status(struct nfsd4_compoundargs *argp,
+-                          struct nfsd4_offload_status *os)
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_offload_status *os = &u->offload_status;
+       os->count = 0;
+       os->status = 0;
+       return nfsd4_decode_stateid4(argp, &os->stateid);
+ }
+ static __be32
+-nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
++nfsd4_decode_seek(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_seek *seek = &u->seek;
+       __be32 status;
+       status = nfsd4_decode_stateid4(argp, &seek->seek_stateid);
+@@ -2028,8 +2082,9 @@ nfsd4_decode_seek(struct nfsd4_compounda
+ }
+ static __be32
+-nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
++nfsd4_decode_clone(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
+ {
++      struct nfsd4_clone *clone = &u->clone;
+       __be32 status;
+       status = nfsd4_decode_stateid4(argp, &clone->cl_src_stateid);
+@@ -2154,8 +2209,9 @@ nfsd4_decode_xattr_name(struct nfsd4_com
+  */
+ static __be32
+ nfsd4_decode_getxattr(struct nfsd4_compoundargs *argp,
+-                    struct nfsd4_getxattr *getxattr)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_getxattr *getxattr = &u->getxattr;
+       __be32 status;
+       u32 maxcount;
+@@ -2173,8 +2229,9 @@ nfsd4_decode_getxattr(struct nfsd4_compo
+ static __be32
+ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
+-                    struct nfsd4_setxattr *setxattr)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_setxattr *setxattr = &u->setxattr;
+       u32 flags, maxcount, size;
+       __be32 status;
+@@ -2214,8 +2271,9 @@ nfsd4_decode_setxattr(struct nfsd4_compo
+ static __be32
+ nfsd4_decode_listxattrs(struct nfsd4_compoundargs *argp,
+-                      struct nfsd4_listxattrs *listxattrs)
++                      union nfsd4_op_u *u)
+ {
++      struct nfsd4_listxattrs *listxattrs = &u->listxattrs;
+       u32 maxcount;
+       memset(listxattrs, 0, sizeof(*listxattrs));
+@@ -2245,113 +2303,114 @@ nfsd4_decode_listxattrs(struct nfsd4_com
+ static __be32
+ nfsd4_decode_removexattr(struct nfsd4_compoundargs *argp,
+-                       struct nfsd4_removexattr *removexattr)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_removexattr *removexattr = &u->removexattr;
+       memset(removexattr, 0, sizeof(*removexattr));
+       return nfsd4_decode_xattr_name(argp, &removexattr->rmxa_name);
+ }
+ static __be32
+-nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
++nfsd4_decode_noop(struct nfsd4_compoundargs *argp, union nfsd4_op_u *p)
+ {
+       return nfs_ok;
+ }
+ static __be32
+-nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
++nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, union nfsd4_op_u *p)
+ {
+       return nfserr_notsupp;
+ }
+-typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
++typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u);
+ static const nfsd4_dec nfsd4_dec_ops[] = {
+-      [OP_ACCESS]             = (nfsd4_dec)nfsd4_decode_access,
+-      [OP_CLOSE]              = (nfsd4_dec)nfsd4_decode_close,
+-      [OP_COMMIT]             = (nfsd4_dec)nfsd4_decode_commit,
+-      [OP_CREATE]             = (nfsd4_dec)nfsd4_decode_create,
+-      [OP_DELEGPURGE]         = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_DELEGRETURN]        = (nfsd4_dec)nfsd4_decode_delegreturn,
+-      [OP_GETATTR]            = (nfsd4_dec)nfsd4_decode_getattr,
+-      [OP_GETFH]              = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_LINK]               = (nfsd4_dec)nfsd4_decode_link,
+-      [OP_LOCK]               = (nfsd4_dec)nfsd4_decode_lock,
+-      [OP_LOCKT]              = (nfsd4_dec)nfsd4_decode_lockt,
+-      [OP_LOCKU]              = (nfsd4_dec)nfsd4_decode_locku,
+-      [OP_LOOKUP]             = (nfsd4_dec)nfsd4_decode_lookup,
+-      [OP_LOOKUPP]            = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_NVERIFY]            = (nfsd4_dec)nfsd4_decode_verify,
+-      [OP_OPEN]               = (nfsd4_dec)nfsd4_decode_open,
+-      [OP_OPENATTR]           = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_OPEN_CONFIRM]       = (nfsd4_dec)nfsd4_decode_open_confirm,
+-      [OP_OPEN_DOWNGRADE]     = (nfsd4_dec)nfsd4_decode_open_downgrade,
+-      [OP_PUTFH]              = (nfsd4_dec)nfsd4_decode_putfh,
+-      [OP_PUTPUBFH]           = (nfsd4_dec)nfsd4_decode_putpubfh,
+-      [OP_PUTROOTFH]          = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_READ]               = (nfsd4_dec)nfsd4_decode_read,
+-      [OP_READDIR]            = (nfsd4_dec)nfsd4_decode_readdir,
+-      [OP_READLINK]           = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_REMOVE]             = (nfsd4_dec)nfsd4_decode_remove,
+-      [OP_RENAME]             = (nfsd4_dec)nfsd4_decode_rename,
+-      [OP_RENEW]              = (nfsd4_dec)nfsd4_decode_renew,
+-      [OP_RESTOREFH]          = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_SAVEFH]             = (nfsd4_dec)nfsd4_decode_noop,
+-      [OP_SECINFO]            = (nfsd4_dec)nfsd4_decode_secinfo,
+-      [OP_SETATTR]            = (nfsd4_dec)nfsd4_decode_setattr,
+-      [OP_SETCLIENTID]        = (nfsd4_dec)nfsd4_decode_setclientid,
+-      [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
+-      [OP_VERIFY]             = (nfsd4_dec)nfsd4_decode_verify,
+-      [OP_WRITE]              = (nfsd4_dec)nfsd4_decode_write,
+-      [OP_RELEASE_LOCKOWNER]  = (nfsd4_dec)nfsd4_decode_release_lockowner,
++      [OP_ACCESS]             = nfsd4_decode_access,
++      [OP_CLOSE]              = nfsd4_decode_close,
++      [OP_COMMIT]             = nfsd4_decode_commit,
++      [OP_CREATE]             = nfsd4_decode_create,
++      [OP_DELEGPURGE]         = nfsd4_decode_notsupp,
++      [OP_DELEGRETURN]        = nfsd4_decode_delegreturn,
++      [OP_GETATTR]            = nfsd4_decode_getattr,
++      [OP_GETFH]              = nfsd4_decode_noop,
++      [OP_LINK]               = nfsd4_decode_link,
++      [OP_LOCK]               = nfsd4_decode_lock,
++      [OP_LOCKT]              = nfsd4_decode_lockt,
++      [OP_LOCKU]              = nfsd4_decode_locku,
++      [OP_LOOKUP]             = nfsd4_decode_lookup,
++      [OP_LOOKUPP]            = nfsd4_decode_noop,
++      [OP_NVERIFY]            = nfsd4_decode_verify,
++      [OP_OPEN]               = nfsd4_decode_open,
++      [OP_OPENATTR]           = nfsd4_decode_notsupp,
++      [OP_OPEN_CONFIRM]       = nfsd4_decode_open_confirm,
++      [OP_OPEN_DOWNGRADE]     = nfsd4_decode_open_downgrade,
++      [OP_PUTFH]              = nfsd4_decode_putfh,
++      [OP_PUTPUBFH]           = nfsd4_decode_putpubfh,
++      [OP_PUTROOTFH]          = nfsd4_decode_noop,
++      [OP_READ]               = nfsd4_decode_read,
++      [OP_READDIR]            = nfsd4_decode_readdir,
++      [OP_READLINK]           = nfsd4_decode_noop,
++      [OP_REMOVE]             = nfsd4_decode_remove,
++      [OP_RENAME]             = nfsd4_decode_rename,
++      [OP_RENEW]              = nfsd4_decode_renew,
++      [OP_RESTOREFH]          = nfsd4_decode_noop,
++      [OP_SAVEFH]             = nfsd4_decode_noop,
++      [OP_SECINFO]            = nfsd4_decode_secinfo,
++      [OP_SETATTR]            = nfsd4_decode_setattr,
++      [OP_SETCLIENTID]        = nfsd4_decode_setclientid,
++      [OP_SETCLIENTID_CONFIRM] = nfsd4_decode_setclientid_confirm,
++      [OP_VERIFY]             = nfsd4_decode_verify,
++      [OP_WRITE]              = nfsd4_decode_write,
++      [OP_RELEASE_LOCKOWNER]  = nfsd4_decode_release_lockowner,
+       /* new operations for NFSv4.1 */
+-      [OP_BACKCHANNEL_CTL]    = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
+-      [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
+-      [OP_EXCHANGE_ID]        = (nfsd4_dec)nfsd4_decode_exchange_id,
+-      [OP_CREATE_SESSION]     = (nfsd4_dec)nfsd4_decode_create_session,
+-      [OP_DESTROY_SESSION]    = (nfsd4_dec)nfsd4_decode_destroy_session,
+-      [OP_FREE_STATEID]       = (nfsd4_dec)nfsd4_decode_free_stateid,
+-      [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
++      [OP_BACKCHANNEL_CTL]    = nfsd4_decode_backchannel_ctl,
++      [OP_BIND_CONN_TO_SESSION] = nfsd4_decode_bind_conn_to_session,
++      [OP_EXCHANGE_ID]        = nfsd4_decode_exchange_id,
++      [OP_CREATE_SESSION]     = nfsd4_decode_create_session,
++      [OP_DESTROY_SESSION]    = nfsd4_decode_destroy_session,
++      [OP_FREE_STATEID]       = nfsd4_decode_free_stateid,
++      [OP_GET_DIR_DELEGATION] = nfsd4_decode_notsupp,
+ #ifdef CONFIG_NFSD_PNFS
+-      [OP_GETDEVICEINFO]      = (nfsd4_dec)nfsd4_decode_getdeviceinfo,
+-      [OP_GETDEVICELIST]      = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTCOMMIT]       = (nfsd4_dec)nfsd4_decode_layoutcommit,
+-      [OP_LAYOUTGET]          = (nfsd4_dec)nfsd4_decode_layoutget,
+-      [OP_LAYOUTRETURN]       = (nfsd4_dec)nfsd4_decode_layoutreturn,
++      [OP_GETDEVICEINFO]      = nfsd4_decode_getdeviceinfo,
++      [OP_GETDEVICELIST]      = nfsd4_decode_notsupp,
++      [OP_LAYOUTCOMMIT]       = nfsd4_decode_layoutcommit,
++      [OP_LAYOUTGET]          = nfsd4_decode_layoutget,
++      [OP_LAYOUTRETURN]       = nfsd4_decode_layoutreturn,
+ #else
+-      [OP_GETDEVICEINFO]      = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_GETDEVICELIST]      = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTCOMMIT]       = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTGET]          = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTRETURN]       = (nfsd4_dec)nfsd4_decode_notsupp,
++      [OP_GETDEVICEINFO]      = nfsd4_decode_notsupp,
++      [OP_GETDEVICELIST]      = nfsd4_decode_notsupp,
++      [OP_LAYOUTCOMMIT]       = nfsd4_decode_notsupp,
++      [OP_LAYOUTGET]          = nfsd4_decode_notsupp,
++      [OP_LAYOUTRETURN]       = nfsd4_decode_notsupp,
+ #endif
+-      [OP_SECINFO_NO_NAME]    = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
+-      [OP_SEQUENCE]           = (nfsd4_dec)nfsd4_decode_sequence,
+-      [OP_SET_SSV]            = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_TEST_STATEID]       = (nfsd4_dec)nfsd4_decode_test_stateid,
+-      [OP_WANT_DELEGATION]    = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_DESTROY_CLIENTID]   = (nfsd4_dec)nfsd4_decode_destroy_clientid,
+-      [OP_RECLAIM_COMPLETE]   = (nfsd4_dec)nfsd4_decode_reclaim_complete,
++      [OP_SECINFO_NO_NAME]    = nfsd4_decode_secinfo_no_name,
++      [OP_SEQUENCE]           = nfsd4_decode_sequence,
++      [OP_SET_SSV]            = nfsd4_decode_notsupp,
++      [OP_TEST_STATEID]       = nfsd4_decode_test_stateid,
++      [OP_WANT_DELEGATION]    = nfsd4_decode_notsupp,
++      [OP_DESTROY_CLIENTID]   = nfsd4_decode_destroy_clientid,
++      [OP_RECLAIM_COMPLETE]   = nfsd4_decode_reclaim_complete,
+       /* new operations for NFSv4.2 */
+-      [OP_ALLOCATE]           = (nfsd4_dec)nfsd4_decode_fallocate,
+-      [OP_COPY]               = (nfsd4_dec)nfsd4_decode_copy,
+-      [OP_COPY_NOTIFY]        = (nfsd4_dec)nfsd4_decode_copy_notify,
+-      [OP_DEALLOCATE]         = (nfsd4_dec)nfsd4_decode_fallocate,
+-      [OP_IO_ADVISE]          = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTERROR]        = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_LAYOUTSTATS]        = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_OFFLOAD_CANCEL]     = (nfsd4_dec)nfsd4_decode_offload_status,
+-      [OP_OFFLOAD_STATUS]     = (nfsd4_dec)nfsd4_decode_offload_status,
+-      [OP_READ_PLUS]          = (nfsd4_dec)nfsd4_decode_read,
+-      [OP_SEEK]               = (nfsd4_dec)nfsd4_decode_seek,
+-      [OP_WRITE_SAME]         = (nfsd4_dec)nfsd4_decode_notsupp,
+-      [OP_CLONE]              = (nfsd4_dec)nfsd4_decode_clone,
++      [OP_ALLOCATE]           = nfsd4_decode_fallocate,
++      [OP_COPY]               = nfsd4_decode_copy,
++      [OP_COPY_NOTIFY]        = nfsd4_decode_copy_notify,
++      [OP_DEALLOCATE]         = nfsd4_decode_fallocate,
++      [OP_IO_ADVISE]          = nfsd4_decode_notsupp,
++      [OP_LAYOUTERROR]        = nfsd4_decode_notsupp,
++      [OP_LAYOUTSTATS]        = nfsd4_decode_notsupp,
++      [OP_OFFLOAD_CANCEL]     = nfsd4_decode_offload_status,
++      [OP_OFFLOAD_STATUS]     = nfsd4_decode_offload_status,
++      [OP_READ_PLUS]          = nfsd4_decode_read,
++      [OP_SEEK]               = nfsd4_decode_seek,
++      [OP_WRITE_SAME]         = nfsd4_decode_notsupp,
++      [OP_CLONE]              = nfsd4_decode_clone,
+       /* RFC 8276 extended atributes operations */
+-      [OP_GETXATTR]           = (nfsd4_dec)nfsd4_decode_getxattr,
+-      [OP_SETXATTR]           = (nfsd4_dec)nfsd4_decode_setxattr,
+-      [OP_LISTXATTRS]         = (nfsd4_dec)nfsd4_decode_listxattrs,
+-      [OP_REMOVEXATTR]        = (nfsd4_dec)nfsd4_decode_removexattr,
++      [OP_GETXATTR]           = nfsd4_decode_getxattr,
++      [OP_SETXATTR]           = nfsd4_decode_setxattr,
++      [OP_LISTXATTRS]         = nfsd4_decode_listxattrs,
++      [OP_REMOVEXATTR]        = nfsd4_decode_removexattr,
+ };
+ static inline bool
+@@ -3643,8 +3702,10 @@ nfsd4_encode_stateid(struct xdr_stream *
+ }
+ static __be32
+-nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
++nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr,
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_access *access = &u->access;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3656,8 +3717,10 @@ nfsd4_encode_access(struct nfsd4_compoun
+       return 0;
+ }
+-static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
++static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr,
++                                              union nfsd4_op_u *u)
+ {
++      struct nfsd4_bind_conn_to_session *bcts = &u->bind_conn_to_session;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3673,8 +3736,10 @@ static __be32 nfsd4_encode_bind_conn_to_
+ }
+ static __be32
+-nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
++nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr,
++                 union nfsd4_op_u *u)
+ {
++      struct nfsd4_close *close = &u->close;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_encode_stateid(xdr, &close->cl_stateid);
+@@ -3682,8 +3747,10 @@ nfsd4_encode_close(struct nfsd4_compound
+ static __be32
+-nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
++nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr,
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_commit *commit = &u->commit;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3696,8 +3763,10 @@ nfsd4_encode_commit(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
++nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr,
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_create *create = &u->create;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3710,8 +3779,10 @@ nfsd4_encode_create(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
++nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr,
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_getattr *getattr = &u->getattr;
+       struct svc_fh *fhp = getattr->ga_fhp;
+       struct xdr_stream *xdr = resp->xdr;
+@@ -3720,8 +3791,10 @@ nfsd4_encode_getattr(struct nfsd4_compou
+ }
+ static __be32
+-nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
++nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr,
++                 union nfsd4_op_u *u)
+ {
++      struct svc_fh **fhpp = &u->getfh;
+       struct xdr_stream *xdr = resp->xdr;
+       struct svc_fh *fhp = *fhpp;
+       unsigned int len;
+@@ -3775,8 +3848,10 @@ again:
+ }
+ static __be32
+-nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
++nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr,
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_lock *lock = &u->lock;
+       struct xdr_stream *xdr = resp->xdr;
+       if (!nfserr)
+@@ -3788,8 +3863,10 @@ nfsd4_encode_lock(struct nfsd4_compoundr
+ }
+ static __be32
+-nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
++nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr,
++                 union nfsd4_op_u *u)
+ {
++      struct nfsd4_lockt *lockt = &u->lockt;
+       struct xdr_stream *xdr = resp->xdr;
+       if (nfserr == nfserr_denied)
+@@ -3798,8 +3875,10 @@ nfsd4_encode_lockt(struct nfsd4_compound
+ }
+ static __be32
+-nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
++nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr,
++                 union nfsd4_op_u *u)
+ {
++      struct nfsd4_locku *locku = &u->locku;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_encode_stateid(xdr, &locku->lu_stateid);
+@@ -3807,8 +3886,10 @@ nfsd4_encode_locku(struct nfsd4_compound
+ static __be32
+-nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
++nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr,
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_link *link = &u->link;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3821,8 +3902,10 @@ nfsd4_encode_link(struct nfsd4_compoundr
+ static __be32
+-nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
++nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr,
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_open *open = &u->open;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -3915,16 +3998,20 @@ nfsd4_encode_open(struct nfsd4_compoundr
+ }
+ static __be32
+-nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
++nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr,
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_open_confirm *oc = &u->open_confirm;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid);
+ }
+ static __be32
+-nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
++nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr,
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_open_downgrade *od = &u->open_downgrade;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_encode_stateid(xdr, &od->od_stateid);
+@@ -4023,8 +4110,9 @@ static __be32 nfsd4_encode_readv(struct
+ static __be32
+ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                struct nfsd4_read *read)
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_read *read = &u->read;
+       bool splice_ok = test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);
+       unsigned long maxcount;
+       struct xdr_stream *xdr = resp->xdr;
+@@ -4065,8 +4153,10 @@ nfsd4_encode_read(struct nfsd4_compoundr
+ }
+ static __be32
+-nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
++nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr,
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_readlink *readlink = &u->readlink;
+       __be32 *p, *maxcount_p, zero = xdr_zero;
+       struct xdr_stream *xdr = resp->xdr;
+       int length_offset = xdr->buf->len;
+@@ -4110,8 +4200,10 @@ out_err:
+ }
+ static __be32
+-nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
++nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr,
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_readdir *readdir = &u->readdir;
+       int maxcount;
+       int bytes_left;
+       loff_t offset;
+@@ -4201,8 +4293,10 @@ err_no_verf:
+ }
+ static __be32
+-nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
++nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr,
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_remove *remove = &u->remove;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4214,8 +4308,10 @@ nfsd4_encode_remove(struct nfsd4_compoun
+ }
+ static __be32
+-nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
++nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr,
++                  union nfsd4_op_u *u)
+ {
++      struct nfsd4_rename *rename = &u->rename;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4297,8 +4393,9 @@ nfsd4_do_encode_secinfo(struct xdr_strea
+ static __be32
+ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                   struct nfsd4_secinfo *secinfo)
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_secinfo *secinfo = &u->secinfo;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_do_encode_secinfo(xdr, secinfo->si_exp);
+@@ -4306,8 +4403,9 @@ nfsd4_encode_secinfo(struct nfsd4_compou
+ static __be32
+ nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                   struct nfsd4_secinfo_no_name *secinfo)
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_secinfo_no_name *secinfo = &u->secinfo_no_name;
+       struct xdr_stream *xdr = resp->xdr;
+       return nfsd4_do_encode_secinfo(xdr, secinfo->sin_exp);
+@@ -4318,8 +4416,10 @@ nfsd4_encode_secinfo_no_name(struct nfsd
+  * regardless of the error status.
+  */
+ static __be32
+-nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
++nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr,
++                   union nfsd4_op_u *u)
+ {
++      struct nfsd4_setattr *setattr = &u->setattr;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4342,8 +4442,10 @@ nfsd4_encode_setattr(struct nfsd4_compou
+ }
+ static __be32
+-nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
++nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr,
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_setclientid *scd = &u->setclientid;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4366,8 +4468,10 @@ nfsd4_encode_setclientid(struct nfsd4_co
+ }
+ static __be32
+-nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
++nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr,
++                 union nfsd4_op_u *u)
+ {
++      struct nfsd4_write *write = &u->write;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4383,8 +4487,9 @@ nfsd4_encode_write(struct nfsd4_compound
+ static __be32
+ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                       struct nfsd4_exchange_id *exid)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_exchange_id *exid = &u->exchange_id;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+       char *major_id;
+@@ -4461,8 +4566,9 @@ nfsd4_encode_exchange_id(struct nfsd4_co
+ static __be32
+ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                          struct nfsd4_create_session *sess)
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_create_session *sess = &u->create_session;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4514,8 +4620,9 @@ nfsd4_encode_create_session(struct nfsd4
+ static __be32
+ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                    struct nfsd4_sequence *seq)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_sequence *seq = &u->sequence;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4537,8 +4644,9 @@ nfsd4_encode_sequence(struct nfsd4_compo
+ static __be32
+ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                        struct nfsd4_test_stateid *test_stateid)
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_test_stateid *test_stateid = &u->test_stateid;
+       struct xdr_stream *xdr = resp->xdr;
+       struct nfsd4_test_stateid_id *stateid, *next;
+       __be32 *p;
+@@ -4558,8 +4666,9 @@ nfsd4_encode_test_stateid(struct nfsd4_c
+ #ifdef CONFIG_NFSD_PNFS
+ static __be32
+ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
+-              struct nfsd4_getdeviceinfo *gdev)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_getdeviceinfo *gdev = &u->getdeviceinfo;
+       struct xdr_stream *xdr = resp->xdr;
+       const struct nfsd4_layout_ops *ops;
+       u32 starting_len = xdr->buf->len, needed_len;
+@@ -4611,8 +4720,9 @@ toosmall:
+ static __be32
+ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
+-              struct nfsd4_layoutget *lgp)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutget *lgp = &u->layoutget;
+       struct xdr_stream *xdr = resp->xdr;
+       const struct nfsd4_layout_ops *ops;
+       __be32 *p;
+@@ -4638,8 +4748,9 @@ nfsd4_encode_layoutget(struct nfsd4_comp
+ static __be32
+ nfsd4_encode_layoutcommit(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                        struct nfsd4_layoutcommit *lcp)
++                        union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutcommit *lcp = &u->layoutcommit;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4659,8 +4770,9 @@ nfsd4_encode_layoutcommit(struct nfsd4_c
+ static __be32
+ nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
+-              struct nfsd4_layoutreturn *lrp)
++              union nfsd4_op_u *u)
+ {
++      struct nfsd4_layoutreturn *lrp = &u->layoutreturn;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4745,8 +4857,9 @@ nfsd42_encode_nl4_server(struct nfsd4_co
+ static __be32
+ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                struct nfsd4_copy *copy)
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_copy *copy = &u->copy;
+       __be32 *p;
+       nfserr = nfsd42_encode_write_res(resp, &copy->cp_res,
+@@ -4762,8 +4875,9 @@ nfsd4_encode_copy(struct nfsd4_compoundr
+ static __be32
+ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                          struct nfsd4_offload_status *os)
++                          union nfsd4_op_u *u)
+ {
++      struct nfsd4_offload_status *os = &u->offload_status;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4813,8 +4927,9 @@ nfsd4_encode_read_plus_data(struct nfsd4
+ static __be32
+ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                     struct nfsd4_read *read)
++                     union nfsd4_op_u *u)
+ {
++      struct nfsd4_read *read = &u->read;
+       struct file *file = read->rd_nf->nf_file;
+       struct xdr_stream *xdr = resp->xdr;
+       int starting_len = xdr->buf->len;
+@@ -4850,8 +4965,9 @@ out:
+ static __be32
+ nfsd4_encode_copy_notify(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                       struct nfsd4_copy_notify *cn)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_copy_notify *cn = &u->copy_notify;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -4885,8 +5001,9 @@ nfsd4_encode_copy_notify(struct nfsd4_co
+ static __be32
+ nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                struct nfsd4_seek *seek)
++                union nfsd4_op_u *u)
+ {
++      struct nfsd4_seek *seek = &u->seek;
+       __be32 *p;
+       p = xdr_reserve_space(resp->xdr, 4 + 8);
+@@ -4897,7 +5014,8 @@ nfsd4_encode_seek(struct nfsd4_compoundr
+ }
+ static __be32
+-nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
++nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr,
++                union nfsd4_op_u *p)
+ {
+       return nfserr;
+ }
+@@ -4948,8 +5066,9 @@ nfsd4_vbuf_to_stream(struct xdr_stream *
+ static __be32
+ nfsd4_encode_getxattr(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                    struct nfsd4_getxattr *getxattr)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_getxattr *getxattr = &u->getxattr;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p, err;
+@@ -4972,8 +5091,9 @@ nfsd4_encode_getxattr(struct nfsd4_compo
+ static __be32
+ nfsd4_encode_setxattr(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                    struct nfsd4_setxattr *setxattr)
++                    union nfsd4_op_u *u)
+ {
++      struct nfsd4_setxattr *setxattr = &u->setxattr;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -5013,8 +5133,9 @@ nfsd4_listxattr_validate_cookie(struct n
+ static __be32
+ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                      struct nfsd4_listxattrs *listxattrs)
++                      union nfsd4_op_u *u)
+ {
++      struct nfsd4_listxattrs *listxattrs = &u->listxattrs;
+       struct xdr_stream *xdr = resp->xdr;
+       u32 cookie_offset, count_offset, eof;
+       u32 left, xdrleft, slen, count;
+@@ -5124,8 +5245,9 @@ out:
+ static __be32
+ nfsd4_encode_removexattr(struct nfsd4_compoundres *resp, __be32 nfserr,
+-                       struct nfsd4_removexattr *removexattr)
++                       union nfsd4_op_u *u)
+ {
++      struct nfsd4_removexattr *removexattr = &u->removexattr;
+       struct xdr_stream *xdr = resp->xdr;
+       __be32 *p;
+@@ -5137,7 +5259,7 @@ nfsd4_encode_removexattr(struct nfsd4_co
+       return 0;
+ }
+-typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
++typedef __be32(*nfsd4_enc)(struct nfsd4_compoundres *, __be32, union nfsd4_op_u *u);
+ /*
+  * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1
+@@ -5145,93 +5267,93 @@ typedef __be32(* nfsd4_enc)(struct nfsd4
+  * done in the decoding phase.
+  */
+ static const nfsd4_enc nfsd4_enc_ops[] = {
+-      [OP_ACCESS]             = (nfsd4_enc)nfsd4_encode_access,
+-      [OP_CLOSE]              = (nfsd4_enc)nfsd4_encode_close,
+-      [OP_COMMIT]             = (nfsd4_enc)nfsd4_encode_commit,
+-      [OP_CREATE]             = (nfsd4_enc)nfsd4_encode_create,
+-      [OP_DELEGPURGE]         = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_DELEGRETURN]        = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_GETATTR]            = (nfsd4_enc)nfsd4_encode_getattr,
+-      [OP_GETFH]              = (nfsd4_enc)nfsd4_encode_getfh,
+-      [OP_LINK]               = (nfsd4_enc)nfsd4_encode_link,
+-      [OP_LOCK]               = (nfsd4_enc)nfsd4_encode_lock,
+-      [OP_LOCKT]              = (nfsd4_enc)nfsd4_encode_lockt,
+-      [OP_LOCKU]              = (nfsd4_enc)nfsd4_encode_locku,
+-      [OP_LOOKUP]             = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LOOKUPP]            = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_NVERIFY]            = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_OPEN]               = (nfsd4_enc)nfsd4_encode_open,
+-      [OP_OPENATTR]           = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_OPEN_CONFIRM]       = (nfsd4_enc)nfsd4_encode_open_confirm,
+-      [OP_OPEN_DOWNGRADE]     = (nfsd4_enc)nfsd4_encode_open_downgrade,
+-      [OP_PUTFH]              = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_PUTPUBFH]           = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_PUTROOTFH]          = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_READ]               = (nfsd4_enc)nfsd4_encode_read,
+-      [OP_READDIR]            = (nfsd4_enc)nfsd4_encode_readdir,
+-      [OP_READLINK]           = (nfsd4_enc)nfsd4_encode_readlink,
+-      [OP_REMOVE]             = (nfsd4_enc)nfsd4_encode_remove,
+-      [OP_RENAME]             = (nfsd4_enc)nfsd4_encode_rename,
+-      [OP_RENEW]              = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_RESTOREFH]          = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_SAVEFH]             = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_SECINFO]            = (nfsd4_enc)nfsd4_encode_secinfo,
+-      [OP_SETATTR]            = (nfsd4_enc)nfsd4_encode_setattr,
+-      [OP_SETCLIENTID]        = (nfsd4_enc)nfsd4_encode_setclientid,
+-      [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_VERIFY]             = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_WRITE]              = (nfsd4_enc)nfsd4_encode_write,
+-      [OP_RELEASE_LOCKOWNER]  = (nfsd4_enc)nfsd4_encode_noop,
++      [OP_ACCESS]             = nfsd4_encode_access,
++      [OP_CLOSE]              = nfsd4_encode_close,
++      [OP_COMMIT]             = nfsd4_encode_commit,
++      [OP_CREATE]             = nfsd4_encode_create,
++      [OP_DELEGPURGE]         = nfsd4_encode_noop,
++      [OP_DELEGRETURN]        = nfsd4_encode_noop,
++      [OP_GETATTR]            = nfsd4_encode_getattr,
++      [OP_GETFH]              = nfsd4_encode_getfh,
++      [OP_LINK]               = nfsd4_encode_link,
++      [OP_LOCK]               = nfsd4_encode_lock,
++      [OP_LOCKT]              = nfsd4_encode_lockt,
++      [OP_LOCKU]              = nfsd4_encode_locku,
++      [OP_LOOKUP]             = nfsd4_encode_noop,
++      [OP_LOOKUPP]            = nfsd4_encode_noop,
++      [OP_NVERIFY]            = nfsd4_encode_noop,
++      [OP_OPEN]               = nfsd4_encode_open,
++      [OP_OPENATTR]           = nfsd4_encode_noop,
++      [OP_OPEN_CONFIRM]       = nfsd4_encode_open_confirm,
++      [OP_OPEN_DOWNGRADE]     = nfsd4_encode_open_downgrade,
++      [OP_PUTFH]              = nfsd4_encode_noop,
++      [OP_PUTPUBFH]           = nfsd4_encode_noop,
++      [OP_PUTROOTFH]          = nfsd4_encode_noop,
++      [OP_READ]               = nfsd4_encode_read,
++      [OP_READDIR]            = nfsd4_encode_readdir,
++      [OP_READLINK]           = nfsd4_encode_readlink,
++      [OP_REMOVE]             = nfsd4_encode_remove,
++      [OP_RENAME]             = nfsd4_encode_rename,
++      [OP_RENEW]              = nfsd4_encode_noop,
++      [OP_RESTOREFH]          = nfsd4_encode_noop,
++      [OP_SAVEFH]             = nfsd4_encode_noop,
++      [OP_SECINFO]            = nfsd4_encode_secinfo,
++      [OP_SETATTR]            = nfsd4_encode_setattr,
++      [OP_SETCLIENTID]        = nfsd4_encode_setclientid,
++      [OP_SETCLIENTID_CONFIRM] = nfsd4_encode_noop,
++      [OP_VERIFY]             = nfsd4_encode_noop,
++      [OP_WRITE]              = nfsd4_encode_write,
++      [OP_RELEASE_LOCKOWNER]  = nfsd4_encode_noop,
+       /* NFSv4.1 operations */
+-      [OP_BACKCHANNEL_CTL]    = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
+-      [OP_EXCHANGE_ID]        = (nfsd4_enc)nfsd4_encode_exchange_id,
+-      [OP_CREATE_SESSION]     = (nfsd4_enc)nfsd4_encode_create_session,
+-      [OP_DESTROY_SESSION]    = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_FREE_STATEID]       = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
++      [OP_BACKCHANNEL_CTL]    = nfsd4_encode_noop,
++      [OP_BIND_CONN_TO_SESSION] = nfsd4_encode_bind_conn_to_session,
++      [OP_EXCHANGE_ID]        = nfsd4_encode_exchange_id,
++      [OP_CREATE_SESSION]     = nfsd4_encode_create_session,
++      [OP_DESTROY_SESSION]    = nfsd4_encode_noop,
++      [OP_FREE_STATEID]       = nfsd4_encode_noop,
++      [OP_GET_DIR_DELEGATION] = nfsd4_encode_noop,
+ #ifdef CONFIG_NFSD_PNFS
+-      [OP_GETDEVICEINFO]      = (nfsd4_enc)nfsd4_encode_getdeviceinfo,
+-      [OP_GETDEVICELIST]      = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTCOMMIT]       = (nfsd4_enc)nfsd4_encode_layoutcommit,
+-      [OP_LAYOUTGET]          = (nfsd4_enc)nfsd4_encode_layoutget,
+-      [OP_LAYOUTRETURN]       = (nfsd4_enc)nfsd4_encode_layoutreturn,
++      [OP_GETDEVICEINFO]      = nfsd4_encode_getdeviceinfo,
++      [OP_GETDEVICELIST]      = nfsd4_encode_noop,
++      [OP_LAYOUTCOMMIT]       = nfsd4_encode_layoutcommit,
++      [OP_LAYOUTGET]          = nfsd4_encode_layoutget,
++      [OP_LAYOUTRETURN]       = nfsd4_encode_layoutreturn,
+ #else
+-      [OP_GETDEVICEINFO]      = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_GETDEVICELIST]      = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTCOMMIT]       = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTGET]          = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTRETURN]       = (nfsd4_enc)nfsd4_encode_noop,
++      [OP_GETDEVICEINFO]      = nfsd4_encode_noop,
++      [OP_GETDEVICELIST]      = nfsd4_encode_noop,
++      [OP_LAYOUTCOMMIT]       = nfsd4_encode_noop,
++      [OP_LAYOUTGET]          = nfsd4_encode_noop,
++      [OP_LAYOUTRETURN]       = nfsd4_encode_noop,
+ #endif
+-      [OP_SECINFO_NO_NAME]    = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
+-      [OP_SEQUENCE]           = (nfsd4_enc)nfsd4_encode_sequence,
+-      [OP_SET_SSV]            = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_TEST_STATEID]       = (nfsd4_enc)nfsd4_encode_test_stateid,
+-      [OP_WANT_DELEGATION]    = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_DESTROY_CLIENTID]   = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_RECLAIM_COMPLETE]   = (nfsd4_enc)nfsd4_encode_noop,
++      [OP_SECINFO_NO_NAME]    = nfsd4_encode_secinfo_no_name,
++      [OP_SEQUENCE]           = nfsd4_encode_sequence,
++      [OP_SET_SSV]            = nfsd4_encode_noop,
++      [OP_TEST_STATEID]       = nfsd4_encode_test_stateid,
++      [OP_WANT_DELEGATION]    = nfsd4_encode_noop,
++      [OP_DESTROY_CLIENTID]   = nfsd4_encode_noop,
++      [OP_RECLAIM_COMPLETE]   = nfsd4_encode_noop,
+       /* NFSv4.2 operations */
+-      [OP_ALLOCATE]           = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_COPY]               = (nfsd4_enc)nfsd4_encode_copy,
+-      [OP_COPY_NOTIFY]        = (nfsd4_enc)nfsd4_encode_copy_notify,
+-      [OP_DEALLOCATE]         = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_IO_ADVISE]          = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTERROR]        = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_LAYOUTSTATS]        = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_OFFLOAD_CANCEL]     = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_OFFLOAD_STATUS]     = (nfsd4_enc)nfsd4_encode_offload_status,
+-      [OP_READ_PLUS]          = (nfsd4_enc)nfsd4_encode_read_plus,
+-      [OP_SEEK]               = (nfsd4_enc)nfsd4_encode_seek,
+-      [OP_WRITE_SAME]         = (nfsd4_enc)nfsd4_encode_noop,
+-      [OP_CLONE]              = (nfsd4_enc)nfsd4_encode_noop,
++      [OP_ALLOCATE]           = nfsd4_encode_noop,
++      [OP_COPY]               = nfsd4_encode_copy,
++      [OP_COPY_NOTIFY]        = nfsd4_encode_copy_notify,
++      [OP_DEALLOCATE]         = nfsd4_encode_noop,
++      [OP_IO_ADVISE]          = nfsd4_encode_noop,
++      [OP_LAYOUTERROR]        = nfsd4_encode_noop,
++      [OP_LAYOUTSTATS]        = nfsd4_encode_noop,
++      [OP_OFFLOAD_CANCEL]     = nfsd4_encode_noop,
++      [OP_OFFLOAD_STATUS]     = nfsd4_encode_offload_status,
++      [OP_READ_PLUS]          = nfsd4_encode_read_plus,
++      [OP_SEEK]               = nfsd4_encode_seek,
++      [OP_WRITE_SAME]         = nfsd4_encode_noop,
++      [OP_CLONE]              = nfsd4_encode_noop,
+       /* RFC 8276 extended atributes operations */
+-      [OP_GETXATTR]           = (nfsd4_enc)nfsd4_encode_getxattr,
+-      [OP_SETXATTR]           = (nfsd4_enc)nfsd4_encode_setxattr,
+-      [OP_LISTXATTRS]         = (nfsd4_enc)nfsd4_encode_listxattrs,
+-      [OP_REMOVEXATTR]        = (nfsd4_enc)nfsd4_encode_removexattr,
++      [OP_GETXATTR]           = nfsd4_encode_getxattr,
++      [OP_SETXATTR]           = nfsd4_encode_setxattr,
++      [OP_LISTXATTRS]         = nfsd4_encode_listxattrs,
++      [OP_REMOVEXATTR]        = nfsd4_encode_removexattr,
+ };
+ /*
diff --git a/queue-6.1/nfsd-clean-up-find_or_add_file.patch b/queue-6.1/nfsd-clean-up-find_or_add_file.patch
new file mode 100644 (file)
index 0000000..77f48b6
--- /dev/null
@@ -0,0 +1,123 @@
+From 51805844c0d7f3311515967959269b4f38278d31 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:41 -0400
+Subject: NFSD: Clean up find_or_add_file()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9270fc514ba7d415636b23bcb937573a1ce54f6a ]
+
+Remove the call to find_file_locked() in insert_nfs4_file(). Tracing
+shows that over 99% of these calls return NULL. Thus it is not worth
+the expense of the extra bucket list traversal. insert_file() already
+deals correctly with the case where the item is already in the hash
+bucket.
+
+Since nfsd4_file_hash_insert() is now just a wrapper around
+insert_file(), move the meat of insert_file() into
+nfsd4_file_hash_insert() and get rid of it.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   64 ++++++++++++++++++++++------------------------------
+ 1 file changed, 28 insertions(+), 36 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4699,24 +4699,42 @@ find_file_locked(const struct svc_fh *fh
+       return NULL;
+ }
+-static struct nfs4_file *insert_file(struct nfs4_file *new, struct svc_fh *fh,
+-                                   unsigned int hashval)
++static struct nfs4_file * find_file(struct svc_fh *fh)
+ {
+       struct nfs4_file *fp;
++      unsigned int hashval = file_hashval(fh);
++
++      rcu_read_lock();
++      fp = find_file_locked(fh, hashval);
++      rcu_read_unlock();
++      return fp;
++}
++
++/*
++ * On hash insertion, identify entries with the same inode but
++ * distinct filehandles. They will all be in the same hash bucket
++ * because nfs4_file's are hashed by the address in the fi_inode
++ * field.
++ */
++static noinline_for_stack struct nfs4_file *
++nfsd4_file_hash_insert(struct nfs4_file *new, const struct svc_fh *fhp)
++{
++      unsigned int hashval = file_hashval(fhp);
+       struct nfs4_file *ret = NULL;
+       bool alias_found = false;
++      struct nfs4_file *fi;
+       spin_lock(&state_lock);
+-      hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash,
++      hlist_for_each_entry_rcu(fi, &file_hashtbl[hashval], fi_hash,
+                                lockdep_is_held(&state_lock)) {
+-              if (fh_match(&fp->fi_fhandle, &fh->fh_handle)) {
+-                      if (refcount_inc_not_zero(&fp->fi_ref))
+-                              ret = fp;
+-              } else if (d_inode(fh->fh_dentry) == fp->fi_inode)
+-                      fp->fi_aliased = alias_found = true;
++              if (fh_match(&fi->fi_fhandle, &fhp->fh_handle)) {
++                      if (refcount_inc_not_zero(&fi->fi_ref))
++                              ret = fi;
++              } else if (d_inode(fhp->fh_dentry) == fi->fi_inode)
++                      fi->fi_aliased = alias_found = true;
+       }
+       if (likely(ret == NULL)) {
+-              nfsd4_file_init(fh, new);
++              nfsd4_file_init(fhp, new);
+               hlist_add_head_rcu(&new->fi_hash, &file_hashtbl[hashval]);
+               new->fi_aliased = alias_found;
+               ret = new;
+@@ -4725,32 +4743,6 @@ static struct nfs4_file *insert_file(str
+       return ret;
+ }
+-static struct nfs4_file * find_file(struct svc_fh *fh)
+-{
+-      struct nfs4_file *fp;
+-      unsigned int hashval = file_hashval(fh);
+-
+-      rcu_read_lock();
+-      fp = find_file_locked(fh, hashval);
+-      rcu_read_unlock();
+-      return fp;
+-}
+-
+-static struct nfs4_file *
+-find_or_add_file(struct nfs4_file *new, struct svc_fh *fh)
+-{
+-      struct nfs4_file *fp;
+-      unsigned int hashval = file_hashval(fh);
+-
+-      rcu_read_lock();
+-      fp = find_file_locked(fh, hashval);
+-      rcu_read_unlock();
+-      if (fp)
+-              return fp;
+-
+-      return insert_file(new, fh, hashval);
+-}
+-
+ static noinline_for_stack void nfsd4_file_hash_remove(struct nfs4_file *fi)
+ {
+       hlist_del_rcu(&fi->fi_hash);
+@@ -5661,7 +5653,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
+        * and check for delegations in the process of being recalled.
+        * If not found, create the nfs4_file struct
+        */
+-      fp = find_or_add_file(open->op_file, current_fh);
++      fp = nfsd4_file_hash_insert(open->op_file, current_fh);
+       if (fp != open->op_file) {
+               status = nfs4_check_deleg(cl, open, &dp);
+               if (status)
diff --git a/queue-6.1/nfsd-clean-up-nfs4_preprocess_stateid_op-call-sites.patch b/queue-6.1/nfsd-clean-up-nfs4_preprocess_stateid_op-call-sites.patch
new file mode 100644 (file)
index 0000000..5b59f20
--- /dev/null
@@ -0,0 +1,106 @@
+From 757d584649721520e10e32a12d7919f5035e0334 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:46:57 -0400
+Subject: NFSD: Clean up nfs4_preprocess_stateid_op() call sites
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit eeff73f7c1c583f79a401284f46c619294859310 ]
+
+Remove the lame-duck dprintk()s around nfs4_preprocess_stateid_op()
+call sites.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c |   31 +++++++------------------------
+ 1 file changed, 7 insertions(+), 24 deletions(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -943,12 +943,7 @@ nfsd4_read(struct svc_rqst *rqstp, struc
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
+                                       &read->rd_stateid, RD_STATE,
+                                       &read->rd_nf, NULL);
+-      if (status) {
+-              dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
+-              goto out;
+-      }
+-      status = nfs_ok;
+-out:
++
+       read->rd_rqstp = rqstp;
+       read->rd_fhp = &cstate->current_fh;
+       return status;
+@@ -1117,10 +1112,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
+               status = nfs4_preprocess_stateid_op(rqstp, cstate,
+                               &cstate->current_fh, &setattr->sa_stateid,
+                               WR_STATE, NULL, NULL);
+-              if (status) {
+-                      dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
++              if (status)
+                       return status;
+-              }
+       }
+       err = fh_want_write(&cstate->current_fh);
+       if (err)
+@@ -1170,10 +1163,8 @@ nfsd4_write(struct svc_rqst *rqstp, stru
+                              write->wr_offset, cnt);
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
+                                               stateid, WR_STATE, &nf, NULL);
+-      if (status) {
+-              dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
++      if (status)
+               return status;
+-      }
+       write->wr_how_written = write->wr_stable_how;
+@@ -1204,17 +1195,13 @@ nfsd4_verify_copy(struct svc_rqst *rqstp
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
+                                           src_stateid, RD_STATE, src, NULL);
+-      if (status) {
+-              dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
++      if (status)
+               goto out;
+-      }
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
+                                           dst_stateid, WR_STATE, dst, NULL);
+-      if (status) {
+-              dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
++      if (status)
+               goto out_put_src;
+-      }
+       /* fix up for NFS-specific error code */
+       if (!S_ISREG(file_inode((*src)->nf_file)->i_mode) ||
+@@ -1935,10 +1922,8 @@ nfsd4_fallocate(struct svc_rqst *rqstp,
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
+                                           &fallocate->falloc_stateid,
+                                           WR_STATE, &nf, NULL);
+-      if (status != nfs_ok) {
+-              dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
++      if (status != nfs_ok)
+               return status;
+-      }
+       status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, nf->nf_file,
+                                    fallocate->falloc_offset,
+@@ -1994,10 +1979,8 @@ nfsd4_seek(struct svc_rqst *rqstp, struc
+       status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
+                                           &seek->seek_stateid,
+                                           RD_STATE, &nf, NULL);
+-      if (status) {
+-              dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
++      if (status)
+               return status;
+-      }
+       switch (seek->seek_whence) {
+       case NFS4_CONTENT_DATA:
diff --git a/queue-6.1/nfsd-clean-up-nfsd4_init_file.patch b/queue-6.1/nfsd-clean-up-nfsd4_init_file.patch
new file mode 100644 (file)
index 0000000..72e8059
--- /dev/null
@@ -0,0 +1,61 @@
+From 4ff0477fc99f1f54c18bb867bf4b4fcfc752a090 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:28 -0400
+Subject: NFSD: Clean up nfsd4_init_file()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 81a21fa3e7fdecb3c5b97014f0fc5a17d5806cae ]
+
+Name this function more consistently. I'm going to use nfsd4_file_
+and nfsd4_file_hash_ for these helpers.
+
+Change the @fh parameter to be const pointer for better type safety.
+
+Finally, move the hash insertion operation to the caller. This is
+typical for most other "init_object" type helpers, and it is where
+most of the other nfs4_file hash table operations are located.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4278,11 +4278,9 @@ static struct nfs4_file *nfsd4_alloc_fil
+ }
+ /* OPEN Share state helper functions */
+-static void nfsd4_init_file(struct svc_fh *fh, unsigned int hashval,
+-                              struct nfs4_file *fp)
+-{
+-      lockdep_assert_held(&state_lock);
++static void nfsd4_file_init(const struct svc_fh *fh, struct nfs4_file *fp)
++{
+       refcount_set(&fp->fi_ref, 1);
+       spin_lock_init(&fp->fi_lock);
+       INIT_LIST_HEAD(&fp->fi_stateids);
+@@ -4300,7 +4298,6 @@ static void nfsd4_init_file(struct svc_f
+       INIT_LIST_HEAD(&fp->fi_lo_states);
+       atomic_set(&fp->fi_lo_recalls, 0);
+ #endif
+-      hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]);
+ }
+ void
+@@ -4718,7 +4715,8 @@ static struct nfs4_file *insert_file(str
+                       fp->fi_aliased = alias_found = true;
+       }
+       if (likely(ret == NULL)) {
+-              nfsd4_init_file(fh, hashval, new);
++              nfsd4_file_init(fh, new);
++              hlist_add_head_rcu(&new->fi_hash, &file_hashtbl[hashval]);
+               new->fi_aliased = alias_found;
+               ret = new;
+       }
diff --git a/queue-6.1/nfsd-don-t-destroy-global-nfs4_file-table-in-per-net-shutdown.patch b/queue-6.1/nfsd-don-t-destroy-global-nfs4_file-table-in-per-net-shutdown.patch
new file mode 100644 (file)
index 0000000..4994ca3
--- /dev/null
@@ -0,0 +1,42 @@
+From a6bc8b37ffcdf3cbd880a5725b717c4c215b7196 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Sat, 11 Feb 2023 07:50:08 -0500
+Subject: nfsd: don't destroy global nfs4_file table in per-net shutdown
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 4102db175b5d884d133270fdbd0e59111ce688fc ]
+
+The nfs4_file table is global, so shutting it down when a containerized
+nfsd is shut down is wrong and can lead to double-frees. Tear down the
+nfs4_file_rhltable in nfs4_state_shutdown instead of
+nfs4_state_shutdown_net.
+
+Fixes: d47b295e8d76 ("NFSD: Use rhashtable for managing nfs4_file objects")
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=2169017
+Reported-by: JianHong Yin <jiyin@redhat.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -8212,7 +8212,6 @@ nfs4_state_shutdown_net(struct net *net)
+       nfsd4_client_tracking_exit(net);
+       nfs4_state_destroy_net(net);
+-      rhltable_destroy(&nfs4_file_rhltable);
+ #ifdef CONFIG_NFSD_V4_2_INTER_SSC
+       nfsd4_ssc_shutdown_umount(nn);
+ #endif
+@@ -8222,6 +8221,7 @@ void
+ nfs4_state_shutdown(void)
+ {
+       nfsd4_destroy_callback_queue();
++      rhltable_destroy(&nfs4_file_rhltable);
+ }
+ static void
diff --git a/queue-6.1/nfsd-fix-licensing-header-in-filecache.c.patch b/queue-6.1/nfsd-fix-licensing-header-in-filecache.c.patch
new file mode 100644 (file)
index 0000000..a57a7e5
--- /dev/null
@@ -0,0 +1,29 @@
+From 275fc0e08f2112b49b304af978f149b684d4ac14 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Mon, 31 Oct 2022 09:53:26 -0400
+Subject: NFSD: Fix licensing header in filecache.c
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 3f054211b29c0fa06dfdcab402c795fd7e906be1 ]
+
+Add a missing SPDX header.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/filecache.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -1,5 +1,6 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+- * Open file cache.
++ * The NFSD open file cache.
+  *
+  * (c) 2015 - Jeff Layton <jeff.layton@primarydata.com>
+  *
diff --git a/queue-6.1/nfsd-fix-up-the-filecache-laundrette-scheduling.patch b/queue-6.1/nfsd-fix-up-the-filecache-laundrette-scheduling.patch
new file mode 100644 (file)
index 0000000..2b8f57e
--- /dev/null
@@ -0,0 +1,53 @@
+From 98f2fa4692468cd565264518f82d6d669e982547 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 2 Nov 2022 14:44:50 -0400
+Subject: nfsd: fix up the filecache laundrette scheduling
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 22ae4c114f77b55a4c5036e8f70409a0799a08f8 ]
+
+We don't really care whether there are hashed entries when it comes to
+scheduling the laundrette. They might all be non-gc entries, after all.
+We only want to schedule it if there are entries on the LRU.
+
+Switch to using list_lru_count, and move the check into
+nfsd_file_gc_worker. The other callsite in nfsd_file_put doesn't need to
+count entries, since it only schedules the laundrette after adding an
+entry to the LRU.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/filecache.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -211,12 +211,9 @@ static const struct rhashtable_params nf
+ static void
+ nfsd_file_schedule_laundrette(void)
+ {
+-      if ((atomic_read(&nfsd_file_rhash_tbl.nelems) == 0) ||
+-          test_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 0)
+-              return;
+-
+-      queue_delayed_work(system_wq, &nfsd_filecache_laundrette,
+-                      NFSD_LAUNDRETTE_DELAY);
++      if (test_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags))
++              queue_delayed_work(system_wq, &nfsd_filecache_laundrette,
++                                 NFSD_LAUNDRETTE_DELAY);
+ }
+ static void
+@@ -614,7 +611,8 @@ static void
+ nfsd_file_gc_worker(struct work_struct *work)
+ {
+       nfsd_file_gc();
+-      nfsd_file_schedule_laundrette();
++      if (list_lru_count(&nfsd_file_lru))
++              nfsd_file_schedule_laundrette();
+ }
+ static unsigned long
diff --git a/queue-6.1/nfsd-flesh-out-a-documenting-comment-for-filecache.c.patch b/queue-6.1/nfsd-flesh-out-a-documenting-comment-for-filecache.c.patch
new file mode 100644 (file)
index 0000000..5a00ada
--- /dev/null
@@ -0,0 +1,54 @@
+From 06d8447f0ae19330b1214367aa39fbd956dc4fee Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue, 1 Nov 2022 13:30:46 -0400
+Subject: NFSD: Flesh out a documenting comment for filecache.c
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit b3276c1f5b268ff56622e9e125b792b4c3dc03ac ]
+
+Record what we've learned recently about the NFSD filecache in a
+documenting comment so our future selves don't forget what all this
+is for.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/filecache.c |   24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -2,6 +2,30 @@
+  * Open file cache.
+  *
+  * (c) 2015 - Jeff Layton <jeff.layton@primarydata.com>
++ *
++ * An nfsd_file object is a per-file collection of open state that binds
++ * together:
++ *   - a struct file *
++ *   - a user credential
++ *   - a network namespace
++ *   - a read-ahead context
++ *   - monitoring for writeback errors
++ *
++ * nfsd_file objects are reference-counted. Consumers acquire a new
++ * object via the nfsd_file_acquire API. They manage their interest in
++ * the acquired object, and hence the object's reference count, via
++ * nfsd_file_get and nfsd_file_put. There are two varieties of nfsd_file
++ * object:
++ *
++ *  * non-garbage-collected: When a consumer wants to precisely control
++ *    the lifetime of a file's open state, it acquires a non-garbage-
++ *    collected nfsd_file. The final nfsd_file_put releases the open
++ *    state immediately.
++ *
++ *  * garbage-collected: When a consumer does not control the lifetime
++ *    of open state, it acquires a garbage-collected nfsd_file. The
++ *    final nfsd_file_put allows the open state to linger for a period
++ *    during which it may be re-used.
+  */
+ #include <linux/hash.h>
diff --git a/queue-6.1/nfsd-ignore-requests-to-disable-unsupported-versions.patch b/queue-6.1/nfsd-ignore-requests-to-disable-unsupported-versions.patch
new file mode 100644 (file)
index 0000000..f69f9f9
--- /dev/null
@@ -0,0 +1,35 @@
+From 8fdcafa904d391a0b4e26c8bcc9b7126676c4631 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 18 Oct 2022 07:47:54 -0400
+Subject: nfsd: ignore requests to disable unsupported versions
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 8e823bafff2308753d430566256c83d8085952da ]
+
+The kernel currently errors out if you attempt to enable or disable a
+version that it doesn't recognize. Change it to ignore attempts to
+disable an unrecognized version. If we don't support it, then there is
+no harm in doing so.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Tom Talpey <tom@talpey.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfsctl.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -601,7 +601,9 @@ static ssize_t __write_versions(struct f
+                               }
+                               break;
+                       default:
+-                              return -EINVAL;
++                              /* Ignore requests to disable non-existent versions */
++                              if (cmd == NFSD_SET)
++                                      return -EINVAL;
+                       }
+                       vers += len + 1;
+               } while ((len = qword_get(&mesg, vers, size)) > 0);
diff --git a/queue-6.1/nfsd-move-nfserrno-to-vfs.c.patch b/queue-6.1/nfsd-move-nfserrno-to-vfs.c.patch
new file mode 100644 (file)
index 0000000..e26f593
--- /dev/null
@@ -0,0 +1,231 @@
+From 7cc60aa13f695b5585a494331d16d0c7e31fc05f Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 18 Oct 2022 07:47:55 -0400
+Subject: nfsd: move nfserrno() to vfs.c
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit cb12fae1c34b1fa7eaae92c5aadc72d86d7fae19 ]
+
+nfserrno() is common to all nfs versions, but nfsproc.c is specifically
+for NFSv2. Move it to vfs.c, and the prototype to vfs.h.
+
+While we're in here, remove the #ifdef EDQUOT check in this function.
+It's apparently a holdover from the initial merge of the nfsd code in
+1997. No other place in the kernel checks that that symbol is defined
+before using it, so I think we can dispense with it here.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/blocklayout.c    |    1 
+ fs/nfsd/blocklayoutxdr.c |    1 
+ fs/nfsd/export.h         |    1 
+ fs/nfsd/flexfilelayout.c |    1 
+ fs/nfsd/nfs4idmap.c      |    1 
+ fs/nfsd/nfsproc.c        |   62 ----------------------------------------------
+ fs/nfsd/vfs.c            |   63 +++++++++++++++++++++++++++++++++++++++++++++++
+ fs/nfsd/vfs.h            |    1 
+ 8 files changed, 68 insertions(+), 63 deletions(-)
+
+--- a/fs/nfsd/blocklayout.c
++++ b/fs/nfsd/blocklayout.c
+@@ -12,6 +12,7 @@
+ #include "blocklayoutxdr.h"
+ #include "pnfs.h"
+ #include "filecache.h"
++#include "vfs.h"
+ #define NFSDDBG_FACILITY      NFSDDBG_PNFS
+--- a/fs/nfsd/blocklayoutxdr.c
++++ b/fs/nfsd/blocklayoutxdr.c
+@@ -9,6 +9,7 @@
+ #include "nfsd.h"
+ #include "blocklayoutxdr.h"
++#include "vfs.h"
+ #define NFSDDBG_FACILITY      NFSDDBG_PNFS
+--- a/fs/nfsd/export.h
++++ b/fs/nfsd/export.h
+@@ -115,7 +115,6 @@ struct svc_export *        rqst_find_fsidzero_e
+ int                   exp_rootfh(struct net *, struct auth_domain *,
+                                       char *path, struct knfsd_fh *, int maxsize);
+ __be32                        exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
+-__be32                        nfserrno(int errno);
+ static inline void exp_put(struct svc_export *exp)
+ {
+--- a/fs/nfsd/flexfilelayout.c
++++ b/fs/nfsd/flexfilelayout.c
+@@ -15,6 +15,7 @@
+ #include "flexfilelayoutxdr.h"
+ #include "pnfs.h"
++#include "vfs.h"
+ #define NFSDDBG_FACILITY      NFSDDBG_PNFS
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -41,6 +41,7 @@
+ #include "idmap.h"
+ #include "nfsd.h"
+ #include "netns.h"
++#include "vfs.h"
+ /*
+  * Turn off idmapping when using AUTH_SYS.
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -848,65 +848,3 @@ const struct svc_version nfsd_version2 =
+       .vs_dispatch    = nfsd_dispatch,
+       .vs_xdrsize     = NFS2_SVC_XDRSIZE,
+ };
+-
+-/*
+- * Map errnos to NFS errnos.
+- */
+-__be32
+-nfserrno (int errno)
+-{
+-      static struct {
+-              __be32  nfserr;
+-              int     syserr;
+-      } nfs_errtbl[] = {
+-              { nfs_ok, 0 },
+-              { nfserr_perm, -EPERM },
+-              { nfserr_noent, -ENOENT },
+-              { nfserr_io, -EIO },
+-              { nfserr_nxio, -ENXIO },
+-              { nfserr_fbig, -E2BIG },
+-              { nfserr_stale, -EBADF },
+-              { nfserr_acces, -EACCES },
+-              { nfserr_exist, -EEXIST },
+-              { nfserr_xdev, -EXDEV },
+-              { nfserr_mlink, -EMLINK },
+-              { nfserr_nodev, -ENODEV },
+-              { nfserr_notdir, -ENOTDIR },
+-              { nfserr_isdir, -EISDIR },
+-              { nfserr_inval, -EINVAL },
+-              { nfserr_fbig, -EFBIG },
+-              { nfserr_nospc, -ENOSPC },
+-              { nfserr_rofs, -EROFS },
+-              { nfserr_mlink, -EMLINK },
+-              { nfserr_nametoolong, -ENAMETOOLONG },
+-              { nfserr_notempty, -ENOTEMPTY },
+-#ifdef EDQUOT
+-              { nfserr_dquot, -EDQUOT },
+-#endif
+-              { nfserr_stale, -ESTALE },
+-              { nfserr_jukebox, -ETIMEDOUT },
+-              { nfserr_jukebox, -ERESTARTSYS },
+-              { nfserr_jukebox, -EAGAIN },
+-              { nfserr_jukebox, -EWOULDBLOCK },
+-              { nfserr_jukebox, -ENOMEM },
+-              { nfserr_io, -ETXTBSY },
+-              { nfserr_notsupp, -EOPNOTSUPP },
+-              { nfserr_toosmall, -ETOOSMALL },
+-              { nfserr_serverfault, -ESERVERFAULT },
+-              { nfserr_serverfault, -ENFILE },
+-              { nfserr_io, -EREMOTEIO },
+-              { nfserr_stale, -EOPENSTALE },
+-              { nfserr_io, -EUCLEAN },
+-              { nfserr_perm, -ENOKEY },
+-              { nfserr_no_grace, -ENOGRACE},
+-      };
+-      int     i;
+-
+-      for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
+-              if (nfs_errtbl[i].syserr == errno)
+-                      return nfs_errtbl[i].nfserr;
+-      }
+-      WARN_ONCE(1, "nfsd: non-standard errno: %d\n", errno);
+-      return nfserr_io;
+-}
+-
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -49,6 +49,69 @@
+ #define NFSDDBG_FACILITY              NFSDDBG_FILEOP
++/**
++ * nfserrno - Map Linux errnos to NFS errnos
++ * @errno: POSIX(-ish) error code to be mapped
++ *
++ * Returns the appropriate (net-endian) nfserr_* (or nfs_ok if errno is 0). If
++ * it's an error we don't expect, log it once and return nfserr_io.
++ */
++__be32
++nfserrno (int errno)
++{
++      static struct {
++              __be32  nfserr;
++              int     syserr;
++      } nfs_errtbl[] = {
++              { nfs_ok, 0 },
++              { nfserr_perm, -EPERM },
++              { nfserr_noent, -ENOENT },
++              { nfserr_io, -EIO },
++              { nfserr_nxio, -ENXIO },
++              { nfserr_fbig, -E2BIG },
++              { nfserr_stale, -EBADF },
++              { nfserr_acces, -EACCES },
++              { nfserr_exist, -EEXIST },
++              { nfserr_xdev, -EXDEV },
++              { nfserr_mlink, -EMLINK },
++              { nfserr_nodev, -ENODEV },
++              { nfserr_notdir, -ENOTDIR },
++              { nfserr_isdir, -EISDIR },
++              { nfserr_inval, -EINVAL },
++              { nfserr_fbig, -EFBIG },
++              { nfserr_nospc, -ENOSPC },
++              { nfserr_rofs, -EROFS },
++              { nfserr_mlink, -EMLINK },
++              { nfserr_nametoolong, -ENAMETOOLONG },
++              { nfserr_notempty, -ENOTEMPTY },
++              { nfserr_dquot, -EDQUOT },
++              { nfserr_stale, -ESTALE },
++              { nfserr_jukebox, -ETIMEDOUT },
++              { nfserr_jukebox, -ERESTARTSYS },
++              { nfserr_jukebox, -EAGAIN },
++              { nfserr_jukebox, -EWOULDBLOCK },
++              { nfserr_jukebox, -ENOMEM },
++              { nfserr_io, -ETXTBSY },
++              { nfserr_notsupp, -EOPNOTSUPP },
++              { nfserr_toosmall, -ETOOSMALL },
++              { nfserr_serverfault, -ESERVERFAULT },
++              { nfserr_serverfault, -ENFILE },
++              { nfserr_io, -EREMOTEIO },
++              { nfserr_stale, -EOPENSTALE },
++              { nfserr_io, -EUCLEAN },
++              { nfserr_perm, -ENOKEY },
++              { nfserr_no_grace, -ENOGRACE},
++      };
++      int     i;
++
++      for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
++              if (nfs_errtbl[i].syserr == errno)
++                      return nfs_errtbl[i].nfserr;
++      }
++      WARN_ONCE(1, "nfsd: non-standard errno: %d\n", errno);
++      return nfserr_io;
++}
++
+ /* 
+  * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
+  * a mount point.
+--- a/fs/nfsd/vfs.h
++++ b/fs/nfsd/vfs.h
+@@ -60,6 +60,7 @@ static inline void nfsd_attrs_free(struc
+       posix_acl_release(attrs->na_dpacl);
+ }
++__be32                nfserrno (int errno);
+ int           nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+                               struct svc_export **expp);
+ __be32                nfsd_lookup(struct svc_rqst *, struct svc_fh *,
diff --git a/queue-6.1/nfsd-refactor-find_file.patch b/queue-6.1/nfsd-refactor-find_file.patch
new file mode 100644 (file)
index 0000000..b27b853
--- /dev/null
@@ -0,0 +1,80 @@
+From 77b17162b368c0ba3ac6f505cbee2d23a01d6294 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:47 -0400
+Subject: NFSD: Refactor find_file()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 15424748001a9b5ea62b3e6ad45f0a8b27f01df9 ]
+
+find_file() is now the only caller of find_file_locked(), so just
+fold these two together.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   36 +++++++++++++++---------------------
+ 1 file changed, 15 insertions(+), 21 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4683,31 +4683,24 @@ move_to_close_lru(struct nfs4_ol_stateid
+               nfs4_put_stid(&last->st_stid);
+ }
+-/* search file_hashtbl[] for file */
+-static struct nfs4_file *
+-find_file_locked(const struct svc_fh *fh, unsigned int hashval)
++static noinline_for_stack struct nfs4_file *
++nfsd4_file_hash_lookup(const struct svc_fh *fhp)
+ {
+-      struct nfs4_file *fp;
++      unsigned int hashval = file_hashval(fhp);
++      struct nfs4_file *fi;
+-      hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash,
+-                              lockdep_is_held(&state_lock)) {
+-              if (fh_match(&fp->fi_fhandle, &fh->fh_handle)) {
+-                      if (refcount_inc_not_zero(&fp->fi_ref))
+-                              return fp;
++      rcu_read_lock();
++      hlist_for_each_entry_rcu(fi, &file_hashtbl[hashval], fi_hash,
++                               lockdep_is_held(&state_lock)) {
++              if (fh_match(&fi->fi_fhandle, &fhp->fh_handle)) {
++                      if (refcount_inc_not_zero(&fi->fi_ref)) {
++                              rcu_read_unlock();
++                              return fi;
++                      }
+               }
+       }
+-      return NULL;
+-}
+-
+-static struct nfs4_file * find_file(struct svc_fh *fh)
+-{
+-      struct nfs4_file *fp;
+-      unsigned int hashval = file_hashval(fh);
+-
+-      rcu_read_lock();
+-      fp = find_file_locked(fh, hashval);
+       rcu_read_unlock();
+-      return fp;
++      return NULL;
+ }
+ /*
+@@ -4758,9 +4751,10 @@ nfs4_share_conflict(struct svc_fh *curre
+       struct nfs4_file *fp;
+       __be32 ret = nfs_ok;
+-      fp = find_file(current_fh);
++      fp = nfsd4_file_hash_lookup(current_fh);
+       if (!fp)
+               return ret;
++
+       /* Check for conflicting share reservations */
+       spin_lock(&fp->fi_lock);
+       if (fp->fi_share_deny & deny_type)
diff --git a/queue-6.1/nfsd-refactoring-courtesy_client_reaper-to-a-generic-low-memory-shrinker.patch b/queue-6.1/nfsd-refactoring-courtesy_client_reaper-to-a-generic-low-memory-shrinker.patch
new file mode 100644 (file)
index 0000000..3a642ce
--- /dev/null
@@ -0,0 +1,88 @@
+From 1644e0ed649c0f951c08c81853485cbbcb3d5eaf Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 16 Nov 2022 19:44:45 -0800
+Subject: NFSD: refactoring courtesy_client_reaper to a generic low memory shrinker
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit a1049eb47f20b9eabf9afb218578fff16b4baca6 ]
+
+Refactoring courtesy_client_reaper to generic low memory
+shrinker so it can be used for other purposes.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4362,7 +4362,7 @@ out:
+ }
+ static unsigned long
+-nfsd_courtesy_client_count(struct shrinker *shrink, struct shrink_control *sc)
++nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
+ {
+       int cnt;
+       struct nfsd_net *nn = container_of(shrink,
+@@ -4375,7 +4375,7 @@ nfsd_courtesy_client_count(struct shrink
+ }
+ static unsigned long
+-nfsd_courtesy_client_scan(struct shrinker *shrink, struct shrink_control *sc)
++nfsd4_state_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
+ {
+       return SHRINK_STOP;
+ }
+@@ -4402,8 +4402,8 @@ nfsd4_init_leases_net(struct nfsd_net *n
+       nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
+       atomic_set(&nn->nfsd_courtesy_clients, 0);
+-      nn->nfsd_client_shrinker.scan_objects = nfsd_courtesy_client_scan;
+-      nn->nfsd_client_shrinker.count_objects = nfsd_courtesy_client_count;
++      nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
++      nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
+       nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
+       return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
+ }
+@@ -6171,17 +6171,24 @@ laundromat_main(struct work_struct *laun
+ }
+ static void
+-courtesy_client_reaper(struct work_struct *reaper)
++courtesy_client_reaper(struct nfsd_net *nn)
+ {
+       struct list_head reaplist;
+-      struct delayed_work *dwork = to_delayed_work(reaper);
+-      struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+-                                      nfsd_shrinker_work);
+       nfs4_get_courtesy_client_reaplist(nn, &reaplist);
+       nfs4_process_client_reaplist(&reaplist);
+ }
++static void
++nfsd4_state_shrinker_worker(struct work_struct *work)
++{
++      struct delayed_work *dwork = to_delayed_work(work);
++      struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
++                              nfsd_shrinker_work);
++
++      courtesy_client_reaper(nn);
++}
++
+ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp)
+ {
+       if (!fh_match(&fhp->fh_handle, &stp->sc_file->fi_fhandle))
+@@ -8007,7 +8014,7 @@ static int nfs4_state_create_net(struct
+       INIT_LIST_HEAD(&nn->blocked_locks_lru);
+       INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
+-      INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, courtesy_client_reaper);
++      INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
+       get_net(net);
+       return 0;
diff --git a/queue-6.1/nfsd-register-unregister-of-nfsd-client-shrinker-at-nfsd-startup-shutdown-time.patch b/queue-6.1/nfsd-register-unregister-of-nfsd-client-shrinker-at-nfsd-startup-shutdown-time.patch
new file mode 100644 (file)
index 0000000..1a2d399
--- /dev/null
@@ -0,0 +1,136 @@
+From 11c632570a2654947799ddc6d16db0780d2232c2 Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 11 Jan 2023 12:17:09 -0800
+Subject: NFSD: register/unregister of nfsd-client shrinker at nfsd startup/shutdown time
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit f385f7d244134246f984975ed34cd75f77de479f ]
+
+Currently the nfsd-client shrinker is registered and unregistered at
+the time the nfsd module is loaded and unloaded. The problem with this
+is the shrinker is being registered before all of the relevant fields
+in nfsd_net are initialized when nfsd is started. This can lead to an
+oops when memory is low and the shrinker is called while nfsd is not
+running.
+
+This patch moves the  register/unregister of nfsd-client shrinker from
+module load/unload time to nfsd startup/shutdown time.
+
+Fixes: 44df6f439a17 ("NFSD: add delegation reaper to react to low memory condition")
+Reported-by: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   22 +++++++++++-----------
+ fs/nfsd/nfsctl.c    |    7 +------
+ fs/nfsd/nfsd.h      |    6 ++----
+ 3 files changed, 14 insertions(+), 21 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4422,7 +4422,7 @@ nfsd4_state_shrinker_scan(struct shrinke
+       return SHRINK_STOP;
+ }
+-int
++void
+ nfsd4_init_leases_net(struct nfsd_net *nn)
+ {
+       struct sysinfo si;
+@@ -4444,16 +4444,6 @@ nfsd4_init_leases_net(struct nfsd_net *n
+       nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
+       atomic_set(&nn->nfsd_courtesy_clients, 0);
+-      nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
+-      nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
+-      nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
+-      return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
+-}
+-
+-void
+-nfsd4_leases_net_shutdown(struct nfsd_net *nn)
+-{
+-      unregister_shrinker(&nn->nfsd_client_shrinker);
+ }
+ static void init_nfs4_replay(struct nfs4_replay *rp)
+@@ -8099,8 +8089,17 @@ static int nfs4_state_create_net(struct
+       INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
+       get_net(net);
++      nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
++      nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
++      nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
++
++      if (register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client"))
++              goto err_shrinker;
+       return 0;
++err_shrinker:
++      put_net(net);
++      kfree(nn->sessionid_hashtbl);
+ err_sessionid:
+       kfree(nn->unconf_id_hashtbl);
+ err_unconf_id:
+@@ -8193,6 +8192,7 @@ nfs4_state_shutdown_net(struct net *net)
+       struct list_head *pos, *next, reaplist;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
++      unregister_shrinker(&nn->nfsd_client_shrinker);
+       cancel_delayed_work_sync(&nn->laundromat_work);
+       locks_end_grace(&nn->nfsd4_manager);
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1452,9 +1452,7 @@ static __net_init int nfsd_init_net(stru
+               goto out_idmap_error;
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+-      retval = nfsd4_init_leases_net(nn);
+-      if (retval)
+-              goto out_drc_error;
++      nfsd4_init_leases_net(nn);
+       retval = nfsd_reply_cache_init(nn);
+       if (retval)
+               goto out_cache_error;
+@@ -1464,8 +1462,6 @@ static __net_init int nfsd_init_net(stru
+       return 0;
+ out_cache_error:
+-      nfsd4_leases_net_shutdown(nn);
+-out_drc_error:
+       nfsd_idmap_shutdown(net);
+ out_idmap_error:
+       nfsd_export_shutdown(net);
+@@ -1481,7 +1477,6 @@ static __net_exit void nfsd_exit_net(str
+       nfsd_idmap_shutdown(net);
+       nfsd_export_shutdown(net);
+       nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
+-      nfsd4_leases_net_shutdown(nn);
+ }
+ static struct pernet_operations nfsd_net_ops = {
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -504,8 +504,7 @@ extern void unregister_cld_notifier(void
+ extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn);
+ #endif
+-extern int nfsd4_init_leases_net(struct nfsd_net *nn);
+-extern void nfsd4_leases_net_shutdown(struct nfsd_net *nn);
++extern void nfsd4_init_leases_net(struct nfsd_net *nn);
+ #else /* CONFIG_NFSD_V4 */
+ static inline int nfsd4_is_junction(struct dentry *dentry)
+@@ -513,8 +512,7 @@ static inline int nfsd4_is_junction(stru
+       return 0;
+ }
+-static inline int nfsd4_init_leases_net(struct nfsd_net *nn) { return 0; };
+-static inline void nfsd4_leases_net_shutdown(struct nfsd_net *nn) {};
++static inline void nfsd4_init_leases_net(struct nfsd_net *nn) { };
+ #define register_cld_notifier() 0
+ #define unregister_cld_notifier() do { } while(0)
diff --git a/queue-6.1/nfsd-remove-redundant-assignment-to-variable-host_err.patch b/queue-6.1/nfsd-remove-redundant-assignment-to-variable-host_err.patch
new file mode 100644 (file)
index 0000000..d06efc8
--- /dev/null
@@ -0,0 +1,34 @@
+From 2e3aa79f392f5bfca11a1dbbdf422bc088a1a65a Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.i.king@gmail.com>
+Date: Mon, 10 Oct 2022 21:24:23 +0100
+Subject: NFSD: Remove redundant assignment to variable host_err
+
+From: Colin Ian King <colin.i.king@gmail.com>
+
+[ Upstream commit 69eed23baf877bbb1f14d7f4df54f89807c9ee2a ]
+
+Variable host_err is assigned a value that is never read, it is being
+re-assigned a value in every different execution path in the following
+switch statement. The assignment is redundant and can be removed.
+
+Cleans up clang-scan warning:
+warning: Value stored to 'host_err' is never read [deadcode.DeadStores]
+
+Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/vfs.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1317,7 +1317,6 @@ nfsd_create_locked(struct svc_rqst *rqst
+               iap->ia_mode &= ~current_umask();
+       err = 0;
+-      host_err = 0;
+       switch (type) {
+       case S_IFREG:
+               host_err = vfs_create(&init_user_ns, dirp, dchild, iap->ia_mode, true);
diff --git a/queue-6.1/nfsd-replace-delayed_work-with-work_struct-for-nfsd_client_shrinker.patch b/queue-6.1/nfsd-replace-delayed_work-with-work_struct-for-nfsd_client_shrinker.patch
new file mode 100644 (file)
index 0000000..6f6b261
--- /dev/null
@@ -0,0 +1,74 @@
+From da15771ea07c26181d5eece014d9336ff7ff6d07 Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Wed, 11 Jan 2023 16:06:51 -0800
+Subject: NFSD: replace delayed_work with work_struct for nfsd_client_shrinker
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit 7c24fa225081f31bc6da6a355c1ba801889ab29a ]
+
+Since nfsd4_state_shrinker_count always calls mod_delayed_work with
+0 delay, we can replace delayed_work with work_struct to save some
+space and overhead.
+
+Also add the call to cancel_work after unregister the shrinker
+in nfs4_state_shutdown_net.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/netns.h     |    2 +-
+ fs/nfsd/nfs4state.c |    8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -195,7 +195,7 @@ struct nfsd_net {
+       atomic_t                nfsd_courtesy_clients;
+       struct shrinker         nfsd_client_shrinker;
+-      struct delayed_work     nfsd_shrinker_work;
++      struct work_struct      nfsd_shrinker_work;
+ };
+ /* Simple check to find out if a given net was properly initialized */
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4412,7 +4412,7 @@ nfsd4_state_shrinker_count(struct shrink
+       if (!count)
+               count = atomic_long_read(&num_delegations);
+       if (count)
+-              mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0);
++              queue_work(laundry_wq, &nn->nfsd_shrinker_work);
+       return (unsigned long)count;
+ }
+@@ -6253,8 +6253,7 @@ deleg_reaper(struct nfsd_net *nn)
+ static void
+ nfsd4_state_shrinker_worker(struct work_struct *work)
+ {
+-      struct delayed_work *dwork = to_delayed_work(work);
+-      struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
++      struct nfsd_net *nn = container_of(work, struct nfsd_net,
+                               nfsd_shrinker_work);
+       courtesy_client_reaper(nn);
+@@ -8086,7 +8085,7 @@ static int nfs4_state_create_net(struct
+       INIT_LIST_HEAD(&nn->blocked_locks_lru);
+       INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
+-      INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
++      INIT_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
+       get_net(net);
+       nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
+@@ -8193,6 +8192,7 @@ nfs4_state_shutdown_net(struct net *net)
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       unregister_shrinker(&nn->nfsd_client_shrinker);
++      cancel_work(&nn->nfsd_shrinker_work);
+       cancel_delayed_work_sync(&nn->laundromat_work);
+       locks_end_grace(&nn->nfsd4_manager);
diff --git a/queue-6.1/nfsd-simplify-read_plus.patch b/queue-6.1/nfsd-simplify-read_plus.patch
new file mode 100644 (file)
index 0000000..a4ac086
--- /dev/null
@@ -0,0 +1,205 @@
+From 46a3747d8b4e5aa83a6f8cc8adbad5c1643a69a1 Mon Sep 17 00:00:00 2001
+From: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Date: Tue, 13 Sep 2022 14:01:51 -0400
+Subject: NFSD: Simplify READ_PLUS
+
+From: Anna Schumaker <Anna.Schumaker@Netapp.com>
+
+[ Upstream commit eeadcb75794516839078c28b3730132aeb700ce6 ]
+
+Chuck had suggested reverting READ_PLUS so it returns a single DATA
+segment covering the requested read range. This prepares the server for
+a future "sparse read" function so support can easily be added without
+needing to rip out the old READ_PLUS code at the same time.
+
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4xdr.c |  139 ++++++++++++------------------------------------------
+ 1 file changed, 32 insertions(+), 107 deletions(-)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -4777,79 +4777,37 @@ nfsd4_encode_offload_status(struct nfsd4
+ static __be32
+ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp,
+-                          struct nfsd4_read *read,
+-                          unsigned long *maxcount, u32 *eof,
+-                          loff_t *pos)
++                          struct nfsd4_read *read)
+ {
+-      struct xdr_stream *xdr = resp->xdr;
++      bool splice_ok = test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);
+       struct file *file = read->rd_nf->nf_file;
+-      int starting_len = xdr->buf->len;
+-      loff_t hole_pos;
+-      __be32 nfserr;
+-      __be32 *p, tmp;
+-      __be64 tmp64;
+-
+-      hole_pos = pos ? *pos : vfs_llseek(file, read->rd_offset, SEEK_HOLE);
+-      if (hole_pos > read->rd_offset)
+-              *maxcount = min_t(unsigned long, *maxcount, hole_pos - read->rd_offset);
+-      *maxcount = min_t(unsigned long, *maxcount, (xdr->buf->buflen - xdr->buf->len));
++      struct xdr_stream *xdr = resp->xdr;
++      unsigned long maxcount;
++      __be32 nfserr, *p;
+       /* Content type, offset, byte count */
+       p = xdr_reserve_space(xdr, 4 + 8 + 4);
+       if (!p)
+-              return nfserr_resource;
++              return nfserr_io;
++      if (resp->xdr->buf->page_len && splice_ok) {
++              WARN_ON_ONCE(splice_ok);
++              return nfserr_serverfault;
++      }
+-      read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, *maxcount);
+-      if (read->rd_vlen < 0)
+-              return nfserr_resource;
++      maxcount = min_t(unsigned long, read->rd_length,
++                       (xdr->buf->buflen - xdr->buf->len));
+-      nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
+-                          resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
++      if (file->f_op->splice_read && splice_ok)
++              nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
++      else
++              nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
+       if (nfserr)
+               return nfserr;
+-      xdr_truncate_encode(xdr, starting_len + 16 + xdr_align_size(*maxcount));
+-
+-      tmp = htonl(NFS4_CONTENT_DATA);
+-      write_bytes_to_xdr_buf(xdr->buf, starting_len,      &tmp,   4);
+-      tmp64 = cpu_to_be64(read->rd_offset);
+-      write_bytes_to_xdr_buf(xdr->buf, starting_len + 4,  &tmp64, 8);
+-      tmp = htonl(*maxcount);
+-      write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp,   4);
+-
+-      tmp = xdr_zero;
+-      write_bytes_to_xdr_buf(xdr->buf, starting_len + 16 + *maxcount, &tmp,
+-                             xdr_pad_size(*maxcount));
+-      return nfs_ok;
+-}
+-
+-static __be32
+-nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp,
+-                          struct nfsd4_read *read,
+-                          unsigned long *maxcount, u32 *eof)
+-{
+-      struct file *file = read->rd_nf->nf_file;
+-      loff_t data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA);
+-      loff_t f_size = i_size_read(file_inode(file));
+-      unsigned long count;
+-      __be32 *p;
+-
+-      if (data_pos == -ENXIO)
+-              data_pos = f_size;
+-      else if (data_pos <= read->rd_offset || (data_pos < f_size && data_pos % PAGE_SIZE))
+-              return nfsd4_encode_read_plus_data(resp, read, maxcount, eof, &f_size);
+-      count = data_pos - read->rd_offset;
+-      /* Content type, offset, byte count */
+-      p = xdr_reserve_space(resp->xdr, 4 + 8 + 8);
+-      if (!p)
+-              return nfserr_resource;
+-
+-      *p++ = htonl(NFS4_CONTENT_HOLE);
++      *p++ = cpu_to_be32(NFS4_CONTENT_DATA);
+       p = xdr_encode_hyper(p, read->rd_offset);
+-      p = xdr_encode_hyper(p, count);
++      *p = cpu_to_be32(read->rd_length);
+-      *eof = (read->rd_offset + count) >= f_size;
+-      *maxcount = min_t(unsigned long, count, *maxcount);
+       return nfs_ok;
+ }
+@@ -4857,69 +4815,36 @@ static __be32
+ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
+                      struct nfsd4_read *read)
+ {
+-      unsigned long maxcount, count;
++      struct file *file = read->rd_nf->nf_file;
+       struct xdr_stream *xdr = resp->xdr;
+-      struct file *file;
+       int starting_len = xdr->buf->len;
+-      int last_segment = xdr->buf->len;
+-      int segments = 0;
+-      __be32 *p, tmp;
+-      bool is_data;
+-      loff_t pos;
+-      u32 eof;
++      u32 segments = 0;
++      __be32 *p;
+       if (nfserr)
+               return nfserr;
+-      file = read->rd_nf->nf_file;
+       /* eof flag, segment count */
+       p = xdr_reserve_space(xdr, 4 + 4);
+       if (!p)
+-              return nfserr_resource;
++              return nfserr_io;
+       xdr_commit_encode(xdr);
+-      maxcount = min_t(unsigned long, read->rd_length,
+-                       (xdr->buf->buflen - xdr->buf->len));
+-      count    = maxcount;
+-
+-      eof = read->rd_offset >= i_size_read(file_inode(file));
+-      if (eof)
++      read->rd_eof = read->rd_offset >= i_size_read(file_inode(file));
++      if (read->rd_eof)
+               goto out;
+-      pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE);
+-      is_data = pos > read->rd_offset;
+-
+-      while (count > 0 && !eof) {
+-              maxcount = count;
+-              if (is_data)
+-                      nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof,
+-                                              segments == 0 ? &pos : NULL);
+-              else
+-                      nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof);
+-              if (nfserr)
+-                      goto out;
+-              count -= maxcount;
+-              read->rd_offset += maxcount;
+-              is_data = !is_data;
+-              last_segment = xdr->buf->len;
+-              segments++;
+-      }
+-
+-out:
+-      if (nfserr && segments == 0)
++      nfserr = nfsd4_encode_read_plus_data(resp, read);
++      if (nfserr) {
+               xdr_truncate_encode(xdr, starting_len);
+-      else {
+-              if (nfserr) {
+-                      xdr_truncate_encode(xdr, last_segment);
+-                      nfserr = nfs_ok;
+-                      eof = 0;
+-              }
+-              tmp = htonl(eof);
+-              write_bytes_to_xdr_buf(xdr->buf, starting_len,     &tmp, 4);
+-              tmp = htonl(segments);
+-              write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
++              return nfserr;
+       }
++      segments++;
++
++out:
++      p = xdr_encode_bool(p, read->rd_eof);
++      *p = cpu_to_be32(segments);
+       return nfserr;
+ }
diff --git a/queue-6.1/nfsd-trace-delegation-revocations.patch b/queue-6.1/nfsd-trace-delegation-revocations.patch
new file mode 100644 (file)
index 0000000..983e6d0
--- /dev/null
@@ -0,0 +1,103 @@
+From b41a2f6cb1d1aeea3275b6a96504ea5dc82b0012 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:09 -0400
+Subject: NFSD: Trace delegation revocations
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit a1c74569bbde91299f24535abf711be5c84df9de ]
+
+Delegation revocation is an exceptional event that is not otherwise
+visible externally (eg, no network traffic is emitted). Generate a
+trace record when it occurs so that revocation can be observed or
+other activity can be triggered. Example:
+
+nfsd-1104  [005]  1912.002544: nfsd_stid_revoke:        client 633c9343:4e82788d stateid 00000003:00000001 ref=2 type=DELEG
+
+Trace infrastructure is provided for subsequent additional tracing
+related to nfs4_stid activity.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    2 +
+ fs/nfsd/trace.h     |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 57 insertions(+)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1367,6 +1367,8 @@ static void revoke_delegation(struct nfs
+       WARN_ON(!list_empty(&dp->dl_recall_lru));
++      trace_nfsd_stid_revoke(&dp->dl_stid);
++
+       if (clp->cl_minorversion) {
+               spin_lock(&clp->cl_lock);
+               dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -637,6 +637,61 @@ DEFINE_EVENT(nfsd_stateseqid_class, nfsd
+ DEFINE_STATESEQID_EVENT(preprocess);
+ DEFINE_STATESEQID_EVENT(open_confirm);
++TRACE_DEFINE_ENUM(NFS4_OPEN_STID);
++TRACE_DEFINE_ENUM(NFS4_LOCK_STID);
++TRACE_DEFINE_ENUM(NFS4_DELEG_STID);
++TRACE_DEFINE_ENUM(NFS4_CLOSED_STID);
++TRACE_DEFINE_ENUM(NFS4_REVOKED_DELEG_STID);
++TRACE_DEFINE_ENUM(NFS4_CLOSED_DELEG_STID);
++TRACE_DEFINE_ENUM(NFS4_LAYOUT_STID);
++
++#define show_stid_type(x)                                             \
++      __print_flags(x, "|",                                           \
++              { NFS4_OPEN_STID,               "OPEN" },               \
++              { NFS4_LOCK_STID,               "LOCK" },               \
++              { NFS4_DELEG_STID,              "DELEG" },              \
++              { NFS4_CLOSED_STID,             "CLOSED" },             \
++              { NFS4_REVOKED_DELEG_STID,      "REVOKED" },            \
++              { NFS4_CLOSED_DELEG_STID,       "CLOSED_DELEG" },       \
++              { NFS4_LAYOUT_STID,             "LAYOUT" })
++
++DECLARE_EVENT_CLASS(nfsd_stid_class,
++      TP_PROTO(
++              const struct nfs4_stid *stid
++      ),
++      TP_ARGS(stid),
++      TP_STRUCT__entry(
++              __field(unsigned long, sc_type)
++              __field(int, sc_count)
++              __field(u32, cl_boot)
++              __field(u32, cl_id)
++              __field(u32, si_id)
++              __field(u32, si_generation)
++      ),
++      TP_fast_assign(
++              const stateid_t *stp = &stid->sc_stateid;
++
++              __entry->sc_type = stid->sc_type;
++              __entry->sc_count = refcount_read(&stid->sc_count);
++              __entry->cl_boot = stp->si_opaque.so_clid.cl_boot;
++              __entry->cl_id = stp->si_opaque.so_clid.cl_id;
++              __entry->si_id = stp->si_opaque.so_id;
++              __entry->si_generation = stp->si_generation;
++      ),
++      TP_printk("client %08x:%08x stateid %08x:%08x ref=%d type=%s",
++              __entry->cl_boot, __entry->cl_id,
++              __entry->si_id, __entry->si_generation,
++              __entry->sc_count, show_stid_type(__entry->sc_type)
++      )
++);
++
++#define DEFINE_STID_EVENT(name)                                       \
++DEFINE_EVENT(nfsd_stid_class, nfsd_stid_##name,                       \
++      TP_PROTO(const struct nfs4_stid *stid),                 \
++      TP_ARGS(stid))
++
++DEFINE_STID_EVENT(revoke);
++
+ DECLARE_EVENT_CLASS(nfsd_clientid_class,
+       TP_PROTO(const clientid_t *clid),
+       TP_ARGS(clid),
diff --git a/queue-6.1/nfsd-trace-stateids-returned-via-delegreturn.patch b/queue-6.1/nfsd-trace-stateids-returned-via-delegreturn.patch
new file mode 100644 (file)
index 0000000..76ad26e
--- /dev/null
@@ -0,0 +1,42 @@
+From 8bf3a8b39dca377e31a2fb35c6166bcd09e4c614 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:03 -0400
+Subject: NFSD: Trace stateids returned via DELEGRETURN
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 20eee313ff4b8a7e71ae9560f5c4ba27cd763005 ]
+
+Handing out a delegation stateid is recorded with the
+nfsd_deleg_read tracepoint, but there isn't a matching tracepoint
+for recording when the stateid is returned.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    1 +
+ fs/nfsd/trace.h     |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -6935,6 +6935,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp
+       if (status)
+               goto put_stateid;
++      trace_nfsd_deleg_return(stateid);
+       wake_up_var(d_inode(cstate->current_fh.fh_dentry));
+       destroy_delegation(dp);
+ put_stateid:
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -604,6 +604,7 @@ DEFINE_STATEID_EVENT(layout_recall_relea
+ DEFINE_STATEID_EVENT(open);
+ DEFINE_STATEID_EVENT(deleg_read);
++DEFINE_STATEID_EVENT(deleg_return);
+ DEFINE_STATEID_EVENT(deleg_recall);
+ DECLARE_EVENT_CLASS(nfsd_stateseqid_class,
diff --git a/queue-6.1/nfsd-update-file_hashtbl-helpers.patch b/queue-6.1/nfsd-update-file_hashtbl-helpers.patch
new file mode 100644 (file)
index 0000000..bce7a2e
--- /dev/null
@@ -0,0 +1,40 @@
+From 3ac41c7dc2312e3fd4ce27676c54c596f06981f4 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:22 -0400
+Subject: NFSD: Update file_hashtbl() helpers
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 3fe828caddd81e68e9d29353c6e9285a658ca056 ]
+
+Enable callers to use const pointers for type safety.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -721,7 +721,7 @@ static unsigned int ownerstr_hashval(str
+ #define FILE_HASH_BITS                   8
+ #define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
+-static unsigned int file_hashval(struct svc_fh *fh)
++static unsigned int file_hashval(const struct svc_fh *fh)
+ {
+       struct inode *inode = d_inode(fh->fh_dentry);
+@@ -4687,7 +4687,7 @@ move_to_close_lru(struct nfs4_ol_stateid
+ /* search file_hashtbl[] for file */
+ static struct nfs4_file *
+-find_file_locked(struct svc_fh *fh, unsigned int hashval)
++find_file_locked(const struct svc_fh *fh, unsigned int hashval)
+ {
+       struct nfs4_file *fp;
diff --git a/queue-6.1/nfsd-use-const-pointers-as-parameters-to-fh_-helpers.patch b/queue-6.1/nfsd-use-const-pointers-as-parameters-to-fh_-helpers.patch
new file mode 100644 (file)
index 0000000..0ee4a4a
--- /dev/null
@@ -0,0 +1,61 @@
+From 26e1bf703d792962a07841f94026324d690a938d Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:16 -0400
+Subject: NFSD: Use const pointers as parameters to fh_ helpers
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit b48f8056c034f28dd54668399f1d22be421b0bef ]
+
+Enable callers to use const pointers where they are able to.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfsfh.h |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/nfsd/nfsfh.h
++++ b/fs/nfsd/nfsfh.h
+@@ -220,7 +220,7 @@ __be32     fh_update(struct svc_fh *);
+ void  fh_put(struct svc_fh *);
+ static __inline__ struct svc_fh *
+-fh_copy(struct svc_fh *dst, struct svc_fh *src)
++fh_copy(struct svc_fh *dst, const struct svc_fh *src)
+ {
+       WARN_ON(src->fh_dentry);
+@@ -229,7 +229,7 @@ fh_copy(struct svc_fh *dst, struct svc_f
+ }
+ static inline void
+-fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
++fh_copy_shallow(struct knfsd_fh *dst, const struct knfsd_fh *src)
+ {
+       dst->fh_size = src->fh_size;
+       memcpy(&dst->fh_raw, &src->fh_raw, src->fh_size);
+@@ -243,7 +243,8 @@ fh_init(struct svc_fh *fhp, int maxsize)
+       return fhp;
+ }
+-static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
++static inline bool fh_match(const struct knfsd_fh *fh1,
++                          const struct knfsd_fh *fh2)
+ {
+       if (fh1->fh_size != fh2->fh_size)
+               return false;
+@@ -252,7 +253,8 @@ static inline bool fh_match(struct knfsd
+       return true;
+ }
+-static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
++static inline bool fh_fsid_match(const struct knfsd_fh *fh1,
++                               const struct knfsd_fh *fh2)
+ {
+       if (fh1->fh_fsid_type != fh2->fh_fsid_type)
+               return false;
diff --git a/queue-6.1/nfsd-use-locks_inode_context-helper.patch b/queue-6.1/nfsd-use-locks_inode_context-helper.patch
new file mode 100644 (file)
index 0000000..544f820
--- /dev/null
@@ -0,0 +1,51 @@
+From 38d71d411f45436b789a5db9bfeb814a049ea1d3 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 16 Nov 2022 09:36:07 -0500
+Subject: nfsd: use locks_inode_context helper
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 77c67530e1f95ac25c7075635f32f04367380894 ]
+
+nfsd currently doesn't access i_flctx safely everywhere. This requires a
+smp_load_acquire, as the pointer is set via cmpxchg (a release
+operation).
+
+Acked-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4784,7 +4784,7 @@ nfs4_share_conflict(struct svc_fh *curre
+ static bool nfsd4_deleg_present(const struct inode *inode)
+ {
+-      struct file_lock_context *ctx = smp_load_acquire(&inode->i_flctx);
++      struct file_lock_context *ctx = locks_inode_context(inode);
+       return ctx && !list_empty_careful(&ctx->flc_lease);
+ }
+@@ -5944,7 +5944,7 @@ nfs4_lockowner_has_blockers(struct nfs4_
+       list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) {
+               nf = stp->st_stid.sc_file;
+-              ctx = nf->fi_inode->i_flctx;
++              ctx = locks_inode_context(nf->fi_inode);
+               if (!ctx)
+                       continue;
+               if (locks_owner_has_blockers(ctx, lo))
+@@ -7761,7 +7761,7 @@ check_for_locks(struct nfs4_file *fp, st
+       }
+       inode = locks_inode(nf->nf_file);
+-      flctx = inode->i_flctx;
++      flctx = locks_inode_context(inode);
+       if (flctx && !list_empty_careful(&flctx->flc_posix)) {
+               spin_lock(&flctx->flc_lock);
diff --git a/queue-6.1/nfsd-use-only-rq_dropme-to-signal-the-need-to-drop-a-reply.patch b/queue-6.1/nfsd-use-only-rq_dropme-to-signal-the-need-to-drop-a-reply.patch
new file mode 100644 (file)
index 0000000..ef4167a
--- /dev/null
@@ -0,0 +1,53 @@
+From c719a184ac3261c27c996d0ca852456be53ed7b8 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 26 Nov 2022 15:55:30 -0500
+Subject: NFSD: Use only RQ_DROPME to signal the need to drop a reply
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9315564747cb6a570e99196b3a4880fb817635fd ]
+
+Clean up: NFSv2 has the only two usages of rpc_drop_reply in the
+NFSD code base. Since NFSv2 is going away at some point, replace
+these in order to simplify the "drop this reply?" check in
+nfsd_dispatch().
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfsproc.c |    4 ++--
+ fs/nfsd/nfssvc.c  |    2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -211,7 +211,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
+       if (resp->status == nfs_ok)
+               resp->status = fh_getattr(&resp->fh, &resp->stat);
+       else if (resp->status == nfserr_jukebox)
+-              return rpc_drop_reply;
++              __set_bit(RQ_DROPME, &rqstp->rq_flags);
+       return rpc_success;
+ }
+@@ -246,7 +246,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+       if (resp->status == nfs_ok)
+               resp->status = fh_getattr(&resp->fh, &resp->stat);
+       else if (resp->status == nfserr_jukebox)
+-              return rpc_drop_reply;
++              __set_bit(RQ_DROPME, &rqstp->rq_flags);
+       return rpc_success;
+ }
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -1071,7 +1071,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp
+       nfs_reply = xdr_inline_decode(&rqstp->rq_res_stream, 0);
+       *statp = proc->pc_func(rqstp);
+-      if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
++      if (test_bit(RQ_DROPME, &rqstp->rq_flags))
+               goto out_update_drop;
+       if (!proc->pc_encode(rqstp, &rqstp->rq_res_stream))
diff --git a/queue-6.1/nfsd-use-rhashtable-for-managing-nfs4_file-objects.patch b/queue-6.1/nfsd-use-rhashtable-for-managing-nfs4_file-objects.patch
new file mode 100644 (file)
index 0000000..307326f
--- /dev/null
@@ -0,0 +1,244 @@
+From d43d4bc06612be58600f8999e59dc569c0c45ca8 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 28 Oct 2022 10:47:53 -0400
+Subject: NFSD: Use rhashtable for managing nfs4_file objects
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit d47b295e8d76a4d69f0e2ea0cd8a79c9d3488280 ]
+
+fh_match() is costly, especially when filehandles are large (as is
+the case for NFSv4). It needs to be used sparingly when searching
+data structures. Unfortunately, with common workloads, I see
+multiple thousands of objects stored in file_hashtbl[], which has
+just 256 buckets, making its bucket hash chains quite lengthy.
+
+Walking long hash chains with the state_lock held blocks other
+activity that needs that lock. Sizable hash chains are a common
+occurrance once the server has handed out some delegations, for
+example -- IIUC, each delegated file is held open on the server by
+an nfs4_file object.
+
+To help mitigate the cost of searching with fh_match(), replace the
+nfs4_file hash table with an rhashtable, which can dynamically
+resize its bucket array to minimize hash chain length.
+
+The result of this modification is an improvement in the latency of
+NFSv4 operations, and the reduction of nfsd CPU utilization due to
+eliminating the cost of multiple calls to fh_match() and reducing
+the CPU cache misses incurred while walking long hash chains in the
+nfs4_file hash table.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   97 +++++++++++++++++++++++++++++++++-------------------
+ fs/nfsd/state.h     |    5 --
+ 2 files changed, 63 insertions(+), 39 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -44,7 +44,9 @@
+ #include <linux/jhash.h>
+ #include <linux/string_helpers.h>
+ #include <linux/fsnotify.h>
++#include <linux/rhashtable.h>
+ #include <linux/nfs_ssc.h>
++
+ #include "xdr4.h"
+ #include "xdr4cb.h"
+ #include "vfs.h"
+@@ -589,11 +591,8 @@ static void nfsd4_free_file_rcu(struct r
+ void
+ put_nfs4_file(struct nfs4_file *fi)
+ {
+-      might_lock(&state_lock);
+-
+-      if (refcount_dec_and_lock(&fi->fi_ref, &state_lock)) {
++      if (refcount_dec_and_test(&fi->fi_ref)) {
+               nfsd4_file_hash_remove(fi);
+-              spin_unlock(&state_lock);
+               WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
+               WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
+               call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu);
+@@ -718,19 +717,20 @@ static unsigned int ownerstr_hashval(str
+       return ret & OWNER_HASH_MASK;
+ }
+-/* hash table for nfs4_file */
+-#define FILE_HASH_BITS                   8
+-#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
+-
+-static unsigned int file_hashval(const struct svc_fh *fh)
+-{
+-      struct inode *inode = d_inode(fh->fh_dentry);
++static struct rhltable nfs4_file_rhltable ____cacheline_aligned_in_smp;
+-      /* XXX: why not (here & in file cache) use inode? */
+-      return (unsigned int)hash_long(inode->i_ino, FILE_HASH_BITS);
+-}
++static const struct rhashtable_params nfs4_file_rhash_params = {
++      .key_len                = sizeof_field(struct nfs4_file, fi_inode),
++      .key_offset             = offsetof(struct nfs4_file, fi_inode),
++      .head_offset            = offsetof(struct nfs4_file, fi_rlist),
+-static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
++      /*
++       * Start with a single page hash table to reduce resizing churn
++       * on light workloads.
++       */
++      .min_size               = 256,
++      .automatic_shrinking    = true,
++};
+ /*
+  * Check if courtesy clients have conflicting access and resolve it if possible
+@@ -4686,12 +4686,14 @@ move_to_close_lru(struct nfs4_ol_stateid
+ static noinline_for_stack struct nfs4_file *
+ nfsd4_file_hash_lookup(const struct svc_fh *fhp)
+ {
+-      unsigned int hashval = file_hashval(fhp);
++      struct inode *inode = d_inode(fhp->fh_dentry);
++      struct rhlist_head *tmp, *list;
+       struct nfs4_file *fi;
+       rcu_read_lock();
+-      hlist_for_each_entry_rcu(fi, &file_hashtbl[hashval], fi_hash,
+-                               lockdep_is_held(&state_lock)) {
++      list = rhltable_lookup(&nfs4_file_rhltable, &inode,
++                             nfs4_file_rhash_params);
++      rhl_for_each_entry_rcu(fi, tmp, list, fi_rlist) {
+               if (fh_match(&fi->fi_fhandle, &fhp->fh_handle)) {
+                       if (refcount_inc_not_zero(&fi->fi_ref)) {
+                               rcu_read_unlock();
+@@ -4705,40 +4707,56 @@ nfsd4_file_hash_lookup(const struct svc_
+ /*
+  * On hash insertion, identify entries with the same inode but
+- * distinct filehandles. They will all be in the same hash bucket
+- * because nfs4_file's are hashed by the address in the fi_inode
+- * field.
++ * distinct filehandles. They will all be on the list returned
++ * by rhltable_lookup().
++ *
++ * inode->i_lock prevents racing insertions from adding an entry
++ * for the same inode/fhp pair twice.
+  */
+ static noinline_for_stack struct nfs4_file *
+ nfsd4_file_hash_insert(struct nfs4_file *new, const struct svc_fh *fhp)
+ {
+-      unsigned int hashval = file_hashval(fhp);
++      struct inode *inode = d_inode(fhp->fh_dentry);
++      struct rhlist_head *tmp, *list;
+       struct nfs4_file *ret = NULL;
+       bool alias_found = false;
+       struct nfs4_file *fi;
++      int err;
+-      spin_lock(&state_lock);
+-      hlist_for_each_entry_rcu(fi, &file_hashtbl[hashval], fi_hash,
+-                               lockdep_is_held(&state_lock)) {
++      rcu_read_lock();
++      spin_lock(&inode->i_lock);
++
++      list = rhltable_lookup(&nfs4_file_rhltable, &inode,
++                             nfs4_file_rhash_params);
++      rhl_for_each_entry_rcu(fi, tmp, list, fi_rlist) {
+               if (fh_match(&fi->fi_fhandle, &fhp->fh_handle)) {
+                       if (refcount_inc_not_zero(&fi->fi_ref))
+                               ret = fi;
+-              } else if (d_inode(fhp->fh_dentry) == fi->fi_inode)
++              } else
+                       fi->fi_aliased = alias_found = true;
+       }
+-      if (likely(ret == NULL)) {
+-              nfsd4_file_init(fhp, new);
+-              hlist_add_head_rcu(&new->fi_hash, &file_hashtbl[hashval]);
+-              new->fi_aliased = alias_found;
+-              ret = new;
+-      }
+-      spin_unlock(&state_lock);
++      if (ret)
++              goto out_unlock;
++
++      nfsd4_file_init(fhp, new);
++      err = rhltable_insert(&nfs4_file_rhltable, &new->fi_rlist,
++                            nfs4_file_rhash_params);
++      if (err)
++              goto out_unlock;
++
++      new->fi_aliased = alias_found;
++      ret = new;
++
++out_unlock:
++      spin_unlock(&inode->i_lock);
++      rcu_read_unlock();
+       return ret;
+ }
+ static noinline_for_stack void nfsd4_file_hash_remove(struct nfs4_file *fi)
+ {
+-      hlist_del_rcu(&fi->fi_hash);
++      rhltable_remove(&nfs4_file_rhltable, &fi->fi_rlist,
++                      nfs4_file_rhash_params);
+ }
+ /*
+@@ -5648,6 +5666,8 @@ nfsd4_process_open2(struct svc_rqst *rqs
+        * If not found, create the nfs4_file struct
+        */
+       fp = nfsd4_file_hash_insert(open->op_file, current_fh);
++      if (unlikely(!fp))
++              return nfserr_jukebox;
+       if (fp != open->op_file) {
+               status = nfs4_check_deleg(cl, open, &dp);
+               if (status)
+@@ -8064,10 +8084,16 @@ nfs4_state_start(void)
+ {
+       int ret;
+-      ret = nfsd4_create_callback_queue();
++      ret = rhltable_init(&nfs4_file_rhltable, &nfs4_file_rhash_params);
+       if (ret)
+               return ret;
++      ret = nfsd4_create_callback_queue();
++      if (ret) {
++              rhltable_destroy(&nfs4_file_rhltable);
++              return ret;
++      }
++
+       set_max_delegations();
+       return 0;
+ }
+@@ -8098,6 +8124,7 @@ nfs4_state_shutdown_net(struct net *net)
+       nfsd4_client_tracking_exit(net);
+       nfs4_state_destroy_net(net);
++      rhltable_destroy(&nfs4_file_rhltable);
+ #ifdef CONFIG_NFSD_V4_2_INTER_SSC
+       nfsd4_ssc_shutdown_umount(nn);
+ #endif
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -536,16 +536,13 @@ struct nfs4_clnt_odstate {
+  * inode can have multiple filehandles associated with it, so there is
+  * (potentially) a many to one relationship between this struct and struct
+  * inode.
+- *
+- * These are hashed by filehandle in the file_hashtbl, which is protected by
+- * the global state_lock spinlock.
+  */
+ struct nfs4_file {
+       refcount_t              fi_ref;
+       struct inode *          fi_inode;
+       bool                    fi_aliased;
+       spinlock_t              fi_lock;
+-      struct hlist_node       fi_hash;        /* hash on fi_fhandle */
++      struct rhlist_head      fi_rlist;
+       struct list_head        fi_stateids;
+       union {
+               struct list_head        fi_delegations;
diff --git a/queue-6.1/nfsd-use-set_bit-rq_dropme.patch b/queue-6.1/nfsd-use-set_bit-rq_dropme.patch
new file mode 100644 (file)
index 0000000..18de91a
--- /dev/null
@@ -0,0 +1,41 @@
+From a84e0f59363de87491392d26c0b8a61993276898 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 7 Jan 2023 10:15:35 -0500
+Subject: NFSD: Use set_bit(RQ_DROPME)
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 5304930dbae82d259bcf7e5611db7c81e7a42eff ]
+
+The premise that "Once an svc thread is scheduled and executing an
+RPC, no other processes will touch svc_rqst::rq_flags" is false.
+svc_xprt_enqueue() examines the RQ_BUSY flag in scheduled nfsd
+threads when determining which thread to wake up next.
+
+Fixes: 9315564747cb ("NFSD: Use only RQ_DROPME to signal the need to drop a reply")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfsproc.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -211,7 +211,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
+       if (resp->status == nfs_ok)
+               resp->status = fh_getattr(&resp->fh, &resp->stat);
+       else if (resp->status == nfserr_jukebox)
+-              __set_bit(RQ_DROPME, &rqstp->rq_flags);
++              set_bit(RQ_DROPME, &rqstp->rq_flags);
+       return rpc_success;
+ }
+@@ -246,7 +246,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+       if (resp->status == nfs_ok)
+               resp->status = fh_getattr(&resp->fh, &resp->stat);
+       else if (resp->status == nfserr_jukebox)
+-              __set_bit(RQ_DROPME, &rqstp->rq_flags);
++              set_bit(RQ_DROPME, &rqstp->rq_flags);
+       return rpc_success;
+ }
diff --git a/queue-6.1/nfsd-use-struct_size-helper-in-alloc_session.patch b/queue-6.1/nfsd-use-struct_size-helper-in-alloc_session.patch
new file mode 100644 (file)
index 0000000..cc02fc3
--- /dev/null
@@ -0,0 +1,39 @@
+From dd2b71cd068ca2cad01164b0500faae1dc607005 Mon Sep 17 00:00:00 2001
+From: Xiu Jianfeng <xiujianfeng@huawei.com>
+Date: Fri, 11 Nov 2022 17:18:35 +0800
+Subject: NFSD: Use struct_size() helper in alloc_session()
+
+From: Xiu Jianfeng <xiujianfeng@huawei.com>
+
+[ Upstream commit 85a0d0c9a58002ef7d1bf5e3ea630f4fbd42a4f0 ]
+
+Use struct_size() helper to simplify the code, no functional changes.
+
+Signed-off-by: Xiu Jianfeng <xiujianfeng@huawei.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1834,13 +1834,12 @@ static struct nfsd4_session *alloc_sessi
+       int numslots = fattrs->maxreqs;
+       int slotsize = slot_bytes(fattrs);
+       struct nfsd4_session *new;
+-      int mem, i;
++      int i;
+-      BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
+-                      + sizeof(struct nfsd4_session) > PAGE_SIZE);
+-      mem = numslots * sizeof(struct nfsd4_slot *);
++      BUILD_BUG_ON(struct_size(new, se_slots, NFSD_MAX_SLOTS_PER_SESSION)
++                   > PAGE_SIZE);
+-      new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
++      new = kzalloc(struct_size(new, se_slots, numslots), GFP_KERNEL);
+       if (!new)
+               return NULL;
+       /* allocate each struct nfsd4_slot and data cache in one piece */
index c56397b0b3edeeb34cb7f652b5ae2dfedd4b7bf1..c8819c120b667b500ec005a818628aef76c23377 100644 (file)
@@ -141,3 +141,40 @@ x86-decompressor-move-global-symbol-references-to-c-code.patch
 decompress-use-8-byte-alignment.patch
 drm-amd-display-increase-frame-warning-limit-with-kasan-or-kcsan-in-dml.patch
 nfs-fix-data-corruption-caused-by-congestion.patch
+nfsd-simplify-read_plus.patch
+nfsd-remove-redundant-assignment-to-variable-host_err.patch
+nfsd-ignore-requests-to-disable-unsupported-versions.patch
+nfsd-move-nfserrno-to-vfs.c.patch
+nfsd-allow-disabling-nfsv2-at-compile-time.patch
+exportfs-use-pr_debug-for-unreachable-debug-statements.patch
+nfsd-flesh-out-a-documenting-comment-for-filecache.c.patch
+nfsd-clean-up-nfs4_preprocess_stateid_op-call-sites.patch
+nfsd-trace-stateids-returned-via-delegreturn.patch
+nfsd-trace-delegation-revocations.patch
+nfsd-use-const-pointers-as-parameters-to-fh_-helpers.patch
+nfsd-update-file_hashtbl-helpers.patch
+nfsd-clean-up-nfsd4_init_file.patch
+nfsd-add-a-nfsd4_file_hash_remove-helper.patch
+nfsd-clean-up-find_or_add_file.patch
+nfsd-refactor-find_file.patch
+nfsd-use-rhashtable-for-managing-nfs4_file-objects.patch
+nfsd-fix-licensing-header-in-filecache.c.patch
+filelock-add-a-new-locks_inode_context-accessor-function.patch
+lockd-use-locks_inode_context-helper.patch
+nfsd-use-locks_inode_context-helper.patch
+nfsd-fix-up-the-filecache-laundrette-scheduling.patch
+nfsd-use-struct_size-helper-in-alloc_session.patch
+lockd-set-missing-fl_flags-field-when-retrieving-args.patch
+lockd-ensure-we-use-the-correct-file-descriptor-when-unlocking.patch
+lockd-fix-file-selection-in-nlmsvc_cancel_blocked.patch
+trace-relocate-event-helper-files.patch
+nfsd-refactoring-courtesy_client_reaper-to-a-generic-low-memory-shrinker.patch
+nfsd-add-support-for-sending-cb_recall_any.patch
+nfsd-add-delegation-reaper-to-react-to-low-memory-condition.patch
+nfsd-add-cb_recall_any-tracepoints.patch
+nfsd-use-only-rq_dropme-to-signal-the-need-to-drop-a-reply.patch
+nfsd-avoid-clashing-function-prototypes.patch
+nfsd-use-set_bit-rq_dropme.patch
+nfsd-register-unregister-of-nfsd-client-shrinker-at-nfsd-startup-shutdown-time.patch
+nfsd-replace-delayed_work-with-work_struct-for-nfsd_client_shrinker.patch
+nfsd-don-t-destroy-global-nfs4_file-table-in-per-net-shutdown.patch
diff --git a/queue-6.1/trace-relocate-event-helper-files.patch b/queue-6.1/trace-relocate-event-helper-files.patch
new file mode 100644 (file)
index 0000000..34ee35f
--- /dev/null
@@ -0,0 +1,1559 @@
+From 9611f3b43fd527f64ebd2a6620268096affc46e8 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Mon, 14 Nov 2022 08:57:43 -0500
+Subject: trace: Relocate event helper files
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 247c01ff5f8d66e62a404c91733be52fecb8b7f6 ]
+
+Steven Rostedt says:
+> The include/trace/events/ directory should only hold files that
+> are to create events, not headers that hold helper functions.
+>
+> Can you please move them out of include/trace/events/ as that
+> directory is "special" in the creation of events.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Acked-by: Leon Romanovsky <leonro@nvidia.com>
+Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Acked-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Stable-dep-of: 638593be55c0 ("NFSD: add CB_RECALL_ANY tracepoints")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS                                           | 7 +++++++
+ drivers/infiniband/core/cm_trace.h                    | 2 +-
+ drivers/infiniband/core/cma_trace.h                   | 2 +-
+ fs/nfs/nfs4trace.h                                    | 6 +++---
+ fs/nfs/nfstrace.h                                     | 6 +++---
+ include/trace/events/rpcgss.h                         | 2 +-
+ include/trace/events/rpcrdma.h                        | 4 ++--
+ include/trace/events/sunrpc.h                         | 2 +-
+ include/trace/{events => misc}/fs.h                   | 0
+ include/trace/{events => misc}/nfs.h                  | 0
+ include/trace/{events => misc}/rdma.h                 | 0
+ include/trace/{events/sunrpc_base.h => misc/sunrpc.h} | 0
+ MAINTAINERS                         |    7 
+ drivers/infiniband/core/cm_trace.h  |    2 
+ drivers/infiniband/core/cma_trace.h |    2 
+ fs/nfs/nfs4trace.h                  |    6 
+ fs/nfs/nfstrace.h                   |    6 
+ include/trace/events/fs.h           |  122 -----------
+ include/trace/events/nfs.h          |  375 ------------------------------------
+ include/trace/events/rdma.h         |  168 ----------------
+ include/trace/events/rpcgss.h       |    2 
+ include/trace/events/rpcrdma.h      |    4 
+ include/trace/events/sunrpc.h       |    2 
+ include/trace/events/sunrpc_base.h  |   18 -
+ include/trace/misc/fs.h             |  122 +++++++++++
+ include/trace/misc/nfs.h            |  375 ++++++++++++++++++++++++++++++++++++
+ include/trace/misc/rdma.h           |  168 ++++++++++++++++
+ include/trace/misc/sunrpc.h         |   18 +
+ 16 files changed, 702 insertions(+), 695 deletions(-)
+ rename include/trace/{events => misc}/fs.h (100%)
+ rename include/trace/{events => misc}/nfs.h (100%)
+ rename include/trace/{events => misc}/rdma.h (100%)
+ rename include/trace/{events/sunrpc_base.h => misc/sunrpc.h} (100%)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -10051,6 +10051,7 @@ F:     drivers/infiniband/
+ F:    include/rdma/
+ F:    include/trace/events/ib_mad.h
+ F:    include/trace/events/ib_umad.h
++F:    include/trace/misc/rdma.h
+ F:    include/uapi/linux/if_infiniband.h
+ F:    include/uapi/rdma/
+ F:    samples/bpf/ibumad_kern.c
+@@ -11139,6 +11140,12 @@ F:    fs/nfs_common/
+ F:    fs/nfsd/
+ F:    include/linux/lockd/
+ F:    include/linux/sunrpc/
++F:    include/trace/events/rpcgss.h
++F:    include/trace/events/rpcrdma.h
++F:    include/trace/events/sunrpc.h
++F:    include/trace/misc/fs.h
++F:    include/trace/misc/nfs.h
++F:    include/trace/misc/sunrpc.h
+ F:    include/uapi/linux/nfsd/
+ F:    include/uapi/linux/sunrpc/
+ F:    net/sunrpc/
+--- a/drivers/infiniband/core/cm_trace.h
++++ b/drivers/infiniband/core/cm_trace.h
+@@ -16,7 +16,7 @@
+ #include <linux/tracepoint.h>
+ #include <rdma/ib_cm.h>
+-#include <trace/events/rdma.h>
++#include <trace/misc/rdma.h>
+ /*
+  * enum ib_cm_state, from include/rdma/ib_cm.h
+--- a/drivers/infiniband/core/cma_trace.h
++++ b/drivers/infiniband/core/cma_trace.h
+@@ -15,7 +15,7 @@
+ #define _TRACE_RDMA_CMA_H
+ #include <linux/tracepoint.h>
+-#include <trace/events/rdma.h>
++#include <trace/misc/rdma.h>
+ DECLARE_EVENT_CLASS(cma_fsm_class,
+--- a/fs/nfs/nfs4trace.h
++++ b/fs/nfs/nfs4trace.h
+@@ -9,10 +9,10 @@
+ #define _TRACE_NFS4_H
+ #include <linux/tracepoint.h>
+-#include <trace/events/sunrpc_base.h>
++#include <trace/misc/sunrpc.h>
+-#include <trace/events/fs.h>
+-#include <trace/events/nfs.h>
++#include <trace/misc/fs.h>
++#include <trace/misc/nfs.h>
+ #define show_nfs_fattr_flags(valid) \
+       __print_flags((unsigned long)valid, "|", \
+--- a/fs/nfs/nfstrace.h
++++ b/fs/nfs/nfstrace.h
+@@ -11,9 +11,9 @@
+ #include <linux/tracepoint.h>
+ #include <linux/iversion.h>
+-#include <trace/events/fs.h>
+-#include <trace/events/nfs.h>
+-#include <trace/events/sunrpc_base.h>
++#include <trace/misc/fs.h>
++#include <trace/misc/nfs.h>
++#include <trace/misc/sunrpc.h>
+ #define nfs_show_cache_validity(v) \
+       __print_flags(v, "|", \
+--- a/include/trace/events/fs.h
++++ /dev/null
+@@ -1,122 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Display helpers for generic filesystem items
+- *
+- * Author: Chuck Lever <chuck.lever@oracle.com>
+- *
+- * Copyright (c) 2020, Oracle and/or its affiliates.
+- */
+-
+-#include <linux/fs.h>
+-
+-#define show_fs_dirent_type(x) \
+-      __print_symbolic(x, \
+-              { DT_UNKNOWN,           "UNKNOWN" }, \
+-              { DT_FIFO,              "FIFO" }, \
+-              { DT_CHR,               "CHR" }, \
+-              { DT_DIR,               "DIR" }, \
+-              { DT_BLK,               "BLK" }, \
+-              { DT_REG,               "REG" }, \
+-              { DT_LNK,               "LNK" }, \
+-              { DT_SOCK,              "SOCK" }, \
+-              { DT_WHT,               "WHT" })
+-
+-#define show_fs_fcntl_open_flags(x) \
+-      __print_flags(x, "|", \
+-              { O_WRONLY,             "O_WRONLY" }, \
+-              { O_RDWR,               "O_RDWR" }, \
+-              { O_CREAT,              "O_CREAT" }, \
+-              { O_EXCL,               "O_EXCL" }, \
+-              { O_NOCTTY,             "O_NOCTTY" }, \
+-              { O_TRUNC,              "O_TRUNC" }, \
+-              { O_APPEND,             "O_APPEND" }, \
+-              { O_NONBLOCK,           "O_NONBLOCK" }, \
+-              { O_DSYNC,              "O_DSYNC" }, \
+-              { O_DIRECT,             "O_DIRECT" }, \
+-              { O_LARGEFILE,          "O_LARGEFILE" }, \
+-              { O_DIRECTORY,          "O_DIRECTORY" }, \
+-              { O_NOFOLLOW,           "O_NOFOLLOW" }, \
+-              { O_NOATIME,            "O_NOATIME" }, \
+-              { O_CLOEXEC,            "O_CLOEXEC" })
+-
+-#define __fmode_flag(x)       { (__force unsigned long)FMODE_##x, #x }
+-#define show_fs_fmode_flags(x) \
+-      __print_flags(x, "|", \
+-              __fmode_flag(READ), \
+-              __fmode_flag(WRITE), \
+-              __fmode_flag(EXEC))
+-
+-#ifdef CONFIG_64BIT
+-#define show_fs_fcntl_cmd(x) \
+-      __print_symbolic(x, \
+-              { F_DUPFD,              "DUPFD" }, \
+-              { F_GETFD,              "GETFD" }, \
+-              { F_SETFD,              "SETFD" }, \
+-              { F_GETFL,              "GETFL" }, \
+-              { F_SETFL,              "SETFL" }, \
+-              { F_GETLK,              "GETLK" }, \
+-              { F_SETLK,              "SETLK" }, \
+-              { F_SETLKW,             "SETLKW" }, \
+-              { F_SETOWN,             "SETOWN" }, \
+-              { F_GETOWN,             "GETOWN" }, \
+-              { F_SETSIG,             "SETSIG" }, \
+-              { F_GETSIG,             "GETSIG" }, \
+-              { F_SETOWN_EX,          "SETOWN_EX" }, \
+-              { F_GETOWN_EX,          "GETOWN_EX" }, \
+-              { F_GETOWNER_UIDS,      "GETOWNER_UIDS" }, \
+-              { F_OFD_GETLK,          "OFD_GETLK" }, \
+-              { F_OFD_SETLK,          "OFD_SETLK" }, \
+-              { F_OFD_SETLKW,         "OFD_SETLKW" })
+-#else /* CONFIG_64BIT */
+-#define show_fs_fcntl_cmd(x) \
+-      __print_symbolic(x, \
+-              { F_DUPFD,              "DUPFD" }, \
+-              { F_GETFD,              "GETFD" }, \
+-              { F_SETFD,              "SETFD" }, \
+-              { F_GETFL,              "GETFL" }, \
+-              { F_SETFL,              "SETFL" }, \
+-              { F_GETLK,              "GETLK" }, \
+-              { F_SETLK,              "SETLK" }, \
+-              { F_SETLKW,             "SETLKW" }, \
+-              { F_SETOWN,             "SETOWN" }, \
+-              { F_GETOWN,             "GETOWN" }, \
+-              { F_SETSIG,             "SETSIG" }, \
+-              { F_GETSIG,             "GETSIG" }, \
+-              { F_GETLK64,            "GETLK64" }, \
+-              { F_SETLK64,            "SETLK64" }, \
+-              { F_SETLKW64,           "SETLKW64" }, \
+-              { F_SETOWN_EX,          "SETOWN_EX" }, \
+-              { F_GETOWN_EX,          "GETOWN_EX" }, \
+-              { F_GETOWNER_UIDS,      "GETOWNER_UIDS" }, \
+-              { F_OFD_GETLK,          "OFD_GETLK" }, \
+-              { F_OFD_SETLK,          "OFD_SETLK" }, \
+-              { F_OFD_SETLKW,         "OFD_SETLKW" })
+-#endif /* CONFIG_64BIT */
+-
+-#define show_fs_fcntl_lock_type(x) \
+-      __print_symbolic(x, \
+-              { F_RDLCK,              "RDLCK" }, \
+-              { F_WRLCK,              "WRLCK" }, \
+-              { F_UNLCK,              "UNLCK" })
+-
+-#define show_fs_lookup_flags(flags) \
+-      __print_flags(flags, "|", \
+-              { LOOKUP_FOLLOW,        "FOLLOW" }, \
+-              { LOOKUP_DIRECTORY,     "DIRECTORY" }, \
+-              { LOOKUP_AUTOMOUNT,     "AUTOMOUNT" }, \
+-              { LOOKUP_EMPTY,         "EMPTY" }, \
+-              { LOOKUP_DOWN,          "DOWN" }, \
+-              { LOOKUP_MOUNTPOINT,    "MOUNTPOINT" }, \
+-              { LOOKUP_REVAL,         "REVAL" }, \
+-              { LOOKUP_RCU,           "RCU" }, \
+-              { LOOKUP_OPEN,          "OPEN" }, \
+-              { LOOKUP_CREATE,        "CREATE" }, \
+-              { LOOKUP_EXCL,          "EXCL" }, \
+-              { LOOKUP_RENAME_TARGET, "RENAME_TARGET" }, \
+-              { LOOKUP_PARENT,        "PARENT" }, \
+-              { LOOKUP_NO_SYMLINKS,   "NO_SYMLINKS" }, \
+-              { LOOKUP_NO_MAGICLINKS, "NO_MAGICLINKS" }, \
+-              { LOOKUP_NO_XDEV,       "NO_XDEV" }, \
+-              { LOOKUP_BENEATH,       "BENEATH" }, \
+-              { LOOKUP_IN_ROOT,       "IN_ROOT" }, \
+-              { LOOKUP_CACHED,        "CACHED" })
+--- a/include/trace/events/nfs.h
++++ /dev/null
+@@ -1,375 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Display helpers for NFS protocol elements
+- *
+- * Author: Chuck Lever <chuck.lever@oracle.com>
+- *
+- * Copyright (c) 2020, Oracle and/or its affiliates.
+- */
+-
+-#include <linux/nfs.h>
+-#include <linux/nfs4.h>
+-#include <uapi/linux/nfs.h>
+-
+-TRACE_DEFINE_ENUM(NFS_OK);
+-TRACE_DEFINE_ENUM(NFSERR_PERM);
+-TRACE_DEFINE_ENUM(NFSERR_NOENT);
+-TRACE_DEFINE_ENUM(NFSERR_IO);
+-TRACE_DEFINE_ENUM(NFSERR_NXIO);
+-TRACE_DEFINE_ENUM(NFSERR_EAGAIN);
+-TRACE_DEFINE_ENUM(NFSERR_ACCES);
+-TRACE_DEFINE_ENUM(NFSERR_EXIST);
+-TRACE_DEFINE_ENUM(NFSERR_XDEV);
+-TRACE_DEFINE_ENUM(NFSERR_NODEV);
+-TRACE_DEFINE_ENUM(NFSERR_NOTDIR);
+-TRACE_DEFINE_ENUM(NFSERR_ISDIR);
+-TRACE_DEFINE_ENUM(NFSERR_INVAL);
+-TRACE_DEFINE_ENUM(NFSERR_FBIG);
+-TRACE_DEFINE_ENUM(NFSERR_NOSPC);
+-TRACE_DEFINE_ENUM(NFSERR_ROFS);
+-TRACE_DEFINE_ENUM(NFSERR_MLINK);
+-TRACE_DEFINE_ENUM(NFSERR_OPNOTSUPP);
+-TRACE_DEFINE_ENUM(NFSERR_NAMETOOLONG);
+-TRACE_DEFINE_ENUM(NFSERR_NOTEMPTY);
+-TRACE_DEFINE_ENUM(NFSERR_DQUOT);
+-TRACE_DEFINE_ENUM(NFSERR_STALE);
+-TRACE_DEFINE_ENUM(NFSERR_REMOTE);
+-TRACE_DEFINE_ENUM(NFSERR_WFLUSH);
+-TRACE_DEFINE_ENUM(NFSERR_BADHANDLE);
+-TRACE_DEFINE_ENUM(NFSERR_NOT_SYNC);
+-TRACE_DEFINE_ENUM(NFSERR_BAD_COOKIE);
+-TRACE_DEFINE_ENUM(NFSERR_NOTSUPP);
+-TRACE_DEFINE_ENUM(NFSERR_TOOSMALL);
+-TRACE_DEFINE_ENUM(NFSERR_SERVERFAULT);
+-TRACE_DEFINE_ENUM(NFSERR_BADTYPE);
+-TRACE_DEFINE_ENUM(NFSERR_JUKEBOX);
+-
+-#define show_nfs_status(x) \
+-      __print_symbolic(x, \
+-              { NFS_OK,                       "OK" }, \
+-              { NFSERR_PERM,                  "PERM" }, \
+-              { NFSERR_NOENT,                 "NOENT" }, \
+-              { NFSERR_IO,                    "IO" }, \
+-              { NFSERR_NXIO,                  "NXIO" }, \
+-              { ECHILD,                       "CHILD" }, \
+-              { NFSERR_EAGAIN,                "AGAIN" }, \
+-              { NFSERR_ACCES,                 "ACCES" }, \
+-              { NFSERR_EXIST,                 "EXIST" }, \
+-              { NFSERR_XDEV,                  "XDEV" }, \
+-              { NFSERR_NODEV,                 "NODEV" }, \
+-              { NFSERR_NOTDIR,                "NOTDIR" }, \
+-              { NFSERR_ISDIR,                 "ISDIR" }, \
+-              { NFSERR_INVAL,                 "INVAL" }, \
+-              { NFSERR_FBIG,                  "FBIG" }, \
+-              { NFSERR_NOSPC,                 "NOSPC" }, \
+-              { NFSERR_ROFS,                  "ROFS" }, \
+-              { NFSERR_MLINK,                 "MLINK" }, \
+-              { NFSERR_OPNOTSUPP,             "OPNOTSUPP" }, \
+-              { NFSERR_NAMETOOLONG,           "NAMETOOLONG" }, \
+-              { NFSERR_NOTEMPTY,              "NOTEMPTY" }, \
+-              { NFSERR_DQUOT,                 "DQUOT" }, \
+-              { NFSERR_STALE,                 "STALE" }, \
+-              { NFSERR_REMOTE,                "REMOTE" }, \
+-              { NFSERR_WFLUSH,                "WFLUSH" }, \
+-              { NFSERR_BADHANDLE,             "BADHANDLE" }, \
+-              { NFSERR_NOT_SYNC,              "NOTSYNC" }, \
+-              { NFSERR_BAD_COOKIE,            "BADCOOKIE" }, \
+-              { NFSERR_NOTSUPP,               "NOTSUPP" }, \
+-              { NFSERR_TOOSMALL,              "TOOSMALL" }, \
+-              { NFSERR_SERVERFAULT,           "REMOTEIO" }, \
+-              { NFSERR_BADTYPE,               "BADTYPE" }, \
+-              { NFSERR_JUKEBOX,               "JUKEBOX" })
+-
+-TRACE_DEFINE_ENUM(NFS_UNSTABLE);
+-TRACE_DEFINE_ENUM(NFS_DATA_SYNC);
+-TRACE_DEFINE_ENUM(NFS_FILE_SYNC);
+-
+-#define show_nfs_stable_how(x) \
+-      __print_symbolic(x, \
+-              { NFS_UNSTABLE,                 "UNSTABLE" }, \
+-              { NFS_DATA_SYNC,                "DATA_SYNC" }, \
+-              { NFS_FILE_SYNC,                "FILE_SYNC" })
+-
+-TRACE_DEFINE_ENUM(NFS4_OK);
+-TRACE_DEFINE_ENUM(NFS4ERR_ACCESS);
+-TRACE_DEFINE_ENUM(NFS4ERR_ATTRNOTSUPP);
+-TRACE_DEFINE_ENUM(NFS4ERR_ADMIN_REVOKED);
+-TRACE_DEFINE_ENUM(NFS4ERR_BACK_CHAN_BUSY);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADCHAR);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADHANDLE);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADIOMODE);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADLAYOUT);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADLABEL);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADNAME);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADOWNER);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADSESSION);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADSLOT);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADTYPE);
+-TRACE_DEFINE_ENUM(NFS4ERR_BADXDR);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_COOKIE);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_HIGH_SLOT);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_RANGE);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_SEQID);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_SESSION_DIGEST);
+-TRACE_DEFINE_ENUM(NFS4ERR_BAD_STATEID);
+-TRACE_DEFINE_ENUM(NFS4ERR_CB_PATH_DOWN);
+-TRACE_DEFINE_ENUM(NFS4ERR_CLID_INUSE);
+-TRACE_DEFINE_ENUM(NFS4ERR_CLIENTID_BUSY);
+-TRACE_DEFINE_ENUM(NFS4ERR_COMPLETE_ALREADY);
+-TRACE_DEFINE_ENUM(NFS4ERR_CONN_NOT_BOUND_TO_SESSION);
+-TRACE_DEFINE_ENUM(NFS4ERR_DEADLOCK);
+-TRACE_DEFINE_ENUM(NFS4ERR_DEADSESSION);
+-TRACE_DEFINE_ENUM(NFS4ERR_DELAY);
+-TRACE_DEFINE_ENUM(NFS4ERR_DELEG_ALREADY_WANTED);
+-TRACE_DEFINE_ENUM(NFS4ERR_DELEG_REVOKED);
+-TRACE_DEFINE_ENUM(NFS4ERR_DENIED);
+-TRACE_DEFINE_ENUM(NFS4ERR_DIRDELEG_UNAVAIL);
+-TRACE_DEFINE_ENUM(NFS4ERR_DQUOT);
+-TRACE_DEFINE_ENUM(NFS4ERR_ENCR_ALG_UNSUPP);
+-TRACE_DEFINE_ENUM(NFS4ERR_EXIST);
+-TRACE_DEFINE_ENUM(NFS4ERR_EXPIRED);
+-TRACE_DEFINE_ENUM(NFS4ERR_FBIG);
+-TRACE_DEFINE_ENUM(NFS4ERR_FHEXPIRED);
+-TRACE_DEFINE_ENUM(NFS4ERR_FILE_OPEN);
+-TRACE_DEFINE_ENUM(NFS4ERR_GRACE);
+-TRACE_DEFINE_ENUM(NFS4ERR_HASH_ALG_UNSUPP);
+-TRACE_DEFINE_ENUM(NFS4ERR_INVAL);
+-TRACE_DEFINE_ENUM(NFS4ERR_IO);
+-TRACE_DEFINE_ENUM(NFS4ERR_ISDIR);
+-TRACE_DEFINE_ENUM(NFS4ERR_LAYOUTTRYLATER);
+-TRACE_DEFINE_ENUM(NFS4ERR_LAYOUTUNAVAILABLE);
+-TRACE_DEFINE_ENUM(NFS4ERR_LEASE_MOVED);
+-TRACE_DEFINE_ENUM(NFS4ERR_LOCKED);
+-TRACE_DEFINE_ENUM(NFS4ERR_LOCKS_HELD);
+-TRACE_DEFINE_ENUM(NFS4ERR_LOCK_RANGE);
+-TRACE_DEFINE_ENUM(NFS4ERR_MINOR_VERS_MISMATCH);
+-TRACE_DEFINE_ENUM(NFS4ERR_MLINK);
+-TRACE_DEFINE_ENUM(NFS4ERR_MOVED);
+-TRACE_DEFINE_ENUM(NFS4ERR_NAMETOOLONG);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOENT);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOFILEHANDLE);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOMATCHING_LAYOUT);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOSPC);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOTDIR);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOTEMPTY);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOTSUPP);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOT_ONLY_OP);
+-TRACE_DEFINE_ENUM(NFS4ERR_NOT_SAME);
+-TRACE_DEFINE_ENUM(NFS4ERR_NO_GRACE);
+-TRACE_DEFINE_ENUM(NFS4ERR_NXIO);
+-TRACE_DEFINE_ENUM(NFS4ERR_OLD_STATEID);
+-TRACE_DEFINE_ENUM(NFS4ERR_OPENMODE);
+-TRACE_DEFINE_ENUM(NFS4ERR_OP_ILLEGAL);
+-TRACE_DEFINE_ENUM(NFS4ERR_OP_NOT_IN_SESSION);
+-TRACE_DEFINE_ENUM(NFS4ERR_PERM);
+-TRACE_DEFINE_ENUM(NFS4ERR_PNFS_IO_HOLE);
+-TRACE_DEFINE_ENUM(NFS4ERR_PNFS_NO_LAYOUT);
+-TRACE_DEFINE_ENUM(NFS4ERR_RECALLCONFLICT);
+-TRACE_DEFINE_ENUM(NFS4ERR_RECLAIM_BAD);
+-TRACE_DEFINE_ENUM(NFS4ERR_RECLAIM_CONFLICT);
+-TRACE_DEFINE_ENUM(NFS4ERR_REJECT_DELEG);
+-TRACE_DEFINE_ENUM(NFS4ERR_REP_TOO_BIG);
+-TRACE_DEFINE_ENUM(NFS4ERR_REP_TOO_BIG_TO_CACHE);
+-TRACE_DEFINE_ENUM(NFS4ERR_REQ_TOO_BIG);
+-TRACE_DEFINE_ENUM(NFS4ERR_RESOURCE);
+-TRACE_DEFINE_ENUM(NFS4ERR_RESTOREFH);
+-TRACE_DEFINE_ENUM(NFS4ERR_RETRY_UNCACHED_REP);
+-TRACE_DEFINE_ENUM(NFS4ERR_RETURNCONFLICT);
+-TRACE_DEFINE_ENUM(NFS4ERR_ROFS);
+-TRACE_DEFINE_ENUM(NFS4ERR_SAME);
+-TRACE_DEFINE_ENUM(NFS4ERR_SHARE_DENIED);
+-TRACE_DEFINE_ENUM(NFS4ERR_SEQUENCE_POS);
+-TRACE_DEFINE_ENUM(NFS4ERR_SEQ_FALSE_RETRY);
+-TRACE_DEFINE_ENUM(NFS4ERR_SEQ_MISORDERED);
+-TRACE_DEFINE_ENUM(NFS4ERR_SERVERFAULT);
+-TRACE_DEFINE_ENUM(NFS4ERR_STALE);
+-TRACE_DEFINE_ENUM(NFS4ERR_STALE_CLIENTID);
+-TRACE_DEFINE_ENUM(NFS4ERR_STALE_STATEID);
+-TRACE_DEFINE_ENUM(NFS4ERR_SYMLINK);
+-TRACE_DEFINE_ENUM(NFS4ERR_TOOSMALL);
+-TRACE_DEFINE_ENUM(NFS4ERR_TOO_MANY_OPS);
+-TRACE_DEFINE_ENUM(NFS4ERR_UNKNOWN_LAYOUTTYPE);
+-TRACE_DEFINE_ENUM(NFS4ERR_UNSAFE_COMPOUND);
+-TRACE_DEFINE_ENUM(NFS4ERR_WRONGSEC);
+-TRACE_DEFINE_ENUM(NFS4ERR_WRONG_CRED);
+-TRACE_DEFINE_ENUM(NFS4ERR_WRONG_TYPE);
+-TRACE_DEFINE_ENUM(NFS4ERR_XDEV);
+-
+-TRACE_DEFINE_ENUM(NFS4ERR_RESET_TO_MDS);
+-TRACE_DEFINE_ENUM(NFS4ERR_RESET_TO_PNFS);
+-
+-#define show_nfs4_status(x) \
+-      __print_symbolic(x, \
+-              { NFS4_OK,                      "OK" }, \
+-              { EPERM,                        "EPERM" }, \
+-              { ENOENT,                       "ENOENT" }, \
+-              { EIO,                          "EIO" }, \
+-              { ENXIO,                        "ENXIO" }, \
+-              { EACCES,                       "EACCES" }, \
+-              { EEXIST,                       "EEXIST" }, \
+-              { EXDEV,                        "EXDEV" }, \
+-              { ENOTDIR,                      "ENOTDIR" }, \
+-              { EISDIR,                       "EISDIR" }, \
+-              { EFBIG,                        "EFBIG" }, \
+-              { ENOSPC,                       "ENOSPC" }, \
+-              { EROFS,                        "EROFS" }, \
+-              { EMLINK,                       "EMLINK" }, \
+-              { ENAMETOOLONG,                 "ENAMETOOLONG" }, \
+-              { ENOTEMPTY,                    "ENOTEMPTY" }, \
+-              { EDQUOT,                       "EDQUOT" }, \
+-              { ESTALE,                       "ESTALE" }, \
+-              { EBADHANDLE,                   "EBADHANDLE" }, \
+-              { EBADCOOKIE,                   "EBADCOOKIE" }, \
+-              { ENOTSUPP,                     "ENOTSUPP" }, \
+-              { ETOOSMALL,                    "ETOOSMALL" }, \
+-              { EREMOTEIO,                    "EREMOTEIO" }, \
+-              { EBADTYPE,                     "EBADTYPE" }, \
+-              { EAGAIN,                       "EAGAIN" }, \
+-              { ELOOP,                        "ELOOP" }, \
+-              { EOPNOTSUPP,                   "EOPNOTSUPP" }, \
+-              { EDEADLK,                      "EDEADLK" }, \
+-              { ENOMEM,                       "ENOMEM" }, \
+-              { EKEYEXPIRED,                  "EKEYEXPIRED" }, \
+-              { ETIMEDOUT,                    "ETIMEDOUT" }, \
+-              { ERESTARTSYS,                  "ERESTARTSYS" }, \
+-              { ECONNREFUSED,                 "ECONNREFUSED" }, \
+-              { ECONNRESET,                   "ECONNRESET" }, \
+-              { ENETUNREACH,                  "ENETUNREACH" }, \
+-              { EHOSTUNREACH,                 "EHOSTUNREACH" }, \
+-              { EHOSTDOWN,                    "EHOSTDOWN" }, \
+-              { EPIPE,                        "EPIPE" }, \
+-              { EPFNOSUPPORT,                 "EPFNOSUPPORT" }, \
+-              { EPROTONOSUPPORT,              "EPROTONOSUPPORT" }, \
+-              { NFS4ERR_ACCESS,               "ACCESS" }, \
+-              { NFS4ERR_ATTRNOTSUPP,          "ATTRNOTSUPP" }, \
+-              { NFS4ERR_ADMIN_REVOKED,        "ADMIN_REVOKED" }, \
+-              { NFS4ERR_BACK_CHAN_BUSY,       "BACK_CHAN_BUSY" }, \
+-              { NFS4ERR_BADCHAR,              "BADCHAR" }, \
+-              { NFS4ERR_BADHANDLE,            "BADHANDLE" }, \
+-              { NFS4ERR_BADIOMODE,            "BADIOMODE" }, \
+-              { NFS4ERR_BADLAYOUT,            "BADLAYOUT" }, \
+-              { NFS4ERR_BADLABEL,             "BADLABEL" }, \
+-              { NFS4ERR_BADNAME,              "BADNAME" }, \
+-              { NFS4ERR_BADOWNER,             "BADOWNER" }, \
+-              { NFS4ERR_BADSESSION,           "BADSESSION" }, \
+-              { NFS4ERR_BADSLOT,              "BADSLOT" }, \
+-              { NFS4ERR_BADTYPE,              "BADTYPE" }, \
+-              { NFS4ERR_BADXDR,               "BADXDR" }, \
+-              { NFS4ERR_BAD_COOKIE,           "BAD_COOKIE" }, \
+-              { NFS4ERR_BAD_HIGH_SLOT,        "BAD_HIGH_SLOT" }, \
+-              { NFS4ERR_BAD_RANGE,            "BAD_RANGE" }, \
+-              { NFS4ERR_BAD_SEQID,            "BAD_SEQID" }, \
+-              { NFS4ERR_BAD_SESSION_DIGEST,   "BAD_SESSION_DIGEST" }, \
+-              { NFS4ERR_BAD_STATEID,          "BAD_STATEID" }, \
+-              { NFS4ERR_CB_PATH_DOWN,         "CB_PATH_DOWN" }, \
+-              { NFS4ERR_CLID_INUSE,           "CLID_INUSE" }, \
+-              { NFS4ERR_CLIENTID_BUSY,        "CLIENTID_BUSY" }, \
+-              { NFS4ERR_COMPLETE_ALREADY,     "COMPLETE_ALREADY" }, \
+-              { NFS4ERR_CONN_NOT_BOUND_TO_SESSION, "CONN_NOT_BOUND_TO_SESSION" }, \
+-              { NFS4ERR_DEADLOCK,             "DEADLOCK" }, \
+-              { NFS4ERR_DEADSESSION,          "DEAD_SESSION" }, \
+-              { NFS4ERR_DELAY,                "DELAY" }, \
+-              { NFS4ERR_DELEG_ALREADY_WANTED, "DELEG_ALREADY_WANTED" }, \
+-              { NFS4ERR_DELEG_REVOKED,        "DELEG_REVOKED" }, \
+-              { NFS4ERR_DENIED,               "DENIED" }, \
+-              { NFS4ERR_DIRDELEG_UNAVAIL,     "DIRDELEG_UNAVAIL" }, \
+-              { NFS4ERR_DQUOT,                "DQUOT" }, \
+-              { NFS4ERR_ENCR_ALG_UNSUPP,      "ENCR_ALG_UNSUPP" }, \
+-              { NFS4ERR_EXIST,                "EXIST" }, \
+-              { NFS4ERR_EXPIRED,              "EXPIRED" }, \
+-              { NFS4ERR_FBIG,                 "FBIG" }, \
+-              { NFS4ERR_FHEXPIRED,            "FHEXPIRED" }, \
+-              { NFS4ERR_FILE_OPEN,            "FILE_OPEN" }, \
+-              { NFS4ERR_GRACE,                "GRACE" }, \
+-              { NFS4ERR_HASH_ALG_UNSUPP,      "HASH_ALG_UNSUPP" }, \
+-              { NFS4ERR_INVAL,                "INVAL" }, \
+-              { NFS4ERR_IO,                   "IO" }, \
+-              { NFS4ERR_ISDIR,                "ISDIR" }, \
+-              { NFS4ERR_LAYOUTTRYLATER,       "LAYOUTTRYLATER" }, \
+-              { NFS4ERR_LAYOUTUNAVAILABLE,    "LAYOUTUNAVAILABLE" }, \
+-              { NFS4ERR_LEASE_MOVED,          "LEASE_MOVED" }, \
+-              { NFS4ERR_LOCKED,               "LOCKED" }, \
+-              { NFS4ERR_LOCKS_HELD,           "LOCKS_HELD" }, \
+-              { NFS4ERR_LOCK_RANGE,           "LOCK_RANGE" }, \
+-              { NFS4ERR_MINOR_VERS_MISMATCH,  "MINOR_VERS_MISMATCH" }, \
+-              { NFS4ERR_MLINK,                "MLINK" }, \
+-              { NFS4ERR_MOVED,                "MOVED" }, \
+-              { NFS4ERR_NAMETOOLONG,          "NAMETOOLONG" }, \
+-              { NFS4ERR_NOENT,                "NOENT" }, \
+-              { NFS4ERR_NOFILEHANDLE,         "NOFILEHANDLE" }, \
+-              { NFS4ERR_NOMATCHING_LAYOUT,    "NOMATCHING_LAYOUT" }, \
+-              { NFS4ERR_NOSPC,                "NOSPC" }, \
+-              { NFS4ERR_NOTDIR,               "NOTDIR" }, \
+-              { NFS4ERR_NOTEMPTY,             "NOTEMPTY" }, \
+-              { NFS4ERR_NOTSUPP,              "NOTSUPP" }, \
+-              { NFS4ERR_NOT_ONLY_OP,          "NOT_ONLY_OP" }, \
+-              { NFS4ERR_NOT_SAME,             "NOT_SAME" }, \
+-              { NFS4ERR_NO_GRACE,             "NO_GRACE" }, \
+-              { NFS4ERR_NXIO,                 "NXIO" }, \
+-              { NFS4ERR_OLD_STATEID,          "OLD_STATEID" }, \
+-              { NFS4ERR_OPENMODE,             "OPENMODE" }, \
+-              { NFS4ERR_OP_ILLEGAL,           "OP_ILLEGAL" }, \
+-              { NFS4ERR_OP_NOT_IN_SESSION,    "OP_NOT_IN_SESSION" }, \
+-              { NFS4ERR_PERM,                 "PERM" }, \
+-              { NFS4ERR_PNFS_IO_HOLE,         "PNFS_IO_HOLE" }, \
+-              { NFS4ERR_PNFS_NO_LAYOUT,       "PNFS_NO_LAYOUT" }, \
+-              { NFS4ERR_RECALLCONFLICT,       "RECALLCONFLICT" }, \
+-              { NFS4ERR_RECLAIM_BAD,          "RECLAIM_BAD" }, \
+-              { NFS4ERR_RECLAIM_CONFLICT,     "RECLAIM_CONFLICT" }, \
+-              { NFS4ERR_REJECT_DELEG,         "REJECT_DELEG" }, \
+-              { NFS4ERR_REP_TOO_BIG,          "REP_TOO_BIG" }, \
+-              { NFS4ERR_REP_TOO_BIG_TO_CACHE, "REP_TOO_BIG_TO_CACHE" }, \
+-              { NFS4ERR_REQ_TOO_BIG,          "REQ_TOO_BIG" }, \
+-              { NFS4ERR_RESOURCE,             "RESOURCE" }, \
+-              { NFS4ERR_RESTOREFH,            "RESTOREFH" }, \
+-              { NFS4ERR_RETRY_UNCACHED_REP,   "RETRY_UNCACHED_REP" }, \
+-              { NFS4ERR_RETURNCONFLICT,       "RETURNCONFLICT" }, \
+-              { NFS4ERR_ROFS,                 "ROFS" }, \
+-              { NFS4ERR_SAME,                 "SAME" }, \
+-              { NFS4ERR_SHARE_DENIED,         "SHARE_DENIED" }, \
+-              { NFS4ERR_SEQUENCE_POS,         "SEQUENCE_POS" }, \
+-              { NFS4ERR_SEQ_FALSE_RETRY,      "SEQ_FALSE_RETRY" }, \
+-              { NFS4ERR_SEQ_MISORDERED,       "SEQ_MISORDERED" }, \
+-              { NFS4ERR_SERVERFAULT,          "SERVERFAULT" }, \
+-              { NFS4ERR_STALE,                "STALE" }, \
+-              { NFS4ERR_STALE_CLIENTID,       "STALE_CLIENTID" }, \
+-              { NFS4ERR_STALE_STATEID,        "STALE_STATEID" }, \
+-              { NFS4ERR_SYMLINK,              "SYMLINK" }, \
+-              { NFS4ERR_TOOSMALL,             "TOOSMALL" }, \
+-              { NFS4ERR_TOO_MANY_OPS,         "TOO_MANY_OPS" }, \
+-              { NFS4ERR_UNKNOWN_LAYOUTTYPE,   "UNKNOWN_LAYOUTTYPE" }, \
+-              { NFS4ERR_UNSAFE_COMPOUND,      "UNSAFE_COMPOUND" }, \
+-              { NFS4ERR_WRONGSEC,             "WRONGSEC" }, \
+-              { NFS4ERR_WRONG_CRED,           "WRONG_CRED" }, \
+-              { NFS4ERR_WRONG_TYPE,           "WRONG_TYPE" }, \
+-              { NFS4ERR_XDEV,                 "XDEV" }, \
+-              /* ***** Internal to Linux NFS client ***** */ \
+-              { NFS4ERR_RESET_TO_MDS,         "RESET_TO_MDS" }, \
+-              { NFS4ERR_RESET_TO_PNFS,        "RESET_TO_PNFS" })
+-
+-#define show_nfs4_verifier(x) \
+-      __print_hex_str(x, NFS4_VERIFIER_SIZE)
+-
+-TRACE_DEFINE_ENUM(IOMODE_READ);
+-TRACE_DEFINE_ENUM(IOMODE_RW);
+-TRACE_DEFINE_ENUM(IOMODE_ANY);
+-
+-#define show_pnfs_layout_iomode(x) \
+-      __print_symbolic(x, \
+-              { IOMODE_READ,                  "READ" }, \
+-              { IOMODE_RW,                    "RW" }, \
+-              { IOMODE_ANY,                   "ANY" })
+-
+-#define show_nfs4_seq4_status(x) \
+-      __print_flags(x, "|", \
+-              { SEQ4_STATUS_CB_PATH_DOWN,             "CB_PATH_DOWN" }, \
+-              { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING, "CB_GSS_CONTEXTS_EXPIRING" }, \
+-              { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED,  "CB_GSS_CONTEXTS_EXPIRED" }, \
+-              { SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED, "EXPIRED_ALL_STATE_REVOKED" }, \
+-              { SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED, "EXPIRED_SOME_STATE_REVOKED" }, \
+-              { SEQ4_STATUS_ADMIN_STATE_REVOKED,      "ADMIN_STATE_REVOKED" }, \
+-              { SEQ4_STATUS_RECALLABLE_STATE_REVOKED, "RECALLABLE_STATE_REVOKED" }, \
+-              { SEQ4_STATUS_LEASE_MOVED,              "LEASE_MOVED" }, \
+-              { SEQ4_STATUS_RESTART_RECLAIM_NEEDED,   "RESTART_RECLAIM_NEEDED" }, \
+-              { SEQ4_STATUS_CB_PATH_DOWN_SESSION,     "CB_PATH_DOWN_SESSION" }, \
+-              { SEQ4_STATUS_BACKCHANNEL_FAULT,        "BACKCHANNEL_FAULT" })
+--- a/include/trace/events/rdma.h
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Copyright (c) 2017 Oracle.  All rights reserved.
+- */
+-
+-/*
+- * enum ib_event_type, from include/rdma/ib_verbs.h
+- */
+-#define IB_EVENT_LIST                         \
+-      ib_event(CQ_ERR)                        \
+-      ib_event(QP_FATAL)                      \
+-      ib_event(QP_REQ_ERR)                    \
+-      ib_event(QP_ACCESS_ERR)                 \
+-      ib_event(COMM_EST)                      \
+-      ib_event(SQ_DRAINED)                    \
+-      ib_event(PATH_MIG)                      \
+-      ib_event(PATH_MIG_ERR)                  \
+-      ib_event(DEVICE_FATAL)                  \
+-      ib_event(PORT_ACTIVE)                   \
+-      ib_event(PORT_ERR)                      \
+-      ib_event(LID_CHANGE)                    \
+-      ib_event(PKEY_CHANGE)                   \
+-      ib_event(SM_CHANGE)                     \
+-      ib_event(SRQ_ERR)                       \
+-      ib_event(SRQ_LIMIT_REACHED)             \
+-      ib_event(QP_LAST_WQE_REACHED)           \
+-      ib_event(CLIENT_REREGISTER)             \
+-      ib_event(GID_CHANGE)                    \
+-      ib_event_end(WQ_FATAL)
+-
+-#undef ib_event
+-#undef ib_event_end
+-
+-#define ib_event(x)           TRACE_DEFINE_ENUM(IB_EVENT_##x);
+-#define ib_event_end(x)               TRACE_DEFINE_ENUM(IB_EVENT_##x);
+-
+-IB_EVENT_LIST
+-
+-#undef ib_event
+-#undef ib_event_end
+-
+-#define ib_event(x)           { IB_EVENT_##x, #x },
+-#define ib_event_end(x)               { IB_EVENT_##x, #x }
+-
+-#define rdma_show_ib_event(x) \
+-              __print_symbolic(x, IB_EVENT_LIST)
+-
+-/*
+- * enum ib_wc_status type, from include/rdma/ib_verbs.h
+- */
+-#define IB_WC_STATUS_LIST                     \
+-      ib_wc_status(SUCCESS)                   \
+-      ib_wc_status(LOC_LEN_ERR)               \
+-      ib_wc_status(LOC_QP_OP_ERR)             \
+-      ib_wc_status(LOC_EEC_OP_ERR)            \
+-      ib_wc_status(LOC_PROT_ERR)              \
+-      ib_wc_status(WR_FLUSH_ERR)              \
+-      ib_wc_status(MW_BIND_ERR)               \
+-      ib_wc_status(BAD_RESP_ERR)              \
+-      ib_wc_status(LOC_ACCESS_ERR)            \
+-      ib_wc_status(REM_INV_REQ_ERR)           \
+-      ib_wc_status(REM_ACCESS_ERR)            \
+-      ib_wc_status(REM_OP_ERR)                \
+-      ib_wc_status(RETRY_EXC_ERR)             \
+-      ib_wc_status(RNR_RETRY_EXC_ERR)         \
+-      ib_wc_status(LOC_RDD_VIOL_ERR)          \
+-      ib_wc_status(REM_INV_RD_REQ_ERR)        \
+-      ib_wc_status(REM_ABORT_ERR)             \
+-      ib_wc_status(INV_EECN_ERR)              \
+-      ib_wc_status(INV_EEC_STATE_ERR)         \
+-      ib_wc_status(FATAL_ERR)                 \
+-      ib_wc_status(RESP_TIMEOUT_ERR)          \
+-      ib_wc_status_end(GENERAL_ERR)
+-
+-#undef ib_wc_status
+-#undef ib_wc_status_end
+-
+-#define ib_wc_status(x)               TRACE_DEFINE_ENUM(IB_WC_##x);
+-#define ib_wc_status_end(x)   TRACE_DEFINE_ENUM(IB_WC_##x);
+-
+-IB_WC_STATUS_LIST
+-
+-#undef ib_wc_status
+-#undef ib_wc_status_end
+-
+-#define ib_wc_status(x)               { IB_WC_##x, #x },
+-#define ib_wc_status_end(x)   { IB_WC_##x, #x }
+-
+-#define rdma_show_wc_status(x) \
+-              __print_symbolic(x, IB_WC_STATUS_LIST)
+-
+-/*
+- * enum ib_cm_event_type, from include/rdma/ib_cm.h
+- */
+-#define IB_CM_EVENT_LIST                      \
+-      ib_cm_event(REQ_ERROR)                  \
+-      ib_cm_event(REQ_RECEIVED)               \
+-      ib_cm_event(REP_ERROR)                  \
+-      ib_cm_event(REP_RECEIVED)               \
+-      ib_cm_event(RTU_RECEIVED)               \
+-      ib_cm_event(USER_ESTABLISHED)           \
+-      ib_cm_event(DREQ_ERROR)                 \
+-      ib_cm_event(DREQ_RECEIVED)              \
+-      ib_cm_event(DREP_RECEIVED)              \
+-      ib_cm_event(TIMEWAIT_EXIT)              \
+-      ib_cm_event(MRA_RECEIVED)               \
+-      ib_cm_event(REJ_RECEIVED)               \
+-      ib_cm_event(LAP_ERROR)                  \
+-      ib_cm_event(LAP_RECEIVED)               \
+-      ib_cm_event(APR_RECEIVED)               \
+-      ib_cm_event(SIDR_REQ_ERROR)             \
+-      ib_cm_event(SIDR_REQ_RECEIVED)          \
+-      ib_cm_event_end(SIDR_REP_RECEIVED)
+-
+-#undef ib_cm_event
+-#undef ib_cm_event_end
+-
+-#define ib_cm_event(x)                TRACE_DEFINE_ENUM(IB_CM_##x);
+-#define ib_cm_event_end(x)    TRACE_DEFINE_ENUM(IB_CM_##x);
+-
+-IB_CM_EVENT_LIST
+-
+-#undef ib_cm_event
+-#undef ib_cm_event_end
+-
+-#define ib_cm_event(x)                { IB_CM_##x, #x },
+-#define ib_cm_event_end(x)    { IB_CM_##x, #x }
+-
+-#define rdma_show_ib_cm_event(x) \
+-              __print_symbolic(x, IB_CM_EVENT_LIST)
+-
+-/*
+- * enum rdma_cm_event_type, from include/rdma/rdma_cm.h
+- */
+-#define RDMA_CM_EVENT_LIST                    \
+-      rdma_cm_event(ADDR_RESOLVED)            \
+-      rdma_cm_event(ADDR_ERROR)               \
+-      rdma_cm_event(ROUTE_RESOLVED)           \
+-      rdma_cm_event(ROUTE_ERROR)              \
+-      rdma_cm_event(CONNECT_REQUEST)          \
+-      rdma_cm_event(CONNECT_RESPONSE)         \
+-      rdma_cm_event(CONNECT_ERROR)            \
+-      rdma_cm_event(UNREACHABLE)              \
+-      rdma_cm_event(REJECTED)                 \
+-      rdma_cm_event(ESTABLISHED)              \
+-      rdma_cm_event(DISCONNECTED)             \
+-      rdma_cm_event(DEVICE_REMOVAL)           \
+-      rdma_cm_event(MULTICAST_JOIN)           \
+-      rdma_cm_event(MULTICAST_ERROR)          \
+-      rdma_cm_event(ADDR_CHANGE)              \
+-      rdma_cm_event_end(TIMEWAIT_EXIT)
+-
+-#undef rdma_cm_event
+-#undef rdma_cm_event_end
+-
+-#define rdma_cm_event(x)      TRACE_DEFINE_ENUM(RDMA_CM_EVENT_##x);
+-#define rdma_cm_event_end(x)  TRACE_DEFINE_ENUM(RDMA_CM_EVENT_##x);
+-
+-RDMA_CM_EVENT_LIST
+-
+-#undef rdma_cm_event
+-#undef rdma_cm_event_end
+-
+-#define rdma_cm_event(x)      { RDMA_CM_EVENT_##x, #x },
+-#define rdma_cm_event_end(x)  { RDMA_CM_EVENT_##x, #x }
+-
+-#define rdma_show_cm_event(x) \
+-              __print_symbolic(x, RDMA_CM_EVENT_LIST)
+--- a/include/trace/events/rpcgss.h
++++ b/include/trace/events/rpcgss.h
+@@ -13,7 +13,7 @@
+ #include <linux/tracepoint.h>
+-#include <trace/events/sunrpc_base.h>
++#include <trace/misc/sunrpc.h>
+ /**
+  ** GSS-API related trace events
+--- a/include/trace/events/rpcrdma.h
++++ b/include/trace/events/rpcrdma.h
+@@ -15,8 +15,8 @@
+ #include <linux/tracepoint.h>
+ #include <rdma/ib_cm.h>
+-#include <trace/events/rdma.h>
+-#include <trace/events/sunrpc_base.h>
++#include <trace/misc/rdma.h>
++#include <trace/misc/sunrpc.h>
+ /**
+  ** Event classes
+--- a/include/trace/events/sunrpc.h
++++ b/include/trace/events/sunrpc.h
+@@ -14,7 +14,7 @@
+ #include <linux/net.h>
+ #include <linux/tracepoint.h>
+-#include <trace/events/sunrpc_base.h>
++#include <trace/misc/sunrpc.h>
+ TRACE_DEFINE_ENUM(SOCK_STREAM);
+ TRACE_DEFINE_ENUM(SOCK_DGRAM);
+--- a/include/trace/events/sunrpc_base.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Copyright (c) 2021 Oracle and/or its affiliates.
+- *
+- * Common types and format specifiers for sunrpc.
+- */
+-
+-#if !defined(_TRACE_SUNRPC_BASE_H)
+-#define _TRACE_SUNRPC_BASE_H
+-
+-#include <linux/tracepoint.h>
+-
+-#define SUNRPC_TRACE_PID_SPECIFIER    "%08x"
+-#define SUNRPC_TRACE_CLID_SPECIFIER   "%08x"
+-#define SUNRPC_TRACE_TASK_SPECIFIER \
+-      "task:" SUNRPC_TRACE_PID_SPECIFIER "@" SUNRPC_TRACE_CLID_SPECIFIER
+-
+-#endif /* _TRACE_SUNRPC_BASE_H */
+--- /dev/null
++++ b/include/trace/misc/fs.h
+@@ -0,0 +1,122 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Display helpers for generic filesystem items
++ *
++ * Author: Chuck Lever <chuck.lever@oracle.com>
++ *
++ * Copyright (c) 2020, Oracle and/or its affiliates.
++ */
++
++#include <linux/fs.h>
++
++#define show_fs_dirent_type(x) \
++      __print_symbolic(x, \
++              { DT_UNKNOWN,           "UNKNOWN" }, \
++              { DT_FIFO,              "FIFO" }, \
++              { DT_CHR,               "CHR" }, \
++              { DT_DIR,               "DIR" }, \
++              { DT_BLK,               "BLK" }, \
++              { DT_REG,               "REG" }, \
++              { DT_LNK,               "LNK" }, \
++              { DT_SOCK,              "SOCK" }, \
++              { DT_WHT,               "WHT" })
++
++#define show_fs_fcntl_open_flags(x) \
++      __print_flags(x, "|", \
++              { O_WRONLY,             "O_WRONLY" }, \
++              { O_RDWR,               "O_RDWR" }, \
++              { O_CREAT,              "O_CREAT" }, \
++              { O_EXCL,               "O_EXCL" }, \
++              { O_NOCTTY,             "O_NOCTTY" }, \
++              { O_TRUNC,              "O_TRUNC" }, \
++              { O_APPEND,             "O_APPEND" }, \
++              { O_NONBLOCK,           "O_NONBLOCK" }, \
++              { O_DSYNC,              "O_DSYNC" }, \
++              { O_DIRECT,             "O_DIRECT" }, \
++              { O_LARGEFILE,          "O_LARGEFILE" }, \
++              { O_DIRECTORY,          "O_DIRECTORY" }, \
++              { O_NOFOLLOW,           "O_NOFOLLOW" }, \
++              { O_NOATIME,            "O_NOATIME" }, \
++              { O_CLOEXEC,            "O_CLOEXEC" })
++
++#define __fmode_flag(x)       { (__force unsigned long)FMODE_##x, #x }
++#define show_fs_fmode_flags(x) \
++      __print_flags(x, "|", \
++              __fmode_flag(READ), \
++              __fmode_flag(WRITE), \
++              __fmode_flag(EXEC))
++
++#ifdef CONFIG_64BIT
++#define show_fs_fcntl_cmd(x) \
++      __print_symbolic(x, \
++              { F_DUPFD,              "DUPFD" }, \
++              { F_GETFD,              "GETFD" }, \
++              { F_SETFD,              "SETFD" }, \
++              { F_GETFL,              "GETFL" }, \
++              { F_SETFL,              "SETFL" }, \
++              { F_GETLK,              "GETLK" }, \
++              { F_SETLK,              "SETLK" }, \
++              { F_SETLKW,             "SETLKW" }, \
++              { F_SETOWN,             "SETOWN" }, \
++              { F_GETOWN,             "GETOWN" }, \
++              { F_SETSIG,             "SETSIG" }, \
++              { F_GETSIG,             "GETSIG" }, \
++              { F_SETOWN_EX,          "SETOWN_EX" }, \
++              { F_GETOWN_EX,          "GETOWN_EX" }, \
++              { F_GETOWNER_UIDS,      "GETOWNER_UIDS" }, \
++              { F_OFD_GETLK,          "OFD_GETLK" }, \
++              { F_OFD_SETLK,          "OFD_SETLK" }, \
++              { F_OFD_SETLKW,         "OFD_SETLKW" })
++#else /* CONFIG_64BIT */
++#define show_fs_fcntl_cmd(x) \
++      __print_symbolic(x, \
++              { F_DUPFD,              "DUPFD" }, \
++              { F_GETFD,              "GETFD" }, \
++              { F_SETFD,              "SETFD" }, \
++              { F_GETFL,              "GETFL" }, \
++              { F_SETFL,              "SETFL" }, \
++              { F_GETLK,              "GETLK" }, \
++              { F_SETLK,              "SETLK" }, \
++              { F_SETLKW,             "SETLKW" }, \
++              { F_SETOWN,             "SETOWN" }, \
++              { F_GETOWN,             "GETOWN" }, \
++              { F_SETSIG,             "SETSIG" }, \
++              { F_GETSIG,             "GETSIG" }, \
++              { F_GETLK64,            "GETLK64" }, \
++              { F_SETLK64,            "SETLK64" }, \
++              { F_SETLKW64,           "SETLKW64" }, \
++              { F_SETOWN_EX,          "SETOWN_EX" }, \
++              { F_GETOWN_EX,          "GETOWN_EX" }, \
++              { F_GETOWNER_UIDS,      "GETOWNER_UIDS" }, \
++              { F_OFD_GETLK,          "OFD_GETLK" }, \
++              { F_OFD_SETLK,          "OFD_SETLK" }, \
++              { F_OFD_SETLKW,         "OFD_SETLKW" })
++#endif /* CONFIG_64BIT */
++
++#define show_fs_fcntl_lock_type(x) \
++      __print_symbolic(x, \
++              { F_RDLCK,              "RDLCK" }, \
++              { F_WRLCK,              "WRLCK" }, \
++              { F_UNLCK,              "UNLCK" })
++
++#define show_fs_lookup_flags(flags) \
++      __print_flags(flags, "|", \
++              { LOOKUP_FOLLOW,        "FOLLOW" }, \
++              { LOOKUP_DIRECTORY,     "DIRECTORY" }, \
++              { LOOKUP_AUTOMOUNT,     "AUTOMOUNT" }, \
++              { LOOKUP_EMPTY,         "EMPTY" }, \
++              { LOOKUP_DOWN,          "DOWN" }, \
++              { LOOKUP_MOUNTPOINT,    "MOUNTPOINT" }, \
++              { LOOKUP_REVAL,         "REVAL" }, \
++              { LOOKUP_RCU,           "RCU" }, \
++              { LOOKUP_OPEN,          "OPEN" }, \
++              { LOOKUP_CREATE,        "CREATE" }, \
++              { LOOKUP_EXCL,          "EXCL" }, \
++              { LOOKUP_RENAME_TARGET, "RENAME_TARGET" }, \
++              { LOOKUP_PARENT,        "PARENT" }, \
++              { LOOKUP_NO_SYMLINKS,   "NO_SYMLINKS" }, \
++              { LOOKUP_NO_MAGICLINKS, "NO_MAGICLINKS" }, \
++              { LOOKUP_NO_XDEV,       "NO_XDEV" }, \
++              { LOOKUP_BENEATH,       "BENEATH" }, \
++              { LOOKUP_IN_ROOT,       "IN_ROOT" }, \
++              { LOOKUP_CACHED,        "CACHED" })
+--- /dev/null
++++ b/include/trace/misc/nfs.h
+@@ -0,0 +1,375 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Display helpers for NFS protocol elements
++ *
++ * Author: Chuck Lever <chuck.lever@oracle.com>
++ *
++ * Copyright (c) 2020, Oracle and/or its affiliates.
++ */
++
++#include <linux/nfs.h>
++#include <linux/nfs4.h>
++#include <uapi/linux/nfs.h>
++
++TRACE_DEFINE_ENUM(NFS_OK);
++TRACE_DEFINE_ENUM(NFSERR_PERM);
++TRACE_DEFINE_ENUM(NFSERR_NOENT);
++TRACE_DEFINE_ENUM(NFSERR_IO);
++TRACE_DEFINE_ENUM(NFSERR_NXIO);
++TRACE_DEFINE_ENUM(NFSERR_EAGAIN);
++TRACE_DEFINE_ENUM(NFSERR_ACCES);
++TRACE_DEFINE_ENUM(NFSERR_EXIST);
++TRACE_DEFINE_ENUM(NFSERR_XDEV);
++TRACE_DEFINE_ENUM(NFSERR_NODEV);
++TRACE_DEFINE_ENUM(NFSERR_NOTDIR);
++TRACE_DEFINE_ENUM(NFSERR_ISDIR);
++TRACE_DEFINE_ENUM(NFSERR_INVAL);
++TRACE_DEFINE_ENUM(NFSERR_FBIG);
++TRACE_DEFINE_ENUM(NFSERR_NOSPC);
++TRACE_DEFINE_ENUM(NFSERR_ROFS);
++TRACE_DEFINE_ENUM(NFSERR_MLINK);
++TRACE_DEFINE_ENUM(NFSERR_OPNOTSUPP);
++TRACE_DEFINE_ENUM(NFSERR_NAMETOOLONG);
++TRACE_DEFINE_ENUM(NFSERR_NOTEMPTY);
++TRACE_DEFINE_ENUM(NFSERR_DQUOT);
++TRACE_DEFINE_ENUM(NFSERR_STALE);
++TRACE_DEFINE_ENUM(NFSERR_REMOTE);
++TRACE_DEFINE_ENUM(NFSERR_WFLUSH);
++TRACE_DEFINE_ENUM(NFSERR_BADHANDLE);
++TRACE_DEFINE_ENUM(NFSERR_NOT_SYNC);
++TRACE_DEFINE_ENUM(NFSERR_BAD_COOKIE);
++TRACE_DEFINE_ENUM(NFSERR_NOTSUPP);
++TRACE_DEFINE_ENUM(NFSERR_TOOSMALL);
++TRACE_DEFINE_ENUM(NFSERR_SERVERFAULT);
++TRACE_DEFINE_ENUM(NFSERR_BADTYPE);
++TRACE_DEFINE_ENUM(NFSERR_JUKEBOX);
++
++#define show_nfs_status(x) \
++      __print_symbolic(x, \
++              { NFS_OK,                       "OK" }, \
++              { NFSERR_PERM,                  "PERM" }, \
++              { NFSERR_NOENT,                 "NOENT" }, \
++              { NFSERR_IO,                    "IO" }, \
++              { NFSERR_NXIO,                  "NXIO" }, \
++              { ECHILD,                       "CHILD" }, \
++              { NFSERR_EAGAIN,                "AGAIN" }, \
++              { NFSERR_ACCES,                 "ACCES" }, \
++              { NFSERR_EXIST,                 "EXIST" }, \
++              { NFSERR_XDEV,                  "XDEV" }, \
++              { NFSERR_NODEV,                 "NODEV" }, \
++              { NFSERR_NOTDIR,                "NOTDIR" }, \
++              { NFSERR_ISDIR,                 "ISDIR" }, \
++              { NFSERR_INVAL,                 "INVAL" }, \
++              { NFSERR_FBIG,                  "FBIG" }, \
++              { NFSERR_NOSPC,                 "NOSPC" }, \
++              { NFSERR_ROFS,                  "ROFS" }, \
++              { NFSERR_MLINK,                 "MLINK" }, \
++              { NFSERR_OPNOTSUPP,             "OPNOTSUPP" }, \
++              { NFSERR_NAMETOOLONG,           "NAMETOOLONG" }, \
++              { NFSERR_NOTEMPTY,              "NOTEMPTY" }, \
++              { NFSERR_DQUOT,                 "DQUOT" }, \
++              { NFSERR_STALE,                 "STALE" }, \
++              { NFSERR_REMOTE,                "REMOTE" }, \
++              { NFSERR_WFLUSH,                "WFLUSH" }, \
++              { NFSERR_BADHANDLE,             "BADHANDLE" }, \
++              { NFSERR_NOT_SYNC,              "NOTSYNC" }, \
++              { NFSERR_BAD_COOKIE,            "BADCOOKIE" }, \
++              { NFSERR_NOTSUPP,               "NOTSUPP" }, \
++              { NFSERR_TOOSMALL,              "TOOSMALL" }, \
++              { NFSERR_SERVERFAULT,           "REMOTEIO" }, \
++              { NFSERR_BADTYPE,               "BADTYPE" }, \
++              { NFSERR_JUKEBOX,               "JUKEBOX" })
++
++TRACE_DEFINE_ENUM(NFS_UNSTABLE);
++TRACE_DEFINE_ENUM(NFS_DATA_SYNC);
++TRACE_DEFINE_ENUM(NFS_FILE_SYNC);
++
++#define show_nfs_stable_how(x) \
++      __print_symbolic(x, \
++              { NFS_UNSTABLE,                 "UNSTABLE" }, \
++              { NFS_DATA_SYNC,                "DATA_SYNC" }, \
++              { NFS_FILE_SYNC,                "FILE_SYNC" })
++
++TRACE_DEFINE_ENUM(NFS4_OK);
++TRACE_DEFINE_ENUM(NFS4ERR_ACCESS);
++TRACE_DEFINE_ENUM(NFS4ERR_ATTRNOTSUPP);
++TRACE_DEFINE_ENUM(NFS4ERR_ADMIN_REVOKED);
++TRACE_DEFINE_ENUM(NFS4ERR_BACK_CHAN_BUSY);
++TRACE_DEFINE_ENUM(NFS4ERR_BADCHAR);
++TRACE_DEFINE_ENUM(NFS4ERR_BADHANDLE);
++TRACE_DEFINE_ENUM(NFS4ERR_BADIOMODE);
++TRACE_DEFINE_ENUM(NFS4ERR_BADLAYOUT);
++TRACE_DEFINE_ENUM(NFS4ERR_BADLABEL);
++TRACE_DEFINE_ENUM(NFS4ERR_BADNAME);
++TRACE_DEFINE_ENUM(NFS4ERR_BADOWNER);
++TRACE_DEFINE_ENUM(NFS4ERR_BADSESSION);
++TRACE_DEFINE_ENUM(NFS4ERR_BADSLOT);
++TRACE_DEFINE_ENUM(NFS4ERR_BADTYPE);
++TRACE_DEFINE_ENUM(NFS4ERR_BADXDR);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_COOKIE);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_HIGH_SLOT);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_RANGE);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_SEQID);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_SESSION_DIGEST);
++TRACE_DEFINE_ENUM(NFS4ERR_BAD_STATEID);
++TRACE_DEFINE_ENUM(NFS4ERR_CB_PATH_DOWN);
++TRACE_DEFINE_ENUM(NFS4ERR_CLID_INUSE);
++TRACE_DEFINE_ENUM(NFS4ERR_CLIENTID_BUSY);
++TRACE_DEFINE_ENUM(NFS4ERR_COMPLETE_ALREADY);
++TRACE_DEFINE_ENUM(NFS4ERR_CONN_NOT_BOUND_TO_SESSION);
++TRACE_DEFINE_ENUM(NFS4ERR_DEADLOCK);
++TRACE_DEFINE_ENUM(NFS4ERR_DEADSESSION);
++TRACE_DEFINE_ENUM(NFS4ERR_DELAY);
++TRACE_DEFINE_ENUM(NFS4ERR_DELEG_ALREADY_WANTED);
++TRACE_DEFINE_ENUM(NFS4ERR_DELEG_REVOKED);
++TRACE_DEFINE_ENUM(NFS4ERR_DENIED);
++TRACE_DEFINE_ENUM(NFS4ERR_DIRDELEG_UNAVAIL);
++TRACE_DEFINE_ENUM(NFS4ERR_DQUOT);
++TRACE_DEFINE_ENUM(NFS4ERR_ENCR_ALG_UNSUPP);
++TRACE_DEFINE_ENUM(NFS4ERR_EXIST);
++TRACE_DEFINE_ENUM(NFS4ERR_EXPIRED);
++TRACE_DEFINE_ENUM(NFS4ERR_FBIG);
++TRACE_DEFINE_ENUM(NFS4ERR_FHEXPIRED);
++TRACE_DEFINE_ENUM(NFS4ERR_FILE_OPEN);
++TRACE_DEFINE_ENUM(NFS4ERR_GRACE);
++TRACE_DEFINE_ENUM(NFS4ERR_HASH_ALG_UNSUPP);
++TRACE_DEFINE_ENUM(NFS4ERR_INVAL);
++TRACE_DEFINE_ENUM(NFS4ERR_IO);
++TRACE_DEFINE_ENUM(NFS4ERR_ISDIR);
++TRACE_DEFINE_ENUM(NFS4ERR_LAYOUTTRYLATER);
++TRACE_DEFINE_ENUM(NFS4ERR_LAYOUTUNAVAILABLE);
++TRACE_DEFINE_ENUM(NFS4ERR_LEASE_MOVED);
++TRACE_DEFINE_ENUM(NFS4ERR_LOCKED);
++TRACE_DEFINE_ENUM(NFS4ERR_LOCKS_HELD);
++TRACE_DEFINE_ENUM(NFS4ERR_LOCK_RANGE);
++TRACE_DEFINE_ENUM(NFS4ERR_MINOR_VERS_MISMATCH);
++TRACE_DEFINE_ENUM(NFS4ERR_MLINK);
++TRACE_DEFINE_ENUM(NFS4ERR_MOVED);
++TRACE_DEFINE_ENUM(NFS4ERR_NAMETOOLONG);
++TRACE_DEFINE_ENUM(NFS4ERR_NOENT);
++TRACE_DEFINE_ENUM(NFS4ERR_NOFILEHANDLE);
++TRACE_DEFINE_ENUM(NFS4ERR_NOMATCHING_LAYOUT);
++TRACE_DEFINE_ENUM(NFS4ERR_NOSPC);
++TRACE_DEFINE_ENUM(NFS4ERR_NOTDIR);
++TRACE_DEFINE_ENUM(NFS4ERR_NOTEMPTY);
++TRACE_DEFINE_ENUM(NFS4ERR_NOTSUPP);
++TRACE_DEFINE_ENUM(NFS4ERR_NOT_ONLY_OP);
++TRACE_DEFINE_ENUM(NFS4ERR_NOT_SAME);
++TRACE_DEFINE_ENUM(NFS4ERR_NO_GRACE);
++TRACE_DEFINE_ENUM(NFS4ERR_NXIO);
++TRACE_DEFINE_ENUM(NFS4ERR_OLD_STATEID);
++TRACE_DEFINE_ENUM(NFS4ERR_OPENMODE);
++TRACE_DEFINE_ENUM(NFS4ERR_OP_ILLEGAL);
++TRACE_DEFINE_ENUM(NFS4ERR_OP_NOT_IN_SESSION);
++TRACE_DEFINE_ENUM(NFS4ERR_PERM);
++TRACE_DEFINE_ENUM(NFS4ERR_PNFS_IO_HOLE);
++TRACE_DEFINE_ENUM(NFS4ERR_PNFS_NO_LAYOUT);
++TRACE_DEFINE_ENUM(NFS4ERR_RECALLCONFLICT);
++TRACE_DEFINE_ENUM(NFS4ERR_RECLAIM_BAD);
++TRACE_DEFINE_ENUM(NFS4ERR_RECLAIM_CONFLICT);
++TRACE_DEFINE_ENUM(NFS4ERR_REJECT_DELEG);
++TRACE_DEFINE_ENUM(NFS4ERR_REP_TOO_BIG);
++TRACE_DEFINE_ENUM(NFS4ERR_REP_TOO_BIG_TO_CACHE);
++TRACE_DEFINE_ENUM(NFS4ERR_REQ_TOO_BIG);
++TRACE_DEFINE_ENUM(NFS4ERR_RESOURCE);
++TRACE_DEFINE_ENUM(NFS4ERR_RESTOREFH);
++TRACE_DEFINE_ENUM(NFS4ERR_RETRY_UNCACHED_REP);
++TRACE_DEFINE_ENUM(NFS4ERR_RETURNCONFLICT);
++TRACE_DEFINE_ENUM(NFS4ERR_ROFS);
++TRACE_DEFINE_ENUM(NFS4ERR_SAME);
++TRACE_DEFINE_ENUM(NFS4ERR_SHARE_DENIED);
++TRACE_DEFINE_ENUM(NFS4ERR_SEQUENCE_POS);
++TRACE_DEFINE_ENUM(NFS4ERR_SEQ_FALSE_RETRY);
++TRACE_DEFINE_ENUM(NFS4ERR_SEQ_MISORDERED);
++TRACE_DEFINE_ENUM(NFS4ERR_SERVERFAULT);
++TRACE_DEFINE_ENUM(NFS4ERR_STALE);
++TRACE_DEFINE_ENUM(NFS4ERR_STALE_CLIENTID);
++TRACE_DEFINE_ENUM(NFS4ERR_STALE_STATEID);
++TRACE_DEFINE_ENUM(NFS4ERR_SYMLINK);
++TRACE_DEFINE_ENUM(NFS4ERR_TOOSMALL);
++TRACE_DEFINE_ENUM(NFS4ERR_TOO_MANY_OPS);
++TRACE_DEFINE_ENUM(NFS4ERR_UNKNOWN_LAYOUTTYPE);
++TRACE_DEFINE_ENUM(NFS4ERR_UNSAFE_COMPOUND);
++TRACE_DEFINE_ENUM(NFS4ERR_WRONGSEC);
++TRACE_DEFINE_ENUM(NFS4ERR_WRONG_CRED);
++TRACE_DEFINE_ENUM(NFS4ERR_WRONG_TYPE);
++TRACE_DEFINE_ENUM(NFS4ERR_XDEV);
++
++TRACE_DEFINE_ENUM(NFS4ERR_RESET_TO_MDS);
++TRACE_DEFINE_ENUM(NFS4ERR_RESET_TO_PNFS);
++
++#define show_nfs4_status(x) \
++      __print_symbolic(x, \
++              { NFS4_OK,                      "OK" }, \
++              { EPERM,                        "EPERM" }, \
++              { ENOENT,                       "ENOENT" }, \
++              { EIO,                          "EIO" }, \
++              { ENXIO,                        "ENXIO" }, \
++              { EACCES,                       "EACCES" }, \
++              { EEXIST,                       "EEXIST" }, \
++              { EXDEV,                        "EXDEV" }, \
++              { ENOTDIR,                      "ENOTDIR" }, \
++              { EISDIR,                       "EISDIR" }, \
++              { EFBIG,                        "EFBIG" }, \
++              { ENOSPC,                       "ENOSPC" }, \
++              { EROFS,                        "EROFS" }, \
++              { EMLINK,                       "EMLINK" }, \
++              { ENAMETOOLONG,                 "ENAMETOOLONG" }, \
++              { ENOTEMPTY,                    "ENOTEMPTY" }, \
++              { EDQUOT,                       "EDQUOT" }, \
++              { ESTALE,                       "ESTALE" }, \
++              { EBADHANDLE,                   "EBADHANDLE" }, \
++              { EBADCOOKIE,                   "EBADCOOKIE" }, \
++              { ENOTSUPP,                     "ENOTSUPP" }, \
++              { ETOOSMALL,                    "ETOOSMALL" }, \
++              { EREMOTEIO,                    "EREMOTEIO" }, \
++              { EBADTYPE,                     "EBADTYPE" }, \
++              { EAGAIN,                       "EAGAIN" }, \
++              { ELOOP,                        "ELOOP" }, \
++              { EOPNOTSUPP,                   "EOPNOTSUPP" }, \
++              { EDEADLK,                      "EDEADLK" }, \
++              { ENOMEM,                       "ENOMEM" }, \
++              { EKEYEXPIRED,                  "EKEYEXPIRED" }, \
++              { ETIMEDOUT,                    "ETIMEDOUT" }, \
++              { ERESTARTSYS,                  "ERESTARTSYS" }, \
++              { ECONNREFUSED,                 "ECONNREFUSED" }, \
++              { ECONNRESET,                   "ECONNRESET" }, \
++              { ENETUNREACH,                  "ENETUNREACH" }, \
++              { EHOSTUNREACH,                 "EHOSTUNREACH" }, \
++              { EHOSTDOWN,                    "EHOSTDOWN" }, \
++              { EPIPE,                        "EPIPE" }, \
++              { EPFNOSUPPORT,                 "EPFNOSUPPORT" }, \
++              { EPROTONOSUPPORT,              "EPROTONOSUPPORT" }, \
++              { NFS4ERR_ACCESS,               "ACCESS" }, \
++              { NFS4ERR_ATTRNOTSUPP,          "ATTRNOTSUPP" }, \
++              { NFS4ERR_ADMIN_REVOKED,        "ADMIN_REVOKED" }, \
++              { NFS4ERR_BACK_CHAN_BUSY,       "BACK_CHAN_BUSY" }, \
++              { NFS4ERR_BADCHAR,              "BADCHAR" }, \
++              { NFS4ERR_BADHANDLE,            "BADHANDLE" }, \
++              { NFS4ERR_BADIOMODE,            "BADIOMODE" }, \
++              { NFS4ERR_BADLAYOUT,            "BADLAYOUT" }, \
++              { NFS4ERR_BADLABEL,             "BADLABEL" }, \
++              { NFS4ERR_BADNAME,              "BADNAME" }, \
++              { NFS4ERR_BADOWNER,             "BADOWNER" }, \
++              { NFS4ERR_BADSESSION,           "BADSESSION" }, \
++              { NFS4ERR_BADSLOT,              "BADSLOT" }, \
++              { NFS4ERR_BADTYPE,              "BADTYPE" }, \
++              { NFS4ERR_BADXDR,               "BADXDR" }, \
++              { NFS4ERR_BAD_COOKIE,           "BAD_COOKIE" }, \
++              { NFS4ERR_BAD_HIGH_SLOT,        "BAD_HIGH_SLOT" }, \
++              { NFS4ERR_BAD_RANGE,            "BAD_RANGE" }, \
++              { NFS4ERR_BAD_SEQID,            "BAD_SEQID" }, \
++              { NFS4ERR_BAD_SESSION_DIGEST,   "BAD_SESSION_DIGEST" }, \
++              { NFS4ERR_BAD_STATEID,          "BAD_STATEID" }, \
++              { NFS4ERR_CB_PATH_DOWN,         "CB_PATH_DOWN" }, \
++              { NFS4ERR_CLID_INUSE,           "CLID_INUSE" }, \
++              { NFS4ERR_CLIENTID_BUSY,        "CLIENTID_BUSY" }, \
++              { NFS4ERR_COMPLETE_ALREADY,     "COMPLETE_ALREADY" }, \
++              { NFS4ERR_CONN_NOT_BOUND_TO_SESSION, "CONN_NOT_BOUND_TO_SESSION" }, \
++              { NFS4ERR_DEADLOCK,             "DEADLOCK" }, \
++              { NFS4ERR_DEADSESSION,          "DEAD_SESSION" }, \
++              { NFS4ERR_DELAY,                "DELAY" }, \
++              { NFS4ERR_DELEG_ALREADY_WANTED, "DELEG_ALREADY_WANTED" }, \
++              { NFS4ERR_DELEG_REVOKED,        "DELEG_REVOKED" }, \
++              { NFS4ERR_DENIED,               "DENIED" }, \
++              { NFS4ERR_DIRDELEG_UNAVAIL,     "DIRDELEG_UNAVAIL" }, \
++              { NFS4ERR_DQUOT,                "DQUOT" }, \
++              { NFS4ERR_ENCR_ALG_UNSUPP,      "ENCR_ALG_UNSUPP" }, \
++              { NFS4ERR_EXIST,                "EXIST" }, \
++              { NFS4ERR_EXPIRED,              "EXPIRED" }, \
++              { NFS4ERR_FBIG,                 "FBIG" }, \
++              { NFS4ERR_FHEXPIRED,            "FHEXPIRED" }, \
++              { NFS4ERR_FILE_OPEN,            "FILE_OPEN" }, \
++              { NFS4ERR_GRACE,                "GRACE" }, \
++              { NFS4ERR_HASH_ALG_UNSUPP,      "HASH_ALG_UNSUPP" }, \
++              { NFS4ERR_INVAL,                "INVAL" }, \
++              { NFS4ERR_IO,                   "IO" }, \
++              { NFS4ERR_ISDIR,                "ISDIR" }, \
++              { NFS4ERR_LAYOUTTRYLATER,       "LAYOUTTRYLATER" }, \
++              { NFS4ERR_LAYOUTUNAVAILABLE,    "LAYOUTUNAVAILABLE" }, \
++              { NFS4ERR_LEASE_MOVED,          "LEASE_MOVED" }, \
++              { NFS4ERR_LOCKED,               "LOCKED" }, \
++              { NFS4ERR_LOCKS_HELD,           "LOCKS_HELD" }, \
++              { NFS4ERR_LOCK_RANGE,           "LOCK_RANGE" }, \
++              { NFS4ERR_MINOR_VERS_MISMATCH,  "MINOR_VERS_MISMATCH" }, \
++              { NFS4ERR_MLINK,                "MLINK" }, \
++              { NFS4ERR_MOVED,                "MOVED" }, \
++              { NFS4ERR_NAMETOOLONG,          "NAMETOOLONG" }, \
++              { NFS4ERR_NOENT,                "NOENT" }, \
++              { NFS4ERR_NOFILEHANDLE,         "NOFILEHANDLE" }, \
++              { NFS4ERR_NOMATCHING_LAYOUT,    "NOMATCHING_LAYOUT" }, \
++              { NFS4ERR_NOSPC,                "NOSPC" }, \
++              { NFS4ERR_NOTDIR,               "NOTDIR" }, \
++              { NFS4ERR_NOTEMPTY,             "NOTEMPTY" }, \
++              { NFS4ERR_NOTSUPP,              "NOTSUPP" }, \
++              { NFS4ERR_NOT_ONLY_OP,          "NOT_ONLY_OP" }, \
++              { NFS4ERR_NOT_SAME,             "NOT_SAME" }, \
++              { NFS4ERR_NO_GRACE,             "NO_GRACE" }, \
++              { NFS4ERR_NXIO,                 "NXIO" }, \
++              { NFS4ERR_OLD_STATEID,          "OLD_STATEID" }, \
++              { NFS4ERR_OPENMODE,             "OPENMODE" }, \
++              { NFS4ERR_OP_ILLEGAL,           "OP_ILLEGAL" }, \
++              { NFS4ERR_OP_NOT_IN_SESSION,    "OP_NOT_IN_SESSION" }, \
++              { NFS4ERR_PERM,                 "PERM" }, \
++              { NFS4ERR_PNFS_IO_HOLE,         "PNFS_IO_HOLE" }, \
++              { NFS4ERR_PNFS_NO_LAYOUT,       "PNFS_NO_LAYOUT" }, \
++              { NFS4ERR_RECALLCONFLICT,       "RECALLCONFLICT" }, \
++              { NFS4ERR_RECLAIM_BAD,          "RECLAIM_BAD" }, \
++              { NFS4ERR_RECLAIM_CONFLICT,     "RECLAIM_CONFLICT" }, \
++              { NFS4ERR_REJECT_DELEG,         "REJECT_DELEG" }, \
++              { NFS4ERR_REP_TOO_BIG,          "REP_TOO_BIG" }, \
++              { NFS4ERR_REP_TOO_BIG_TO_CACHE, "REP_TOO_BIG_TO_CACHE" }, \
++              { NFS4ERR_REQ_TOO_BIG,          "REQ_TOO_BIG" }, \
++              { NFS4ERR_RESOURCE,             "RESOURCE" }, \
++              { NFS4ERR_RESTOREFH,            "RESTOREFH" }, \
++              { NFS4ERR_RETRY_UNCACHED_REP,   "RETRY_UNCACHED_REP" }, \
++              { NFS4ERR_RETURNCONFLICT,       "RETURNCONFLICT" }, \
++              { NFS4ERR_ROFS,                 "ROFS" }, \
++              { NFS4ERR_SAME,                 "SAME" }, \
++              { NFS4ERR_SHARE_DENIED,         "SHARE_DENIED" }, \
++              { NFS4ERR_SEQUENCE_POS,         "SEQUENCE_POS" }, \
++              { NFS4ERR_SEQ_FALSE_RETRY,      "SEQ_FALSE_RETRY" }, \
++              { NFS4ERR_SEQ_MISORDERED,       "SEQ_MISORDERED" }, \
++              { NFS4ERR_SERVERFAULT,          "SERVERFAULT" }, \
++              { NFS4ERR_STALE,                "STALE" }, \
++              { NFS4ERR_STALE_CLIENTID,       "STALE_CLIENTID" }, \
++              { NFS4ERR_STALE_STATEID,        "STALE_STATEID" }, \
++              { NFS4ERR_SYMLINK,              "SYMLINK" }, \
++              { NFS4ERR_TOOSMALL,             "TOOSMALL" }, \
++              { NFS4ERR_TOO_MANY_OPS,         "TOO_MANY_OPS" }, \
++              { NFS4ERR_UNKNOWN_LAYOUTTYPE,   "UNKNOWN_LAYOUTTYPE" }, \
++              { NFS4ERR_UNSAFE_COMPOUND,      "UNSAFE_COMPOUND" }, \
++              { NFS4ERR_WRONGSEC,             "WRONGSEC" }, \
++              { NFS4ERR_WRONG_CRED,           "WRONG_CRED" }, \
++              { NFS4ERR_WRONG_TYPE,           "WRONG_TYPE" }, \
++              { NFS4ERR_XDEV,                 "XDEV" }, \
++              /* ***** Internal to Linux NFS client ***** */ \
++              { NFS4ERR_RESET_TO_MDS,         "RESET_TO_MDS" }, \
++              { NFS4ERR_RESET_TO_PNFS,        "RESET_TO_PNFS" })
++
++#define show_nfs4_verifier(x) \
++      __print_hex_str(x, NFS4_VERIFIER_SIZE)
++
++TRACE_DEFINE_ENUM(IOMODE_READ);
++TRACE_DEFINE_ENUM(IOMODE_RW);
++TRACE_DEFINE_ENUM(IOMODE_ANY);
++
++#define show_pnfs_layout_iomode(x) \
++      __print_symbolic(x, \
++              { IOMODE_READ,                  "READ" }, \
++              { IOMODE_RW,                    "RW" }, \
++              { IOMODE_ANY,                   "ANY" })
++
++#define show_nfs4_seq4_status(x) \
++      __print_flags(x, "|", \
++              { SEQ4_STATUS_CB_PATH_DOWN,             "CB_PATH_DOWN" }, \
++              { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING, "CB_GSS_CONTEXTS_EXPIRING" }, \
++              { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED,  "CB_GSS_CONTEXTS_EXPIRED" }, \
++              { SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED, "EXPIRED_ALL_STATE_REVOKED" }, \
++              { SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED, "EXPIRED_SOME_STATE_REVOKED" }, \
++              { SEQ4_STATUS_ADMIN_STATE_REVOKED,      "ADMIN_STATE_REVOKED" }, \
++              { SEQ4_STATUS_RECALLABLE_STATE_REVOKED, "RECALLABLE_STATE_REVOKED" }, \
++              { SEQ4_STATUS_LEASE_MOVED,              "LEASE_MOVED" }, \
++              { SEQ4_STATUS_RESTART_RECLAIM_NEEDED,   "RESTART_RECLAIM_NEEDED" }, \
++              { SEQ4_STATUS_CB_PATH_DOWN_SESSION,     "CB_PATH_DOWN_SESSION" }, \
++              { SEQ4_STATUS_BACKCHANNEL_FAULT,        "BACKCHANNEL_FAULT" })
+--- /dev/null
++++ b/include/trace/misc/rdma.h
+@@ -0,0 +1,168 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (c) 2017 Oracle.  All rights reserved.
++ */
++
++/*
++ * enum ib_event_type, from include/rdma/ib_verbs.h
++ */
++#define IB_EVENT_LIST                         \
++      ib_event(CQ_ERR)                        \
++      ib_event(QP_FATAL)                      \
++      ib_event(QP_REQ_ERR)                    \
++      ib_event(QP_ACCESS_ERR)                 \
++      ib_event(COMM_EST)                      \
++      ib_event(SQ_DRAINED)                    \
++      ib_event(PATH_MIG)                      \
++      ib_event(PATH_MIG_ERR)                  \
++      ib_event(DEVICE_FATAL)                  \
++      ib_event(PORT_ACTIVE)                   \
++      ib_event(PORT_ERR)                      \
++      ib_event(LID_CHANGE)                    \
++      ib_event(PKEY_CHANGE)                   \
++      ib_event(SM_CHANGE)                     \
++      ib_event(SRQ_ERR)                       \
++      ib_event(SRQ_LIMIT_REACHED)             \
++      ib_event(QP_LAST_WQE_REACHED)           \
++      ib_event(CLIENT_REREGISTER)             \
++      ib_event(GID_CHANGE)                    \
++      ib_event_end(WQ_FATAL)
++
++#undef ib_event
++#undef ib_event_end
++
++#define ib_event(x)           TRACE_DEFINE_ENUM(IB_EVENT_##x);
++#define ib_event_end(x)               TRACE_DEFINE_ENUM(IB_EVENT_##x);
++
++IB_EVENT_LIST
++
++#undef ib_event
++#undef ib_event_end
++
++#define ib_event(x)           { IB_EVENT_##x, #x },
++#define ib_event_end(x)               { IB_EVENT_##x, #x }
++
++#define rdma_show_ib_event(x) \
++              __print_symbolic(x, IB_EVENT_LIST)
++
++/*
++ * enum ib_wc_status type, from include/rdma/ib_verbs.h
++ */
++#define IB_WC_STATUS_LIST                     \
++      ib_wc_status(SUCCESS)                   \
++      ib_wc_status(LOC_LEN_ERR)               \
++      ib_wc_status(LOC_QP_OP_ERR)             \
++      ib_wc_status(LOC_EEC_OP_ERR)            \
++      ib_wc_status(LOC_PROT_ERR)              \
++      ib_wc_status(WR_FLUSH_ERR)              \
++      ib_wc_status(MW_BIND_ERR)               \
++      ib_wc_status(BAD_RESP_ERR)              \
++      ib_wc_status(LOC_ACCESS_ERR)            \
++      ib_wc_status(REM_INV_REQ_ERR)           \
++      ib_wc_status(REM_ACCESS_ERR)            \
++      ib_wc_status(REM_OP_ERR)                \
++      ib_wc_status(RETRY_EXC_ERR)             \
++      ib_wc_status(RNR_RETRY_EXC_ERR)         \
++      ib_wc_status(LOC_RDD_VIOL_ERR)          \
++      ib_wc_status(REM_INV_RD_REQ_ERR)        \
++      ib_wc_status(REM_ABORT_ERR)             \
++      ib_wc_status(INV_EECN_ERR)              \
++      ib_wc_status(INV_EEC_STATE_ERR)         \
++      ib_wc_status(FATAL_ERR)                 \
++      ib_wc_status(RESP_TIMEOUT_ERR)          \
++      ib_wc_status_end(GENERAL_ERR)
++
++#undef ib_wc_status
++#undef ib_wc_status_end
++
++#define ib_wc_status(x)               TRACE_DEFINE_ENUM(IB_WC_##x);
++#define ib_wc_status_end(x)   TRACE_DEFINE_ENUM(IB_WC_##x);
++
++IB_WC_STATUS_LIST
++
++#undef ib_wc_status
++#undef ib_wc_status_end
++
++#define ib_wc_status(x)               { IB_WC_##x, #x },
++#define ib_wc_status_end(x)   { IB_WC_##x, #x }
++
++#define rdma_show_wc_status(x) \
++              __print_symbolic(x, IB_WC_STATUS_LIST)
++
++/*
++ * enum ib_cm_event_type, from include/rdma/ib_cm.h
++ */
++#define IB_CM_EVENT_LIST                      \
++      ib_cm_event(REQ_ERROR)                  \
++      ib_cm_event(REQ_RECEIVED)               \
++      ib_cm_event(REP_ERROR)                  \
++      ib_cm_event(REP_RECEIVED)               \
++      ib_cm_event(RTU_RECEIVED)               \
++      ib_cm_event(USER_ESTABLISHED)           \
++      ib_cm_event(DREQ_ERROR)                 \
++      ib_cm_event(DREQ_RECEIVED)              \
++      ib_cm_event(DREP_RECEIVED)              \
++      ib_cm_event(TIMEWAIT_EXIT)              \
++      ib_cm_event(MRA_RECEIVED)               \
++      ib_cm_event(REJ_RECEIVED)               \
++      ib_cm_event(LAP_ERROR)                  \
++      ib_cm_event(LAP_RECEIVED)               \
++      ib_cm_event(APR_RECEIVED)               \
++      ib_cm_event(SIDR_REQ_ERROR)             \
++      ib_cm_event(SIDR_REQ_RECEIVED)          \
++      ib_cm_event_end(SIDR_REP_RECEIVED)
++
++#undef ib_cm_event
++#undef ib_cm_event_end
++
++#define ib_cm_event(x)                TRACE_DEFINE_ENUM(IB_CM_##x);
++#define ib_cm_event_end(x)    TRACE_DEFINE_ENUM(IB_CM_##x);
++
++IB_CM_EVENT_LIST
++
++#undef ib_cm_event
++#undef ib_cm_event_end
++
++#define ib_cm_event(x)                { IB_CM_##x, #x },
++#define ib_cm_event_end(x)    { IB_CM_##x, #x }
++
++#define rdma_show_ib_cm_event(x) \
++              __print_symbolic(x, IB_CM_EVENT_LIST)
++
++/*
++ * enum rdma_cm_event_type, from include/rdma/rdma_cm.h
++ */
++#define RDMA_CM_EVENT_LIST                    \
++      rdma_cm_event(ADDR_RESOLVED)            \
++      rdma_cm_event(ADDR_ERROR)               \
++      rdma_cm_event(ROUTE_RESOLVED)           \
++      rdma_cm_event(ROUTE_ERROR)              \
++      rdma_cm_event(CONNECT_REQUEST)          \
++      rdma_cm_event(CONNECT_RESPONSE)         \
++      rdma_cm_event(CONNECT_ERROR)            \
++      rdma_cm_event(UNREACHABLE)              \
++      rdma_cm_event(REJECTED)                 \
++      rdma_cm_event(ESTABLISHED)              \
++      rdma_cm_event(DISCONNECTED)             \
++      rdma_cm_event(DEVICE_REMOVAL)           \
++      rdma_cm_event(MULTICAST_JOIN)           \
++      rdma_cm_event(MULTICAST_ERROR)          \
++      rdma_cm_event(ADDR_CHANGE)              \
++      rdma_cm_event_end(TIMEWAIT_EXIT)
++
++#undef rdma_cm_event
++#undef rdma_cm_event_end
++
++#define rdma_cm_event(x)      TRACE_DEFINE_ENUM(RDMA_CM_EVENT_##x);
++#define rdma_cm_event_end(x)  TRACE_DEFINE_ENUM(RDMA_CM_EVENT_##x);
++
++RDMA_CM_EVENT_LIST
++
++#undef rdma_cm_event
++#undef rdma_cm_event_end
++
++#define rdma_cm_event(x)      { RDMA_CM_EVENT_##x, #x },
++#define rdma_cm_event_end(x)  { RDMA_CM_EVENT_##x, #x }
++
++#define rdma_show_cm_event(x) \
++              __print_symbolic(x, RDMA_CM_EVENT_LIST)
+--- /dev/null
++++ b/include/trace/misc/sunrpc.h
+@@ -0,0 +1,18 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (c) 2021 Oracle and/or its affiliates.
++ *
++ * Common types and format specifiers for sunrpc.
++ */
++
++#if !defined(_TRACE_SUNRPC_BASE_H)
++#define _TRACE_SUNRPC_BASE_H
++
++#include <linux/tracepoint.h>
++
++#define SUNRPC_TRACE_PID_SPECIFIER    "%08x"
++#define SUNRPC_TRACE_CLID_SPECIFIER   "%08x"
++#define SUNRPC_TRACE_TASK_SPECIFIER \
++      "task:" SUNRPC_TRACE_PID_SPECIFIER "@" SUNRPC_TRACE_CLID_SPECIFIER
++
++#endif /* _TRACE_SUNRPC_BASE_H */