From: Greg Kroah-Hartman Date: Thu, 15 Aug 2024 08:39:55 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v4.19.320~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ede4c2c45e9142142163ccbd13712bf7b2eae243;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches 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 --- 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 index 00000000000..845e7faf6a2 --- /dev/null +++ b/queue-6.1/drm-i915-gem-fix-virtual-memory-mapping-boundaries-calculation.patch @@ -0,0 +1,126 @@ +From 8bdd9ef7e9b1b2a73e394712b72b22055e0e26c3 Mon Sep 17 00:00:00 2001 +From: Andi Shyti +Date: Fri, 2 Aug 2024 10:38:50 +0200 +Subject: drm/i915/gem: Fix Virtual Memory mapping boundaries calculation + +From: Andi Shyti + +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 +Co-developed-by: Chris Wilson +Signed-off-by: Chris Wilson +Signed-off-by: Andi Shyti +Cc: Joonas Lahtinen +Cc: Matthew Auld +Cc: Rodrigo Vivi +Cc: # v4.9+ +Reviewed-by: Jann Horn +Reviewed-by: Jonathan Cavitt +[Joonas: Add Requires: tag] +Requires: 60a2066c5005 ("drm/i915/gem: Adjust vma offset for framebuffer mmap offset") +Signed-off-by: Joonas Lahtinen +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7a2a98fe72b --- /dev/null +++ b/queue-6.1/loongarch-define-__arch_want_new_stat-in-unistd.h.patch @@ -0,0 +1,63 @@ +From 7697a0fe0154468f5df35c23ebd7aa48994c2cdc Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Sat, 20 Jul 2024 22:40:58 +0800 +Subject: LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h + +From: Huacai Chen + +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..582a3eb1893 --- /dev/null +++ b/queue-6.1/mptcp-fully-established-after-add_addr-echo-on-mpj.patch @@ -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)" +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 , "Matthieu Baerts (NGI0)" , Mat Martineau , Jakub Kicinski +Message-ID: <20240813090606.939542-2-matttbe@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +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 +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-1-c8a9b036493b@kernel.org +Signed-off-by: Jakub Kicinski +[ 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) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..50b3723b38a --- /dev/null +++ b/queue-6.1/nfsd-expose-proc-net-sunrpc-nfsd-in-net-namespaces.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-16-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2d341fb9711 --- /dev/null +++ b/queue-6.1/nfsd-fix-frame-size-warning-in-svc_export_parse.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , kernel test robot , Amir Goldstein , Jeff Layton +Message-ID: <20240810200009.9882-9-cel@kernel.org> + +From: Chuck Lever + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202310012359.YEw5IrK6-lkp@intel.com/ +Cc: Amir Goldstein +Reviewed-by: Jeff Layton +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2e81bdac424 --- /dev/null +++ b/queue-6.1/nfsd-make-all-of-the-nfsd-stats-per-network-namespace.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-17-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +[ cel: adjusted to apply to v6.1.y ] +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include ++#include + #include + #include + +@@ -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 + #include + +- +-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 index 00000000000..66f2e6a0a60 --- /dev/null +++ b/queue-6.1/nfsd-make-svc_stat-per-network-namespace-instead-of-global.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-19-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + /* 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 + #include + +-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 index 00000000000..4af69e85512 --- /dev/null +++ b/queue-6.1/nfsd-move-init-of-percpu-reply_cache_stats-counters-back-to-nfsd_init_net.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Jeff Layton , Eirik Fuller +Message-ID: <20240810200009.9882-3-cel@kernel.org> + +From: Jeff Layton + +[ 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 +Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2215429 +Signed-off-by: Jeff Layton +Stable-dep-of: 4b14885411f7 ("nfsd: make all of the nfsd stats per-network namespace") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5b66ae34201 --- /dev/null +++ b/queue-6.1/nfsd-move-reply-cache-initialization-into-nfsd-startup.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Jeff Layton , Dai Ngo +Message-ID: <20240810200009.9882-2-cel@kernel.org> + +From: Jeff Layton + +[ 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 +Signed-off-by: Jeff Layton +Stable-dep-of: ed9ab7346e90 ("nfsd: move init of percpu reply_cache_stats counters back to nfsd_init_net") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4988ea425a0 --- /dev/null +++ b/queue-6.1/nfsd-refactor-nfsd_reply_cache_free_locked.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , Jeff Layton +Message-ID: <20240810200009.9882-4-cel@kernel.org> + +From: Chuck Lever + +[ 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_. + +Reviewed-by: Jeff Layton +Stable-dep-of: a9507f6af145 ("NFSD: Replace nfsd_prune_bucket()") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..6e2e08db465 --- /dev/null +++ b/queue-6.1/nfsd-refactor-the-duplicate-reply-cache-shrinker.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , Jeff Layton +Message-ID: <20240810200009.9882-7-cel@kernel.org> + +From: Chuck Lever + +[ 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 +[ cel: adjusted to apply to v6.1.y -- this one might not be necessary ] +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..780e28c6cef --- /dev/null +++ b/queue-6.1/nfsd-remove-nfsd_stats-make-th_cnt-a-global-counter.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-18-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + +-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 index 00000000000..505b21ec64d --- /dev/null +++ b/queue-6.1/nfsd-rename-nfsd_net_-to-nfsd_stats_.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-15-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5d5495cce86 --- /dev/null +++ b/queue-6.1/nfsd-rename-nfsd_reply_cache_alloc.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , Jeff Layton +Message-ID: <20240810200009.9882-5-cel@kernel.org> + +From: Chuck Lever + +[ Upstream commit ff0d169329768c1102b7b07eebe5a9839aa1c143 ] + +For readability, rename to match the other helpers. + +Reviewed-by: Jeff Layton +Stable-dep-of: 4b14885411f7 ("nfsd: make all of the nfsd stats per-network namespace") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b37916eb8b0 --- /dev/null +++ b/queue-6.1/nfsd-replace-nfsd_prune_bucket.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , Jeff Layton +Message-ID: <20240810200009.9882-6-cel@kernel.org> + +From: Chuck Lever + +[ 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 +Stable-dep-of: c135e1269f34 ("NFSD: Refactor the duplicate reply cache shrinker") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3b885954c65 --- /dev/null +++ b/queue-6.1/nfsd-rewrite-synopsis-of-nfsd_percpu_counters_init.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Chuck Lever , Amir Goldstein , Jeff Layton +Message-ID: <20240810200009.9882-8-cel@kernel.org> + +From: Chuck Lever + +[ 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 +Reviewed-by: Jeff Layton +Stable-dep-of: 93483ac5fec6 ("nfsd: expose /proc/net/sunrpc/nfsd in net namespaces") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..701d6da48b3 --- /dev/null +++ b/queue-6.1/nfsd-stop-setting-pg_stats-for-unused-stats.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-11-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..09f2a5a1429 --- /dev/null +++ b/queue-6.1/nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch @@ -0,0 +1,39 @@ +From ab091ec536cb7b271983c0c063b17f62f3591583 Mon Sep 17 00:00:00 2001 +From: WangYuli +Date: Mon, 15 Jul 2024 17:31:44 +0800 +Subject: nvme/pci: Add APST quirk for Lenovo N60z laptop + +From: WangYuli + +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 +Signed-off-by: Wentao Guan +Signed-off-by: WangYuli +Signed-off-by: Keith Busch +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + diff --git a/queue-6.1/series b/queue-6.1/series index c5715f0c50d..0ecdb3fe698 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 00000000000..e787f96344a --- /dev/null +++ b/queue-6.1/sunrpc-don-t-change-sv_stats-if-it-doesn-t-exist.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-10-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +[ cel: adjusted to apply to v6.1.y ] +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..adb52d7f915 --- /dev/null +++ b/queue-6.1/sunrpc-pass-in-the-sv_stats-struct-through-svc_create_pooled.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-12-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +[ cel: adjusted to apply to v6.1.y ] +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..e54c451e1a6 --- /dev/null +++ b/queue-6.1/sunrpc-remove-pg_stats-from-svc_program.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-13-cel@kernel.org> + +From: Josef Bacik + +[ Upstream commit 3f6ef182f144dcc9a4d942f97b6a8ed969f13c95 ] + +Now that this isn't used anywhere, remove it. + +Signed-off-by: Josef Bacik +Reviewed-by: Jeff Layton +[ cel: adjusted to apply to v6.1.y ] +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3316b7c6bf2 --- /dev/null +++ b/queue-6.1/sunrpc-use-the-struct-net-as-the-svc-proc-private.patch @@ -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: +Cc: , pvorel@suse.cz, sherry.yang@oracle.com, calum.mackay@oracle.com, kernel-team@fb.com, ltp@lists.linux.it, Josef Bacik , Jeff Layton +Message-ID: <20240810200009.9882-14-cel@kernel.org> + +From: Josef Bacik + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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); +