]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Aug 2024 08:39:55 +0000 (10:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Aug 2024 08:39:55 +0000 (10:39 +0200)
added patches:
drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch
loongarch-define-__arch_want_new_stat-in-unistd.h.patch
mptcp-fully-established-after-add_addr-echo-on-mpj.patch
nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch
nfsd-fix-frame-size-warning-in-svc_export_parse.patch
nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch
nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch
nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch
nfsd-move-reply-cache-initialization-into-nfsd-startup.patch
nfsd-refactor-nfsd_reply_cache_free_locked.patch
nfsd-refactor-the-duplicate-reply-cache-shrinker.patch
nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch
nfsd-rename-nfsd_net_-to-nfsd_stats_.patch
nfsd-rename-nfsd_reply_cache_alloc.patch
nfsd-replace-nfsd_prune_bucket.patch
nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch
nfsd-stop-setting-pg_stats-for-unused-stats.patch
nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch
sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch
sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch
sunrpc-remove-pg_stats-from-svc_program.patch
sunrpc-use-the-struct-net-as-the-svc-proc-private.patch

23 files changed:
queue-6.1/drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch [new file with mode: 0644]
queue-6.1/loongarch-define-__arch_want_new_stat-in-unistd.h.patch [new file with mode: 0644]
queue-6.1/mptcp-fully-established-after-add_addr-echo-on-mpj.patch [new file with mode: 0644]
queue-6.1/nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch [new file with mode: 0644]
queue-6.1/nfsd-fix-frame-size-warning-in-svc_export_parse.patch [new file with mode: 0644]
queue-6.1/nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch [new file with mode: 0644]
queue-6.1/nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch [new file with mode: 0644]
queue-6.1/nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch [new file with mode: 0644]
queue-6.1/nfsd-move-reply-cache-initialization-into-nfsd-startup.patch [new file with mode: 0644]
queue-6.1/nfsd-refactor-nfsd_reply_cache_free_locked.patch [new file with mode: 0644]
queue-6.1/nfsd-refactor-the-duplicate-reply-cache-shrinker.patch [new file with mode: 0644]
queue-6.1/nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch [new file with mode: 0644]
queue-6.1/nfsd-rename-nfsd_net_-to-nfsd_stats_.patch [new file with mode: 0644]
queue-6.1/nfsd-rename-nfsd_reply_cache_alloc.patch [new file with mode: 0644]
queue-6.1/nfsd-replace-nfsd_prune_bucket.patch [new file with mode: 0644]
queue-6.1/nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch [new file with mode: 0644]
queue-6.1/nfsd-stop-setting-pg_stats-for-unused-stats.patch [new file with mode: 0644]
queue-6.1/nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch [new file with mode: 0644]
queue-6.1/sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch [new file with mode: 0644]
queue-6.1/sunrpc-remove-pg_stats-from-svc_program.patch [new file with mode: 0644]
queue-6.1/sunrpc-use-the-struct-net-as-the-svc-proc-private.patch [new file with mode: 0644]

diff --git a/queue-6.1/drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch b/queue-6.1/drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch
new file mode 100644 (file)
index 0000000..845e7fa
--- /dev/null
@@ -0,0 +1,126 @@
+From 8bdd9ef7e9b1b2a73e394712b72b22055e0e26c3 Mon Sep 17 00:00:00 2001
+From: Andi Shyti <andi.shyti@linux.intel.com>
+Date: Fri, 2 Aug 2024 10:38:50 +0200
+Subject: drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
+
+From: Andi Shyti <andi.shyti@linux.intel.com>
+
+commit 8bdd9ef7e9b1b2a73e394712b72b22055e0e26c3 upstream.
+
+Calculating the size of the mapped area as the lesser value
+between the requested size and the actual size does not consider
+the partial mapping offset. This can cause page fault access.
+
+Fix the calculation of the starting and ending addresses, the
+total size is now deduced from the difference between the end and
+start addresses.
+
+Additionally, the calculations have been rewritten in a clearer
+and more understandable form.
+
+Fixes: c58305af1835 ("drm/i915: Use remap_io_mapping() to prefault all PTE in a single pass")
+Reported-by: Jann Horn <jannh@google.com>
+Co-developed-by: Chris Wilson <chris.p.wilson@linux.intel.com>
+Signed-off-by: Chris Wilson <chris.p.wilson@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
+Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Cc: Matthew Auld <matthew.auld@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Cc: <stable@vger.kernel.org> # v4.9+
+Reviewed-by: Jann Horn <jannh@google.com>
+Reviewed-by: Jonathan Cavitt <Jonathan.cavitt@intel.com>
+[Joonas: Add Requires: tag]
+Requires: 60a2066c5005 ("drm/i915/gem: Adjust vma offset for framebuffer mmap offset")
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240802083850.103694-3-andi.shyti@linux.intel.com
+(cherry picked from commit 97b6784753da06d9d40232328efc5c5367e53417)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/gem/i915_gem_mman.c |   53 +++++++++++++++++++++++++++----
+ 1 file changed, 47 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+@@ -290,6 +290,41 @@ out:
+       return i915_error_to_vmf_fault(err);
+ }
++static void set_address_limits(struct vm_area_struct *area,
++                             struct i915_vma *vma,
++                             unsigned long obj_offset,
++                             unsigned long *start_vaddr,
++                             unsigned long *end_vaddr)
++{
++      unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */
++      long start, end; /* memory boundaries */
++
++      /*
++       * Let's move into the ">> PAGE_SHIFT"
++       * domain to be sure not to lose bits
++       */
++      vm_start = area->vm_start >> PAGE_SHIFT;
++      vm_end = area->vm_end >> PAGE_SHIFT;
++      vma_size = vma->size >> PAGE_SHIFT;
++
++      /*
++       * Calculate the memory boundaries by considering the offset
++       * provided by the user during memory mapping and the offset
++       * provided for the partial mapping.
++       */
++      start = vm_start;
++      start -= obj_offset;
++      start += vma->gtt_view.partial.offset;
++      end = start + vma_size;
++
++      start = max_t(long, start, vm_start);
++      end = min_t(long, end, vm_end);
++
++      /* Let's move back into the "<< PAGE_SHIFT" domain */
++      *start_vaddr = (unsigned long)start << PAGE_SHIFT;
++      *end_vaddr = (unsigned long)end << PAGE_SHIFT;
++}
++
+ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
+ {
+ #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
+@@ -302,14 +337,18 @@ static vm_fault_t vm_fault_gtt(struct vm
+       struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+       bool write = area->vm_flags & VM_WRITE;
+       struct i915_gem_ww_ctx ww;
++      unsigned long obj_offset;
++      unsigned long start, end; /* memory boundaries */
+       intel_wakeref_t wakeref;
+       struct i915_vma *vma;
+       pgoff_t page_offset;
++      unsigned long pfn;
+       int srcu;
+       int ret;
+-      /* We don't use vmf->pgoff since that has the fake offset */
++      obj_offset = area->vm_pgoff - drm_vma_node_start(&mmo->vma_node);
+       page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
++      page_offset += obj_offset;
+       trace_i915_gem_object_fault(obj, page_offset, true, write);
+@@ -393,12 +432,14 @@ retry:
+       if (ret)
+               goto err_unpin;
++      set_address_limits(area, vma, obj_offset, &start, &end);
++
++      pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT;
++      pfn += (start - area->vm_start) >> PAGE_SHIFT;
++      pfn += obj_offset - vma->gtt_view.partial.offset;
++
+       /* Finally, remap it using the new GTT offset */
+-      ret = remap_io_mapping(area,
+-                             area->vm_start + (vma->gtt_view.partial.offset << PAGE_SHIFT),
+-                             (ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
+-                             min_t(u64, vma->size, area->vm_end - area->vm_start),
+-                             &ggtt->iomap);
++      ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
+       if (ret)
+               goto err_fence;
diff --git a/queue-6.1/loongarch-define-__arch_want_new_stat-in-unistd.h.patch b/queue-6.1/loongarch-define-__arch_want_new_stat-in-unistd.h.patch
new file mode 100644 (file)
index 0000000..7a2a98f
--- /dev/null
@@ -0,0 +1,63 @@
+From 7697a0fe0154468f5df35c23ebd7aa48994c2cdc Mon Sep 17 00:00:00 2001
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Sat, 20 Jul 2024 22:40:58 +0800
+Subject: LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+commit 7697a0fe0154468f5df35c23ebd7aa48994c2cdc upstream.
+
+Chromium sandbox apparently wants to deny statx [1] so it could properly
+inspect arguments after the sandboxed process later falls back to fstat.
+Because there's currently not a "fd-only" version of statx, so that the
+sandbox has no way to ensure the path argument is empty without being
+able to peek into the sandboxed process's memory. For architectures able
+to do newfstatat though, glibc falls back to newfstatat after getting
+-ENOSYS for statx, then the respective SIGSYS handler [2] takes care of
+inspecting the path argument, transforming allowed newfstatat's into
+fstat instead which is allowed and has the same type of return value.
+
+But, as LoongArch is the first architecture to not have fstat nor
+newfstatat, the LoongArch glibc does not attempt falling back at all
+when it gets -ENOSYS for statx -- and you see the problem there!
+
+Actually, back when the LoongArch port was under review, people were
+aware of the same problem with sandboxing clone3 [3], so clone was
+eventually kept. Unfortunately it seemed at that time no one had noticed
+statx, so besides restoring fstat/newfstatat to LoongArch uapi (and
+postponing the problem further), it seems inevitable that we would need
+to tackle seccomp deep argument inspection.
+
+However, this is obviously a decision that shouldn't be taken lightly,
+so we just restore fstat/newfstatat by defining __ARCH_WANT_NEW_STAT
+in unistd.h. This is the simplest solution for now, and so we hope the
+community will tackle the long-standing problem of seccomp deep argument
+inspection in the future [4][5].
+
+Also add "newstat" to syscall_abis_64 in Makefile.syscalls due to
+upstream asm-generic changes.
+
+More infomation please reading this thread [6].
+
+[1] https://chromium-review.googlesource.com/c/chromium/src/+/2823150
+[2] https://chromium.googlesource.com/chromium/src/sandbox/+/c085b51940bd/linux/seccomp-bpf-helpers/sigsys_handlers.cc#355
+[3] https://lore.kernel.org/linux-arch/20220511211231.GG7074@brightrain.aerifal.cx/
+[4] https://lwn.net/Articles/799557/
+[5] https://lpc.events/event/4/contributions/560/attachments/397/640/deep-arg-inspection.pdf
+[6] https://lore.kernel.org/loongarch/20240226-granit-seilschaft-eccc2433014d@brauner/T/#t
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/loongarch/include/uapi/asm/unistd.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/loongarch/include/uapi/asm/unistd.h
++++ b/arch/loongarch/include/uapi/asm/unistd.h
+@@ -1,4 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++#define __ARCH_WANT_NEW_STAT
+ #define __ARCH_WANT_SYS_CLONE
+ #define __ARCH_WANT_SYS_CLONE3
diff --git a/queue-6.1/mptcp-fully-established-after-add_addr-echo-on-mpj.patch b/queue-6.1/mptcp-fully-established-after-add_addr-echo-on-mpj.patch
new file mode 100644 (file)
index 0000000..582a3eb
--- /dev/null
@@ -0,0 +1,55 @@
+From stable+bounces-67432-greg=kroah.com@vger.kernel.org Tue Aug 13 11:07:51 2024
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Tue, 13 Aug 2024 11:06:07 +0200
+Subject: mptcp: fully established after ADD_ADDR echo on MPJ
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: MPTCP Upstream <mptcp@lists.linux.dev>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20240813090606.939542-2-matttbe@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+commit d67c5649c1541dc93f202eeffc6f49220a4ed71d upstream.
+
+Before this patch, receiving an ADD_ADDR echo on the just connected
+MP_JOIN subflow -- initiator side, after the MP_JOIN 3WHS -- was
+resulting in an MP_RESET. That's because only ACKs with a DSS or
+ADD_ADDRs without the echo bit were allowed.
+
+Not allowing the ADD_ADDR echo after an MP_CAPABLE 3WHS makes sense, as
+we are not supposed to send an ADD_ADDR before because it requires to be
+in full established mode first. For the MP_JOIN 3WHS, that's different:
+the ADD_ADDR can be sent on a previous subflow, and the ADD_ADDR echo
+can be received on the recently created one. The other peer will already
+be in fully established, so it is allowed to send that.
+
+We can then relax the conditions here to accept the ADD_ADDR echo for
+MPJ subflows.
+
+Fixes: 67b12f792d5e ("mptcp: full fully established support after ADD_ADDR")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-1-c8a9b036493b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflicts in options.c, because the context has changed in commit
+  b3ea6b272d79 ("mptcp: consolidate initial ack seq generation"), which
+  is not in this version. This commit is unrelated to this
+  modification. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/options.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/mptcp/options.c
++++ b/net/mptcp/options.c
+@@ -950,7 +950,8 @@ static bool check_fully_established(stru
+       }
+       if (((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) ||
+-          ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo)) {
++          ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) &&
++           (!mp_opt->echo || subflow->mp_join))) {
+               /* subflows are fully established as soon as we get any
+                * additional ack, including ADD_ADDR.
+                */
diff --git a/queue-6.1/nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch b/queue-6.1/nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch
new file mode 100644 (file)
index 0000000..50b3723
--- /dev/null
@@ -0,0 +1,136 @@
+From stable+bounces-66336-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:25 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:06 -0400
+Subject: nfsd: expose /proc/net/sunrpc/nfsd in net namespaces
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-16-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 93483ac5fec62cc1de166051b219d953bb5e4ef4 ]
+
+We are running nfsd servers inside of containers with their own network
+namespace, and we want to monitor these services using the stats found
+in /proc.  However these are not exposed in the proc inside of the
+container, so we have to bind mount the host /proc into our containers
+to get at this information.
+
+Separate out the stat counters init and the proc registration, and move
+the proc registration into the pernet operations entry and exit points
+so that these stats can be exposed inside of network namespaces.
+
+This is an intermediate step, this just exposes the global counters in
+the network namespace.  Subsequent patches will move these counters into
+the per-network namespace container.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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/nfsctl.c |    8 +++++---
+ fs/nfsd/stats.c  |   21 ++++++---------------
+ fs/nfsd/stats.h  |    6 ++++--
+ 3 files changed, 15 insertions(+), 20 deletions(-)
+
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1458,6 +1458,7 @@ static __net_init int nfsd_init_net(stru
+       nfsd4_init_leases_net(nn);
+       get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
+       seqlock_init(&nn->writeverf_lock);
++      nfsd_proc_stat_init(net);
+       return 0;
+@@ -1473,6 +1474,7 @@ static __net_exit void nfsd_exit_net(str
+ {
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
++      nfsd_proc_stat_shutdown(net);
+       nfsd_net_reply_cache_destroy(nn);
+       nfsd_idmap_shutdown(net);
+       nfsd_export_shutdown(net);
+@@ -1496,7 +1498,7 @@ static int __init init_nfsd(void)
+       retval = nfsd4_init_pnfs();
+       if (retval)
+               goto out_free_slabs;
+-      retval = nfsd_stat_init();      /* Statistics */
++      retval = nfsd_stat_counters_init();     /* Statistics */
+       if (retval)
+               goto out_free_pnfs;
+       retval = nfsd_drc_slab_create();
+@@ -1532,7 +1534,7 @@ out_free_lockd:
+       nfsd_lockd_shutdown();
+       nfsd_drc_slab_free();
+ out_free_stat:
+-      nfsd_stat_shutdown();
++      nfsd_stat_counters_destroy();
+ out_free_pnfs:
+       nfsd4_exit_pnfs();
+ out_free_slabs:
+@@ -1549,7 +1551,7 @@ static void __exit exit_nfsd(void)
+       nfsd_drc_slab_free();
+       remove_proc_entry("fs/nfs/exports", NULL);
+       remove_proc_entry("fs/nfs", NULL);
+-      nfsd_stat_shutdown();
++      nfsd_stat_counters_destroy();
+       nfsd_lockd_shutdown();
+       nfsd4_free_slabs();
+       nfsd4_exit_pnfs();
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -106,31 +106,22 @@ void nfsd_percpu_counters_destroy(struct
+               percpu_counter_destroy(&counters[i]);
+ }
+-static int nfsd_stat_counters_init(void)
++int nfsd_stat_counters_init(void)
+ {
+       return nfsd_percpu_counters_init(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
+ }
+-static void nfsd_stat_counters_destroy(void)
++void nfsd_stat_counters_destroy(void)
+ {
+       nfsd_percpu_counters_destroy(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
+ }
+-int nfsd_stat_init(void)
++void nfsd_proc_stat_init(struct net *net)
+ {
+-      int err;
+-
+-      err = nfsd_stat_counters_init();
+-      if (err)
+-              return err;
+-
+-      svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops);
+-
+-      return 0;
++      svc_proc_register(net, &nfsd_svcstats, &nfsd_proc_ops);
+ }
+-void nfsd_stat_shutdown(void)
++void nfsd_proc_stat_shutdown(struct net *net)
+ {
+-      nfsd_stat_counters_destroy();
+-      svc_proc_unregister(&init_net, "nfsd");
++      svc_proc_unregister(net, "nfsd");
+ }
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -39,8 +39,10 @@ extern struct svc_stat              nfsd_svcstats;
+ int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
+-int nfsd_stat_init(void);
+-void nfsd_stat_shutdown(void);
++int nfsd_stat_counters_init(void);
++void nfsd_stat_counters_destroy(void);
++void nfsd_proc_stat_init(struct net *net);
++void nfsd_proc_stat_shutdown(struct net *net);
+ static inline void nfsd_stats_rc_hits_inc(void)
+ {
diff --git a/queue-6.1/nfsd-fix-frame-size-warning-in-svc_export_parse.patch b/queue-6.1/nfsd-fix-frame-size-warning-in-svc_export_parse.patch
new file mode 100644 (file)
index 0000000..2d341fb
--- /dev/null
@@ -0,0 +1,167 @@
+From stable+bounces-66329-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:08 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:59 -0400
+Subject: NFSD: Fix frame size warning in svc_export_parse()
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, kernel test robot <lkp@intel.com>, Amir Goldstein <amir73il@gmail.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-9-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 6939ace1f22681fface7841cdbf34d3204cc94b5 ]
+
+fs/nfsd/export.c: In function 'svc_export_parse':
+fs/nfsd/export.c:737:1: warning: the frame size of 1040 bytes is larger than 1024 bytes [-Wframe-larger-than=]
+    737 | }
+
+On my systems, svc_export_parse() has a stack frame of over 800
+bytes, not 1040, but nonetheless, it could do with some reduction.
+
+When a struct svc_export is on the stack, it's a temporary structure
+used as an argument, and not visible as an actual exported FS. No
+need to reserve space for export_stats in such cases.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202310012359.YEw5IrK6-lkp@intel.com/
+Cc: Amir Goldstein <amir73il@gmail.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 4b14885411f7 ("nfsd: make all of the nfsd stats per-network namespace")
+[ cel: adjusted to apply to v6.1.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/export.c |   32 +++++++++++++++++++++++---------
+ fs/nfsd/export.h |    4 ++--
+ fs/nfsd/stats.h  |   12 ++++++------
+ 3 files changed, 31 insertions(+), 17 deletions(-)
+
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -339,12 +339,16 @@ static int export_stats_init(struct expo
+ static void export_stats_reset(struct export_stats *stats)
+ {
+-      nfsd_percpu_counters_reset(stats->counter, EXP_STATS_COUNTERS_NUM);
++      if (stats)
++              nfsd_percpu_counters_reset(stats->counter,
++                                         EXP_STATS_COUNTERS_NUM);
+ }
+ static void export_stats_destroy(struct export_stats *stats)
+ {
+-      nfsd_percpu_counters_destroy(stats->counter, EXP_STATS_COUNTERS_NUM);
++      if (stats)
++              nfsd_percpu_counters_destroy(stats->counter,
++                                           EXP_STATS_COUNTERS_NUM);
+ }
+ static void svc_export_put(struct kref *ref)
+@@ -353,7 +357,8 @@ static void svc_export_put(struct kref *
+       path_put(&exp->ex_path);
+       auth_domain_put(exp->ex_client);
+       nfsd4_fslocs_free(&exp->ex_fslocs);
+-      export_stats_destroy(&exp->ex_stats);
++      export_stats_destroy(exp->ex_stats);
++      kfree(exp->ex_stats);
+       kfree(exp->ex_uuid);
+       kfree_rcu(exp, ex_rcu);
+ }
+@@ -744,13 +749,15 @@ static int svc_export_show(struct seq_fi
+       seq_putc(m, '\t');
+       seq_escape(m, exp->ex_client->name, " \t\n\\");
+       if (export_stats) {
+-              seq_printf(m, "\t%lld\n", exp->ex_stats.start_time);
++              struct percpu_counter *counter = exp->ex_stats->counter;
++
++              seq_printf(m, "\t%lld\n", exp->ex_stats->start_time);
+               seq_printf(m, "\tfh_stale: %lld\n",
+-                         percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_FH_STALE]));
++                         percpu_counter_sum_positive(&counter[EXP_STATS_FH_STALE]));
+               seq_printf(m, "\tio_read: %lld\n",
+-                         percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_IO_READ]));
++                         percpu_counter_sum_positive(&counter[EXP_STATS_IO_READ]));
+               seq_printf(m, "\tio_write: %lld\n",
+-                         percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_IO_WRITE]));
++                         percpu_counter_sum_positive(&counter[EXP_STATS_IO_WRITE]));
+               seq_putc(m, '\n');
+               return 0;
+       }
+@@ -796,7 +803,7 @@ static void svc_export_init(struct cache
+       new->ex_layout_types = 0;
+       new->ex_uuid = NULL;
+       new->cd = item->cd;
+-      export_stats_reset(&new->ex_stats);
++      export_stats_reset(new->ex_stats);
+ }
+ static void export_update(struct cache_head *cnew, struct cache_head *citem)
+@@ -832,7 +839,14 @@ static struct cache_head *svc_export_all
+       if (!i)
+               return NULL;
+-      if (export_stats_init(&i->ex_stats)) {
++      i->ex_stats = kmalloc(sizeof(*(i->ex_stats)), GFP_KERNEL);
++      if (!i->ex_stats) {
++              kfree(i);
++              return NULL;
++      }
++
++      if (export_stats_init(i->ex_stats)) {
++              kfree(i->ex_stats);
+               kfree(i);
+               return NULL;
+       }
+--- a/fs/nfsd/export.h
++++ b/fs/nfsd/export.h
+@@ -64,10 +64,10 @@ struct svc_export {
+       struct cache_head       h;
+       struct auth_domain *    ex_client;
+       int                     ex_flags;
++      int                     ex_fsid;
+       struct path             ex_path;
+       kuid_t                  ex_anon_uid;
+       kgid_t                  ex_anon_gid;
+-      int                     ex_fsid;
+       unsigned char *         ex_uuid; /* 16 byte fsid */
+       struct nfsd4_fs_locations ex_fslocs;
+       uint32_t                ex_nflavors;
+@@ -76,7 +76,7 @@ struct svc_export {
+       struct nfsd4_deviceid_map *ex_devid_map;
+       struct cache_detail     *cd;
+       struct rcu_head         ex_rcu;
+-      struct export_stats     ex_stats;
++      struct export_stats     *ex_stats;
+ };
+ /* an "export key" (expkey) maps a filehandlefragement to an
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -60,22 +60,22 @@ static inline void nfsd_stats_rc_nocache
+ static inline void nfsd_stats_fh_stale_inc(struct svc_export *exp)
+ {
+       percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_FH_STALE]);
+-      if (exp)
+-              percpu_counter_inc(&exp->ex_stats.counter[EXP_STATS_FH_STALE]);
++      if (exp && exp->ex_stats)
++              percpu_counter_inc(&exp->ex_stats->counter[EXP_STATS_FH_STALE]);
+ }
+ static inline void nfsd_stats_io_read_add(struct svc_export *exp, s64 amount)
+ {
+       percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_READ], amount);
+-      if (exp)
+-              percpu_counter_add(&exp->ex_stats.counter[EXP_STATS_IO_READ], amount);
++      if (exp && exp->ex_stats)
++              percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_READ], amount);
+ }
+ static inline void nfsd_stats_io_write_add(struct svc_export *exp, s64 amount)
+ {
+       percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_WRITE], amount);
+-      if (exp)
+-              percpu_counter_add(&exp->ex_stats.counter[EXP_STATS_IO_WRITE], amount);
++      if (exp && exp->ex_stats)
++              percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_WRITE], amount);
+ }
+ static inline void nfsd_stats_payload_misses_inc(struct nfsd_net *nn)
diff --git a/queue-6.1/nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch b/queue-6.1/nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch
new file mode 100644 (file)
index 0000000..2e81bda
--- /dev/null
@@ -0,0 +1,436 @@
+From stable+bounces-66337-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:28 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:07 -0400
+Subject: nfsd: make all of the nfsd stats per-network namespace
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-17-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 4b14885411f74b2b0ce0eb2b39d0fffe54e5ca0d ]
+
+We have a global set of counters that we modify for all of the nfsd
+operations, but now that we're exposing these stats across all network
+namespaces we need to make the stats also be per-network namespace.  We
+already have some caching stats that are per-network namespace, so move
+these definitions into the same counter and then adjust all the helpers
+and users of these stats to provide the appropriate nfsd_net struct so
+that the stats are maintained for the per-network namespace objects.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to v6.1.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/cache.h    |    2 --
+ fs/nfsd/netns.h    |   17 +++++++++++++++--
+ fs/nfsd/nfs4proc.c |    6 +++---
+ fs/nfsd/nfscache.c |   36 +++++++-----------------------------
+ fs/nfsd/nfsctl.c   |   12 +++---------
+ fs/nfsd/nfsfh.c    |    3 ++-
+ fs/nfsd/stats.c    |   24 +++++++++++++-----------
+ fs/nfsd/stats.h    |   49 +++++++++++++++++--------------------------------
+ fs/nfsd/vfs.c      |    6 ++++--
+ 9 files changed, 64 insertions(+), 91 deletions(-)
+
+--- a/fs/nfsd/cache.h
++++ b/fs/nfsd/cache.h
+@@ -80,8 +80,6 @@ enum {
+ int   nfsd_drc_slab_create(void);
+ void  nfsd_drc_slab_free(void);
+-int   nfsd_net_reply_cache_init(struct nfsd_net *nn);
+-void  nfsd_net_reply_cache_destroy(struct nfsd_net *nn);
+ int   nfsd_reply_cache_init(struct nfsd_net *);
+ void  nfsd_reply_cache_shutdown(struct nfsd_net *);
+ int   nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -10,6 +10,7 @@
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
++#include <linux/nfs4.h>
+ #include <linux/percpu_counter.h>
+ #include <linux/siphash.h>
+@@ -28,7 +29,19 @@ enum {
+       NFSD_STATS_PAYLOAD_MISSES,
+       /* amount of memory (in bytes) currently consumed by the DRC */
+       NFSD_STATS_DRC_MEM_USAGE,
+-      NFSD_NET_COUNTERS_NUM
++      NFSD_STATS_RC_HITS,             /* repcache hits */
++      NFSD_STATS_RC_MISSES,           /* repcache misses */
++      NFSD_STATS_RC_NOCACHE,          /* uncached reqs */
++      NFSD_STATS_FH_STALE,            /* FH stale error */
++      NFSD_STATS_IO_READ,             /* bytes returned to read requests */
++      NFSD_STATS_IO_WRITE,            /* bytes passed in write requests */
++#ifdef CONFIG_NFSD_V4
++      NFSD_STATS_FIRST_NFS4_OP,       /* count of individual nfsv4 operations */
++      NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
++#define NFSD_STATS_NFS4_OP(op)        (NFSD_STATS_FIRST_NFS4_OP + (op))
++      NFSD_STATS_WDELEG_GETATTR,      /* count of getattr conflict with wdeleg */
++#endif
++      NFSD_STATS_COUNTERS_NUM
+ };
+ /*
+@@ -168,7 +181,7 @@ struct nfsd_net {
+       atomic_t                 num_drc_entries;
+       /* Per-netns stats counters */
+-      struct percpu_counter    counter[NFSD_NET_COUNTERS_NUM];
++      struct percpu_counter    counter[NFSD_STATS_COUNTERS_NUM];
+       /* longest hash chain seen */
+       unsigned int             longest_chain;
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2430,10 +2430,10 @@ nfsd4_proc_null(struct svc_rqst *rqstp)
+       return rpc_success;
+ }
+-static inline void nfsd4_increment_op_stats(u32 opnum)
++static inline void nfsd4_increment_op_stats(struct nfsd_net *nn, u32 opnum)
+ {
+       if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
+-              percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_NFS4_OP(opnum)]);
++              percpu_counter_inc(&nn->counter[NFSD_STATS_NFS4_OP(opnum)]);
+ }
+ static const struct nfsd4_operation nfsd4_ops[];
+@@ -2708,7 +2708,7 @@ encode_op:
+                                          status, nfsd4_op_name(op->opnum));
+               nfsd4_cstate_clear_replay(cstate);
+-              nfsd4_increment_op_stats(op->opnum);
++              nfsd4_increment_op_stats(nn, op->opnum);
+       }
+       fh_put(current_fh);
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -176,27 +176,6 @@ void nfsd_drc_slab_free(void)
+       kmem_cache_destroy(drc_slab);
+ }
+-/**
+- * nfsd_net_reply_cache_init - per net namespace reply cache set-up
+- * @nn: nfsd_net being initialized
+- *
+- * Returns zero on succes; otherwise a negative errno is returned.
+- */
+-int nfsd_net_reply_cache_init(struct nfsd_net *nn)
+-{
+-      return nfsd_percpu_counters_init(nn->counter, NFSD_NET_COUNTERS_NUM);
+-}
+-
+-/**
+- * nfsd_net_reply_cache_destroy - per net namespace reply cache tear-down
+- * @nn: nfsd_net being freed
+- *
+- */
+-void nfsd_net_reply_cache_destroy(struct nfsd_net *nn)
+-{
+-      nfsd_percpu_counters_destroy(nn->counter, NFSD_NET_COUNTERS_NUM);
+-}
+-
+ int nfsd_reply_cache_init(struct nfsd_net *nn)
+ {
+       unsigned int hashsize;
+@@ -501,7 +480,7 @@ out:
+ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+                     unsigned int len)
+ {
+-      struct nfsd_net         *nn;
++      struct nfsd_net         *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       struct svc_cacherep     *rp, *found;
+       __wsum                  csum;
+       struct nfsd_drc_bucket  *b;
+@@ -512,7 +491,7 @@ int nfsd_cache_lookup(struct svc_rqst *r
+       rqstp->rq_cacherep = NULL;
+       if (type == RC_NOCACHE) {
+-              nfsd_stats_rc_nocache_inc();
++              nfsd_stats_rc_nocache_inc(nn);
+               goto out;
+       }
+@@ -522,7 +501,6 @@ int nfsd_cache_lookup(struct svc_rqst *r
+        * Since the common case is a cache miss followed by an insert,
+        * preallocate an entry.
+        */
+-      nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       rp = nfsd_cacherep_alloc(rqstp, csum, nn);
+       if (!rp)
+               goto out;
+@@ -540,7 +518,7 @@ int nfsd_cache_lookup(struct svc_rqst *r
+       freed = nfsd_cacherep_dispose(&dispose);
+       trace_nfsd_drc_gc(nn, freed);
+-      nfsd_stats_rc_misses_inc();
++      nfsd_stats_rc_misses_inc(nn);
+       atomic_inc(&nn->num_drc_entries);
+       nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp));
+       goto out;
+@@ -548,7 +526,7 @@ int nfsd_cache_lookup(struct svc_rqst *r
+ found_entry:
+       /* We found a matching entry which is either in progress or done. */
+       nfsd_reply_cache_free_locked(NULL, rp, nn);
+-      nfsd_stats_rc_hits_inc();
++      nfsd_stats_rc_hits_inc(nn);
+       rtn = RC_DROPIT;
+       rp = found;
+@@ -698,11 +676,11 @@ int nfsd_reply_cache_stats_show(struct s
+       seq_printf(m, "mem usage:             %lld\n",
+                  percpu_counter_sum_positive(&nn->counter[NFSD_STATS_DRC_MEM_USAGE]));
+       seq_printf(m, "cache hits:            %lld\n",
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]));
+       seq_printf(m, "cache misses:          %lld\n",
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]));
+       seq_printf(m, "not cached:            %lld\n",
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]));
+       seq_printf(m, "payload misses:        %lld\n",
+                  percpu_counter_sum_positive(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]));
+       seq_printf(m, "longest chain len:     %u\n", nn->longest_chain);
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1450,7 +1450,7 @@ static __net_init int nfsd_init_net(stru
+       retval = nfsd_idmap_init(net);
+       if (retval)
+               goto out_idmap_error;
+-      retval = nfsd_net_reply_cache_init(nn);
++      retval = nfsd_stat_counters_init(nn);
+       if (retval)
+               goto out_repcache_error;
+       nn->nfsd_versions = NULL;
+@@ -1475,7 +1475,7 @@ static __net_exit void nfsd_exit_net(str
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       nfsd_proc_stat_shutdown(net);
+-      nfsd_net_reply_cache_destroy(nn);
++      nfsd_stat_counters_destroy(nn);
+       nfsd_idmap_shutdown(net);
+       nfsd_export_shutdown(net);
+       nfsd_netns_free_versions(nn);
+@@ -1498,12 +1498,9 @@ static int __init init_nfsd(void)
+       retval = nfsd4_init_pnfs();
+       if (retval)
+               goto out_free_slabs;
+-      retval = nfsd_stat_counters_init();     /* Statistics */
+-      if (retval)
+-              goto out_free_pnfs;
+       retval = nfsd_drc_slab_create();
+       if (retval)
+-              goto out_free_stat;
++              goto out_free_pnfs;
+       nfsd_lockd_init();      /* lockd->nfsd callbacks */
+       retval = create_proc_exports_entry();
+       if (retval)
+@@ -1533,8 +1530,6 @@ out_free_exports:
+ out_free_lockd:
+       nfsd_lockd_shutdown();
+       nfsd_drc_slab_free();
+-out_free_stat:
+-      nfsd_stat_counters_destroy();
+ out_free_pnfs:
+       nfsd4_exit_pnfs();
+ out_free_slabs:
+@@ -1551,7 +1546,6 @@ static void __exit exit_nfsd(void)
+       nfsd_drc_slab_free();
+       remove_proc_entry("fs/nfs/exports", NULL);
+       remove_proc_entry("fs/nfs", NULL);
+-      nfsd_stat_counters_destroy();
+       nfsd_lockd_shutdown();
+       nfsd4_free_slabs();
+       nfsd4_exit_pnfs();
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -327,6 +327,7 @@ out:
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
+ {
++      struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       struct svc_export *exp = NULL;
+       struct dentry   *dentry;
+       __be32          error;
+@@ -395,7 +396,7 @@ skip_pseudoflavor_check:
+ out:
+       trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error);
+       if (error == nfserr_stale)
+-              nfsd_stats_fh_stale_inc(exp);
++              nfsd_stats_fh_stale_inc(nn, exp);
+       return error;
+ }
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -34,15 +34,17 @@ struct svc_stat            nfsd_svcstats = {
+ static int nfsd_show(struct seq_file *seq, void *v)
+ {
++      struct net *net = pde_data(file_inode(seq->file));
++      struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int i;
+       seq_printf(seq, "rc %lld %lld %lld\nfh %lld 0 0 0 0\nio %lld %lld\n",
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]),
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES]),
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]),
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_FH_STALE]),
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_READ]),
+-                 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]),
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]),
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]),
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_FH_STALE]),
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_READ]),
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_WRITE]));
+       /* thread usage: */
+       seq_printf(seq, "th %u 0", atomic_read(&nfsdstats.th_cnt));
+@@ -63,7 +65,7 @@ static int nfsd_show(struct seq_file *se
+       seq_printf(seq,"proc4ops %u", LAST_NFS4_OP + 1);
+       for (i = 0; i <= LAST_NFS4_OP; i++) {
+               seq_printf(seq, " %lld",
+-                         percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_NFS4_OP(i)]));
++                         percpu_counter_sum_positive(&nn->counter[NFSD_STATS_NFS4_OP(i)]));
+       }
+       seq_putc(seq, '\n');
+@@ -106,14 +108,14 @@ void nfsd_percpu_counters_destroy(struct
+               percpu_counter_destroy(&counters[i]);
+ }
+-int nfsd_stat_counters_init(void)
++int nfsd_stat_counters_init(struct nfsd_net *nn)
+ {
+-      return nfsd_percpu_counters_init(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
++      return nfsd_percpu_counters_init(nn->counter, NFSD_STATS_COUNTERS_NUM);
+ }
+-void nfsd_stat_counters_destroy(void)
++void nfsd_stat_counters_destroy(struct nfsd_net *nn)
+ {
+-      nfsd_percpu_counters_destroy(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
++      nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM);
+ }
+ void nfsd_proc_stat_init(struct net *net)
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -10,25 +10,7 @@
+ #include <uapi/linux/nfsd/stats.h>
+ #include <linux/percpu_counter.h>
+-
+-enum {
+-      NFSD_STATS_RC_HITS,             /* repcache hits */
+-      NFSD_STATS_RC_MISSES,           /* repcache misses */
+-      NFSD_STATS_RC_NOCACHE,          /* uncached reqs */
+-      NFSD_STATS_FH_STALE,            /* FH stale error */
+-      NFSD_STATS_IO_READ,             /* bytes returned to read requests */
+-      NFSD_STATS_IO_WRITE,            /* bytes passed in write requests */
+-#ifdef CONFIG_NFSD_V4
+-      NFSD_STATS_FIRST_NFS4_OP,       /* count of individual nfsv4 operations */
+-      NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
+-#define NFSD_STATS_NFS4_OP(op)        (NFSD_STATS_FIRST_NFS4_OP + (op))
+-#endif
+-      NFSD_STATS_COUNTERS_NUM
+-};
+-
+ struct nfsd_stats {
+-      struct percpu_counter   counter[NFSD_STATS_COUNTERS_NUM];
+-
+       atomic_t        th_cnt;         /* number of available threads */
+ };
+@@ -39,43 +21,46 @@ extern struct svc_stat             nfsd_svcstats;
+ int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
+-int nfsd_stat_counters_init(void);
+-void nfsd_stat_counters_destroy(void);
++int nfsd_stat_counters_init(struct nfsd_net *nn);
++void nfsd_stat_counters_destroy(struct nfsd_net *nn);
+ void nfsd_proc_stat_init(struct net *net);
+ void nfsd_proc_stat_shutdown(struct net *net);
+-static inline void nfsd_stats_rc_hits_inc(void)
++static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn)
+ {
+-      percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_HITS]);
++      percpu_counter_inc(&nn->counter[NFSD_STATS_RC_HITS]);
+ }
+-static inline void nfsd_stats_rc_misses_inc(void)
++static inline void nfsd_stats_rc_misses_inc(struct nfsd_net *nn)
+ {
+-      percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_MISSES]);
++      percpu_counter_inc(&nn->counter[NFSD_STATS_RC_MISSES]);
+ }
+-static inline void nfsd_stats_rc_nocache_inc(void)
++static inline void nfsd_stats_rc_nocache_inc(struct nfsd_net *nn)
+ {
+-      percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]);
++      percpu_counter_inc(&nn->counter[NFSD_STATS_RC_NOCACHE]);
+ }
+-static inline void nfsd_stats_fh_stale_inc(struct svc_export *exp)
++static inline void nfsd_stats_fh_stale_inc(struct nfsd_net *nn,
++                                         struct svc_export *exp)
+ {
+-      percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_FH_STALE]);
++      percpu_counter_inc(&nn->counter[NFSD_STATS_FH_STALE]);
+       if (exp && exp->ex_stats)
+               percpu_counter_inc(&exp->ex_stats->counter[EXP_STATS_FH_STALE]);
+ }
+-static inline void nfsd_stats_io_read_add(struct svc_export *exp, s64 amount)
++static inline void nfsd_stats_io_read_add(struct nfsd_net *nn,
++                                        struct svc_export *exp, s64 amount)
+ {
+-      percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_READ], amount);
++      percpu_counter_add(&nn->counter[NFSD_STATS_IO_READ], amount);
+       if (exp && exp->ex_stats)
+               percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_READ], amount);
+ }
+-static inline void nfsd_stats_io_write_add(struct svc_export *exp, s64 amount)
++static inline void nfsd_stats_io_write_add(struct nfsd_net *nn,
++                                         struct svc_export *exp, s64 amount)
+ {
+-      percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_WRITE], amount);
++      percpu_counter_add(&nn->counter[NFSD_STATS_IO_WRITE], amount);
+       if (exp && exp->ex_stats)
+               percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_WRITE], amount);
+ }
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -983,7 +983,9 @@ static __be32 nfsd_finish_read(struct sv
+                              unsigned long *count, u32 *eof, ssize_t host_err)
+ {
+       if (host_err >= 0) {
+-              nfsd_stats_io_read_add(fhp->fh_export, host_err);
++              struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
++
++              nfsd_stats_io_read_add(nn, fhp->fh_export, host_err);
+               *eof = nfsd_eof_on_read(file, offset, host_err, *count);
+               *count = host_err;
+               fsnotify_access(file);
+@@ -1126,7 +1128,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
+               goto out_nfserr;
+       }
+       *cnt = host_err;
+-      nfsd_stats_io_write_add(exp, *cnt);
++      nfsd_stats_io_write_add(nn, exp, *cnt);
+       fsnotify_modify(file);
+       host_err = filemap_check_wb_err(file->f_mapping, since);
+       if (host_err < 0)
diff --git a/queue-6.1/nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch b/queue-6.1/nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch
new file mode 100644 (file)
index 0000000..66f2e6a
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-66339-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:33 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:09 -0400
+Subject: nfsd: make svc_stat per-network namespace instead of global
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-19-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 16fb9808ab2c99979f081987752abcbc5b092eac ]
+
+The final bit of stats that is global is the rpc svc_stat.  Move this
+into the nfsd_net struct and use that everywhere instead of the global
+struct.  Remove the unused global struct.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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  |    4 ++++
+ fs/nfsd/nfsctl.c |    2 ++
+ fs/nfsd/nfssvc.c |    2 +-
+ fs/nfsd/stats.c  |   10 ++++------
+ fs/nfsd/stats.h  |    2 --
+ 5 files changed, 11 insertions(+), 9 deletions(-)
+
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -13,6 +13,7 @@
+ #include <linux/nfs4.h>
+ #include <linux/percpu_counter.h>
+ #include <linux/siphash.h>
++#include <linux/sunrpc/stats.h>
+ /* Hash tables for nfs4_clientid state */
+ #define CLIENT_HASH_BITS                 4
+@@ -183,6 +184,9 @@ struct nfsd_net {
+       /* Per-netns stats counters */
+       struct percpu_counter    counter[NFSD_STATS_COUNTERS_NUM];
++      /* sunrpc svc stats */
++      struct svc_stat          nfsd_svcstats;
++
+       /* longest hash chain seen */
+       unsigned int             longest_chain;
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1453,6 +1453,8 @@ static __net_init int nfsd_init_net(stru
+       retval = nfsd_stat_counters_init(nn);
+       if (retval)
+               goto out_repcache_error;
++      memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
++      nn->nfsd_svcstats.program = &nfsd_program;
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+       nfsd4_init_leases_net(nn);
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -657,7 +657,7 @@ int nfsd_create_serv(struct net *net)
+       if (nfsd_max_blksize == 0)
+               nfsd_max_blksize = nfsd_get_default_max_blksize();
+       nfsd_reset_versions(nn);
+-      serv = svc_create_pooled(&nfsd_program, &nfsd_svcstats,
++      serv = svc_create_pooled(&nfsd_program, &nn->nfsd_svcstats,
+                                nfsd_max_blksize, nfsd);
+       if (serv == NULL)
+               return -ENOMEM;
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -27,10 +27,6 @@
+ #include "nfsd.h"
+-struct svc_stat               nfsd_svcstats = {
+-      .program        = &nfsd_program,
+-};
+-
+ static int nfsd_show(struct seq_file *seq, void *v)
+ {
+       struct net *net = pde_data(file_inode(seq->file));
+@@ -56,7 +52,7 @@ static int nfsd_show(struct seq_file *se
+       seq_puts(seq, "\nra 0 0 0 0 0 0 0 0 0 0 0 0\n");
+       /* show my rpc info */
+-      svc_seq_show(seq, &nfsd_svcstats);
++      svc_seq_show(seq, &nn->nfsd_svcstats);
+ #ifdef CONFIG_NFSD_V4
+       /* Show count for individual nfsv4 operations */
+@@ -119,7 +115,9 @@ void nfsd_stat_counters_destroy(struct n
+ void nfsd_proc_stat_init(struct net *net)
+ {
+-      svc_proc_register(net, &nfsd_svcstats, &nfsd_proc_ops);
++      struct nfsd_net *nn = net_generic(net, nfsd_net_id);
++
++      svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
+ }
+ void nfsd_proc_stat_shutdown(struct net *net)
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -10,8 +10,6 @@
+ #include <uapi/linux/nfsd/stats.h>
+ #include <linux/percpu_counter.h>
+-extern struct svc_stat                nfsd_svcstats;
+-
+ int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
diff --git a/queue-6.1/nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch b/queue-6.1/nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch
new file mode 100644 (file)
index 0000000..4af69e8
--- /dev/null
@@ -0,0 +1,163 @@
+From stable+bounces-66323-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:38 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:53 -0400
+Subject: nfsd: move init of percpu reply_cache_stats counters back to nfsd_init_net
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Jeff Layton <jlayton@kernel.org>, Eirik Fuller <efuller@redhat.com>
+Message-ID: <20240810200009.9882-3-cel@kernel.org>
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit ed9ab7346e908496816cffdecd46932035f66e2e ]
+
+Commit f5f9d4a314da ("nfsd: move reply cache initialization into nfsd
+startup") moved the initialization of the reply cache into nfsd startup,
+but didn't account for the stats counters, which can be accessed before
+nfsd is ever started. The result can be a NULL pointer dereference when
+someone accesses /proc/fs/nfsd/reply_cache_stats while nfsd is still
+shut down.
+
+This is a regression and a user-triggerable oops in the right situation:
+
+- non-x86_64 arch
+- /proc/fs/nfsd is mounted in the namespace
+- nfsd is not started in the namespace
+- unprivileged user calls "cat /proc/fs/nfsd/reply_cache_stats"
+
+Although this is easy to trigger on some arches (like aarch64), on
+x86_64, calling this_cpu_ptr(NULL) evidently returns a pointer to the
+fixed_percpu_data. That struct looks just enough like a newly
+initialized percpu var to allow nfsd_reply_cache_stats_show to access
+it without Oopsing.
+
+Move the initialization of the per-net+per-cpu reply-cache counters
+back into nfsd_init_net, while leaving the rest of the reply cache
+allocations to be done at nfsd startup time.
+
+Kudos to Eirik who did most of the legwork to track this down.
+
+Cc: stable@vger.kernel.org # v6.3+
+Fixes: f5f9d4a314da ("nfsd: move reply cache initialization into nfsd startup")
+Reported-and-tested-by: Eirik Fuller <efuller@redhat.com>
+Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2215429
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 4b14885411f7 ("nfsd: make all of the nfsd stats per-network namespace")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/cache.h    |    2 ++
+ fs/nfsd/nfscache.c |   25 ++++++++++++++-----------
+ fs/nfsd/nfsctl.c   |   10 +++++++++-
+ 3 files changed, 25 insertions(+), 12 deletions(-)
+
+--- a/fs/nfsd/cache.h
++++ b/fs/nfsd/cache.h
+@@ -80,6 +80,8 @@ enum {
+ int   nfsd_drc_slab_create(void);
+ void  nfsd_drc_slab_free(void);
++int   nfsd_net_reply_cache_init(struct nfsd_net *nn);
++void  nfsd_net_reply_cache_destroy(struct nfsd_net *nn);
+ int   nfsd_reply_cache_init(struct nfsd_net *);
+ void  nfsd_reply_cache_shutdown(struct nfsd_net *);
+ int   nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -148,12 +148,23 @@ void nfsd_drc_slab_free(void)
+       kmem_cache_destroy(drc_slab);
+ }
+-static int nfsd_reply_cache_stats_init(struct nfsd_net *nn)
++/**
++ * nfsd_net_reply_cache_init - per net namespace reply cache set-up
++ * @nn: nfsd_net being initialized
++ *
++ * Returns zero on succes; otherwise a negative errno is returned.
++ */
++int nfsd_net_reply_cache_init(struct nfsd_net *nn)
+ {
+       return nfsd_percpu_counters_init(nn->counter, NFSD_NET_COUNTERS_NUM);
+ }
+-static void nfsd_reply_cache_stats_destroy(struct nfsd_net *nn)
++/**
++ * nfsd_net_reply_cache_destroy - per net namespace reply cache tear-down
++ * @nn: nfsd_net being freed
++ *
++ */
++void nfsd_net_reply_cache_destroy(struct nfsd_net *nn)
+ {
+       nfsd_percpu_counters_destroy(nn->counter, NFSD_NET_COUNTERS_NUM);
+ }
+@@ -169,17 +180,13 @@ int nfsd_reply_cache_init(struct nfsd_ne
+       hashsize = nfsd_hashsize(nn->max_drc_entries);
+       nn->maskbits = ilog2(hashsize);
+-      status = nfsd_reply_cache_stats_init(nn);
+-      if (status)
+-              goto out_nomem;
+-
+       nn->nfsd_reply_cache_shrinker.scan_objects = nfsd_reply_cache_scan;
+       nn->nfsd_reply_cache_shrinker.count_objects = nfsd_reply_cache_count;
+       nn->nfsd_reply_cache_shrinker.seeks = 1;
+       status = register_shrinker(&nn->nfsd_reply_cache_shrinker,
+                                  "nfsd-reply:%s", nn->nfsd_name);
+       if (status)
+-              goto out_stats_destroy;
++              return status;
+       nn->drc_hashtbl = kvzalloc(array_size(hashsize,
+                               sizeof(*nn->drc_hashtbl)), GFP_KERNEL);
+@@ -195,9 +202,6 @@ int nfsd_reply_cache_init(struct nfsd_ne
+       return 0;
+ out_shrinker:
+       unregister_shrinker(&nn->nfsd_reply_cache_shrinker);
+-out_stats_destroy:
+-      nfsd_reply_cache_stats_destroy(nn);
+-out_nomem:
+       printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
+       return -ENOMEM;
+ }
+@@ -217,7 +221,6 @@ void nfsd_reply_cache_shutdown(struct nf
+                                                                       rp, nn);
+               }
+       }
+-      nfsd_reply_cache_stats_destroy(nn);
+       kvfree(nn->drc_hashtbl);
+       nn->drc_hashtbl = NULL;
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1450,6 +1450,9 @@ static __net_init int nfsd_init_net(stru
+       retval = nfsd_idmap_init(net);
+       if (retval)
+               goto out_idmap_error;
++      retval = nfsd_net_reply_cache_init(nn);
++      if (retval)
++              goto out_repcache_error;
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+       nfsd4_init_leases_net(nn);
+@@ -1458,6 +1461,8 @@ static __net_init int nfsd_init_net(stru
+       return 0;
++out_repcache_error:
++      nfsd_idmap_shutdown(net);
+ out_idmap_error:
+       nfsd_export_shutdown(net);
+ out_export_error:
+@@ -1466,9 +1471,12 @@ out_export_error:
+ static __net_exit void nfsd_exit_net(struct net *net)
+ {
++      struct nfsd_net *nn = net_generic(net, nfsd_net_id);
++
++      nfsd_net_reply_cache_destroy(nn);
+       nfsd_idmap_shutdown(net);
+       nfsd_export_shutdown(net);
+-      nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
++      nfsd_netns_free_versions(nn);
+ }
+ static struct pernet_operations nfsd_net_ops = {
diff --git a/queue-6.1/nfsd-move-reply-cache-initialization-into-nfsd-startup.patch b/queue-6.1/nfsd-move-reply-cache-initialization-into-nfsd-startup.patch
new file mode 100644 (file)
index 0000000..5b66ae3
--- /dev/null
@@ -0,0 +1,92 @@
+From stable+bounces-66322-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:30 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:52 -0400
+Subject: nfsd: move reply cache initialization into nfsd startup
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Jeff Layton <jlayton@kernel.org>, Dai Ngo <dai.ngo@oracle.com>
+Message-ID: <20240810200009.9882-2-cel@kernel.org>
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit f5f9d4a314da88c0a5faa6d168bf69081b7a25ae ]
+
+There's no need to start the reply cache before nfsd is up and running,
+and doing so means that we register a shrinker for every net namespace
+instead of just the ones where nfsd is running.
+
+Move it to the per-net nfsd startup instead.
+
+Reported-by: Dai Ngo <dai.ngo@oracle.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: ed9ab7346e90 ("nfsd: move init of percpu reply_cache_stats counters back to nfsd_init_net")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfsctl.c |    8 --------
+ fs/nfsd/nfssvc.c |   10 +++++++++-
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1453,16 +1453,11 @@ static __net_init int nfsd_init_net(stru
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+       nfsd4_init_leases_net(nn);
+-      retval = nfsd_reply_cache_init(nn);
+-      if (retval)
+-              goto out_cache_error;
+       get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
+       seqlock_init(&nn->writeverf_lock);
+       return 0;
+-out_cache_error:
+-      nfsd_idmap_shutdown(net);
+ out_idmap_error:
+       nfsd_export_shutdown(net);
+ out_export_error:
+@@ -1471,9 +1466,6 @@ out_export_error:
+ static __net_exit void nfsd_exit_net(struct net *net)
+ {
+-      struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+-
+-      nfsd_reply_cache_shutdown(nn);
+       nfsd_idmap_shutdown(net);
+       nfsd_export_shutdown(net);
+       nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -427,16 +427,23 @@ static int nfsd_startup_net(struct net *
+       ret = nfsd_file_cache_start_net(net);
+       if (ret)
+               goto out_lockd;
+-      ret = nfs4_state_start_net(net);
++
++      ret = nfsd_reply_cache_init(nn);
+       if (ret)
+               goto out_filecache;
++      ret = nfs4_state_start_net(net);
++      if (ret)
++              goto out_reply_cache;
++
+ #ifdef CONFIG_NFSD_V4_2_INTER_SSC
+       nfsd4_ssc_init_umount_work(nn);
+ #endif
+       nn->nfsd_net_up = true;
+       return 0;
++out_reply_cache:
++      nfsd_reply_cache_shutdown(nn);
+ out_filecache:
+       nfsd_file_cache_shutdown_net(net);
+ out_lockd:
+@@ -454,6 +461,7 @@ static void nfsd_shutdown_net(struct net
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       nfs4_state_shutdown_net(net);
++      nfsd_reply_cache_shutdown(nn);
+       nfsd_file_cache_shutdown_net(net);
+       if (nn->lockd_up) {
+               lockd_down(net);
diff --git a/queue-6.1/nfsd-refactor-nfsd_reply_cache_free_locked.patch b/queue-6.1/nfsd-refactor-nfsd_reply_cache_free_locked.patch
new file mode 100644 (file)
index 0000000..4988ea4
--- /dev/null
@@ -0,0 +1,83 @@
+From stable+bounces-66324-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:43 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:54 -0400
+Subject: NFSD: Refactor nfsd_reply_cache_free_locked()
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-4-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 35308e7f0fc3942edc87d9c6dc78c4a096428957 ]
+
+To reduce contention on the bucket locks, we must avoid calling
+kfree() while each bucket lock is held.
+
+Start by refactoring nfsd_reply_cache_free_locked() into a helper
+that removes an entry from the bucket (and must therefore run under
+the lock) and a second helper that frees the entry (which does not
+need to hold the lock).
+
+For readability, rename the helpers nfsd_cacherep_<verb>.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: a9507f6af145 ("NFSD: Replace nfsd_prune_bucket()")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfscache.c |   27 ++++++++++++++++++++-------
+ 1 file changed, 20 insertions(+), 7 deletions(-)
+
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -110,21 +110,33 @@ nfsd_reply_cache_alloc(struct svc_rqst *
+       return rp;
+ }
++static void nfsd_cacherep_free(struct svc_cacherep *rp)
++{
++      if (rp->c_type == RC_REPLBUFF)
++              kfree(rp->c_replvec.iov_base);
++      kmem_cache_free(drc_slab, rp);
++}
++
+ static void
+-nfsd_reply_cache_free_locked(struct nfsd_drc_bucket *b, struct svc_cacherep *rp,
+-                              struct nfsd_net *nn)
++nfsd_cacherep_unlink_locked(struct nfsd_net *nn, struct nfsd_drc_bucket *b,
++                          struct svc_cacherep *rp)
+ {
+-      if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) {
++      if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base)
+               nfsd_stats_drc_mem_usage_sub(nn, rp->c_replvec.iov_len);
+-              kfree(rp->c_replvec.iov_base);
+-      }
+       if (rp->c_state != RC_UNUSED) {
+               rb_erase(&rp->c_node, &b->rb_head);
+               list_del(&rp->c_lru);
+               atomic_dec(&nn->num_drc_entries);
+               nfsd_stats_drc_mem_usage_sub(nn, sizeof(*rp));
+       }
+-      kmem_cache_free(drc_slab, rp);
++}
++
++static void
++nfsd_reply_cache_free_locked(struct nfsd_drc_bucket *b, struct svc_cacherep *rp,
++                              struct nfsd_net *nn)
++{
++      nfsd_cacherep_unlink_locked(nn, b, rp);
++      nfsd_cacherep_free(rp);
+ }
+ static void
+@@ -132,8 +144,9 @@ nfsd_reply_cache_free(struct nfsd_drc_bu
+                       struct nfsd_net *nn)
+ {
+       spin_lock(&b->cache_lock);
+-      nfsd_reply_cache_free_locked(b, rp, nn);
++      nfsd_cacherep_unlink_locked(nn, b, rp);
+       spin_unlock(&b->cache_lock);
++      nfsd_cacherep_free(rp);
+ }
+ int nfsd_drc_slab_create(void)
diff --git a/queue-6.1/nfsd-refactor-the-duplicate-reply-cache-shrinker.patch b/queue-6.1/nfsd-refactor-the-duplicate-reply-cache-shrinker.patch
new file mode 100644 (file)
index 0000000..6e2e08d
--- /dev/null
@@ -0,0 +1,134 @@
+From stable+bounces-66327-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:59 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:57 -0400
+Subject: NFSD: Refactor the duplicate reply cache shrinker
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-7-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit c135e1269f34dfdea4bd94c11060c83a3c0b3c12 ]
+
+Avoid holding the bucket lock while freeing cache entries. This
+change also caps the number of entries that are freed when the
+shrinker calls to reduce the shrinker's impact on the cache's
+effectiveness.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to v6.1.y -- this one might not be necessary ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfscache.c |   83 ++++++++++++++++++++++++-----------------------------
+ 1 file changed, 39 insertions(+), 44 deletions(-)
+
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -310,67 +310,62 @@ nfsd_prune_bucket_locked(struct nfsd_net
+       }
+ }
+-static long prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn,
+-                       unsigned int max)
++/**
++ * nfsd_reply_cache_count - count_objects method for the DRC shrinker
++ * @shrink: our registered shrinker context
++ * @sc: garbage collection parameters
++ *
++ * Returns the total number of entries in the duplicate reply cache. To
++ * keep things simple and quick, this is not the number of expired entries
++ * in the cache (ie, the number that would be removed by a call to
++ * nfsd_reply_cache_scan).
++ */
++static unsigned long
++nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc)
+ {
+-      struct svc_cacherep *rp, *tmp;
+-      long freed = 0;
++      struct nfsd_net *nn = container_of(shrink,
++                              struct nfsd_net, nfsd_reply_cache_shrinker);
+-      list_for_each_entry_safe(rp, tmp, &b->lru_head, c_lru) {
+-              /*
+-               * Don't free entries attached to calls that are still
+-               * in-progress, but do keep scanning the list.
+-               */
+-              if (rp->c_state == RC_INPROG)
+-                      continue;
+-              if (atomic_read(&nn->num_drc_entries) <= nn->max_drc_entries &&
+-                  time_before(jiffies, rp->c_timestamp + RC_EXPIRE))
+-                      break;
+-              nfsd_reply_cache_free_locked(b, rp, nn);
+-              if (max && freed++ > max)
+-                      break;
+-      }
+-      return freed;
++      return atomic_read(&nn->num_drc_entries);
+ }
+-/*
+- * Walk the LRU list and prune off entries that are older than RC_EXPIRE.
+- * Also prune the oldest ones when the total exceeds the max number of entries.
++/**
++ * nfsd_reply_cache_scan - scan_objects method for the DRC shrinker
++ * @shrink: our registered shrinker context
++ * @sc: garbage collection parameters
++ *
++ * Free expired entries on each bucket's LRU list until we've released
++ * nr_to_scan freed objects. Nothing will be released if the cache
++ * has not exceeded it's max_drc_entries limit.
++ *
++ * Returns the number of entries released by this call.
+  */
+-static long
+-prune_cache_entries(struct nfsd_net *nn)
++static unsigned long
++nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc)
+ {
++      struct nfsd_net *nn = container_of(shrink,
++                              struct nfsd_net, nfsd_reply_cache_shrinker);
++      unsigned long freed = 0;
++      LIST_HEAD(dispose);
+       unsigned int i;
+-      long freed = 0;
+       for (i = 0; i < nn->drc_hashsize; i++) {
+               struct nfsd_drc_bucket *b = &nn->drc_hashtbl[i];
+               if (list_empty(&b->lru_head))
+                       continue;
++
+               spin_lock(&b->cache_lock);
+-              freed += prune_bucket(b, nn, 0);
++              nfsd_prune_bucket_locked(nn, b, 0, &dispose);
+               spin_unlock(&b->cache_lock);
+-      }
+-      return freed;
+-}
+-
+-static unsigned long
+-nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc)
+-{
+-      struct nfsd_net *nn = container_of(shrink,
+-                              struct nfsd_net, nfsd_reply_cache_shrinker);
+-      return atomic_read(&nn->num_drc_entries);
+-}
+-
+-static unsigned long
+-nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc)
+-{
+-      struct nfsd_net *nn = container_of(shrink,
+-                              struct nfsd_net, nfsd_reply_cache_shrinker);
++              freed += nfsd_cacherep_dispose(&dispose);
++              if (freed > sc->nr_to_scan)
++                      break;
++      }
+-      return prune_cache_entries(nn);
++      trace_nfsd_drc_gc(nn, freed);
++      return freed;
+ }
+ /**
diff --git a/queue-6.1/nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch b/queue-6.1/nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch
new file mode 100644 (file)
index 0000000..780e28c
--- /dev/null
@@ -0,0 +1,98 @@
+From stable+bounces-66338-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:30 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:08 -0400
+Subject: nfsd: remove nfsd_stats, make th_cnt a global counter
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-18-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit e41ee44cc6a473b1f414031782c3b4283d7f3e5f ]
+
+This is the last global stat, take it out of the nfsd_stats struct and
+make it a global part of nfsd, report it the same as always.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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/nfsd.h   |    1 +
+ fs/nfsd/nfssvc.c |    5 +++--
+ fs/nfsd/stats.c  |    3 +--
+ fs/nfsd/stats.h  |    6 ------
+ 4 files changed, 5 insertions(+), 10 deletions(-)
+
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -69,6 +69,7 @@ extern struct mutex          nfsd_mutex;
+ extern spinlock_t             nfsd_drc_lock;
+ extern unsigned long          nfsd_drc_max_mem;
+ extern unsigned long          nfsd_drc_mem_used;
++extern atomic_t                       nfsd_th_cnt;            /* number of available threads */
+ extern const struct seq_operations nfs_exports_op;
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -34,6 +34,7 @@
+ #define NFSDDBG_FACILITY      NFSDDBG_SVC
++atomic_t                      nfsd_th_cnt = ATOMIC_INIT(0);
+ extern struct svc_program     nfsd_program;
+ static int                    nfsd(void *vrqstp);
+ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+@@ -955,7 +956,7 @@ nfsd(void *vrqstp)
+       current->fs->umask = 0;
+-      atomic_inc(&nfsdstats.th_cnt);
++      atomic_inc(&nfsd_th_cnt);
+       set_freezable();
+@@ -979,7 +980,7 @@ nfsd(void *vrqstp)
+               validate_process_creds();
+       }
+-      atomic_dec(&nfsdstats.th_cnt);
++      atomic_dec(&nfsd_th_cnt);
+ out:
+       /* Take an extra ref so that the svc_put in svc_exit_thread()
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -27,7 +27,6 @@
+ #include "nfsd.h"
+-struct nfsd_stats     nfsdstats;
+ struct svc_stat               nfsd_svcstats = {
+       .program        = &nfsd_program,
+ };
+@@ -47,7 +46,7 @@ static int nfsd_show(struct seq_file *se
+                  percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_WRITE]));
+       /* thread usage: */
+-      seq_printf(seq, "th %u 0", atomic_read(&nfsdstats.th_cnt));
++      seq_printf(seq, "th %u 0", atomic_read(&nfsd_th_cnt));
+       /* deprecated thread usage histogram stats */
+       for (i = 0; i < 10; i++)
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -10,12 +10,6 @@
+ #include <uapi/linux/nfsd/stats.h>
+ #include <linux/percpu_counter.h>
+-struct nfsd_stats {
+-      atomic_t        th_cnt;         /* number of available threads */
+-};
+-
+-extern struct nfsd_stats      nfsdstats;
+-
+ extern struct svc_stat                nfsd_svcstats;
+ int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
diff --git a/queue-6.1/nfsd-rename-nfsd_net_-to-nfsd_stats_.patch b/queue-6.1/nfsd-rename-nfsd_net_-to-nfsd_stats_.patch
new file mode 100644 (file)
index 0000000..505b21e
--- /dev/null
@@ -0,0 +1,83 @@
+From stable+bounces-66335-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:22 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:05 -0400
+Subject: nfsd: rename NFSD_NET_* to NFSD_STATS_*
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-15-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit d98416cc2154053950610bb6880911e3dcbdf8c5 ]
+
+We're going to merge the stats all into per network namespace in
+subsequent patches, rename these nn counters to be consistent with the
+rest of the stats.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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    |    4 ++--
+ fs/nfsd/nfscache.c |    4 ++--
+ fs/nfsd/stats.h    |    6 +++---
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -25,9 +25,9 @@ struct nfsd4_client_tracking_ops;
+ enum {
+       /* cache misses due only to checksum comparison failures */
+-      NFSD_NET_PAYLOAD_MISSES,
++      NFSD_STATS_PAYLOAD_MISSES,
+       /* amount of memory (in bytes) currently consumed by the DRC */
+-      NFSD_NET_DRC_MEM_USAGE,
++      NFSD_STATS_DRC_MEM_USAGE,
+       NFSD_NET_COUNTERS_NUM
+ };
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -696,7 +696,7 @@ int nfsd_reply_cache_stats_show(struct s
+                  atomic_read(&nn->num_drc_entries));
+       seq_printf(m, "hash buckets:          %u\n", 1 << nn->maskbits);
+       seq_printf(m, "mem usage:             %lld\n",
+-                 percpu_counter_sum_positive(&nn->counter[NFSD_NET_DRC_MEM_USAGE]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_DRC_MEM_USAGE]));
+       seq_printf(m, "cache hits:            %lld\n",
+                  percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]));
+       seq_printf(m, "cache misses:          %lld\n",
+@@ -704,7 +704,7 @@ int nfsd_reply_cache_stats_show(struct s
+       seq_printf(m, "not cached:            %lld\n",
+                  percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]));
+       seq_printf(m, "payload misses:        %lld\n",
+-                 percpu_counter_sum_positive(&nn->counter[NFSD_NET_PAYLOAD_MISSES]));
++                 percpu_counter_sum_positive(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]));
+       seq_printf(m, "longest chain len:     %u\n", nn->longest_chain);
+       seq_printf(m, "cachesize at longest:  %u\n", nn->longest_chain_cachesize);
+       return 0;
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -80,17 +80,17 @@ static inline void nfsd_stats_io_write_a
+ static inline void nfsd_stats_payload_misses_inc(struct nfsd_net *nn)
+ {
+-      percpu_counter_inc(&nn->counter[NFSD_NET_PAYLOAD_MISSES]);
++      percpu_counter_inc(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]);
+ }
+ static inline void nfsd_stats_drc_mem_usage_add(struct nfsd_net *nn, s64 amount)
+ {
+-      percpu_counter_add(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount);
++      percpu_counter_add(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ }
+ static inline void nfsd_stats_drc_mem_usage_sub(struct nfsd_net *nn, s64 amount)
+ {
+-      percpu_counter_sub(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount);
++      percpu_counter_sub(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ }
+ #endif /* _NFSD_STATS_H */
diff --git a/queue-6.1/nfsd-rename-nfsd_reply_cache_alloc.patch b/queue-6.1/nfsd-rename-nfsd_reply_cache_alloc.patch
new file mode 100644 (file)
index 0000000..5d5495c
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-66325-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:49 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:55 -0400
+Subject: NFSD: Rename nfsd_reply_cache_alloc()
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-5-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit ff0d169329768c1102b7b07eebe5a9839aa1c143 ]
+
+For readability, rename to match the other helpers.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 4b14885411f7 ("nfsd: make all of the nfsd stats per-network namespace")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfscache.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -85,8 +85,8 @@ nfsd_hashsize(unsigned int limit)
+ }
+ static struct svc_cacherep *
+-nfsd_reply_cache_alloc(struct svc_rqst *rqstp, __wsum csum,
+-                      struct nfsd_net *nn)
++nfsd_cacherep_alloc(struct svc_rqst *rqstp, __wsum csum,
++                  struct nfsd_net *nn)
+ {
+       struct svc_cacherep     *rp;
+@@ -481,7 +481,7 @@ int nfsd_cache_lookup(struct svc_rqst *r
+        * preallocate an entry.
+        */
+       nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+-      rp = nfsd_reply_cache_alloc(rqstp, csum, nn);
++      rp = nfsd_cacherep_alloc(rqstp, csum, nn);
+       if (!rp)
+               goto out;
diff --git a/queue-6.1/nfsd-replace-nfsd_prune_bucket.patch b/queue-6.1/nfsd-replace-nfsd_prune_bucket.patch
new file mode 100644 (file)
index 0000000..b37916e
--- /dev/null
@@ -0,0 +1,187 @@
+From stable+bounces-66326-greg=kroah.com@vger.kernel.org Sat Aug 10 22:00:52 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:56 -0400
+Subject: NFSD: Replace nfsd_prune_bucket()
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-6-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit a9507f6af1450ed26a4a36d979af518f5bb21e5d ]
+
+Enable nfsd_prune_bucket() to drop the bucket lock while calling
+kfree(). Use the same pattern that Jeff recently introduced in the
+NFSD filecache.
+
+A few percpu operations are moved outside the lock since they
+temporarily disable local IRQs which is expensive and does not
+need to be done while the lock is held.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: c135e1269f34 ("NFSD: Refactor the duplicate reply cache shrinker")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfscache.c |   78 ++++++++++++++++++++++++++++++++++++++++++-----------
+ fs/nfsd/trace.h    |   22 ++++++++++++++
+ 2 files changed, 85 insertions(+), 15 deletions(-)
+
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -117,6 +117,21 @@ static void nfsd_cacherep_free(struct sv
+       kmem_cache_free(drc_slab, rp);
+ }
++static unsigned long
++nfsd_cacherep_dispose(struct list_head *dispose)
++{
++      struct svc_cacherep *rp;
++      unsigned long freed = 0;
++
++      while (!list_empty(dispose)) {
++              rp = list_first_entry(dispose, struct svc_cacherep, c_lru);
++              list_del(&rp->c_lru);
++              nfsd_cacherep_free(rp);
++              freed++;
++      }
++      return freed;
++}
++
+ static void
+ nfsd_cacherep_unlink_locked(struct nfsd_net *nn, struct nfsd_drc_bucket *b,
+                           struct svc_cacherep *rp)
+@@ -260,6 +275,41 @@ nfsd_cache_bucket_find(__be32 xid, struc
+       return &nn->drc_hashtbl[hash];
+ }
++/*
++ * Remove and return no more than @max expired entries in bucket @b.
++ * If @max is zero, do not limit the number of removed entries.
++ */
++static void
++nfsd_prune_bucket_locked(struct nfsd_net *nn, struct nfsd_drc_bucket *b,
++                       unsigned int max, struct list_head *dispose)
++{
++      unsigned long expiry = jiffies - RC_EXPIRE;
++      struct svc_cacherep *rp, *tmp;
++      unsigned int freed = 0;
++
++      lockdep_assert_held(&b->cache_lock);
++
++      /* The bucket LRU is ordered oldest-first. */
++      list_for_each_entry_safe(rp, tmp, &b->lru_head, c_lru) {
++              /*
++               * Don't free entries attached to calls that are still
++               * in-progress, but do keep scanning the list.
++               */
++              if (rp->c_state == RC_INPROG)
++                      continue;
++
++              if (atomic_read(&nn->num_drc_entries) <= nn->max_drc_entries &&
++                  time_before(expiry, rp->c_timestamp))
++                      break;
++
++              nfsd_cacherep_unlink_locked(nn, b, rp);
++              list_add(&rp->c_lru, dispose);
++
++              if (max && ++freed > max)
++                      break;
++      }
++}
++
+ static long prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn,
+                        unsigned int max)
+ {
+@@ -283,11 +333,6 @@ static long prune_bucket(struct nfsd_drc
+       return freed;
+ }
+-static long nfsd_prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
+-{
+-      return prune_bucket(b, nn, 3);
+-}
+-
+ /*
+  * Walk the LRU list and prune off entries that are older than RC_EXPIRE.
+  * Also prune the oldest ones when the total exceeds the max number of entries.
+@@ -466,6 +511,8 @@ int nfsd_cache_lookup(struct svc_rqst *r
+       __wsum                  csum;
+       struct nfsd_drc_bucket  *b;
+       int type = rqstp->rq_cachetype;
++      unsigned long freed;
++      LIST_HEAD(dispose);
+       int rtn = RC_DOIT;
+       rqstp->rq_cacherep = NULL;
+@@ -490,20 +537,18 @@ int nfsd_cache_lookup(struct svc_rqst *r
+       found = nfsd_cache_insert(b, rp, nn);
+       if (found != rp)
+               goto found_entry;
+-
+-      nfsd_stats_rc_misses_inc();
+       rqstp->rq_cacherep = rp;
+       rp->c_state = RC_INPROG;
++      nfsd_prune_bucket_locked(nn, b, 3, &dispose);
++      spin_unlock(&b->cache_lock);
++      freed = nfsd_cacherep_dispose(&dispose);
++      trace_nfsd_drc_gc(nn, freed);
++
++      nfsd_stats_rc_misses_inc();
+       atomic_inc(&nn->num_drc_entries);
+       nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp));
+-
+-      nfsd_prune_bucket(b, nn);
+-
+-out_unlock:
+-      spin_unlock(&b->cache_lock);
+-out:
+-      return rtn;
++      goto out;
+ found_entry:
+       /* We found a matching entry which is either in progress or done. */
+@@ -541,7 +586,10 @@ found_entry:
+ out_trace:
+       trace_nfsd_drc_found(nn, rqstp, rtn);
+-      goto out_unlock;
++out_unlock:
++      spin_unlock(&b->cache_lock);
++out:
++      return rtn;
+ }
+ /**
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -1261,6 +1261,28 @@ TRACE_EVENT(nfsd_drc_mismatch,
+               __entry->ingress)
+ );
++TRACE_EVENT_CONDITION(nfsd_drc_gc,
++      TP_PROTO(
++              const struct nfsd_net *nn,
++              unsigned long freed
++      ),
++      TP_ARGS(nn, freed),
++      TP_CONDITION(freed > 0),
++      TP_STRUCT__entry(
++              __field(unsigned long long, boot_time)
++              __field(unsigned long, freed)
++              __field(int, total)
++      ),
++      TP_fast_assign(
++              __entry->boot_time = nn->boot_time;
++              __entry->freed = freed;
++              __entry->total = atomic_read(&nn->num_drc_entries);
++      ),
++      TP_printk("boot_time=%16llx total=%d freed=%lu",
++              __entry->boot_time, __entry->total, __entry->freed
++      )
++);
++
+ TRACE_EVENT(nfsd_cb_args,
+       TP_PROTO(
+               const struct nfs4_client *clp,
diff --git a/queue-6.1/nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch b/queue-6.1/nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch
new file mode 100644 (file)
index 0000000..3b88595
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-66328-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:02 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 15:59:58 -0400
+Subject: NFSD: Rewrite synopsis of nfsd_percpu_counters_init()
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever <chuck.lever@oracle.com>, Amir Goldstein <amir73il@gmail.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-8-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 5ec39944f874e1ecc09f624a70dfaa8ac3bf9d08 ]
+
+In function â€˜export_stats_init’,
+    inlined from â€˜svc_export_alloc’ at fs/nfsd/export.c:866:6:
+fs/nfsd/export.c:337:16: warning: â€˜nfsd_percpu_counters_init’ accessing 40 bytes in a region of size 0 [-Wstringop-overflow=]
+  337 |         return nfsd_percpu_counters_init(&stats->counter, EXP_STATS_COUNTERS_NUM);
+      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+fs/nfsd/export.c:337:16: note: referencing argument 1 of type â€˜struct percpu_counter[0]’
+fs/nfsd/stats.h: In function â€˜svc_export_alloc’:
+fs/nfsd/stats.h:40:5: note: in a call to function â€˜nfsd_percpu_counters_init’
+   40 | int nfsd_percpu_counters_init(struct percpu_counter counters[], int num);
+      |     ^~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cc: Amir Goldstein <amir73il@gmail.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 93483ac5fec6 ("nfsd: expose /proc/net/sunrpc/nfsd in net namespaces")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/stats.c |    2 +-
+ fs/nfsd/stats.h |    6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -74,7 +74,7 @@ static int nfsd_show(struct seq_file *se
+ DEFINE_PROC_SHOW_ATTRIBUTE(nfsd);
+-int nfsd_percpu_counters_init(struct percpu_counter counters[], int num)
++int nfsd_percpu_counters_init(struct percpu_counter *counters, int num)
+ {
+       int i, err = 0;
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -36,9 +36,9 @@ extern struct nfsd_stats     nfsdstats;
+ extern struct svc_stat                nfsd_svcstats;
+-int nfsd_percpu_counters_init(struct percpu_counter counters[], int num);
+-void nfsd_percpu_counters_reset(struct percpu_counter counters[], int num);
+-void nfsd_percpu_counters_destroy(struct percpu_counter counters[], int num);
++int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
++void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
++void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
+ int nfsd_stat_init(void);
+ void nfsd_stat_shutdown(void);
diff --git a/queue-6.1/nfsd-stop-setting-pg_stats-for-unused-stats.patch b/queue-6.1/nfsd-stop-setting-pg_stats-for-unused-stats.patch
new file mode 100644 (file)
index 0000000..701d6da
--- /dev/null
@@ -0,0 +1,89 @@
+From stable+bounces-66331-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:12 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:01 -0400
+Subject: nfsd: stop setting ->pg_stats for unused stats
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-11-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit a2214ed588fb3c5b9824a21cff870482510372bb ]
+
+A lot of places are setting a blank svc_stats in ->pg_stats and never
+utilizing these stats.  Remove all of these extra structs as we're not
+reporting these stats anywhere.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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/lockd/svc.c    |    3 ---
+ fs/nfs/callback.c |    3 ---
+ fs/nfsd/nfssvc.c  |    5 -----
+ 3 files changed, 11 deletions(-)
+
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -759,8 +759,6 @@ static const struct svc_version *nlmsvc_
+ #endif
+ };
+-static struct svc_stat                nlmsvc_stats;
+-
+ #define NLM_NRVERS    ARRAY_SIZE(nlmsvc_version)
+ static struct svc_program     nlmsvc_program = {
+       .pg_prog                = NLM_PROGRAM,          /* program number */
+@@ -768,7 +766,6 @@ static struct svc_program  nlmsvc_program
+       .pg_vers                = nlmsvc_version,       /* version table */
+       .pg_name                = "lockd",              /* service name */
+       .pg_class               = "nfsd",               /* share authentication with nfsd */
+-      .pg_stats               = &nlmsvc_stats,        /* stats table */
+       .pg_authenticate        = &lockd_authenticate,  /* export authentication */
+       .pg_init_request        = svc_generic_init_request,
+       .pg_rpcbind_set         = svc_generic_rpcbind_set,
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -407,15 +407,12 @@ static const struct svc_version *nfs4_ca
+       [4] = &nfs4_callback_version4,
+ };
+-static struct svc_stat nfs4_callback_stats;
+-
+ static struct svc_program nfs4_callback_program = {
+       .pg_prog = NFS4_CALLBACK,                       /* RPC service number */
+       .pg_nvers = ARRAY_SIZE(nfs4_callback_version),  /* Number of entries */
+       .pg_vers = nfs4_callback_version,               /* version table */
+       .pg_name = "NFSv4 callback",                    /* service name */
+       .pg_class = "nfs",                              /* authentication class */
+-      .pg_stats = &nfs4_callback_stats,
+       .pg_authenticate = nfs_callback_authenticate,
+       .pg_init_request = svc_generic_init_request,
+       .pg_rpcbind_set = svc_generic_rpcbind_set,
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -89,7 +89,6 @@ unsigned long        nfsd_drc_max_mem;
+ 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,
+@@ -108,15 +107,11 @@ static struct svc_program        nfsd_acl_progr
+       .pg_vers                = nfsd_acl_version,
+       .pg_name                = "nfsacl",
+       .pg_class               = "nfsd",
+-      .pg_stats               = &nfsd_acl_svcstats,
+       .pg_authenticate        = &svc_set_client,
+       .pg_init_request        = nfsd_acl_init_request,
+       .pg_rpcbind_set         = nfsd_acl_rpcbind_set,
+ };
+-static struct svc_stat        nfsd_acl_svcstats = {
+-      .program        = &nfsd_acl_program,
+-};
+ #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+ static const struct svc_version *nfsd_version[] = {
diff --git a/queue-6.1/nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch b/queue-6.1/nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch
new file mode 100644 (file)
index 0000000..09f2a5a
--- /dev/null
@@ -0,0 +1,39 @@
+From ab091ec536cb7b271983c0c063b17f62f3591583 Mon Sep 17 00:00:00 2001
+From: WangYuli <wangyuli@uniontech.com>
+Date: Mon, 15 Jul 2024 17:31:44 +0800
+Subject: nvme/pci: Add APST quirk for Lenovo N60z laptop
+
+From: WangYuli <wangyuli@uniontech.com>
+
+commit ab091ec536cb7b271983c0c063b17f62f3591583 upstream.
+
+There is a hardware power-saving problem with the Lenovo N60z
+board. When turn it on and leave it for 10 hours, there is a
+20% chance that a nvme disk will not wake up until reboot.
+
+Link: https://lore.kernel.org/all/2B5581C46AC6E335+9c7a81f1-05fb-4fd0-9fbb-108757c21628@uniontech.com
+Signed-off-by: hmy <huanglin@uniontech.com>
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: WangYuli <wangyuli@uniontech.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/pci.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3109,6 +3109,13 @@ static unsigned long check_vendor_combin
+                       return NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND;
+       }
++      /*
++       * NVMe SSD drops off the PCIe bus after system idle
++       * for 10 hours on a Lenovo N60z board.
++       */
++      if (dmi_match(DMI_BOARD_NAME, "LXKT-ZXEG-N6"))
++              return NVME_QUIRK_NO_APST;
++
+       return 0;
+ }
index c5715f0c50dec6be1beb4fa5392f094ec0291b0a..0ecdb3fe6984bb3f41b2b8c1f4ebd2b341cf68c1 100644 (file)
@@ -6,3 +6,25 @@ selftests-mptcp-join-test-both-signal-subflow.patch
 asoc-topology-clean-up-route-loading.patch
 asoc-topology-fix-route-memory-corruption.patch
 exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch
