]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jan 2026 11:51:39 +0000 (12:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jan 2026 11:51:39 +0000 (12:51 +0100)
added patches:
alsa-ac97-fix-a-double-free-in-snd_ac97_controller_register.patch
alsa-ac97bus-use-guard-for-mutex-locks.patch
ksm-use-range-walk-function-to-jump-over-holes-in-scan_get_next_rmap_item.patch
mm-pagewalk-add-walk_page_range_vma.patch
nfs-trace-show-timedout-instead-of-0x6e.patch
nfs_common-factor-out-nfs_errtbl-and-nfs_stat_to_errno.patch
nfsd-provide-locking-for-v4_end_grace.patch
nfsd-remove-nfserr_eagain.patch
pinctrl-qcom-lpass-lpi-mark-the-gpio-controller-as-sleeping.patch

queue-6.1/alsa-ac97-fix-a-double-free-in-snd_ac97_controller_register.patch [new file with mode: 0644]
queue-6.1/alsa-ac97bus-use-guard-for-mutex-locks.patch [new file with mode: 0644]
queue-6.1/ksm-use-range-walk-function-to-jump-over-holes-in-scan_get_next_rmap_item.patch [new file with mode: 0644]
queue-6.1/mm-pagewalk-add-walk_page_range_vma.patch [new file with mode: 0644]
queue-6.1/nfs-trace-show-timedout-instead-of-0x6e.patch [new file with mode: 0644]
queue-6.1/nfs_common-factor-out-nfs_errtbl-and-nfs_stat_to_errno.patch [new file with mode: 0644]
queue-6.1/nfsd-provide-locking-for-v4_end_grace.patch [new file with mode: 0644]
queue-6.1/nfsd-remove-nfserr_eagain.patch [new file with mode: 0644]
queue-6.1/pinctrl-qcom-lpass-lpi-mark-the-gpio-controller-as-sleeping.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/alsa-ac97-fix-a-double-free-in-snd_ac97_controller_register.patch b/queue-6.1/alsa-ac97-fix-a-double-free-in-snd_ac97_controller_register.patch
new file mode 100644 (file)
index 0000000..ca8dbf2
--- /dev/null
@@ -0,0 +1,67 @@
+From stable+bounces-208187-greg=kroah.com@vger.kernel.org Mon Jan 12 18:35:39 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 12:31:09 -0500
+Subject: ALSA: ac97: fix a double free in snd_ac97_controller_register()
+To: stable@vger.kernel.org
+Cc: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112173109.826518-2-sashal@kernel.org>
+
+From: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>
+
+[ Upstream commit 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f ]
+
+If ac97_add_adapter() fails, put_device() is the correct way to drop
+the device reference. kfree() is not required.
+Add kfree() if idr_alloc() fails and in ac97_adapter_release() to do
+the cleanup.
+
+Found by code review.
+
+Fixes: 74426fbff66e ("ALSA: ac97: add an ac97 bus")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>
+Link: https://patch.msgid.link/20251219162845.657525-1-lihaoxiang@isrc.iscas.ac.cn
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/ac97/bus.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/sound/ac97/bus.c
++++ b/sound/ac97/bus.c
+@@ -299,6 +299,7 @@ static void ac97_adapter_release(struct
+       idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
+       dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
+               dev_name(ac97_ctrl->parent));
++      kfree(ac97_ctrl);
+ }
+ static const struct device_type ac97_adapter_type = {
+@@ -320,7 +321,9 @@ static int ac97_add_adapter(struct ac97_
+               ret = device_register(&ac97_ctrl->adap);
+               if (ret)
+                       put_device(&ac97_ctrl->adap);
+-      }
++      } else
++              kfree(ac97_ctrl);
++
+       if (!ret) {
+               list_add(&ac97_ctrl->controllers, &ac97_controllers);
+               dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
+@@ -361,14 +364,11 @@ struct ac97_controller *snd_ac97_control
+       ret = ac97_add_adapter(ac97_ctrl);
+       if (ret)
+-              goto err;
++              return ERR_PTR(ret);
+       ac97_bus_reset(ac97_ctrl);
+       ac97_bus_scan(ac97_ctrl);
+       return ac97_ctrl;
+-err:
+-      kfree(ac97_ctrl);
+-      return ERR_PTR(ret);
+ }
+ EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
diff --git a/queue-6.1/alsa-ac97bus-use-guard-for-mutex-locks.patch b/queue-6.1/alsa-ac97bus-use-guard-for-mutex-locks.patch
new file mode 100644 (file)
index 0000000..d61c918
--- /dev/null
@@ -0,0 +1,92 @@
+From stable+bounces-208186-greg=kroah.com@vger.kernel.org Mon Jan 12 18:35:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 12:31:08 -0500
+Subject: ALSA: ac97bus: Use guard() for mutex locks
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112173109.826518-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit c07824a14d99c10edd4ec4c389d219af336ecf20 ]
+
+Replace the manual mutex lock/unlock pairs with guard() for code
+simplification.
+
+Only code refactoring, and no behavior change.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20250829151335.7342-18-tiwai@suse.de
+Stable-dep-of: 830988b6cf19 ("ALSA: ac97: fix a double free in snd_ac97_controller_register()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/ac97/bus.c |   22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/sound/ac97/bus.c
++++ b/sound/ac97/bus.c
+@@ -242,10 +242,9 @@ static ssize_t cold_reset_store(struct d
+ {
+       struct ac97_controller *ac97_ctrl;
+-      mutex_lock(&ac97_controllers_mutex);
++      guard(mutex)(&ac97_controllers_mutex);
+       ac97_ctrl = to_ac97_controller(dev);
+       ac97_ctrl->ops->reset(ac97_ctrl);
+-      mutex_unlock(&ac97_controllers_mutex);
+       return len;
+ }
+ static DEVICE_ATTR_WO(cold_reset);
+@@ -259,10 +258,9 @@ static ssize_t warm_reset_store(struct d
+       if (!dev)
+               return -ENODEV;
+-      mutex_lock(&ac97_controllers_mutex);
++      guard(mutex)(&ac97_controllers_mutex);
+       ac97_ctrl = to_ac97_controller(dev);
+       ac97_ctrl->ops->warm_reset(ac97_ctrl);
+-      mutex_unlock(&ac97_controllers_mutex);
+       return len;
+ }
+ static DEVICE_ATTR_WO(warm_reset);
+@@ -285,10 +283,10 @@ static const struct attribute_group *ac9
+ static void ac97_del_adapter(struct ac97_controller *ac97_ctrl)
+ {
+-      mutex_lock(&ac97_controllers_mutex);
+-      ac97_ctrl_codecs_unregister(ac97_ctrl);
+-      list_del(&ac97_ctrl->controllers);
+-      mutex_unlock(&ac97_controllers_mutex);
++      scoped_guard(mutex, &ac97_controllers_mutex) {
++              ac97_ctrl_codecs_unregister(ac97_ctrl);
++              list_del(&ac97_ctrl->controllers);
++      }
+       device_unregister(&ac97_ctrl->adap);
+ }
+@@ -312,7 +310,7 @@ static int ac97_add_adapter(struct ac97_
+ {
+       int ret;
+-      mutex_lock(&ac97_controllers_mutex);
++      guard(mutex)(&ac97_controllers_mutex);
+       ret = idr_alloc(&ac97_adapter_idr, ac97_ctrl, 0, 0, GFP_KERNEL);
+       ac97_ctrl->nr = ret;
+       if (ret >= 0) {
+@@ -323,13 +321,11 @@ static int ac97_add_adapter(struct ac97_
+               if (ret)
+                       put_device(&ac97_ctrl->adap);
+       }
+-      if (!ret)
++      if (!ret) {
+               list_add(&ac97_ctrl->controllers, &ac97_controllers);
+-      mutex_unlock(&ac97_controllers_mutex);
+-
+-      if (!ret)
+               dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
+                       dev_name(ac97_ctrl->parent));
++      }
+       return ret;
+ }
diff --git a/queue-6.1/ksm-use-range-walk-function-to-jump-over-holes-in-scan_get_next_rmap_item.patch b/queue-6.1/ksm-use-range-walk-function-to-jump-over-holes-in-scan_get_next_rmap_item.patch
new file mode 100644 (file)
index 0000000..5dc8925
--- /dev/null
@@ -0,0 +1,241 @@
+From stable+bounces-208267-greg=kroah.com@vger.kernel.org Tue Jan 13 14:23:13 2026
+From: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Date: Tue, 13 Jan 2026 10:01:56 -0300
+Subject: ksm: use range-walk function to jump over holes in scan_get_next_rmap_item
+To: stable@vger.kernel.org
+Cc: Zhi.Yang@windriver.com, Pedro Demarchi Gomes <pedrodemargomes@gmail.com>, David Hildenbrand <david@redhat.com>, craftfever <craftfever@airmail.cc>, Chengming Zhou <chengming.zhou@linux.dev>, xu xin <xu.xin16@zte.com.cn>, Andrew Morton <akpm@linux-foundation.org>
+Message-ID: <20260113130156.220078-2-pedrodemargomes@gmail.com>
+
+From: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+
+[ Upstream commit f5548c318d6520d4fa3c5ed6003eeb710763cbc5 ]
+
+Currently, scan_get_next_rmap_item() walks every page address in a VMA to
+locate mergeable pages.  This becomes highly inefficient when scanning
+large virtual memory areas that contain mostly unmapped regions, causing
+ksmd to use large amount of cpu without deduplicating much pages.
+
+This patch replaces the per-address lookup with a range walk using
+walk_page_range().  The range walker allows KSM to skip over entire
+unmapped holes in a VMA, avoiding unnecessary lookups.  This problem was
+previously discussed in [1].
+
+Consider the following test program which creates a 32 TiB mapping in the
+virtual address space but only populates a single page:
+
+/* 32 TiB */
+const size_t size = 32ul * 1024 * 1024 * 1024 * 1024;
+
+int main() {
+        char *area = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                          MAP_NORESERVE | MAP_PRIVATE | MAP_ANON, -1, 0);
+
+        if (area == MAP_FAILED) {
+                perror("mmap() failed\n");
+                return -1;
+        }
+
+        /* Populate a single page such that we get an anon_vma. */
+        *area = 0;
+
+        /* Enable KSM. */
+        madvise(area, size, MADV_MERGEABLE);
+        pause();
+        return 0;
+}
+
+$ ./ksm-sparse  &
+$ echo 1 > /sys/kernel/mm/ksm/run
+
+Without this patch ksmd uses 100% of the cpu for a long time (more then 1
+hour in my test machine) scanning all the 32 TiB virtual address space
+that contain only one mapped page.  This makes ksmd essentially deadlocked
+not able to deduplicate anything of value.  With this patch ksmd walks
+only the one mapped page and skips the rest of the 32 TiB virtual address
+space, making the scan fast using little cpu.
+
+Link: https://lkml.kernel.org/r/20251023035841.41406-1-pedrodemargomes@gmail.com
+Link: https://lkml.kernel.org/r/20251022153059.22763-1-pedrodemargomes@gmail.com
+Link: https://lore.kernel.org/linux-mm/423de7a3-1c62-4e72-8e79-19a6413e420c@redhat.com/ [1]
+Fixes: 31dbd01f3143 ("ksm: Kernel SamePage Merging")
+Signed-off-by: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Co-developed-by: David Hildenbrand <david@redhat.com>
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reported-by: craftfever <craftfever@airmail.cc>
+Closes: https://lkml.kernel.org/r/020cf8de6e773bb78ba7614ef250129f11a63781@murena.io
+Suggested-by: David Hildenbrand <david@redhat.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Cc: Chengming Zhou <chengming.zhou@linux.dev>
+Cc: xu xin <xu.xin16@zte.com.cn>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ replace pmdp_get_lockless with pmd_read_atomic and pmdp_get with
+ READ_ONCE(*pmdp) ]
+Signed-off-by: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/ksm.c |  126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 113 insertions(+), 13 deletions(-)
+
+--- a/mm/ksm.c
++++ b/mm/ksm.c
+@@ -39,6 +39,7 @@
+ #include <linux/freezer.h>
+ #include <linux/oom.h>
+ #include <linux/numa.h>
++#include <linux/pagewalk.h>
+ #include <asm/tlbflush.h>
+ #include "internal.h"
+@@ -2223,6 +2224,94 @@ static struct ksm_rmap_item *get_next_rm
+       return rmap_item;
+ }
++struct ksm_next_page_arg {
++      struct folio *folio;
++      struct page *page;
++      unsigned long addr;
++};
++
++static int ksm_next_page_pmd_entry(pmd_t *pmdp, unsigned long addr, unsigned long end,
++              struct mm_walk *walk)
++{
++      struct ksm_next_page_arg *private = walk->private;
++      struct vm_area_struct *vma = walk->vma;
++      pte_t *start_ptep = NULL, *ptep, pte;
++      struct mm_struct *mm = walk->mm;
++      struct folio *folio;
++      struct page *page;
++      spinlock_t *ptl;
++      pmd_t pmd;
++
++      if (ksm_test_exit(mm))
++              return 0;
++
++      cond_resched();
++
++      pmd = pmd_read_atomic(pmdp);
++      if (!pmd_present(pmd))
++              return 0;
++
++      if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && pmd_leaf(pmd)) {
++              ptl = pmd_lock(mm, pmdp);
++              pmd = READ_ONCE(*pmdp);
++
++              if (!pmd_present(pmd)) {
++                      goto not_found_unlock;
++              } else if (pmd_leaf(pmd)) {
++                      page = vm_normal_page_pmd(vma, addr, pmd);
++                      if (!page)
++                              goto not_found_unlock;
++                      folio = page_folio(page);
++
++                      if (folio_is_zone_device(folio) || !folio_test_anon(folio))
++                              goto not_found_unlock;
++
++                      page += ((addr & (PMD_SIZE - 1)) >> PAGE_SHIFT);
++                      goto found_unlock;
++              }
++              spin_unlock(ptl);
++      }
++
++      start_ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
++      if (!start_ptep)
++              return 0;
++
++      for (ptep = start_ptep; addr < end; ptep++, addr += PAGE_SIZE) {
++              pte = ptep_get(ptep);
++
++              if (!pte_present(pte))
++                      continue;
++
++              page = vm_normal_page(vma, addr, pte);
++              if (!page)
++                      continue;
++              folio = page_folio(page);
++
++              if (folio_is_zone_device(folio) || !folio_test_anon(folio))
++                      continue;
++              goto found_unlock;
++      }
++
++not_found_unlock:
++      spin_unlock(ptl);
++      if (start_ptep)
++              pte_unmap(start_ptep);
++      return 0;
++found_unlock:
++      folio_get(folio);
++      spin_unlock(ptl);
++      if (start_ptep)
++              pte_unmap(start_ptep);
++      private->page = page;
++      private->folio = folio;
++      private->addr = addr;
++      return 1;
++}
++
++static struct mm_walk_ops ksm_next_page_ops = {
++      .pmd_entry = ksm_next_page_pmd_entry,
++};
++
+ static struct ksm_rmap_item *scan_get_next_rmap_item(struct page **page)
+ {
+       struct mm_struct *mm;
+@@ -2307,32 +2396,43 @@ next_mm:
+                       ksm_scan.address = vma->vm_end;
+               while (ksm_scan.address < vma->vm_end) {
++                      struct ksm_next_page_arg ksm_next_page_arg;
++                      struct page *tmp_page = NULL;
++                      struct folio *folio;
++
+                       if (ksm_test_exit(mm))
+                               break;
+-                      *page = follow_page(vma, ksm_scan.address, FOLL_GET);
+-                      if (IS_ERR_OR_NULL(*page)) {
+-                              ksm_scan.address += PAGE_SIZE;
+-                              cond_resched();
+-                              continue;
++
++                      int found;
++
++                      found = walk_page_range_vma(vma, ksm_scan.address,
++                                                  vma->vm_end,
++                                                  &ksm_next_page_ops,
++                                                  &ksm_next_page_arg);
++
++                      if (found > 0) {
++                              folio = ksm_next_page_arg.folio;
++                              tmp_page = ksm_next_page_arg.page;
++                              ksm_scan.address = ksm_next_page_arg.addr;
++                      } else {
++                              VM_WARN_ON_ONCE(found < 0);
++                              ksm_scan.address = vma->vm_end - PAGE_SIZE;
+                       }
+-                      if (is_zone_device_page(*page))
+-                              goto next_page;
+-                      if (PageAnon(*page)) {
+-                              flush_anon_page(vma, *page, ksm_scan.address);
+-                              flush_dcache_page(*page);
++                      if (tmp_page) {
++                              flush_anon_page(vma, tmp_page, ksm_scan.address);
++                              flush_dcache_page(tmp_page);
+                               rmap_item = get_next_rmap_item(mm_slot,
+                                       ksm_scan.rmap_list, ksm_scan.address);
+                               if (rmap_item) {
+                                       ksm_scan.rmap_list =
+                                                       &rmap_item->rmap_list;
+                                       ksm_scan.address += PAGE_SIZE;
++                                      *page = tmp_page;
+                               } else
+-                                      put_page(*page);
++                                      folio_put(folio);
+                               mmap_read_unlock(mm);
+                               return rmap_item;
+                       }
+-next_page:
+-                      put_page(*page);
+                       ksm_scan.address += PAGE_SIZE;
+                       cond_resched();
+               }
diff --git a/queue-6.1/mm-pagewalk-add-walk_page_range_vma.patch b/queue-6.1/mm-pagewalk-add-walk_page_range_vma.patch
new file mode 100644 (file)
index 0000000..5658b7c
--- /dev/null
@@ -0,0 +1,77 @@
+From stable+bounces-208266-greg=kroah.com@vger.kernel.org Tue Jan 13 14:22:18 2026
+From: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Date: Tue, 13 Jan 2026 10:01:55 -0300
+Subject: mm/pagewalk: add walk_page_range_vma()
+To: stable@vger.kernel.org
+Cc: Zhi.Yang@windriver.com, David Hildenbrand <david@redhat.com>, Andrea Arcangeli <aarcange@redhat.com>, Hugh Dickins <hughd@google.com>, Jason Gunthorpe <jgg@nvidia.com>, John Hubbard <jhubbard@nvidia.com>, Matthew Wilcox <willy@infradead.org>, Peter Xu <peterx@redhat.com>, Shuah Khan <shuah@kernel.org>, Vlastimil Babka <vbabka@suse.cz>, Andrew Morton <akpm@linux-foundation.org>, Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Message-ID: <20260113130156.220078-1-pedrodemargomes@gmail.com>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit e07cda5f232fac4de0925d8a4c92e51e41fa2f6e ]
+
+Let's add walk_page_range_vma(), which is similar to walk_page_vma(),
+however, is only interested in a subset of the VMA range.
+
+To be used in KSM code to stop using follow_page() next.
+
+Link: https://lkml.kernel.org/r/20221021101141.84170-8-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Jason Gunthorpe <jgg@nvidia.com>
+Cc: John Hubbard <jhubbard@nvidia.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: f5548c318d6 ("ksm: use range-walk function to jump over holes in scan_get_next_rmap_item")
+Signed-off-by: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/pagewalk.h |    3 +++
+ mm/pagewalk.c            |   20 ++++++++++++++++++++
+ 2 files changed, 23 insertions(+)
+
+--- a/include/linux/pagewalk.h
++++ b/include/linux/pagewalk.h
+@@ -99,6 +99,9 @@ int walk_page_range_novma(struct mm_stru
+                         unsigned long end, const struct mm_walk_ops *ops,
+                         pgd_t *pgd,
+                         void *private);
++int walk_page_range_vma(struct vm_area_struct *vma, unsigned long start,
++                      unsigned long end, const struct mm_walk_ops *ops,
++                      void *private);
+ int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
+               void *private);
+ int walk_page_mapping(struct address_space *mapping, pgoff_t first_index,
+--- a/mm/pagewalk.c
++++ b/mm/pagewalk.c
+@@ -517,6 +517,26 @@ int walk_page_range_novma(struct mm_stru
+       return walk_pgd_range(start, end, &walk);
+ }
++int walk_page_range_vma(struct vm_area_struct *vma, unsigned long start,
++                      unsigned long end, const struct mm_walk_ops *ops,
++                      void *private)
++{
++      struct mm_walk walk = {
++              .ops            = ops,
++              .mm             = vma->vm_mm,
++              .vma            = vma,
++              .private        = private,
++      };
++
++      if (start >= end || !walk.mm)
++              return -EINVAL;
++      if (start < vma->vm_start || end > vma->vm_end)
++              return -EINVAL;
++
++      mmap_assert_locked(walk.mm);
++      return __walk_page_range(start, end, &walk);
++}
++
+ int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
+               void *private)
+ {
diff --git a/queue-6.1/nfs-trace-show-timedout-instead-of-0x6e.patch b/queue-6.1/nfs-trace-show-timedout-instead-of-0x6e.patch
new file mode 100644 (file)
index 0000000..79cf2f4
--- /dev/null
@@ -0,0 +1,42 @@
+From stable+bounces-208127-greg=kroah.com@vger.kernel.org Mon Jan 12 15:45:35 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 09:39:08 -0500
+Subject: NFS: trace: show TIMEDOUT instead of 0x6e
+To: stable@vger.kernel.org
+Cc: Chen Hanxiao <chenhx.fnst@fujitsu.com>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112143910.714632-1-sashal@kernel.org>
+
+From: Chen Hanxiao <chenhx.fnst@fujitsu.com>
+
+[ Upstream commit cef48236dfe55fa266d505e8a497963a7bc5ef2a ]
+
+__nfs_revalidate_inode may return ETIMEDOUT.
+
+print symbol of ETIMEDOUT in nfs trace:
+
+before:
+cat-5191 [005] 119.331127: nfs_revalidate_inode_exit: error=-110 (0x6e)
+
+after:
+cat-1738 [004] 44.365509: nfs_revalidate_inode_exit: error=-110 (TIMEDOUT)
+
+Signed-off-by: Chen Hanxiao <chenhx.fnst@fujitsu.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: c6c209ceb87f ("NFSD: Remove NFSERR_EAGAIN")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/trace/misc/nfs.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/trace/misc/nfs.h
++++ b/include/trace/misc/nfs.h
+@@ -52,6 +52,7 @@ TRACE_DEFINE_ENUM(NFSERR_JUKEBOX);
+               { NFSERR_IO,                    "IO" }, \
+               { NFSERR_NXIO,                  "NXIO" }, \
+               { ECHILD,                       "CHILD" }, \
++              { ETIMEDOUT,                    "TIMEDOUT" }, \
+               { NFSERR_EAGAIN,                "AGAIN" }, \
+               { NFSERR_ACCES,                 "ACCES" }, \
+               { NFSERR_EXIST,                 "EXIST" }, \
diff --git a/queue-6.1/nfs_common-factor-out-nfs_errtbl-and-nfs_stat_to_errno.patch b/queue-6.1/nfs_common-factor-out-nfs_errtbl-and-nfs_stat_to_errno.patch
new file mode 100644 (file)
index 0000000..0b08261
--- /dev/null
@@ -0,0 +1,531 @@
+From stable+bounces-208128-greg=kroah.com@vger.kernel.org Mon Jan 12 15:52:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 09:39:09 -0500
+Subject: nfs_common: factor out nfs_errtbl and nfs_stat_to_errno
+To: stable@vger.kernel.org
+Cc: Mike Snitzer <snitzer@kernel.org>, Jeff Layton <jlayton@kernel.org>, NeilBrown <neilb@suse.de>, Anna Schumaker <anna.schumaker@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112143910.714632-2-sashal@kernel.org>
+
+From: Mike Snitzer <snitzer@kernel.org>
+
+[ Upstream commit 4806ded4c14c5e8fdc6ce885d83221a78c06a428 ]
+
+Common nfs_stat_to_errno() is used by both fs/nfs/nfs2xdr.c and
+fs/nfs/nfs3xdr.c
+
+Will also be used by fs/nfsd/localio.c
+
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
+Stable-dep-of: c6c209ceb87f ("NFSD: Remove NFSERR_EAGAIN")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfs/Kconfig             |    1 
+ fs/nfs/nfs2xdr.c           |   70 -----------------------------
+ fs/nfs/nfs3xdr.c           |  108 ++++++++-------------------------------------
+ fs/nfs/nfs4xdr.c           |    4 -
+ fs/nfs_common/Makefile     |    2 
+ fs/nfs_common/common.c     |   67 +++++++++++++++++++++++++++
+ fs/nfsd/Kconfig            |    1 
+ include/linux/nfs_common.h |   16 ++++++
+ 8 files changed, 109 insertions(+), 160 deletions(-)
+ create mode 100644 fs/nfs_common/common.c
+ create mode 100644 include/linux/nfs_common.h
+
+--- a/fs/nfs/Kconfig
++++ b/fs/nfs/Kconfig
+@@ -5,6 +5,7 @@ config NFS_FS
+       select CRC32
+       select LOCKD
+       select SUNRPC
++      select NFS_COMMON
+       select NFS_ACL_SUPPORT if NFS_V3_ACL
+       help
+         Choose Y here if you want to access files residing on other
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -22,14 +22,12 @@
+ #include <linux/nfs.h>
+ #include <linux/nfs2.h>
+ #include <linux/nfs_fs.h>
++#include <linux/nfs_common.h>
+ #include "nfstrace.h"
+ #include "internal.h"
+ #define NFSDBG_FACILITY               NFSDBG_XDR
+-/* Mapping from NFS error code to "errno" error code. */
+-#define errno_NFSERR_IO               EIO
+-
+ /*
+  * Declare the space requirements for NFS arguments and replies as
+  * number of 32bit-words
+@@ -64,8 +62,6 @@
+ #define NFS_readdirres_sz     (1+NFS_pagepad_sz)
+ #define NFS_statfsres_sz      (1+NFS_info_sz)
+-static int nfs_stat_to_errno(enum nfs_stat);
+-
+ /*
+  * Encode/decode NFSv2 basic data types
+  *
+@@ -1054,70 +1050,6 @@ out_default:
+       return nfs_stat_to_errno(status);
+ }
+-
+-/*
+- * We need to translate between nfs status return values and
+- * the local errno values which may not be the same.
+- */
+-static const struct {
+-      int stat;
+-      int errno;
+-} nfs_errtbl[] = {
+-      { NFS_OK,               0               },
+-      { NFSERR_PERM,          -EPERM          },
+-      { NFSERR_NOENT,         -ENOENT         },
+-      { NFSERR_IO,            -errno_NFSERR_IO},
+-      { NFSERR_NXIO,          -ENXIO          },
+-/*    { NFSERR_EAGAIN,        -EAGAIN         }, */
+-      { NFSERR_ACCES,         -EACCES         },
+-      { NFSERR_EXIST,         -EEXIST         },
+-      { NFSERR_XDEV,          -EXDEV          },
+-      { NFSERR_NODEV,         -ENODEV         },
+-      { NFSERR_NOTDIR,        -ENOTDIR        },
+-      { NFSERR_ISDIR,         -EISDIR         },
+-      { NFSERR_INVAL,         -EINVAL         },
+-      { NFSERR_FBIG,          -EFBIG          },
+-      { NFSERR_NOSPC,         -ENOSPC         },
+-      { NFSERR_ROFS,          -EROFS          },
+-      { NFSERR_MLINK,         -EMLINK         },
+-      { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
+-      { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
+-      { NFSERR_DQUOT,         -EDQUOT         },
+-      { NFSERR_STALE,         -ESTALE         },
+-      { NFSERR_REMOTE,        -EREMOTE        },
+-#ifdef EWFLUSH
+-      { NFSERR_WFLUSH,        -EWFLUSH        },
+-#endif
+-      { NFSERR_BADHANDLE,     -EBADHANDLE     },
+-      { NFSERR_NOT_SYNC,      -ENOTSYNC       },
+-      { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
+-      { NFSERR_NOTSUPP,       -ENOTSUPP       },
+-      { NFSERR_TOOSMALL,      -ETOOSMALL      },
+-      { NFSERR_SERVERFAULT,   -EREMOTEIO      },
+-      { NFSERR_BADTYPE,       -EBADTYPE       },
+-      { NFSERR_JUKEBOX,       -EJUKEBOX       },
+-      { -1,                   -EIO            }
+-};
+-
+-/**
+- * nfs_stat_to_errno - convert an NFS status code to a local errno
+- * @status: NFS status code to convert
+- *
+- * Returns a local errno value, or -EIO if the NFS status code is
+- * not recognized.  This function is used jointly by NFSv2 and NFSv3.
+- */
+-static int nfs_stat_to_errno(enum nfs_stat status)
+-{
+-      int i;
+-
+-      for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+-              if (nfs_errtbl[i].stat == (int)status)
+-                      return nfs_errtbl[i].errno;
+-      }
+-      dprintk("NFS: Unrecognized nfs status value: %u\n", status);
+-      return nfs_errtbl[i].errno;
+-}
+-
+ #define PROC(proc, argtype, restype, timer)                           \
+ [NFSPROC_##proc] = {                                                  \
+       .p_proc     =  NFSPROC_##proc,                                  \
+--- a/fs/nfs/nfs3xdr.c
++++ b/fs/nfs/nfs3xdr.c
+@@ -21,14 +21,13 @@
+ #include <linux/nfs3.h>
+ #include <linux/nfs_fs.h>
+ #include <linux/nfsacl.h>
++#include <linux/nfs_common.h>
++
+ #include "nfstrace.h"
+ #include "internal.h"
+ #define NFSDBG_FACILITY               NFSDBG_XDR
+-/* Mapping from NFS error code to "errno" error code. */
+-#define errno_NFSERR_IO               EIO
+-
+ /*
+  * Declare the space requirements for NFS arguments and replies as
+  * number of 32bit-words
+@@ -91,8 +90,6 @@
+                               NFS3_pagepad_sz)
+ #define ACL3_setaclres_sz     (1+NFS3_post_op_attr_sz)
+-static int nfs3_stat_to_errno(enum nfs_stat);
+-
+ /*
+  * Map file type to S_IFMT bits
+  */
+@@ -1406,7 +1403,7 @@ static int nfs3_xdr_dec_getattr3res(stru
+ out:
+       return error;
+ out_default:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1445,7 +1442,7 @@ static int nfs3_xdr_dec_setattr3res(stru
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1495,7 +1492,7 @@ out_default:
+       error = decode_post_op_attr(xdr, result->dir_attr, userns);
+       if (unlikely(error))
+               goto out;
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1537,7 +1534,7 @@ static int nfs3_xdr_dec_access3res(struc
+ out:
+       return error;
+ out_default:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1578,7 +1575,7 @@ static int nfs3_xdr_dec_readlink3res(str
+ out:
+       return error;
+ out_default:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1658,7 +1655,7 @@ static int nfs3_xdr_dec_read3res(struct
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1728,7 +1725,7 @@ static int nfs3_xdr_dec_write3res(struct
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1795,7 +1792,7 @@ out_default:
+       error = decode_wcc_data(xdr, result->dir_attr, userns);
+       if (unlikely(error))
+               goto out;
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1835,7 +1832,7 @@ static int nfs3_xdr_dec_remove3res(struc
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1881,7 +1878,7 @@ static int nfs3_xdr_dec_rename3res(struc
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -1926,7 +1923,7 @@ static int nfs3_xdr_dec_link3res(struct
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /**
+@@ -2101,7 +2098,7 @@ out_default:
+       error = decode_post_op_attr(xdr, result->dir_attr, rpc_rqst_userns(req));
+       if (unlikely(error))
+               goto out;
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -2167,7 +2164,7 @@ static int nfs3_xdr_dec_fsstat3res(struc
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -2243,7 +2240,7 @@ static int nfs3_xdr_dec_fsinfo3res(struc
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -2304,7 +2301,7 @@ static int nfs3_xdr_dec_pathconf3res(str
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ /*
+@@ -2350,7 +2347,7 @@ static int nfs3_xdr_dec_commit3res(struc
+ out:
+       return error;
+ out_status:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ #ifdef CONFIG_NFS_V3_ACL
+@@ -2416,7 +2413,7 @@ static int nfs3_xdr_dec_getacl3res(struc
+ out:
+       return error;
+ out_default:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
+@@ -2435,76 +2432,11 @@ static int nfs3_xdr_dec_setacl3res(struc
+ out:
+       return error;
+ out_default:
+-      return nfs3_stat_to_errno(status);
++      return nfs_stat_to_errno(status);
+ }
+ #endif  /* CONFIG_NFS_V3_ACL */
+-
+-/*
+- * We need to translate between nfs status return values and
+- * the local errno values which may not be the same.
+- */
+-static const struct {
+-      int stat;
+-      int errno;
+-} nfs_errtbl[] = {
+-      { NFS_OK,               0               },
+-      { NFSERR_PERM,          -EPERM          },
+-      { NFSERR_NOENT,         -ENOENT         },
+-      { NFSERR_IO,            -errno_NFSERR_IO},
+-      { NFSERR_NXIO,          -ENXIO          },
+-/*    { NFSERR_EAGAIN,        -EAGAIN         }, */
+-      { NFSERR_ACCES,         -EACCES         },
+-      { NFSERR_EXIST,         -EEXIST         },
+-      { NFSERR_XDEV,          -EXDEV          },
+-      { NFSERR_NODEV,         -ENODEV         },
+-      { NFSERR_NOTDIR,        -ENOTDIR        },
+-      { NFSERR_ISDIR,         -EISDIR         },
+-      { NFSERR_INVAL,         -EINVAL         },
+-      { NFSERR_FBIG,          -EFBIG          },
+-      { NFSERR_NOSPC,         -ENOSPC         },
+-      { NFSERR_ROFS,          -EROFS          },
+-      { NFSERR_MLINK,         -EMLINK         },
+-      { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
+-      { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
+-      { NFSERR_DQUOT,         -EDQUOT         },
+-      { NFSERR_STALE,         -ESTALE         },
+-      { NFSERR_REMOTE,        -EREMOTE        },
+-#ifdef EWFLUSH
+-      { NFSERR_WFLUSH,        -EWFLUSH        },
+-#endif
+-      { NFSERR_BADHANDLE,     -EBADHANDLE     },
+-      { NFSERR_NOT_SYNC,      -ENOTSYNC       },
+-      { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
+-      { NFSERR_NOTSUPP,       -ENOTSUPP       },
+-      { NFSERR_TOOSMALL,      -ETOOSMALL      },
+-      { NFSERR_SERVERFAULT,   -EREMOTEIO      },
+-      { NFSERR_BADTYPE,       -EBADTYPE       },
+-      { NFSERR_JUKEBOX,       -EJUKEBOX       },
+-      { -1,                   -EIO            }
+-};
+-
+-/**
+- * nfs3_stat_to_errno - convert an NFS status code to a local errno
+- * @status: NFS status code to convert
+- *
+- * Returns a local errno value, or -EIO if the NFS status code is
+- * not recognized.  This function is used jointly by NFSv2 and NFSv3.
+- */
+-static int nfs3_stat_to_errno(enum nfs_stat status)
+-{
+-      int i;
+-
+-      for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+-              if (nfs_errtbl[i].stat == (int)status)
+-                      return nfs_errtbl[i].errno;
+-      }
+-      dprintk("NFS: Unrecognized nfs status value: %u\n", status);
+-      return nfs_errtbl[i].errno;
+-}
+-
+-
+ #define PROC(proc, argtype, restype, timer)                           \
+ [NFS3PROC_##proc] = {                                                 \
+       .p_proc      = NFS3PROC_##proc,                                 \
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -52,6 +52,7 @@
+ #include <linux/nfs.h>
+ #include <linux/nfs4.h>
+ #include <linux/nfs_fs.h>
++#include <linux/nfs_common.h>
+ #include "nfs4_fs.h"
+ #include "nfs4trace.h"
+@@ -63,9 +64,6 @@
+ #define NFSDBG_FACILITY               NFSDBG_XDR
+-/* Mapping from NFS error code to "errno" error code. */
+-#define errno_NFSERR_IO               EIO
+-
+ struct compound_hdr;
+ static int nfs4_stat_to_errno(int);
+ static void encode_layoutget(struct xdr_stream *xdr,
+--- a/fs/nfs_common/Makefile
++++ b/fs/nfs_common/Makefile
+@@ -8,3 +8,5 @@ nfs_acl-objs := nfsacl.o
+ obj-$(CONFIG_GRACE_PERIOD) += grace.o
+ obj-$(CONFIG_NFS_V4_2_SSC_HELPER) += nfs_ssc.o
++
++obj-$(CONFIG_NFS_COMMON) += common.o
+--- /dev/null
++++ b/fs/nfs_common/common.c
+@@ -0,0 +1,67 @@
++// SPDX-License-Identifier: GPL-2.0-only
++
++#include <linux/module.h>
++#include <linux/nfs_common.h>
++
++/*
++ * We need to translate between nfs status return values and
++ * the local errno values which may not be the same.
++ */
++static const struct {
++      int stat;
++      int errno;
++} nfs_errtbl[] = {
++      { NFS_OK,               0               },
++      { NFSERR_PERM,          -EPERM          },
++      { NFSERR_NOENT,         -ENOENT         },
++      { NFSERR_IO,            -errno_NFSERR_IO},
++      { NFSERR_NXIO,          -ENXIO          },
++/*    { NFSERR_EAGAIN,        -EAGAIN         }, */
++      { NFSERR_ACCES,         -EACCES         },
++      { NFSERR_EXIST,         -EEXIST         },
++      { NFSERR_XDEV,          -EXDEV          },
++      { NFSERR_NODEV,         -ENODEV         },
++      { NFSERR_NOTDIR,        -ENOTDIR        },
++      { NFSERR_ISDIR,         -EISDIR         },
++      { NFSERR_INVAL,         -EINVAL         },
++      { NFSERR_FBIG,          -EFBIG          },
++      { NFSERR_NOSPC,         -ENOSPC         },
++      { NFSERR_ROFS,          -EROFS          },
++      { NFSERR_MLINK,         -EMLINK         },
++      { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
++      { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
++      { NFSERR_DQUOT,         -EDQUOT         },
++      { NFSERR_STALE,         -ESTALE         },
++      { NFSERR_REMOTE,        -EREMOTE        },
++#ifdef EWFLUSH
++      { NFSERR_WFLUSH,        -EWFLUSH        },
++#endif
++      { NFSERR_BADHANDLE,     -EBADHANDLE     },
++      { NFSERR_NOT_SYNC,      -ENOTSYNC       },
++      { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
++      { NFSERR_NOTSUPP,       -ENOTSUPP       },
++      { NFSERR_TOOSMALL,      -ETOOSMALL      },
++      { NFSERR_SERVERFAULT,   -EREMOTEIO      },
++      { NFSERR_BADTYPE,       -EBADTYPE       },
++      { NFSERR_JUKEBOX,       -EJUKEBOX       },
++      { -1,                   -EIO            }
++};
++
++/**
++ * nfs_stat_to_errno - convert an NFS status code to a local errno
++ * @status: NFS status code to convert
++ *
++ * Returns a local errno value, or -EIO if the NFS status code is
++ * not recognized.  This function is used jointly by NFSv2 and NFSv3.
++ */
++int nfs_stat_to_errno(enum nfs_stat status)
++{
++      int i;
++
++      for (i = 0; nfs_errtbl[i].stat != -1; i++) {
++              if (nfs_errtbl[i].stat == (int)status)
++                      return nfs_errtbl[i].errno;
++      }
++      return nfs_errtbl[i].errno;
++}
++EXPORT_SYMBOL_GPL(nfs_stat_to_errno);
+--- a/fs/nfsd/Kconfig
++++ b/fs/nfsd/Kconfig
+@@ -8,6 +8,7 @@ config NFSD
+       select LOCKD
+       select SUNRPC
+       select EXPORTFS
++      select NFS_COMMON
+       select NFS_ACL_SUPPORT if NFSD_V2_ACL
+       select NFS_ACL_SUPPORT if NFSD_V3_ACL
+       depends on MULTIUSER
+--- /dev/null
++++ b/include/linux/nfs_common.h
+@@ -0,0 +1,16 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * This file contains constants and methods used by both NFS client and server.
++ */
++#ifndef _LINUX_NFS_COMMON_H
++#define _LINUX_NFS_COMMON_H
++
++#include <linux/errno.h>
++#include <uapi/linux/nfs.h>
++
++/* Mapping from NFS error code to "errno" error code. */
++#define errno_NFSERR_IO EIO
++
++int nfs_stat_to_errno(enum nfs_stat status);
++
++#endif /* _LINUX_NFS_COMMON_H */
diff --git a/queue-6.1/nfsd-provide-locking-for-v4_end_grace.patch b/queue-6.1/nfsd-provide-locking-for-v4_end_grace.patch
new file mode 100644 (file)
index 0000000..4a9858f
--- /dev/null
@@ -0,0 +1,186 @@
+From stable+bounces-208171-greg=kroah.com@vger.kernel.org Mon Jan 12 16:33:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 10:33:51 -0500
+Subject: nfsd: provide locking for v4_end_grace
+To: stable@vger.kernel.org
+Cc: NeilBrown <neil@brown.name>, Li Lingfeng <lilingfeng3@huawei.com>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112153351.742670-1-sashal@kernel.org>
+
+From: NeilBrown <neil@brown.name>
+
+[ Upstream commit 2857bd59feb63fcf40fe4baf55401baea6b4feb4 ]
+
+Writing to v4_end_grace can race with server shutdown and result in
+memory being accessed after it was freed - reclaim_str_hashtbl in
+particularly.
+
+We cannot hold nfsd_mutex across the nfsd4_end_grace() call as that is
+held while client_tracking_op->init() is called and that can wait for
+an upcall to nfsdcltrack which can write to v4_end_grace, resulting in a
+deadlock.
+
+nfsd4_end_grace() is also called by the landromat work queue and this
+doesn't require locking as server shutdown will stop the work and wait
+for it before freeing anything that nfsd4_end_grace() might access.
+
+However, we must be sure that writing to v4_end_grace doesn't restart
+the work item after shutdown has already waited for it.  For this we
+add a new flag protected with nn->client_lock.  It is set only while it
+is safe to make client tracking calls, and v4_end_grace only schedules
+work while the flag is set with the spinlock held.
+
+So this patch adds a nfsd_net field "client_tracking_active" which is
+set as described.  Another field "grace_end_forced", is set when
+v4_end_grace is written.  After this is set, and providing
+client_tracking_active is set, the laundromat is scheduled.
+This "grace_end_forced" field bypasses other checks for whether the
+grace period has finished.
+
+This resolves a race which can result in use-after-free.
+
+Reported-by: Li Lingfeng <lilingfeng3@huawei.com>
+Closes: https://lore.kernel.org/linux-nfs/20250623030015.2353515-1-neil@brown.name/T/#t
+Fixes: 7f5ef2e900d9 ("nfsd: add a v4_end_grace file to /proc/fs/nfsd")
+Cc: stable@vger.kernel.org
+Signed-off-by: NeilBrown <neil@brown.name>
+Tested-by: Li Lingfeng <lilingfeng3@huawei.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/netns.h     |    2 ++
+ fs/nfsd/nfs4state.c |   42 ++++++++++++++++++++++++++++++++++++++++--
+ fs/nfsd/nfsctl.c    |    3 +--
+ fs/nfsd/state.h     |    2 +-
+ 4 files changed, 44 insertions(+), 5 deletions(-)
+
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -64,6 +64,8 @@ struct nfsd_net {
+       struct lock_manager nfsd4_manager;
+       bool grace_ended;
++      bool grace_end_forced;
++      bool client_tracking_active;
+       time64_t boot_time;
+       struct dentry *nfsd_client_dir;
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -84,7 +84,7 @@ static u64 current_sessionid = 1;
+ /* forward declarations */
+ static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner);
+ static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
+-void nfsd4_end_grace(struct nfsd_net *nn);
++static void nfsd4_end_grace(struct nfsd_net *nn);
+ static void _free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_state *cps);
+ static void nfsd4_file_hash_remove(struct nfs4_file *fi);
+@@ -5882,7 +5882,7 @@ nfsd4_renew(struct svc_rqst *rqstp, stru
+       return nfs_ok;
+ }
+-void
++static void
+ nfsd4_end_grace(struct nfsd_net *nn)
+ {
+       /* do nothing if grace period already ended */
+@@ -5915,6 +5915,33 @@ nfsd4_end_grace(struct nfsd_net *nn)
+        */
+ }
++/**
++ * nfsd4_force_end_grace - forcibly end the NFSv4 grace period
++ * @nn: network namespace for the server instance to be updated
++ *
++ * Forces bypass of normal grace period completion, then schedules
++ * the laundromat to end the grace period immediately. Does not wait
++ * for the grace period to fully terminate before returning.
++ *
++ * Return values:
++ *   %true: Grace termination schedule
++ *   %false: No action was taken
++ */
++bool nfsd4_force_end_grace(struct nfsd_net *nn)
++{
++      if (!nn->client_tracking_ops)
++              return false;
++      spin_lock(&nn->client_lock);
++      if (nn->grace_ended || !nn->client_tracking_active) {
++              spin_unlock(&nn->client_lock);
++              return false;
++      }
++      WRITE_ONCE(nn->grace_end_forced, true);
++      mod_delayed_work(laundry_wq, &nn->laundromat_work, 0);
++      spin_unlock(&nn->client_lock);
++      return true;
++}
++
+ /*
+  * If we've waited a lease period but there are still clients trying to
+  * reclaim, wait a little longer to give them a chance to finish.
+@@ -5924,6 +5951,8 @@ static bool clients_still_reclaiming(str
+       time64_t double_grace_period_end = nn->boot_time +
+                                          2 * nn->nfsd4_lease;
++      if (READ_ONCE(nn->grace_end_forced))
++              return false;
+       if (nn->track_reclaim_completes &&
+                       atomic_read(&nn->nr_reclaim_complete) ==
+                       nn->reclaim_str_hashtbl_size)
+@@ -8131,6 +8160,8 @@ static int nfs4_state_create_net(struct
+       nn->unconf_name_tree = RB_ROOT;
+       nn->boot_time = ktime_get_real_seconds();
+       nn->grace_ended = false;
++      nn->grace_end_forced = false;
++      nn->client_tracking_active = false;
+       nn->nfsd4_manager.block_opens = true;
+       INIT_LIST_HEAD(&nn->nfsd4_manager.list);
+       INIT_LIST_HEAD(&nn->client_lru);
+@@ -8207,6 +8238,10 @@ nfs4_state_start_net(struct net *net)
+               return ret;
+       locks_start_grace(net, &nn->nfsd4_manager);
+       nfsd4_client_tracking_init(net);
++      /* safe for laundromat to run now */
++      spin_lock(&nn->client_lock);
++      nn->client_tracking_active = true;
++      spin_unlock(&nn->client_lock);
+       if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
+               goto skip_grace;
+       printk(KERN_INFO "NFSD: starting %lld-second grace period (net %x)\n",
+@@ -8253,6 +8288,9 @@ nfs4_state_shutdown_net(struct net *net)
+       unregister_shrinker(&nn->nfsd_client_shrinker);
+       cancel_work_sync(&nn->nfsd_shrinker_work);
++      spin_lock(&nn->client_lock);
++      nn->client_tracking_active = false;
++      spin_unlock(&nn->client_lock);
+       cancel_delayed_work_sync(&nn->laundromat_work);
+       locks_end_grace(&nn->nfsd4_manager);
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1117,9 +1117,8 @@ static ssize_t write_v4_end_grace(struct
+               case 'Y':
+               case 'y':
+               case '1':
+-                      if (!nn->nfsd_serv)
++                      if (!nfsd4_force_end_grace(nn))
+                               return -EBUSY;
+-                      nfsd4_end_grace(nn);
+                       break;
+               default:
+                       return -EINVAL;
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -719,7 +719,7 @@ static inline void get_nfs4_file(struct
+ struct nfsd_file *find_any_file(struct nfs4_file *f);
+ /* grace period management */
+-void nfsd4_end_grace(struct nfsd_net *nn);
++bool nfsd4_force_end_grace(struct nfsd_net *nn);
+ /* nfs4recover operations */
+ extern int nfsd4_client_tracking_init(struct net *net);
diff --git a/queue-6.1/nfsd-remove-nfserr_eagain.patch b/queue-6.1/nfsd-remove-nfserr_eagain.patch
new file mode 100644 (file)
index 0000000..7583dd7
--- /dev/null
@@ -0,0 +1,101 @@
+From stable+bounces-208129-greg=kroah.com@vger.kernel.org Mon Jan 12 15:45:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 09:39:10 -0500
+Subject: NFSD: Remove NFSERR_EAGAIN
+To: stable@vger.kernel.org
+Cc: Chuck Lever <chuck.lever@oracle.com>, NeilBrown <neil@brown.name>, Jeff Layton <jlayton@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260112143910.714632-3-sashal@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit c6c209ceb87f64a6ceebe61761951dcbbf4a0baa ]
+
+I haven't found an NFSERR_EAGAIN in RFCs 1094, 1813, 7530, or 8881.
+None of these RFCs have an NFS status code that match the numeric
+value "11".
+
+Based on the meaning of the EAGAIN errno, I presume the use of this
+status in NFSD means NFS4ERR_DELAY. So replace the one usage of
+nfserr_eagain, and remove it from NFSD's NFS status conversion
+tables.
+
+As far as I can tell, NFSERR_EAGAIN has existed since the pre-git
+era, but was not actually used by any code until commit f4e44b393389
+("NFSD: delay unmount source's export after inter-server copy
+completed."), at which time it become possible for NFSD to return
+a status code of 11 (which is not valid NFS protocol).
+
+Fixes: f4e44b393389 ("NFSD: delay unmount source's export after inter-server copy completed.")
+Cc: stable@vger.kernel.org
+Reviewed-by: NeilBrown <neil@brown.name>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfs_common/common.c   |    1 -
+ fs/nfsd/nfs4proc.c       |    2 +-
+ fs/nfsd/nfsd.h           |    1 -
+ include/trace/misc/nfs.h |    2 --
+ include/uapi/linux/nfs.h |    1 -
+ 5 files changed, 1 insertion(+), 6 deletions(-)
+
+--- a/fs/nfs_common/common.c
++++ b/fs/nfs_common/common.c
+@@ -16,7 +16,6 @@ static const struct {
+       { NFSERR_NOENT,         -ENOENT         },
+       { NFSERR_IO,            -errno_NFSERR_IO},
+       { NFSERR_NXIO,          -ENXIO          },
+-/*    { NFSERR_EAGAIN,        -EAGAIN         }, */
+       { NFSERR_ACCES,         -EACCES         },
+       { NFSERR_EXIST,         -EEXIST         },
+       { NFSERR_XDEV,          -EXDEV          },
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1321,7 +1321,7 @@ try_again:
+                                       (schedule_timeout(20*HZ) == 0)) {
+                               finish_wait(&nn->nfsd_ssc_waitq, &wait);
+                               kfree(work);
+-                              return nfserr_eagain;
++                              return nfserr_jukebox;
+                       }
+                       finish_wait(&nn->nfsd_ssc_waitq, &wait);
+                       goto try_again;
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -201,7 +201,6 @@ void               nfsd_lockd_shutdown(void);
+ #define       nfserr_noent            cpu_to_be32(NFSERR_NOENT)
+ #define       nfserr_io               cpu_to_be32(NFSERR_IO)
+ #define       nfserr_nxio             cpu_to_be32(NFSERR_NXIO)
+-#define       nfserr_eagain           cpu_to_be32(NFSERR_EAGAIN)
+ #define       nfserr_acces            cpu_to_be32(NFSERR_ACCES)
+ #define       nfserr_exist            cpu_to_be32(NFSERR_EXIST)
+ #define       nfserr_xdev             cpu_to_be32(NFSERR_XDEV)
+--- a/include/trace/misc/nfs.h
++++ b/include/trace/misc/nfs.h
+@@ -16,7 +16,6 @@ TRACE_DEFINE_ENUM(NFSERR_PERM);
+ TRACE_DEFINE_ENUM(NFSERR_NOENT);
+ TRACE_DEFINE_ENUM(NFSERR_IO);
+ TRACE_DEFINE_ENUM(NFSERR_NXIO);
+-TRACE_DEFINE_ENUM(NFSERR_EAGAIN);
+ TRACE_DEFINE_ENUM(NFSERR_ACCES);
+ TRACE_DEFINE_ENUM(NFSERR_EXIST);
+ TRACE_DEFINE_ENUM(NFSERR_XDEV);
+@@ -53,7 +52,6 @@ TRACE_DEFINE_ENUM(NFSERR_JUKEBOX);
+               { NFSERR_NXIO,                  "NXIO" }, \
+               { ECHILD,                       "CHILD" }, \
+               { ETIMEDOUT,                    "TIMEDOUT" }, \
+-              { NFSERR_EAGAIN,                "AGAIN" }, \
+               { NFSERR_ACCES,                 "ACCES" }, \
+               { NFSERR_EXIST,                 "EXIST" }, \
+               { NFSERR_XDEV,                  "XDEV" }, \
+--- a/include/uapi/linux/nfs.h
++++ b/include/uapi/linux/nfs.h
+@@ -49,7 +49,6 @@
+       NFSERR_NOENT = 2,               /* v2 v3 v4 */
+       NFSERR_IO = 5,                  /* v2 v3 v4 */
+       NFSERR_NXIO = 6,                /* v2 v3 v4 */
+-      NFSERR_EAGAIN = 11,             /* v2 v3 */
+       NFSERR_ACCES = 13,              /* v2 v3 v4 */
+       NFSERR_EXIST = 17,              /* v2 v3 v4 */
+       NFSERR_XDEV = 18,               /*    v3 v4 */
diff --git a/queue-6.1/pinctrl-qcom-lpass-lpi-mark-the-gpio-controller-as-sleeping.patch b/queue-6.1/pinctrl-qcom-lpass-lpi-mark-the-gpio-controller-as-sleeping.patch
new file mode 100644 (file)
index 0000000..5284348
--- /dev/null
@@ -0,0 +1,88 @@
+From ebc18e9854e5a2b62a041fb57b216a903af45b85 Mon Sep 17 00:00:00 2001
+From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Date: Wed, 26 Nov 2025 13:22:19 +0100
+Subject: pinctrl: qcom: lpass-lpi: mark the GPIO controller as sleeping
+
+From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+commit ebc18e9854e5a2b62a041fb57b216a903af45b85 upstream.
+
+The gpio_chip settings in this driver say the controller can't sleep
+but it actually uses a mutex for synchronization. This triggers the
+following BUG():
+
+[    9.233659] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:281
+[    9.233665] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 554, name: (udev-worker)
+[    9.233669] preempt_count: 1, expected: 0
+[    9.233673] RCU nest depth: 0, expected: 0
+[    9.233688] Tainted: [W]=WARN
+[    9.233690] Hardware name: Dell Inc. Latitude 7455/0FK7MX, BIOS 2.10.1 05/20/2025
+[    9.233694] Call trace:
+[    9.233696]  show_stack+0x24/0x38 (C)
+[    9.233709]  dump_stack_lvl+0x40/0x88
+[    9.233716]  dump_stack+0x18/0x24
+[    9.233722]  __might_resched+0x148/0x160
+[    9.233731]  __might_sleep+0x38/0x98
+[    9.233736]  mutex_lock+0x30/0xd8
+[    9.233749]  lpi_config_set+0x2e8/0x3c8 [pinctrl_lpass_lpi]
+[    9.233757]  lpi_gpio_direction_output+0x58/0x90 [pinctrl_lpass_lpi]
+[    9.233761]  gpiod_direction_output_raw_commit+0x110/0x428
+[    9.233772]  gpiod_direction_output_nonotify+0x234/0x358
+[    9.233779]  gpiod_direction_output+0x38/0xd0
+[    9.233786]  gpio_shared_proxy_direction_output+0xb8/0x2a8 [gpio_shared_proxy]
+[    9.233792]  gpiod_direction_output_raw_commit+0x110/0x428
+[    9.233799]  gpiod_direction_output_nonotify+0x234/0x358
+[    9.233806]  gpiod_configure_flags+0x2c0/0x580
+[    9.233812]  gpiod_find_and_request+0x358/0x4f8
+[    9.233819]  gpiod_get_index+0x7c/0x98
+[    9.233826]  devm_gpiod_get+0x34/0xb0
+[    9.233829]  reset_gpio_probe+0x58/0x128 [reset_gpio]
+[    9.233836]  auxiliary_bus_probe+0xb0/0xf0
+[    9.233845]  really_probe+0x14c/0x450
+[    9.233853]  __driver_probe_device+0xb0/0x188
+[    9.233858]  driver_probe_device+0x4c/0x250
+[    9.233863]  __driver_attach+0xf8/0x2a0
+[    9.233868]  bus_for_each_dev+0xf8/0x158
+[    9.233872]  driver_attach+0x30/0x48
+[    9.233876]  bus_add_driver+0x158/0x2b8
+[    9.233880]  driver_register+0x74/0x118
+[    9.233886]  __auxiliary_driver_register+0x94/0xe8
+[    9.233893]  init_module+0x34/0xfd0 [reset_gpio]
+[    9.233898]  do_one_initcall+0xec/0x300
+[    9.233903]  do_init_module+0x64/0x260
+[    9.233910]  load_module+0x16c4/0x1900
+[    9.233915]  __arm64_sys_finit_module+0x24c/0x378
+[    9.233919]  invoke_syscall+0x4c/0xe8
+[    9.233925]  el0_svc_common+0x8c/0xf0
+[    9.233929]  do_el0_svc+0x28/0x40
+[    9.233934]  el0_svc+0x38/0x100
+[    9.233938]  el0t_64_sync_handler+0x84/0x130
+[    9.233943]  el0t_64_sync+0x17c/0x180
+
+Mark the controller as sleeping.
+
+Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver")
+Cc: stable@vger.kernel.org
+Reported-by: Val Packett <val@packett.cool>
+Closes: https://lore.kernel.org/all/98c0f185-b0e0-49ea-896c-f3972dd011ca@packett.cool/
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Linus Walleij <linusw@kernel.org>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pinctrl/qcom/pinctrl-lpass-lpi.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
++++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
+@@ -435,7 +435,7 @@ int lpi_pinctrl_probe(struct platform_de
+       pctrl->chip.ngpio = data->npins;
+       pctrl->chip.label = dev_name(dev);
+       pctrl->chip.of_gpio_n_cells = 2;
+-      pctrl->chip.can_sleep = false;
++      pctrl->chip.can_sleep = true;
+       mutex_init(&pctrl->lock);
index 20f9aae319a3fd8ab96884aef0db14ff8ec768fd..0eefb78846815e68d4488dba83d26a897a2c7c8a 100644 (file)
@@ -49,3 +49,12 @@ net-sched-sch_qfq-fix-null-deref-when-deactivating-i.patch
 net-usb-pegasus-fix-memory-leak-in-update_eth_regs_a.patch
 net-enetc-fix-build-warning-when-page_size-is-greate.patch
 arp-do-not-assume-dev_hard_header-does-not-change-sk.patch
+pinctrl-qcom-lpass-lpi-mark-the-gpio-controller-as-sleeping.patch
+mm-pagewalk-add-walk_page_range_vma.patch
+ksm-use-range-walk-function-to-jump-over-holes-in-scan_get_next_rmap_item.patch
+alsa-ac97bus-use-guard-for-mutex-locks.patch
+alsa-ac97-fix-a-double-free-in-snd_ac97_controller_register.patch
+nfsd-provide-locking-for-v4_end_grace.patch
+nfs-trace-show-timedout-instead-of-0x6e.patch
+nfs_common-factor-out-nfs_errtbl-and-nfs_stat_to_errno.patch
+nfsd-remove-nfserr_eagain.patch