Commit Graph

1974 Commits

Author SHA1 Message Date
Sasha Levin
1ea806165e fuse: fix link error with CONFIG_FUSE_PASSTHROUGH=n
Commit 2f19d54c05 ("fuse: support 64 bit, server allocated backing ID")
moved the CONFIG_FUSE_PASSTHROUGH check out of the backing ioctl handlers
and into fuse_get_conn_for_passthrough(). The calls from the handlers
into backing.c, which is only built with CONFIG_FUSE_PASSTHROUGH, are now
only removed if the compiler inlines that helper. It does not have to,
and with gcc 11 and CONFIG_CC_OPTIMIZE_FOR_SIZE it doesn't:

  dev.c:(.text+0x355c): undefined reference to `fuse_backing_open'
  nios2-linux-ld: dev.c:(.text+0x3594): undefined reference to `fuse_backing_open_64'
  nios2-linux-ld: dev.c:(.text+0x35d0): undefined reference to `fuse_backing_close'

Check CONFIG_FUSE_PASSTHROUGH in each handler again, as
fuse_notify_backing_remove() does. The check still comes after the
fuse_get_dev() and -ENOTCONN checks, so the errors userspace sees do not
change.

Fixes: 2f19d54c05 ("fuse: support 64 bit, server allocated backing ID")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202610171310.uqRzJkIx-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202610260719.sj08mXBr-lkp@intel.com/
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-10-30 14:22:37 -10:00
Linus Torvalds
8a36f53fd5 mm.git review status for linus..mm-stable
Everything:
 
 Total patches:       213
 Fixes: tags:         69
 cc:stable patches:   43
 Reviews/patch:       2.04
 Reviewed rate:       86%
 
 Excluding DAMON:
 
 Total patches:       192
 Fixes: tags:         63
 cc:stable patches:   39
 Reviews/patch:       2.18
 Reviewed rate:       89%
 
 Excluding DAMON and selftests:
 
 Total patches:       182
 Fixes: tags:         57
 cc:stable patches:   39
 Reviews/patch:       2.23
 Reviewed rate:       89%
 
 Summary of series in this merge:
 
 - "mm: make VMA flag semantics explicit, eliminate VM_SPECIAL"
   (Lorenzo Stoakes (ARM)):
 
   Replace VM_SPECIAL with helpers describing mapping ownership and
   behavior.  Enforce the mmap flag rules and convert affected drivers,
   removing ambiguous tests shared by driver mappings and ordinary memory.
 
 - "support kselftest on nommu platform" (Hajime Tazaki):
 
   Add opt-in mmap and mremap tests for NOMMU systems.  Teach the runner to
   avoid its fork-dependent timeout command and document the build and
   runtime requirements.
 
 - "mm/collapse: separate a collapse from its callers"
   (Kiryl Shutsemau (Meta)):
 
   Separate huge-page collapse from caller policy.  Replace khugepaged
   identity checks with explicit permissions, and separate scanning from
   collapse with the mmap_lock drop in one place.
 
 - "mm: implement and use vma_has_anon_rmap(), silence KCSAN"
   (Lorenzo Stoakes (ARM)):
 
   Provide a common helper for testing whether a VMA has anonymous reverse
   mappings.  Document the locking rules, annotate intentional concurrent
   reads for KCSAN, and convert the core MM callers.
 
 - "mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups"
   (David Hildenbrand (Arm)):
 
   Remove SECTION_MARKED_PRESENT in favor of the early-section flag.
   Simplify sparse memory initialization, section metadata handling and
   related PFN validity checks.
 
 - "sh: remove NUMA and SPARSEMEM support" (Mike Rapoport (Microsoft)):
 
   Remove SuperH NUMA and SPARSEMEM support.  The extra memory banks have
   been unusable since the NO_BOOTMEM conversion, leaving only the code and
   data overhead.
 
 - "mm: Unify device DAX and HugeTLB vmemmap population paths"
   (Muchun Song):
 
   Unify the generic device DAX and HugeTLB vmemmap population paths and
   shared tail-page handling.  Remove the duplicate DAX machinery while
   retaining the powerpc radix implementation.
 
 - "kselftest: mm: fix some failure of split_huge_page_test" (Yeoreum Yun):
 
   Fix huge-page split tests racing with khugepaged recollapse.  Use pagemap
   and page flags instead of VMA-boundary assumptions which fail when glibc
   has already enabled THP.
 
 - "memcg: move memcgid refcount to objcg to unpin dying memcgs"
   (Bingfang Guo):
 
   Let dying memcgs be freed while swapped-out shmem still holds their IDs.
   Move ID references to reparentable objcgs, with the necessary swap
   accounting and RCU lifetime changes.
 
 - "mm/truncate: fix data loss when truncating straddling large folios"
   (Zhang Yi):
 
   Preserve out-of-range data when truncating straddling large folios.  Fix
   a lookup race and split-failure handling, and handle minimum folio orders
   for the forthcoming ext4 iomap buffered I/O path.
 
 - "mm/damon: introduce damos quota goal target metric complement flag"
   (SJ Park):
 
   Let DAMOS quota goals use a metric's complement, so utilization can also
   express free-memory goals without adding separate metrics.  Add the sysfs
   interface, documentation and tests.
 
 - "arm64/mm: Standardize printing for pgtable entries" (Anshuman Khandual):
 
   Use the generic formatter for arm64 page-table entries, ready for future
   wider entries.  Move the safe-PTE-update check out of the header to avoid
   an include cycle.
 
 - "mm: kmsan: fix iounmap metadata teardown" (Dima Koziuk):
 
   Fix KMSAN metadata leaks on iounmap and failed ioremap allocations.  Free
   backing pages before removing their mappings, and share the teardown with
   partial-allocation cleanup.
 
 - "mm/damon/core: preserve quota state when constructing schemes"
   (Karl Mehltretter):
 
   Preserve running DAMOS quota state while validating parameter updates.
   Even rejected updates could reset accounting and exceed the quota window;
   add tests for both accepted and rejected updates.
 
 - "mm/vmalloc: fix vmalloc_dump_obj VA lookup" (Ye Liu):
 
   Fix vmalloc_dump_obj() lookups for last-page addresses and allocations
   spanning vmap zones.  These allocations were being missed in diagnostic
   output.
 
 - "mm: various (urgent?) fixes" (David Hildenbrand (Arm)):
 
   Fix mmap charge leaks and hugetlb use-after-free, wrong-address
   unmapping, stuck locks and endless faults.  Also preserve reservations on
   failed mremap and handle stale userfaultfd bits.
 
 - "maple_tree: fix maple_range_64 crashes in RCU mode" (Dimitris Charisis):
 
   Fix pointer and metadata confusion during RCU destruction of
   maple_range_64 nodes, avoiding double frees and invalid accesses.  Add a
   regression test; no in-tree user currently uses this combination.
 
 - "mm: fix hugetlb NR_HUGETLB accounting on folio migration" (Hongfu Li):
 
   Fix hugetlb migration and preallocation accounting so /proc/vmstat
   retains the correct count and memory.numa_stat follows the folio to its
   new node.
 
 - "mm/damon: fix a minor bug, clean code, and add a test" (SJ Park):
 
   Fix 32-bit DAMON age overflow which made old regions look young.  Share
   hugetlb folio acquisition code and add a regression test for the
   previously fixed last-region skipping bug.
 
 - "mm/damon/core: cleanup code, reduce stack usage, and add kunit"
   (SJ Park):
 
   Reduce kdamond stack usage and remove unused enums.  Add deterministic
   PSI quota-goal tests which do not depend on the machine's current memory
   pressure.
 
 - "mm/damon: fix the temporal goal tuner's size quota conversion"
   (Donggeun Yoo):
 
   Bound the temporal tuner's quota conversion to prevent overflow and zero
   effective quotas, which could stop schemes making progress.  Add boundary
   tests.
 
 - "Don't use GFP_DMA when calling dma_alloc_coherent" (Baoquan He):
 
   Remove redundant GFP_DMA flags from coherent DMA allocation calls.  The
   DMA API already selects the zone from device limits and ignores the
   caller's flag.
 
 - "kselftest: mm: fix intermittent failure khugepaged test" (Yeoreum Yun):
 
   Propagate child-process failures in the khugepaged tests and prevent
   background collapse from racing their checks.  This removes false passes
   and intermittent failures.
 
 - "MAINTAINERS: cover all hugetlb headers under HUGETLB SUBSYSTEM"
   (Enze Li):
 
   Cover all hugetlb headers in MAINTAINERS so get_maintainer.pl finds the
   right maintainers.  Also label the closing hugetlb_cgroup.h include
   guard.
 
 Summary of the 65 singletons in this merge:
 
 The singletons include a few worthwhile performance fixes. Avoiding
 unnecessary reverse-map tree updates gave a reported 15.9% improvement
 in UnixBench's execl test on a 192-core x86 system. A reclaim retry fix
 stops defrag_mode from spinning under memory.low protection; a reported
 file-creation stress test ran 5.7 times faster, with far less memory
 pressure. Narrower hugetlb invalidations also spare KVM guests needless
 refaults: the reported Redis-in-VM P99 QPS penalty while punching holes
 fell from 7.09% to 1.45%.
 
 Several fixes prevent lost data or corrupted memory. Lazyfree huge-page
 races with mremap()/munmap() could lose data or access freed memory, and
 MADV_COLD could lose a concurrent write's dirty bit. Another fix
 prevents stale migration entries from outliving large folios. On
 filesystems with blocks smaller than a page, extending a file by 4 GiB
 or more could expose bytes written past the old EOF through mmap instead
 of zeroes. That is fixed, along with use-after-free races in
 PAGEMAP_SCAN during process exit and in memory-cgroup accounting on
 PREEMPT_RT kernels.
 
 Other fixes stop UFFDIO_MOVE spinning forever on pinned large folios,
 which could wedge other memory operations, and stop mremap() leaking
 commit charges until allocations fail under strict overcommit. A further
 fix keeps userfaultfd tracking intact on neighboring mappings. NUMA
 binding no longer prevents long-term pins when the chosen node has only
 movable memory, fixing QEMU/VFIO startup and io_uring buffer
 registration failures. MGLRU also gets a fix for early-boot crashes with
 memory cgroups disabled at boot, notably in small crash kernels.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCat66sAAKCRDdBJ7gKXxA
 jrQrAP99kgSXRdlmRZbHeRBHQ6KvI4XnLvQ78MDIzZ3zmBaOugEA5jiIsK2/snFD
 3VaV0oipVZpuwJkVJE6zFkh0tcHgTAo=
 =DHrN
 -----END PGP SIGNATURE-----

Merge tag 'mm-stable-2026-10-25-19-27' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull more MM updates from Andrew Morton:

 - "mm: make VMA flag semantics explicit, eliminate VM_SPECIAL" (Lorenzo
   Stoakes):

   Replace VM_SPECIAL with helpers describing mapping ownership and
   behavior. Enforce the mmap flag rules and convert affected drivers,
   removing ambiguous tests shared by driver mappings and ordinary
   memory.

 - "support kselftest on nommu platform" (Hajime Tazaki):

   Add opt-in mmap and mremap tests for NOMMU systems. Teach the runner
   to avoid its fork-dependent timeout command and document the build
   and runtime requirements.

 - "mm/collapse: separate a collapse from its callers" (Kiryl
   Shutsemau):

   Separate huge-page collapse from caller policy. Replace khugepaged
   identity checks with explicit permissions, and separate scanning from
   collapse with the mmap_lock drop in one place.

 - "mm: implement and use vma_has_anon_rmap(), silence KCSAN" (Lorenzo
   Stoakes):

   Provide a common helper for testing whether a VMA has anonymous
   reverse mappings. Document the locking rules, annotate intentional
   concurrent reads for KCSAN, and convert the core MM callers.

 - "mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups"
   (David Hildenbrand):

   Remove SECTION_MARKED_PRESENT in favor of the early-section flag.
   Simplify sparse memory initialization, section metadata handling and
   related PFN validity checks.

 - "sh: remove NUMA and SPARSEMEM support" (Mike Rapoport):

   Remove SuperH NUMA and SPARSEMEM support. The extra memory banks have
   been unusable since the NO_BOOTMEM conversion, leaving only the code
   and data overhead.

 - "mm: Unify device DAX and HugeTLB vmemmap population paths" (Muchun
   Song):

   Unify the generic device DAX and HugeTLB vmemmap population paths and
   shared tail-page handling. Remove the duplicate DAX machinery while
   retaining the powerpc radix implementation.

 - "kselftest: mm: fix some failure of split_huge_page_test" (Yeoreum
   Yun):

   Fix huge-page split tests racing with khugepaged recollapse. Use
   pagemap and page flags instead of VMA-boundary assumptions which fail
   when glibc has already enabled THP.

 - "memcg: move memcgid refcount to objcg to unpin dying memcgs"
   (Bingfang Guo):

   Let dying memcgs be freed while swapped-out shmem still holds their
   IDs. Move ID references to reparentable objcgs, with the necessary
   swap accounting and RCU lifetime changes.

 - "mm/truncate: fix data loss when truncating straddling large folios"
   (Zhang Yi):

   Preserve out-of-range data when truncating straddling large folios.
   Fix a lookup race and split-failure handling, and handle minimum
   folio orders for the forthcoming ext4 iomap buffered I/O path.

 - "mm/damon: introduce damos quota goal target metric complement flag"
   (SJ Park):

   Let DAMOS quota goals use a metric's complement, so utilization can
   also express free-memory goals without adding separate metrics. Add
   the sysfs interface, documentation and tests.

 - "arm64/mm: Standardize printing for pgtable entries" (Anshuman
   Khandual):

   Use the generic formatter for arm64 page-table entries, ready for
   future wider entries. Move the safe-PTE-update check out of the
   header to avoid an include cycle.

 - "mm: kmsan: fix iounmap metadata teardown" (Dima Koziuk):

   Fix KMSAN metadata leaks on iounmap and failed ioremap allocations.
   Free backing pages before removing their mappings, and share the
   teardown with partial-allocation cleanup.

 - "mm/damon/core: preserve quota state when constructing schemes" (Karl
   Mehltretter):

   Preserve running DAMOS quota state while validating parameter
   updates. Even rejected updates could reset accounting and exceed the
   quota window; add tests for both accepted and rejected updates.

 - "mm/vmalloc: fix vmalloc_dump_obj VA lookup" (Ye Liu):

   Fix vmalloc_dump_obj() lookups for last-page addresses and
   allocations spanning vmap zones. These allocations were being missed
   in diagnostic output.

 - "mm: various (urgent?) fixes" (David Hildenbrand):

   Fix mmap charge leaks and hugetlb use-after-free, wrong-address
   unmapping, stuck locks and endless faults. Also preserve reservations
   on failed mremap and handle stale userfaultfd bits.

 - "maple_tree: fix maple_range_64 crashes in RCU mode" (Dimitris
   Charisis):

   Fix pointer and metadata confusion during RCU destruction of
   maple_range_64 nodes, avoiding double frees and invalid accesses. Add
   a regression test; no in-tree user currently uses this combination.

 - "mm: fix hugetlb NR_HUGETLB accounting on folio migration" (Hongfu
   Li):

   Fix hugetlb migration and preallocation accounting so /proc/vmstat
   retains the correct count and memory.numa_stat follows the folio to
   its new node.

 - "mm/damon: fix a minor bug, clean code, and add a test" (SJ Park):

   Fix 32-bit DAMON age overflow which made old regions look young.
   Share hugetlb folio acquisition code and add a regression test for
   the previously fixed last-region skipping bug.

 - "mm/damon/core: cleanup code, reduce stack usage, and add kunit" (SJ
   Park):

   Reduce kdamond stack usage and remove unused enums. Add deterministic
   PSI quota-goal tests which do not depend on the machine's current
   memory pressure.

 - "mm/damon: fix the temporal goal tuner's size quota conversion"
   (Donggeun Yoo):

   Bound the temporal tuner's quota conversion to prevent overflow and
   zero effective quotas, which could stop schemes making progress. Add
   boundary tests.

 - "Don't use GFP_DMA when calling dma_alloc_coherent" (Baoquan He):

   Remove redundant GFP_DMA flags from coherent DMA allocation calls.
   The DMA API already selects the zone from device limits and ignores
   the caller's flag.

 - "kselftest: mm: fix intermittent failure khugepaged test" (Yeoreum
   Yun):

   Propagate child-process failures in the khugepaged tests and prevent
   background collapse from racing their checks. This removes false
   passes and intermittent failures.

 - "MAINTAINERS: cover all hugetlb headers under HUGETLB SUBSYSTEM"
   (Enze Li):

   Cover all hugetlb headers in MAINTAINERS so get_maintainer.pl finds
   the right maintainers. Also label the closing hugetlb_cgroup.h
   include guard.

Summary of the 65 singletons in this merge:

  The singletons include a few worthwhile performance fixes. Avoiding
  unnecessary reverse-map tree updates gave a reported 15.9% improvement
  in UnixBench's execl test on a 192-core x86 system. A reclaim retry
  fix stops defrag_mode from spinning under memory.low protection; a
  reported file-creation stress test ran 5.7 times faster, with far less
  memory pressure. Narrower hugetlb invalidations also spare KVM guests
  needless refaults: the reported Redis-in-VM P99 QPS penalty while
  punching holes fell from 7.09% to 1.45%.

  Several fixes prevent lost data or corrupted memory. Lazyfree
  huge-page races with mremap()/munmap() could lose data or access freed
  memory, and MADV_COLD could lose a concurrent write's dirty bit.
  Another fix prevents stale migration entries from outliving large
  folios. On filesystems with blocks smaller than a page, extending a
  file by 4 GiB or more could expose bytes written past the old EOF
  through mmap instead of zeroes. That is fixed, along with
  use-after-free races in PAGEMAP_SCAN during process exit and in
  memory-cgroup accounting on PREEMPT_RT kernels.

  Other fixes stop UFFDIO_MOVE spinning forever on pinned large folios,
  which could wedge other memory operations, and stop mremap() leaking
  commit charges until allocations fail under strict overcommit. A
  further fix keeps userfaultfd tracking intact on neighboring mappings.
  NUMA binding no longer prevents long-term pins when the chosen node
  has only movable memory, fixing QEMU/VFIO startup and io_uring buffer
  registration failures. MGLRU also gets a fix for early-boot crashes
  with memory cgroups disabled at boot, notably in small crash kernels.

* tag 'mm-stable-2026-10-25-19-27' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (213 commits)
  mm: multi-gen LRU: fix NULL lruvec->pgdat deref with memcg disabled on cmdline
  mm/page_counter: use WRITE_ONCE() for emin/elow when parent is the root
  mm/memcontrol: publish null pointer before dropping css reference
  test_maple_tree: test maple_range_64 node in RCU mode
  maple_tree: fix maple_range_64 crashes in RCU mode
  mm/vma: avoid broken uffd merge on mremap
  tools/testing/shared: catch a failed posix_memalign()
  mm/damon/core: remove unreachable damos charge_{target,addr}_from
  mm/shrinker: allocate shrinker_info_unit from a dedicated kmem_cache
  riscv: mm: exclude invalid THP PMDs from page table check
  mm/damon/core: filter out damos address filter-split failed region
  fs/proc/task_mmu: pin mm_users in do_pagemap_scan()
  mm/mempolicy: apply bind policies against the scoped allocation zone
  mm/vmscan: reclaim every zone in per-node proactive reclaim
  mm/mremap: correctly uncharge accountable VMAs in error path
  mm/mremap: populate calculated fields in vrm state correctly
  MAINTAINERS: add an entry for MEMORY MANAGEMENT - MEMORY MAP
  mm: bdi: reset min_ratio after the sysfs attributes are gone
  mm/page_vma_mapped: continue past nonmatching huge PMDs
  selftests/mm: skip hugetlb cgroup v2 tests without the needed controllers
  ...
2026-10-27 12:23:17 -10:00
Linus Torvalds
03973f7f35 fuse update for 7.4
-----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQSQHSd0lITzzeNWNm3h3BK/laaZPAUCat+KDwAKCRDh3BK/laaZ
 PMgzAQC8x2eK/+zB6sJSCZonEEP/KemzrnyxAdgaj+1FJCHORQD7BFLBewb5c1FF
 56XJhVSpxeYiaSajAnso7lvI2kfUqwY=
 =FXhB
 -----END PGP SIGNATURE-----

Merge tag 'fuse-update-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse

Pull fuse updates from Miklos Szeredi:

 - Add dax backing and extent map support for famfs (John Groves,
   Miklos)

 - Support large folios (Joanne)

 - Add selftests and documentation of caching behavior (Luis Henriques)

 - Add FUSE_SYNCFS request (Jimmy Zuber)

 - Convert readdir cache to use folios (Tal Zussman)

 - Lots of bug fixes

* tag 'fuse-update-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (53 commits)
  fuse: handle extent map files in fuse_passthrough_fadvise()
  fuse: resolve extent maps in O(1) when possible
  fuse: add support for striped backing
  fuse: add extent map I/O support
  fuse: add extent map data structure
  fuse: add support for opening dax device as backing
  fuse: support opening 64 bit backing ID
  fuse: support 64 bit, server allocated backing ID
  fuse: add helpers for EIO return value with kernel message
  dax: use READ_ONCE() in dax_holder()
  dax: add fsdev_dax_from_file()
  fuse: fix copy_file_range reply handling race
  virtiofs: validate fixed-output response length
  fuse: don't d_drop() before d_splice_alias()
  virtio_fs: read the vring size under virtio_fs_mutex in ->get_tree
  fuse: validate folio state before pipe_buf_try_steal() in fuse_try_move_folio()
  fuse: rename fuse_direct_io() to fuse_do_direct_io()
  fuse: Forward vfs_fadvise to backing_file in passthrough mode
  selftests/fuse: add the missing FUSE_HAS_SYNCFS privilege test
  fuse: don't launder folios of a bad inode
  ...
2026-10-27 08:09:58 -10:00
John Groves
bf56861216 fuse: handle extent map files in fuse_passthrough_fadvise()
This addresses a collision between the pending backing_file fadvise
patch and the new extent-mapping code for famfs (which falls into the
passthrough bucket.

A file opened with FOPEN_PASSTHROUGH on an extent map backing has no
backing file: fuse_passthrough_open() returns before setting
ff->passthrough and ff->cred.  fuse_file_fadvise() routes every
FOPEN_PASSTHROUGH file to fuse_passthrough_fadvise(), which installed
the NULL ff->cred on the task with override_creds() and then passed the
NULL backing file to vfs_fadvise().  Any posix_fadvise(), readahead()
or madvise(MADV_WILLNEED) on such a file oopsed.  fio triggers it at
file open with its default invalidate and fadvise_hint settings.

Fall back to generic_fadvise() when there is no backing file, as the
other passthrough helpers fall back to their extent map or generic
implementations.  generic_fadvise() already ignores advice on DAX
inodes while keeping the EINVAL and ESPIPE checks.

Reported-by: Aravind Ramesh <arramesh@micron.com>
Fixes: 69f77a06ffad ("fuse: Forward vfs_fadvise to backing_file in passthrough mode")
Tested-by: John Groves <john@groves.net>
Signed-off-by: John Groves <john@groves.net>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-26 18:10:12 +01:00
Lorenzo Stoakes (ARM)
b0d88bfa75 fuse: dax: do not set VM_MIXEDMAP
Commit e1fb4a0864 ("dax: remove VM_MIXEDMAP for fsdax and device dax")
prevented fsdax and device-dax from setting VM_MIXEDMAP, as DAX no longer
relies on it to direct core mm paths.

The fuse DAX implementation, added later, copied the old pattern and still
sets it.

Fuse DAX maps pages the same way fsdax does, via dax_iomap_fault() and
ultimately vmf_insert_page_mkwrite() and vmf_insert_folio_pmd(), which
insert ordinary refcounted pages and so do not require VM_MIXEDMAP.

Setting it only serves to mark the mapping as not mm-managed, making fuse
DAX the sole DAX implementation whose mappings are unmergeable, cannot be
mlock()'d, eagerly copy page tables on fork and reject MADV_DOFORK and
MADV_DODUMP.

It also requires vma_is_special_huge() in mm/huge_memory.c to carve DAX out
of its check for mappings not managed by core mm explicitly.

There is no reason for fuse DAX to keep on using this flag so drop it.

Link: https://lore.kernel.org/20261013-b4-mmap-prepare-vma-flag-sanify-v6-38-1aa3c9b139f9@kernel.org
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Nico Pache <nico.pache@linux.dev>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Usama Arif <usama.arif@linux.dev>
Cc: Kiryl Shutsemau <kas@kernel.org>
Cc: Doug Gilbert <dgilbert@interlog.com>
Cc: James Bottomley <james.bottomley@hansenpartnership.com>
Cc: Martin K. Petersen <mkp@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Helge Deller <deller@gmx.de>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Harry Yoo <harry@kernel.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Will Deacon <will@kernel.org>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Anup Patel <anup@brainfault.org>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Janosch Frank <frankja@linux.ibm.com>
Cc: Claudio Imbrenda <imbrenda@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Chris Li <chrisl@kernel.org>
Cc: Kairui Song <kasong@tencent.com>
Cc: Kemeng Shi <shikemeng@huaweicloud.com>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Youngjun Park <youngjun.park@lge.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Qi Zheng <qi.zheng@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Xu Xin <xu.xin@linux.dev>
Cc: Ihor Solodrai <ihor.solodrai@linux.dev>
Cc: Bert Karwatzki <spasswolf@web.de>
2026-10-24 01:56:21 -07:00
John Groves
5a9745611d fuse: resolve extent maps in O(1) when possible
fuse_ext_map_iomap_begin() runs on every mapping fault of a DAX
extent-mapped file, meaning the TLB-miss-plus-page-table-miss case,
and on every chunk of every read/write.  These are not page faults in
the usual sense: nothing is read in from storage.  The fault only
installs page table entries for memory that is already there, so there
is no I/O to amortize the resolver's cost against; whatever it costs
is added to the cost of a memory access.

The rbtree it walks is built from individually allocated nodes.  Each
level is a dependent, un-prefetchable dereference and a potential LLC
miss (~100ns), so a striped file with S strips pays log2(S) of them
per resolution, and that is a large fraction of a mapping fault that
otherwise costs little more than the page table update itself.

Replace the rbtree in struct fuse_backing with a packed, sorted array
of fuse_iext extents, allocated once per map rather than once per
extent.  The array packs the extents into the fewest cache lines, and
fault handling is O(1) when the map allows it:

 - A cyclic (striped) map is required to have equal-length extents
   contiguous from zero, so a file offset converts arithmetically to a
   strip index and cycle number.  This patch validates that and does
   it.

 - A simple map whose extents happen to be equal-length and contiguous
   from zero (the common famfs allocation) resolves as offset / ext_len.
   This patch detects that at populate time and does it.

 - An irregular map falls back to a binary search of the packed array.

famfs currently always produces maps that resolve in O(1).

Because the extents are sorted at populate time, a cyclic map's extents
no longer have to arrive in offset order, and the overlap check is an
adjacent-pair compare over the sorted array rather than a check at each
rbtree insertion.  Error returns are unchanged: -EIO with a message for
malformed extents and overlaps, -EINVAL for a non-uniform cyclic map.

Signed-off-by: John Groves <john@groves.net>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-20 06:39:59 +02:00
Linus Torvalds
00b04f4495 vfs-7.4-rc1.idmap
Please consider pulling these changes from the signed vfs-7.4-rc1.idmap tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCatHrlgAKCRCRxhvAZXjc
 opFuAPwLL5l3D3GSRyD+SyOjKYThylgowvH9c2BcLWbSAIO6yQD9F05GX+rrcbUq
 9ijolxAaQZYpEWsemZIIHx6BBwdDBA4=
 =IH8Z
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.4-rc1.idmap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs idmap constification from Christian Brauner:
 "This makes struct mnt_idmap const throughout the tree.

  A mount's idmapping is immutable. The only thing modified after
  alloc_mnt_idmap() is the reference count and that is hidden behind
  mnt_idmap_get() and mnt_idmap_put(). Everything else only reads from
  it. That is the same model struct cred uses and the idmapping is
  sensitive enough to deserve it.

  The conversion goes bottom up through the vfs{g,u}id and fs{g,u}id
  helpers, the privilege checks, acl, xattr and quota and then every
  inode operation that takes an idmap, so ->permission(), ->getattr(),
  ->setattr(), ->create(), ->mkdir(), ->mknod(), ->symlink(),
  ->rename(), ->tmpfile(), ->get_acl(), ->set_acl() and ->fileattr_set()
  with their implementations in every filesystem, plus the LSM hooks.

  struct vfsmount, struct mount_kattr and struct kstatmount store a
  const pointer and nop_mnt_idmap and invalid_mnt_idmap live in rodata,
  so anything that tries to modify them faults instead of silently
  corrupting the initial idmapping"

* tag 'vfs-7.4-rc1.idmap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (27 commits)
  fs: make nop_mnt_idmap and invalid_mnt_idmap const
  fs: port mnt_idmap() and file_mnt_idmap() to const mnt_idmap
  fs: port vfs_*() helpers to const mnt_idmap
  fs: port ->setattr() to pass const mnt_idmap
  fs: port ->getattr() to pass const mnt_idmap
  fs: port ->create() to pass const mnt_idmap
  fs: port ->symlink() to pass const mnt_idmap
  fs: port ->mkdir() to pass const mnt_idmap
  fs: port ->rename() to pass const mnt_idmap
  fs: port ->mknod() to pass const mnt_idmap
  fs: port ->tmpfile() to pass const mnt_idmap
  fs: port ->get_acl() to pass const mnt_idmap
  fs: port ->set_acl() to pass const mnt_idmap
  fs: port ->fileattr_set() to pass const mnt_idmap
  fs: port xattr to const mnt_idmap
  fs: port ->permission() to pass const mnt_idmap
  fs: port acl to const mnt_idmap
  fs: port inode_init_owner() to const mnt_idmap
  fs: port inode_owner_or_capable() to const mnt_idmap
  fs: port privilege checking helpers to const mnt_idmap
  ...
2026-10-19 17:57:49 -10:00
Miklos Szeredi
dfc68b6c99 fuse: add support for striped backing
Add the FUSE_BACKING_MAP_CYCLIC flag for FUSE_NOTIFY_BACKING_MAP
notifications to enable creating striped maps.

This is just a set of regular extents that repeats after the end of the
last extent using a striping pattern (i.e. on the target backings the
stripes have a contiguous footprint).

Two additional limits apply compared to non-cyclic extent map population:

 - the size of the extents (chunk size) must be equal

 - the extents must start from zero offset and follow each other without
   gaps.

Originally-by: John Groves <john@groves.net>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
e8bc74b6ed fuse: add extent map I/O support
Wire up read, write, splice and mmap operations for extent-mapped
files through the iomap/DAX infrastructure.

When a passthrough file is opened with an EXTMAP backing, I/O is
dispatched to the dax devices referenced by the extent map.

If an address is not mapped, EIO is returned on the I/O operation.

Originally-by: John Groves <john@groves.net>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
bf75733445 fuse: add extent map data structure
Add support for creating and managing extent maps that map file regions to
dax device regions.

Introduce FUSE_NOTIFY_BACKING_MAP for populating extent maps from
userspace.

Extent maps are handled as a new type of backing and are assigned a 64 bit
backing ID by the server.

One extent consists of

 - offset within the containing backing
 - length of extent
 - target backing ID
 - offset into target backing

Extents must be non-overlapping, and can only refer to dax device backings
for now.

At this point only support creating and populating the extent map in one
operation, though the interface is not limited by this and later may be
changed, so that partial population of an extent map would be possible.

Originally-by: John Groves <john@groves.net>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
2fbe4586cf fuse: add support for opening dax device as backing
This is only possible with FUSE_PASSTHROUGH_V2 enabled.

Mark the inode with S_DAX if FUSE_LOOKUP returns with FUSE_ATTR_DAX set.

This patch does not yet provide a way actually use the dax dev backing:
when such a backing ID is provided in reply to FUSE_OPEN with
FOPEN_PASSTHROUGH flag set, an error will be returned.

Truncate and hole punch is not currently allowed on inodes marked with
S_DAX.

Move fuse_backing_put() from fuse_free_inode() to fuse_evict_inode() to
avoid sleeping in atomic context.

Originally-by: John Groves <john@groves.net>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
c712cd3625 fuse: support opening 64 bit backing ID
Add backing_id_64 field to fuse_open_out to allow opening files with
64-bit server-allocated backing IDs.

If the connection was initialized with FUSE_PASSTHROUGH_V2, the kernel
reads the backing ID from open_out.backing_id_64 instead of
open_out.backing_id.

The open reply is now variable-length for backward compatibility with
servers that don't send the new backing_id_64 field.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
2f19d54c05 fuse: support 64 bit, server allocated backing ID
Add support for server allocated 64-bit backing IDs alongside the
existing kernel allocated 32-bit IDs.

Opened with FUSE_DEV_IOC_BACKING_CREATE, the backing ID sent via
fuse_backing_create_in.backing_id.

Closed with FUSE_NOTIFY_BACKING_REMOVE.  Since close only provides the
backing ID, not the file descriptor, it doesn't have to be done with an
ioctl.

Backing ID can take any 64 bit value other than zero.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Miklos Szeredi
b89c73703e fuse: add helpers for EIO return value with kernel message
Conditions are triggered by a buggy fuse server will result in -EIO which
is hard to interpret without any context.

Add helpers that print a short message to the kernel log as well as
returning the error value.  This serves a dual purpose:

 - documents the error condition inside the code

 - allows the implementor of the fuse server to get the context for the
   error

Some debug messages are removed in favor of this.

This also changes the mmap return value from -ETXTBSY to -ENODEV if a
passthrough open raced with the prior check.  This makes both cases return
-ENODEV if the file is in passthrough mode.

Additionally change the return value of fuse_file_cached_io_open() from an
error value to a bool (true on success) as the error value is translated
anyway.

Currently these use the pr_notice_once() variant.  Possibly should be
changed to a ratelimit of e.g. once per minute.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-19 14:56:24 +02:00
Chengfeng Ye
bf4ccbaad8 fuse: fix copy_file_range reply handling race
__fuse_copy_file_range() selects its request opcode and output buffer
using fc->no_copy_file_range_64, then reads the flag again to handle the
reply. Copies to different destination inodes can run concurrently on
the same connection, so the flag may change while a request is pending.

For example, task A submits FUSE_COPY_FILE_RANGE_64 and waits for its
reply. Task B submits the same opcode, receives -ENOSYS and sets
no_copy_file_range_64. When A receives a successful reply, it reads the
uninitialized outarg.size instead of outarg_64.bytes_copied. This can
produce an incorrect return value, page cache invalidation range and
inode size update, and disclose stack contents if automatic stack
initialization is disabled.

If A also receives -ENOSYS, it instead mistakes that reply for rejection
of the legacy opcode and sets no_copy_file_range, skipping the legacy
fallback and unnecessarily disabling copy offload for the connection.

KCSAN reported the conflicting accesses:

  BUG: KCSAN: data-race in __fuse_copy_file_range / __fuse_copy_file_range

  read to 0xffff8881014a4d4d of 1 bytes by task 123 on cpu 4:
   __fuse_copy_file_range+0x1a7/0x6e0
   fuse_copy_file_range+0x54/0xd0
   vfs_copy_file_range+0x290/0x9d0
   __do_sys_copy_file_range+0x10f/0x2f0

  write to 0xffff8881014a4d4d of 8 bytes by task 119 on cpu 0:
   __fuse_copy_file_range+0x633/0x6e0
   fuse_copy_file_range+0x54/0xd0
   vfs_copy_file_range+0x290/0x9d0
   __do_sys_copy_file_range+0x10f/0x2f0

The bug can lead to leak kernel base address for KASLR bypass, the
corresponding reproducer can be provided per request.

Use args.opcode for both -ENOSYS handling and output buffer selection.
It records the opcode actually sent and is updated on fallback, keeping
each reply tied to its request regardless of concurrent flag updates.

Fixes: 7a37f55af7 ("fuse: add COPY_FILE_RANGE_64 that allows large copies")
Cc: stable@vger.kernel.org
Assisted-by: GPT-6 Astra
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 15:41:23 +02:00
Sung Byeongchan
5364d08112 virtiofs: validate fixed-output response length
A short successful virtiofs response can leave the fixed-output portion of
the request argument buffer unwritten.  The completion path nevertheless
copies the full declared output to the request destination, allowing stale
allocator contents to reach callers such as fuse_statfs().

Require successful fixed-output responses to contain their complete
declared output.  Continue to permit a shorter final argument only for
out_argvar requests.  Reject positive and internal restart error values
and require valid error replies to be header-only.  The error already
stored in the FUSE output header is returned by fuse_request_end(), so do
not copy output arguments from an error reply.

This was found by source review with AI assistance.  A header-only
successful FUSE_STATFS reply returned stale fields in nine of nine calls
across three boots.  The fixed kernel rejected the short response and
preserved complete replies, valid negative-error replies, and
variable-output replies.

Fixes: a62a8ef9d9 ("virtio-fs: add virtiofs filesystem")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Sung Byeongchan <tjdqudcks0424@naver.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:21:08 +02:00
NeilBrown
ed6f750f98 fuse: don't d_drop() before d_splice_alias()
create_new_entry() is used to finalise the creation of various
objects (mknod, mkdir, symlink etc).

It currently uses d_drop() which will be a problem for a proposed
new locking scheme.

d_splice_alias() now works on hashed dentries so the d_drop() isn't
needed.  Drop it.

Signed-off-by: NeilBrown <neil@brown.name>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:08 +02:00
Fan Wu
e7ccc777a0 virtio_fs: read the vring size under virtio_fs_mutex in ->get_tree
The vring size was read after virtio_fs_find_instance() had dropped
virtio_fs_mutex, so a concurrent virtio_fs_remove() could free the
virtqueue first. The reference from the lookup keeps the virtio_fs
alive, but not its virtqueues.

Hold the mutex across the lookup and the read.

This issue was found by an in-house static analysis tool.

Fixes: a7f0d7aab0 ("virtiofs: split requests that exceed virtqueue size")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Co-developed-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:08 +02:00
Hui Peng
15c20483d9 fuse: validate folio state before pipe_buf_try_steal() in fuse_try_move_folio()
In fuse_try_move_folio(), check that the pipe buffer's folio is not
hugetlb, swap-backed, or already mapped/anon before attempting
pipe_buf_try_steal() and inserting it into the FUSE inode's page cache,
preventing VM_BUG_ON_FOLIO() and page cache state corruption.

Fixes: 394244b24f ("fuse: support copying large folios")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:08 +02:00
Luis Henriques
bcd3a16ae7 fuse: rename fuse_direct_io() to fuse_do_direct_io()
FUSE has two functions with very similar name: fuse_direct_io() and
fuse_direct_IO().  Which is very confusing.  Rename one of them to remove
the ambiguity.

Signed-off-by: Luis Henriques <luis@igalia.com>
Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:08 +02:00
Shai Barack
3cfce590fe fuse: Forward vfs_fadvise to backing_file in passthrough mode
When an application invokes posix_fadvise(..., POSIX_FADV_DONTNEED) or
other fadvise advice on a FUSE passthrough file descriptor, the VFS
currently only executes generic_fadvise() on the upper FUSE inode
mapping.

Because FUSE passthrough does not forward fadvise operations to the
underlying backing file, pages residing in the lower filesystem's
pagecache remain resident in memory.

During media-heavy workloads (such as image thumbnail generation or
streaming), single-access file data accumulates in the inactive pagecache
of the lower filesystem. Under memory pressure, the kernel retains these
stale media pages and instead evicts active executable pages from
running processes, leading to severe direct reclaim latency spikes.

Architecturally, Linux VFS supports filesystem-specific fadvise
delegation via the .fadvise hook in struct file_operations. Implement
fuse_file_fadvise() in fs/fuse/file.c and register it in
fuse_file_operations. When passthrough is active on a fuse_file,
fuse_file_fadvise() forwards the vfs_fadvise() call to the lower
backing_file under the opened credentials, allowing POSIX_FADV_DONTNEED
to cleanly invalidate the physical backing filesystem pagecache.

Signed-off-by: Shai Barack <shayba@google.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Amir Goldstein <amir73il@gmail.com>
Cc: Bernd Schubert <bschubert@ddn.com>
Cc: Sandeep Dhavale <dhavale@google.com>
Cc: Akilesh Kailash <akailash@google.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: fuse-devel@lists.linux.dev
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Reviewed-by: T.J. Mercier <tjmercier@google.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:08 +02:00
Joanne Koong
01d0f3d294 fuse: don't launder folios of a bad inode
fuse_flush() and fuse_writepages() reject writing back dirty data for
any inode that has been marked bad, but fuse_launder_folio() doesn't.

This can cause the following warning in fuse_write_file_get() to
trigger, as reported by syzbot:

WARNING: fs/fuse/file.c:2043 at fuse_write_file_get fs/fuse/file.c:2043 [inline]
WARNING: fs/fuse/file.c:2043 at fuse_iomap_writeback_range+0x7c8/0x18f0 fs/fuse/file.c:2227
Call Trace:
    iomap_writeback_folio+0x1526/0x2490 fs/iomap/buffered-io.c:2022
    fuse_launder_folio+0x17b/0x240 fs/fuse/file.c:2331
    folio_unmap_invalidate+0x4cd/0x830 mm/truncate.c:634
    invalidate_inode_pages2_range+0x629/0xb30 mm/truncate.c:726
    fuse_open+0x5a6/0x770 fs/fuse/file.c:297

This can be hit on a writeback cache mount:
1) a writeable file is open and a buffered write dirties some pages
2) another thread opens the same file read-only. fuse_open() passes the
   bad inode check and sends OPEN to the server.
3) a SETATTR reply with the wrong file type marks the inode bad
4) the writeable file is closed. Flush and release skip writeback
   because the inode is bad. The pages stay dirty but the file gets
   removed from write_files.
5) server replies to the OPEN. The reply has no FOPEN_KEEP_CACHE, so
   fuse_open() calls invalidate_inode_pages2().
6) the invalidation finds the dirty pages and calls
   fuse_launder_folio(), which finds no wriable file and hits the
   WARN_ON in fuse_write_file_get().

Instead of trying to write back dirty data for the bad inode,
fuse_launder_folio() should return -EIO.

Fixes: 5d069dbe8a ("fuse: fix bad inode")
Reported-by: syzbot+e8200299b0556976e13c@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e8200299b0556976e13c
Cc: stable@vger.kernel.org
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Horst Birthelmer <hbirthelmer@ddn.com>
Tested-by: syzbot+e8200299b0556976e13c@syzkaller.appspotmail.com
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:17:07 +02:00
Miklos Szeredi
f8cef5c74d fuse: fix NULL pointer dereference in fuse_request_find
fuse_dev_install_with_pq() publishes fud->chan before it stores
fud->pq.processing. The write/splice_write and read paths treat a non-NULL
fud->chan as "installed" and then walk fpq->processing[] without taking
fch->lock, so they can see the new chan while processing is still NULL and
oops in fuse_request_find().

Fix by taking fpq->lock around the cmpxchg + fud->pq.processing assignment.
This protects all call sites that dereference fpq->processing, since these
have fpq->lock held.

Fixes: 48649c0603 ("fuse: alloc pqueue before installing fch in fuse_dev")
Reported-by: Cen Zhang <zzzccc427@gmail.com>
Closes: https://lore.kernel.org/fuse-devel/pm-fuse-full-objects-candidate-0002-v2-17d6013e5066de33396c@gmail.com/
Reported-by: 马云龙 <yunlong_ma@buaa.edu.cn>
Closes: https://lore.kernel.org/all/5ddc8efe.1e6d2.1a11fbec860.Coremail.yunlong_ma@buaa.edu.cn/
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-16 12:15:28 +02:00
Tal Zussman
294de5bbbc fuse: convert fuse_readdir_cached() to use folios
Replace find_get_page_flags() with __filemap_get_folio(), and switch the
remaining page helpers to their folio equivalents.

This removes seven hidden calls to compound_head() and the last caller of
find_get_page_flags().

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-15 15:45:22 +02:00
Tal Zussman
b8ada80b9d fuse: convert fuse_add_dirent_to_cache() to use folios
Replace find_lock_page() and find_or_create_page() with
filemap_lock_folio() and filemap_grab_folio(), and switch the remaining
page helpers to their folio equivalents.

Each index of the readdir cache holds one page of dirents. fuse does not
enable large folios, so these folios are always a single page.

Also write the dirent with folio_fill_tail() and memcpy_to_folio()
instead of open-coding it.

This removes two hidden calls to compound_head() and one of the last
callers of find_lock_page().

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-15 15:45:22 +02:00
Tarun Khandelwal
ee8f6dfccb fuse: propagate SB_POSIXACL to submounts
fuse_fill_super_common() always sets SB_POSIXACL on the superblock, but
fuse_fill_super_submount() never does. Submount superblocks are created
from an fs_context with no sb_flags, so the superblock of an automounted
FUSE_ATTR_SUBMOUNT directory (e.g. a virtiofs export containing another
host mount) lacks SB_POSIXACL, even though it shares the fuse_conn, and
thus fc->posix_acl, with its parent.

Since IS_POSIXACL() is false on such a submount, the VFS:

 - fails setting POSIX ACLs with -EOPNOTSUPP and hides existing ACLs,
   without sending any request to the server;
 - applies the umask itself on create, so default ACLs on the server are
   not honoured for new files;
 - skips ACL checks in acl_permission_check(), so with
   default_permissions (implied by FUSE_POSIX_ACL) access is decided by
   the mode bits alone and restrictive ACL entries are not enforced.

Copy SB_POSIXACL from the parent superblock, as is already done for the
other superblock fields inherited from it. It cannot be set in
fuse_sb_defaults(), because fuse_fill_super_common() checks whether the
flag was passed at mount time to decide fc->dont_mask before setting it.

Reproducer, with virtiofsd 1.10.0 started with --posix-acl and an export
containing a nested mount:

  host# mount -t tmpfs none /srv/share
  host# mkdir /srv/share/child
  host# mount -t tmpfs none /srv/share/child
  host# touch /srv/share/rootfile /srv/share/child/childfile
  guest# mount -t virtiofs <tag> /mnt
  guest# setfacl -m u:12345:rw /mnt/rootfile           # works
  guest# setfacl -m u:12345:rw /mnt/child/childfile
  setfacl: /mnt/child/childfile: Operation not supported

With this patch the second setfacl succeeds, ACLs set on the host are
reported by getfacl on the submount, and default ACLs and ACL-based
access checks behave the same as on the root mount. Tested on v7.3-rc5
in a QEMU guest.

Signed-off-by: Tarun Khandelwal <tarun@supabase.io>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-15 13:51:59 +02:00
Miklos Szeredi
b776cbe24c fuse: make fuse_backing_get() static
Since it's not used outside of backing.c.

Also remove the fuse_backing_lookup() stub from fuse_i.h, since it's called
only from passthrough.c.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-01 16:30:38 +02:00
Miklos Szeredi
bbe2d73a82 fuse: don't assume ff->passthrough is set for FOPEN_PASSTHROUGH
Following patch will introduce extent map passthrough mode, where
ff->passthrough is not set.

Check if in passthrough mode via FOPEN_PASSTHROUGH instead.

No functional change.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-01 16:30:38 +02:00
Miklos Szeredi
b6397651e5 fuse: use "vdax" naming for virtiofs DAX
We are introducing DAX functionality largely unrelated to the virtiofs
code.  Rename dax -> vdax for the virtiofs case for clarity.

Also rename CONFIG_FUSE_DAX -> CONFIG_FUSE_VDAX.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-10-01 16:30:31 +02:00
Karl Mehltretter
6e887377a6 fuse: fix GCC 8 build with CONFIG_PROFILE_ALL_BRANCHES
Commit 25307ca50b ("fuse: simplify logic in fuse_notify_store() and
fuse_retrieve()") introduced a loff_t cursor and used it in place of
outarg's offset field. In the min() expression this changed the second
operand from unsigned to signed.

With CONFIG_PROFILE_ALL_BRANCHES, GCC 8 does not propagate the range
established by the preceding MAX_LFS_FILESIZE check through the branch
profiling code. Consequently, min() cannot prove that the signed operand
is nonnegative and rejects the mixed-signedness comparison:

  min(outarg.size, ((loff_t)((long long)(~0ULL >> 1))) - pos)
  signedness error

This happens with GCC 8.1 on x86-64 and GCC 8.5 on arm and s390.
GCC 8.1 remains the minimum supported compiler.

Use umin(), which is intended for comparing an unsigned value with a
signed value that is known to be nonnegative. The preceding bounds check
guarantees that MAX_LFS_FILESIZE - pos is nonnegative, and outarg.size
bounds the result to unsigned int.

Fixes: 25307ca50b ("fuse: simplify logic in fuse_notify_store() and fuse_retrieve()")
Cc: stable@vger.kernel.org # v7.1
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-28 10:57:54 +02:00
Xiang Mei
ab38882862 fuse: return -E2BIG for an oversized SETXATTR over io-uring
fuse_dev_do_read() returns -E2BIG when a SETXATTR does not fit the
server's buffer, since the value may legitimately be that large.  The
io-uring transport fails the copy with -EIO instead.  Map it so both
transports agree.

Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 16:57:41 +02:00
Xiang Mei
c1338aae7b fuse: don't BUG when the copy buffer is exhausted
fuse_copy_fill() hits BUG_ON(!err) once the iterator backing the copy
runs out of pages.  Over io-uring the amount copied is not bounded by the
payload buffer the server registered, so an unprivileged user can drain
the iterator and panic the host - mount a FUSE filesystem with small
payload buffers, then setxattr() a larger value:

  kernel BUG at fs/fuse/dev.c:1064!
  Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
  CPU: 1 UID: 0 PID: 148 Comm: exploit Not tainted 7.3.0-rc1 #2
  RIP: 0010:fuse_copy_fill (fs/fuse/dev.c:1033)
  Call Trace:
   <TASK>
   fuse_copy_args (fs/fuse/dev.c:1354 fs/fuse/dev.c:1380)
   fuse_uring_args_to_ring (fs/fuse/dev_uring.c:891)
   fuse_uring_prepare_send (fs/fuse/dev_uring.c:940 fs/fuse/dev_uring.c:1057)
   fuse_uring_send_in_task (fs/fuse/dev_uring.c:1745)
   tctx_task_work_run (io_uring/tw.c:96)
   tctx_task_work (io_uring/tw.c:133)
   task_work_run (kernel/task_work.c:233)
   io_run_task_work (io_uring/tw.h:84)
   io_cqring_wait (io_uring/wait.c:278)
   __do_sys_io_uring_enter (io_uring/io_uring.c:2676)
   do_syscall_64 (arch/x86/entry/syscall_64.c:61)
   entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)

The reply path can drain it the same way, via the server-supplied
payload_sz in fuse_uring_copy_from_ring().

Return -EIO instead.  All three fuse_copy_fill() callers already
propagate the error.

Fixes: c090c8abae ("fuse: Add io-uring sqe commit and fetch support")
Cc: stable@vger.kernel.org
Reported-by: Weiming Shi <bestswngs@gmail.com>
Suggested-by: Joanne Koong <joannelkoong@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 16:57:41 +02:00
Joanne Koong
b46e096674 fuse: enable large folios
Enable large folios, capping the max order at the largest request fuse
can issue, so a folio always fits within a single request. The order
range minimum is 0, so under memory pressure the allocator falls back to
smaller folios.

Benchmarks (libfuse passthrough_hp, buffered fio, single job, 4 GiB
file, medians, NUMA-pinned, performance governor, strictlimiting on by
default):

tmpfs backing (page-cache bound):
  workload          bs      large folios off   on        delta
  seq read,  cold,  128k    3110 MiB/s    4514 MiB/s     +45%
  seq read,  cold,  1M      3079 MiB/s    5181 MiB/s     +68%
  seq read,  warm,  128k    2438 MiB/s    4486 MiB/s     +84%
  seq read,  warm,  1M      2403 MiB/s    5123 MiB/s    +113%
  writeback write, seq,128k 1211 MiB/s    1699 MiB/s     +40%
  writeback write, seq, 1M  1462 MiB/s    2208 MiB/s     +51%
  writeback write, rand,128k 1101 MiB/s   1757 MiB/s     +60% +
  writeback write, rand, 1M 1284 MiB/s    2228 MiB/s     +74% +

xfs on NVMe backing (device bound for cold I/O):
  workload          bs      large folios off   on        delta
  seq read,  cold,  128k    2030 MiB/s    2172 MiB/s      +7% *
  seq read,  cold,  1M      1999 MiB/s    2181 MiB/s      +9% *
  seq read,  warm,  128k    2451 MiB/s    4939 MiB/s    +101%
  seq read,  warm,  1M      2340 MiB/s    5639 MiB/s    +141%
  writeback write, seq,128k  637 MiB/s     747 MiB/s     +17% *
  writeback write, seq, 1M   694 MiB/s     833 MiB/s     +20% *
  writeback write, rand,128k 1004 MiB/s   1648 MiB/s     +64% +
  writeback write, rand, 1M 1171 MiB/s    2055 MiB/s     +75% +

(*) device-bandwidth bound. Not much throughput gain but system cpu
utilization was roughly halved
(+) random write was tested as an overwrite of a hot region (under
writeback, this is page-cache bound, so the gain comes from lower
per-folio cpu overhead rather than higher backing-device throughput)

Random reads (4k and 128k) and writethrough writes were neutral with
no regression (no read-modify-write or read-amplification penalty from
large folios)

More information about the benchmark setup and results are in
https://github.com/joannekoong/linux/commits/fuse_large_folios_benchmarks/

Reviewed-by: Horst Birthelmer <hbirthelmer@ddn.com>
Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 15:12:05 +02:00
Joanne Koong
a68d10dd8f fuse: replace folio_test_highmem() with folio_test_partial_kmap()
fuse_copy_folio() maps the folio with kmap_local_folio() and limits the
copy to the rest of the mapped page when the folio is in highmem, since
kmap_local_folio() only maps one page in that case.

folio_test_highmem() is not the most accurate test. On a highmem build
with CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP, kmap_local_page() maps just one
page even for lowmem folios, where folio_test_highmem() returns false
(see __kmap_local_page_prot() in mm/highmem.c).

The other highmem.h helpers that walk more than one page of a folio
(memcpy_from_folio(), memcpy_to_folio(), folio_zero_tail(), etc) all use
folio_test_partial_kmap() instead of folio_test_highmem() as well. Fuse
should use it too.

This is a no-op today since with order-0 folios, offset + count never
exceeds PAGE_SIZE. It matters once a descriptor can span more than one
page, which can happen once fuse enables large folios. Without this
change, fuse_copy_do() would copy past the end of the mapping on a
highmem build with CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 13:00:37 +02:00
Joanne Koong
d1c723c516 fuse: drop rather than zero the copied range in copy_file_range()
After a FUSE_COPY_FILE_RANGE the destination page cache holds stale data,
so __fuse_copy_file_range() clears it with truncate_inode_pages_range()
over a page aligned range.

truncate_inode_pages_range() is built for ranges that are meant to read
back as zeros. A folio that the range only partially covers is handed to
truncate_inode_partial_folio(), which zeroes the covered bytes and then
tries to split the folio so that the covered part can be dropped. Today
every folio is a single page, and a page aligned range is therefore also
folio aligned, so every folio in the range is covered in full and nothing
is ever zeroed.

Once folios can be larger than a page, the range may not line up with
folios (eg the folio holding the start of the range can begin before it
and the folio holding the end can go beyond it). In this case, only the
copied ranges inside those folios will get zeroed. If blocks within
those folios are dirty, then splitting returns -EBUSY and
truncate_inode_partial_folio() returns false. The folio stays in the
page cache with the copied range zeroed, and those zeros are written
back to the server, which overwrites the previously copied file range.
__fuse_copy_file_range() issues a synchronous writeback call before
calling truncate_inode_pages_range(), so in most cases the folio is
not dirty, but there is still the possibility that a memory map raced
with the copy (which is the case the comment in the code already calls
out).

Instead of calling truncate_inode_pages_range(), use
invalidate_inode_pages2_range(). It works in whole folios and never
zeroes, and fuse_writeback_range() has already run on the destination, so
the folios are normally clean and are simply dropped. It is also what the
rest of fuse already uses when the cache has to be re-read from the
server.

Outside the mmap race, the two are equivalent over the copied range for
order-0 folios. Regarding the mmap race however, the old call
(truncate_inode_pages_range()) loses the mmap changes but preserves
the copied ones, whereas the new code (invalidate_inode_pages2_range())
launders the folio before dropping it, which means it loses the copied
changes but preserves the mmap ones. Neither is entirely correct, and
the (nontrivial) fix for both is the mapping->invalidate_lock described
in the comment.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 13:00:37 +02:00
Joanne Koong
ad866d756d virtio_fs: zero the correct range on a short read reply
virtio_fs_request_complete() zeroes the unfilled tail of a short reply
at [len, thislen) within the folio. That is only correct when the read
started at the beginning of the folio, which is what the
WARN_ON(descs[i].offset) above it documents.

The assumption holds on every configuration that exists today. A fuse
read covers a sub-range of a folio only when iomap trims it to the
blocks of a folio that are not uptodate, which requires the file system
block size to be smaller than the folio. virtio-fs is not block backed,
so its block size is PAGE_SIZE, an order-0 folio is a single block, and
descs[i].offset is always 0.

Large folios make i_blocks_per_folio() greater than one and the
assumption false. iomap_adjust_read_range() skips the blocks that are
already uptodate at the front of the range and hands the position of the
first block that has to be read to ->read_folio_range(), both when
__iomap_write_begin() fills the blocks around an unaligned write and
when a folio that is only partially uptodate is read - in which case one
folio can take several reads at different offsets. fuse turns that
position into offset_in_folio(folio, iter->pos) and stores it in the
descriptor, so the tail that needs zeroing is
[offset + len, offset + thislen).

Zero that range and drop the WARN_ON(). This is a no-op today and a
prerequisite for enabling large folios.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 13:00:36 +02:00
Joanne Koong
f7585e1ce3 fuse: don't drop destination page cache on a zero byte copy reply
__fuse_copy_file_range() clears the destination page cache after the
server replies:

	truncate_inode_pages_range(inode_out->i_mapping,
				   ALIGN_DOWN(pos_out, PAGE_SIZE),
				   ALIGN(pos_out + bytes_copied, PAGE_SIZE) - 1);

A server may legitimately reply that it copied nothing, eg if the source
file turns out to be shorter than the size the kernel has cached for it.

If pos_out is 0 as well, the end of the range is ALIGN(0, PAGE_SIZE) - 1,
which is -1. lend is a uoff_t and truncate_inode_pages_range() takes -1
as its end of file sentinel, so rather than clearing nothing it drops
every folio in the destination mapping.

That is not only a cache drop. truncate_cleanup_folio() calls
folio_cancel_dirty(), and fuse_writeback_range() only wrote back
[pos_out, pos_out + len - 1], so dirty data elsewhere in the destination
file is discarded without ever reaching the server.

Skip the call when the server copied nothing, since there is nothing
stale to clear in that case.

Fixes: 9b46418c40 ("fuse: copy_file_range should truncate cache")
Cc: stable@vger.kernel.org
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 13:00:31 +02:00
Joanne Koong
d0a079b5b9 fuse: zero the correct range on a short read reply
When a read reply is shorter than the requested range, fuse_copy_folio()
zeroes everything in the folio outside the copied bytes. However, for
folios with block sizes smaller than the folio size, this can clear
blocks outside the requested range which are uptodate, or dirty and have
not yet been written back.

Move the zeroing logic into fuse_copy_folios(), since descs[i].length
needs to be used, and clear only the tail of the requested range that
the server did not send.

The range is also no longer cleared upfront in the non
cs->skip_folio_copy case. This is fine since a failed copy leaves those
blocks non-uptodate, so the uncopied bytes are never visible. This also
matches the pre-existing behavior in the non-short-read case (a failed
copy doesn't zero out the range in the folio). This lets the zeroing
logic stay the same regardless of whether the folio copy is skipped or
not.

Fixes: a4c9ab1d49 ("fuse: use iomap for buffered writes")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Reported-by: Kanishka De Silva <kpskanna1915@gmail.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 12:36:30 +02:00
Joanne Koong
4c72635f91 fuse: don't shorten the folio descriptor at LLONG_MAX
fuse_send_readpages() and fuse_do_readfolio() both decrement the folio
descriptor length when handling the overflow case where a read would
exceed LLONG_MAX after incrementing the file position by the number of
bytes that need to be read in.

Shortening it is unnecessary (and for the virtio-fs paths, a bug), and
with fuse using iomap for handling reads, shortening it is buggy.

For fuse_send_readpages(), ap->descs[] is also what fuse_readpages_end()
reports back to iomap_finish_folio_read(). iomap accounted the full
length when the range was submitted, so the lengths reported on
completion have to add up to what was submitted. Reporting one byte less
leaves ifs->read_bytes_pending nonzero, folio_end_read() is never called,
and the folio stays locked.

This is currently reachable on fuseblk mounts configured with block
sizes smaller than the page size.

Fix this by leaving the descriptor length untouched. The reply will then
be one byte shorter than what the descriptor lengths add up to, and the
last byte will be zeroed in fuse_copy_folios().

This also fixes a bug in virtio-fs that existed before any iomap changes
were added to fuse. For virtio-fs, data there arrives by DMA rather than
through fuse_copy_folios(), so the only zeroing is in
virtio_fs_request_complete(), which compares the reply size against the
descriptor length. With the descriptor length shortened, the two are
equal and nothing gets zeroed, which means the unrequested byte is left
holding whatever was in the folio, when the folio is marked uptodate.
This is both in the fuse_do_readfolio() and fuse_send_readpages() paths.
This dates back to commit 2f1398291b ("fuse: don't overflow LLONG_MAX
with end offset").

Fixes: 4ea907108a ("fuse: use iomap for readahead")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-09-25 12:36:30 +02:00
Christian Brauner
025756ee7b
fs: port mnt_idmap() and file_mnt_idmap() to const mnt_idmap
Now that everything takes a mnt_idmap as const store a const pointer in
struct vfsmount, struct mount_kattr and struct kstatmount and return one
from mnt_idmap(), file_mnt_idmap() and ovl_upper_mnt_idmap(). Finally,
also make mnt_idmap_get() return a const pointer. Also convert the
remaining local variables that are initialized from the accessors.

alloc_mnt_idmap() keeps returning a non-const pointer. It is the only
place where an idmapping is actually written to.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-26-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:51 +02:00
Christian Brauner
e2f0d6d456
fs: port ->setattr() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-24-54ccd48e100b@kernel.org
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:51 +02:00
Christian Brauner
c3150ded7b
fs: port ->getattr() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-23-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:51 +02:00
Christian Brauner
eb50cbe14f
fs: port ->create() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-22-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:51 +02:00
Christian Brauner
6bd532e338
fs: port ->symlink() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-21-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
566707035a
fs: port ->mkdir() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-20-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
8ee61322bb
fs: port ->rename() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-19-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
7d0db72041
fs: port ->mknod() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-18-54ccd48e100b@kernel.org
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
ad664d4153
fs: port ->tmpfile() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-17-54ccd48e100b@kernel.org
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
03a56ee341
fs: port ->get_acl() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-16-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:50 +02:00
Christian Brauner
737362c701
fs: port ->set_acl() to pass const mnt_idmap
Convert to const struct mnt_idmap.

A mount's idmapping is immutable. The only thing that is allowed to be
modified afterwards is the reference count and that is hidden behind
mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads
from the idmapping. This is the same model that struct cred uses and the
idmapping is also rather sensitive.

So make the idmap argument const wherever we can. The conversion is done
from the bottom up so callers can continue to pass a non-const pointer
to a const parameter until the conversion is finished.

No functional changes.

Link: https://patch.msgid.link/20260901-work-idmap-const-v1-15-54ccd48e100b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23 09:19:49 +02:00