+loongarch-define-__arch_want_new_stat-in-unistd.h.patch
+nfsd-move-reply-cache-initialization-into-nfsd-startup.patch
+nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch
+nfsd-refactor-nfsd_reply_cache_free_locked.patch
+nfsd-rename-nfsd_reply_cache_alloc.patch
+nfsd-replace-nfsd_prune_bucket.patch
+nfsd-refactor-the-duplicate-reply-cache-shrinker.patch
+nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch
+nfsd-fix-frame-size-warning-in-svc_export_parse.patch
+sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch
+nfsd-stop-setting-pg_stats-for-unused-stats.patch
+sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch
+sunrpc-remove-pg_stats-from-svc_program.patch
+sunrpc-use-the-struct-net-as-the-svc-proc-private.patch
+nfsd-rename-nfsd_net_-to-nfsd_stats_.patch
+nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch
+nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch
+nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch
+nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch
+nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch
+mptcp-fully-established-after-add_addr-echo-on-mpj.patch
+drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch
diff --git a/queue-6.1/sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch b/queue-6.1/sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch
new file mode 100644 (file)
index 0000000..e787f96
--- /dev/null
@@ -0,0 +1,110 @@
+From stable+bounces-66330-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:11 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:00 -0400
+Subject: sunrpc: don't change ->sv_stats if it doesn't exist
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-10-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit ab42f4d9a26f1723dcfd6c93fcf768032b2bb5e7 ]
+
+We check for the existence of ->sv_stats elsewhere except in the core
+processing code.  It appears that only nfsd actual exports these values
+anywhere, everybody else just has a write only copy of sv_stats in their
+svc_program.  Add a check for ->sv_stats before every adjustment to
+allow us to eliminate the stats struct from all the users who don't
+report the stats.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to v6.1.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/svc.c |   24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -1324,7 +1324,8 @@ svc_process_common(struct svc_rqst *rqst
+               goto err_bad_proc;
+       /* Syntactic check complete */
+-      serv->sv_stats->rpccnt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpccnt++;
+       trace_svc_process(rqstp, progp->pg_name);
+       /* Build the reply header. */
+@@ -1377,7 +1378,8 @@ err_short_len:
+       goto close_xprt;
+ err_bad_rpc:
+-      serv->sv_stats->rpcbadfmt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadfmt++;
+       svc_putnl(resv, 1);     /* REJECT */
+       svc_putnl(resv, 0);     /* RPC_MISMATCH */
+       svc_putnl(resv, 2);     /* Only RPCv2 supported */
+@@ -1387,7 +1389,8 @@ err_bad_rpc:
+ err_bad_auth:
+       dprintk("svc: authentication failed (%d)\n",
+               be32_to_cpu(rqstp->rq_auth_stat));
+-      serv->sv_stats->rpcbadauth++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadauth++;
+       /* Restore write pointer to location of accept status: */
+       xdr_ressize_check(rqstp, reply_statp);
+       svc_putnl(resv, 1);     /* REJECT */
+@@ -1397,7 +1400,8 @@ err_bad_auth:
+ err_bad_prog:
+       dprintk("svc: unknown program %d\n", prog);
+-      serv->sv_stats->rpcbadfmt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadfmt++;
+       svc_putnl(resv, RPC_PROG_UNAVAIL);
+       goto sendit;
+@@ -1405,7 +1409,8 @@ err_bad_vers:
+       svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n",
+                      rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
+-      serv->sv_stats->rpcbadfmt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadfmt++;
+       svc_putnl(resv, RPC_PROG_MISMATCH);
+       svc_putnl(resv, process.mismatch.lovers);
+       svc_putnl(resv, process.mismatch.hivers);
+@@ -1414,7 +1419,8 @@ err_bad_vers:
+ err_bad_proc:
+       svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
+-      serv->sv_stats->rpcbadfmt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadfmt++;
+       svc_putnl(resv, RPC_PROC_UNAVAIL);
+       goto sendit;
+@@ -1423,7 +1429,8 @@ err_garbage:
+       rpc_stat = rpc_garbage_args;
+ err_bad:
+-      serv->sv_stats->rpcbadfmt++;
++      if (serv->sv_stats)
++              serv->sv_stats->rpcbadfmt++;
+       svc_putnl(resv, ntohl(rpc_stat));
+       goto sendit;
+ }
+@@ -1469,7 +1476,8 @@ svc_process(struct svc_rqst *rqstp)
+ out_baddir:
+       svc_printk(rqstp, "bad direction 0x%08x, dropping request\n",
+                  be32_to_cpu(dir));
+-      rqstp->rq_server->sv_stats->rpcbadfmt++;
++      if (rqstp->rq_server->sv_stats)
++              rqstp->rq_server->sv_stats->rpcbadfmt++;
+ out_drop:
+       svc_drop(rqstp);
+       return 0;
diff --git a/queue-6.1/sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch b/queue-6.1/sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch
new file mode 100644 (file)
index 0000000..adb52d7
--- /dev/null
@@ -0,0 +1,107 @@
+From stable+bounces-66332-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:17 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:02 -0400
+Subject: sunrpc: pass in the sv_stats struct through svc_create_pooled
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-12-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit f094323867668d50124886ad884b665de7319537 ]
+
+Since only one service actually reports the rpc stats there's not much
+of a reason to have a pointer to it in the svc_program struct.  Adjust
+the svc_create_pooled function to take the sv_stats as an argument and
+pass the struct through there as desired instead of getting it from the
+svc_program->pg_stats.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to v6.1.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfssvc.c           |    3 ++-
+ include/linux/sunrpc/svc.h |    4 +++-
+ net/sunrpc/svc.c           |   12 +++++++-----
+ 3 files changed, 12 insertions(+), 7 deletions(-)
+
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -657,7 +657,8 @@ int nfsd_create_serv(struct net *net)
+       if (nfsd_max_blksize == 0)
+               nfsd_max_blksize = nfsd_get_default_max_blksize();
+       nfsd_reset_versions(nn);
+-      serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, nfsd);
++      serv = svc_create_pooled(&nfsd_program, &nfsd_svcstats,
++                               nfsd_max_blksize, nfsd);
+       if (serv == NULL)
+               return -ENOMEM;
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -493,7 +493,9 @@ void                  svc_rqst_replace_page(struct sv
+                                        struct page *page);
+ void             svc_rqst_free(struct svc_rqst *);
+ void             svc_exit_thread(struct svc_rqst *);
+-struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
++struct svc_serv *  svc_create_pooled(struct svc_program *prog,
++                                   struct svc_stat *stats,
++                                   unsigned int bufsize,
+                                    int (*threadfn)(void *data));
+ int              svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
+ int              svc_pool_stats_open(struct svc_serv *serv, struct file *file);
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -453,8 +453,8 @@ __svc_init_bc(struct svc_serv *serv)
+  * Create an RPC service
+  */
+ static struct svc_serv *
+-__svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
+-           int (*threadfn)(void *data))
++__svc_create(struct svc_program *prog, struct svc_stat *stats,
++           unsigned int bufsize, int npools, int (*threadfn)(void *data))
+ {
+       struct svc_serv *serv;
+       unsigned int vers;
+@@ -466,7 +466,7 @@ __svc_create(struct svc_program *prog, u
+       serv->sv_name      = prog->pg_name;
+       serv->sv_program   = prog;
+       kref_init(&serv->sv_refcnt);
+-      serv->sv_stats     = prog->pg_stats;
++      serv->sv_stats     = stats;
+       if (bufsize > RPCSVC_MAXPAYLOAD)
+               bufsize = RPCSVC_MAXPAYLOAD;
+       serv->sv_max_payload = bufsize? bufsize : 4096;
+@@ -528,26 +528,28 @@ __svc_create(struct svc_program *prog, u
+ struct svc_serv *svc_create(struct svc_program *prog, unsigned int bufsize,
+                           int (*threadfn)(void *data))
+ {
+-      return __svc_create(prog, bufsize, 1, threadfn);
++      return __svc_create(prog, NULL, bufsize, 1, threadfn);
+ }
+ EXPORT_SYMBOL_GPL(svc_create);
+ /**
+  * svc_create_pooled - Create an RPC service with pooled threads
+  * @prog: the RPC program the new service will handle
++ * @stats: the stats struct if desired
+  * @bufsize: maximum message size for @prog
+  * @threadfn: a function to service RPC requests for @prog
+  *
+  * Returns an instantiated struct svc_serv object or NULL.
+  */
+ struct svc_serv *svc_create_pooled(struct svc_program *prog,
++                                 struct svc_stat *stats,
+                                  unsigned int bufsize,
+                                  int (*threadfn)(void *data))
+ {
+       struct svc_serv *serv;
+       unsigned int npools = svc_pool_map_get();
+-      serv = __svc_create(prog, bufsize, npools, threadfn);
++      serv = __svc_create(prog, stats, bufsize, npools, threadfn);
+       if (!serv)
+               goto out_err;
+       return serv;
diff --git a/queue-6.1/sunrpc-remove-pg_stats-from-svc_program.patch b/queue-6.1/sunrpc-remove-pg_stats-from-svc_program.patch
new file mode 100644 (file)
index 0000000..e54c451
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-66333-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:19 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:03 -0400
+Subject: sunrpc: remove ->pg_stats from svc_program
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-13-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 3f6ef182f144dcc9a4d942f97b6a8ed969f13c95 ]
+
+Now that this isn't used anywhere, remove it.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to v6.1.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfssvc.c           |    1 -
+ include/linux/sunrpc/svc.h |    1 -
+ 2 files changed, 2 deletions(-)
+
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -136,7 +136,6 @@ struct svc_program         nfsd_program = {
+       .pg_vers                = nfsd_version,         /* version table */
+       .pg_name                = "nfsd",               /* program name */
+       .pg_class               = "nfsd",               /* authentication class */
+-      .pg_stats               = &nfsd_svcstats,       /* version table */
+       .pg_authenticate        = &svc_set_client,      /* export authentication */
+       .pg_init_request        = nfsd_init_request,
+       .pg_rpcbind_set         = nfsd_rpcbind_set,
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -422,7 +422,6 @@ struct svc_program {
+       const struct svc_version **pg_vers;     /* version array */
+       char *                  pg_name;        /* service name */
+       char *                  pg_class;       /* class name: services sharing authentication */
+-      struct svc_stat *       pg_stats;       /* rpc statistics */
+       int                     (*pg_authenticate)(struct svc_rqst *);
+       __be32                  (*pg_init_request)(struct svc_rqst *,
+                                                  const struct svc_program *,
diff --git a/queue-6.1/sunrpc-use-the-struct-net-as-the-svc-proc-private.patch b/queue-6.1/sunrpc-use-the-struct-net-as-the-svc-proc-private.patch
new file mode 100644 (file)
index 0000000..3316b7c
--- /dev/null
@@ -0,0 +1,36 @@
+From stable+bounces-66334-greg=kroah.com@vger.kernel.org Sat Aug 10 22:01:23 2024
+From: cel@kernel.org
+Date: Sat, 10 Aug 2024 16:00:04 -0400
+Subject: sunrpc: use the struct net as the svc proc private
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik <josef@toxicpanda.com>, Jeff Layton <jlayton@kernel.org>
+Message-ID: <20240810200009.9882-14-cel@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 418b9687dece5bd763c09b5c27a801a7e3387be9 ]
+
+nfsd is the only thing using this helper, and it doesn't use the private
+currently.  When we switch to per-network namespace stats we will need
+the struct net * in order to get to the nfsd_net.  Use the net as the
+proc private so we can utilize this when we make the switch over.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.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>
+---
+ net/sunrpc/stats.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sunrpc/stats.c
++++ b/net/sunrpc/stats.c
+@@ -309,7 +309,7 @@ EXPORT_SYMBOL_GPL(rpc_proc_unregister);
+ struct proc_dir_entry *
+ svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops)
+ {
+-      return do_register(net, statp->program->pg_name, statp, proc_ops);
++      return do_register(net, statp->program->pg_name, net, proc_ops);
+ }
+ EXPORT_SYMBOL_GPL(svc_proc_register);