summaryrefslogtreecommitdiff
path: root/fs/fuse/file.c
AgeCommit message (Collapse)AuthorFilesLines
9 daystreewide: refresh kmalloc_obj() conversionsKees Cook1-2/+1
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
2026-08-25Merge tag 'fuse-update-7.3' of ↵Linus Torvalds1-4/+16
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse Pull fuse updates from Miklos Szeredi: - Improve performance of the io-uring transport by introducing buffer pools and zero-copy (Joanne) - Fix lots of bugs (Baokun Li) - Fix io-uring initialization issues (Joanne, Bernd) - More prep work for large folios (Joanne) - Don't limit buffered read to 128k (Jim Harris) - Fix zeroing of page end (dirtied with mmap) on file size extension (Jimmy Zuber) - Improve performance in certain cases with wake_up_sync() when queuing request (Xuewen Yan) - Misc fixes and cleanups (Xuewen Yan) * tag 'fuse-update-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (35 commits) fuse: zero the partial EOF page when extending a file io_uring: Add missing include for ITER_SOURCE and ITER_DEST fuse: Fix the condition to enable over-io-uring fuse: invalidate the correct range after O_APPEND direct write selftests/fuse: test post-EOF page zeroing when a file is extended fuse: wake one waiter per freed slot when raising max_background fuse: use min_not_zero() in fuse_init_server_timeout() fuse: copy request headers via a stack buffer for io-uring fuse: give wakeup hints to the scheduler for synchronous requests fuse: check for NULL root inode in fuse_fill_super_submount fuse: reject a duplicate fd= mount option cuse: wait for pending RCU callbacks on module exit fuse: fix invalidate lock leak on open O_TRUNC DAX failure fuse: fix invalidate lock leak on setattr writeback failure fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free fuse: make dentry_tree_work static docs: fuse: document io-uring buffer pool and zero-copy uapi fuse: add zero-copy over io-uring fuse: support registered buffer pools in io-uring fuse: add io-uring buffer pools ...
2026-08-24fuse: zero the partial EOF page when extending a fileJimmy Zuber1-0/+9
Extending a fuse file past a non-page-aligned EOF does not zero the tail of the old last page. When that page is cached and has been mmap-dirtied beyond the old EOF, the now in-bounds tail is served to later reads as stale data rather than zeros, which violates POSIX file-extension semantics. Some file systems get this zeroing automatically at writeback time (block_write_full_folio() / iomap_writeback_handle_eof() zero the tail of the folio straddling i_size). A non-writeback caching fuse file system uses neither path, so it has to zero the tail itself from the size-extending paths, like XFS (xfs_file_write_zero_eof()) and ext4 (ext4_block_zero_eof()) do. Call truncate_pagecache_range() over the newly-exposed range up front from the three paths that extend a file, before the new size is published: - a buffered write whose position is past the old EOF (fuse_perform_write()); - a size-extending setattr/truncate (fuse_do_setattr()); - a size-extending fallocate (fuse_file_fallocate()). This unmaps the stale mappings and zeroes the partial tail of the old EOF folio, so a later read returns zeros. Truncating [old EOF, write start) before a buffered write keeps the dropped range disjoint from the written data, so a write that lands inside the old EOF folio is preserved. writeback_cache connections are unaffected, as their writes go through iomap_file_buffered_write(), which zeroes post-EOF folios. The bug is observable on a non-writeback_cache server that returns FOPEN_KEEP_CACHE on writable files (without FOPEN_DIRECT_IO), and is caught by the new write_extend_eof fuse selftest. Signed-off-by: Jimmy Zuber <jamz@amazon.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-24fuse: invalidate the correct range after O_APPEND direct writeBaokun Li1-2/+3
fuse_direct_write_iter() captures pos before generic_write_checks(), which moves ki_pos to EOF for O_APPEND writes: fuse_direct_write_iter() { pos = iocb->ki_pos; /* 0 (user-supplied) */ generic_write_checks(); /* ki_pos -> EOF */ fuse_direct_io(); /* writes at EOF, correct */ invalidate(pos, pos + res); /* [0, res) -- wrong */ } The post-write invalidation targets a stale range instead of the actual written range at EOF. This can cause data inconsistency when the file size is not page-aligned. The tail page straddling EOF has a valid portion before EOF that concurrent readers can fault back in during the DIO write window: Tail page (file size X not page-aligned): page_start X (EOF) page_end |--- valid data ----|-- stale --| CPU0 (O_APPEND DIO writer) CPU1 (buffered reader) -------------------------- ---------------------- invalidate [X, X+len) tail page evicted FUSE_WRITE in flight ... read [page_start, X) tail page re-faulted [X, page_end) = stale FUSE_WRITE completes i_size = X + len invalidate [0, len) <- WRONG tail page still cached read [X, X+len) hits stale tail page returns old data Fix by reading pos back from iocb->ki_pos after generic_write_checks(), as generic_file_direct_write() does. Also fix a typo in the comment ("may have" -> "may have competed"). Fixes: 2b0408d0284f ("fuse: invalidate page cache after DIO and async DIO writes") Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: fix invalidate lock leak on open O_TRUNC DAX failureBaokun Li1-2/+2
fuse_open() takes filemap_invalidate_lock() for a DAX truncate (dax_truncate = true) and releases it before the out_inode_unlock label. But when fuse_dax_break_layouts() fails, the goto out_inode_unlock skips the unlock and leaks the rwsem, so any later fault or truncate on the file stalls on the stale lock. fuse_dax_break_layouts() can fail with -ERESTARTSYS when a signal interrupts the wait for busy DAX pages to drain: open("file", O_RDWR | O_TRUNC) └─ fuse_open() ├─ filemap_invalidate_lock() # dax_truncate └─ fuse_dax_break_layouts() └─ dax_break_layout() └─ wait_page_idle() # TASK_INTERRUPTIBLE └─ fuse_wait_dax_page() # unlock, schedule, re-lock └─ signal → -ERESTARTSYS goto out_inode_unlock # <- lock leaked Fix this by moving filemap_invalidate_unlock() below the label so that all error paths release the lock, and rename the label to out_unlock as it now covers more than just the inode lock. Fixes: 2fdbb8dd0155 ("fuse: fix deadlock between atomic O_TRUNC and page invalidation") Cc: stable@vger.kernel.org # v6.0+ Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17Merge tag 'vfs-7.3-rc1.iomap' of ↵Linus Torvalds1-19/+5
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull iomap updates from Christian Brauner: "The bulk of this is the conversion of iomap to a single ->iomap_next() callback and thus finishing the move to an iterator model. Every iomap operation drove its iteration through a struct iomap_ops holding ->iomap_begin() and ->iomap_end(). iomap_iter() only ever sees those as pointers. That means every step of every iteration is an indirect call. This collapses both into one ->iomap_next() callback that finishes the previous mapping and produces the next one. This lets callers inline the iteration loop and pass its ->iomap_next() as a compile time constant. That means the compiler can turn it into a direct and hence inlineable call. This also allows future callers to express custom logic to drive the iteration forward better. xfs, btrfs, ext4, ext2, erofs, f2fs, gfs2, hpfs, fuse, exfat, zonefs, ntfs, ntfs3 and the block device mapping are all converted. No functional changes are intended. This also adds a simple direct I/O path for small reads. On Gen5 NVMe the __iomap_dio_rw() dominates 4K random reads. The same single-core io_uring poll mode workload reaches ~3.2M IOPS against the raw block device but only ~1.92M through ext4 or XFS. __iomap_dio_rw(), iomap_iter(), iomap_dio_bio_iter() and kfree() were at the top of the profile. The new path is very lightweight if no special behavior is requested. The bio comes from a dedicated bioset and laid out so the whole request is a single cacheline aligned allocation. Completion runs inline. That takes ext4 from 1.92M to 2.19M IOPS in the original workload. fio shows around: - 4% at libaio queue depths of 64 and up - around 5% for io_uring - up to 10% for io_uring poll mode at depth 256 on both ext4 and xfs. A few other patches: - iomap_folio_mark_uptodate() lets a filesystem that writes into the page cache outside the iomap read and write paths keep iomap's internal uptodate bitmap in sync, which fuse needs for server-pushed notify stores before it can enable large folios; - two fixes for iomap_bio_read_folio_range_sync(): a potential crash when device integrity behavior is changed and a missing bio_uninit(). - a folio batch release fix on iomap callback failures - FGP_NOFS is dropped from iomap_get_folio() - documentation fix" * tag 'vfs-7.3-rc1.iomap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (29 commits) iomap: iomap_bio_read_folio_range_sync is missing a call to bio_uninit iomap: don't free integrity payload that doesn't exist docs: fix grammatical error in iomap docs exfat: convert iomap ops to ->iomap_next() fuse: convert iomap ops to ->iomap_next() hpfs: convert iomap ops to ->iomap_next() gfs2: convert iomap ops to ->iomap_next() f2fs: convert iomap ops to ->iomap_next() block: convert iomap ops to ->iomap_next() ext2: convert iomap ops to ->iomap_next() zonefs: convert iomap ops to ->iomap_next() erofs: convert iomap ops to ->iomap_next() ext4: convert iomap ops to ->iomap_next() ntfs: convert iomap ops to ->iomap_next() ntfs3: convert iomap ops to ->iomap_next() btrfs: convert iomap ops to ->iomap_next() xfs: convert iomap ops to ->iomap_next() iomap: add ->iomap_next() iomap: use GFP_NOWAIT when application for iomap_dio_simple allocations iomap: decouple simple direct I/O reads from iomap_dio_rw ...
2026-08-17fuse: add zero-copy over io-uringJoanne Koong1-0/+2
Implement zero-copy in fuse io-uring to eliminate memory copies between the application, kernel, and server for read/write operations. The server can directly access client pages or page cache folios without copying data through an intermediary buffer. When a fuse request arrives, the kernel registers the relevant pages into a sparse slot in the server's io_uring registered buffer table. The server can then operate on these pages directly using io-uring fixed buffer operations (eg read_fixed/write_fixed) and the kernel unregisters these pages when the request completes. Non-page-backed args (eg op out headers) will go through the payload buffer as normal. The server can specify which open files should have their reads/writes go through zero-copy, by setting the FOPEN_IO_URING_ZERO_COPY flag when servicing opens. This requires CAP_SYS_ADMIN and bufpools. This is gated behind CAP_SYS_ADMIN because zero-copy allows the server direct access to the client's underlying pages, rather than operating on an intermediary buffer that the contents of the client's pages were copied into or on page cache folios. The request flow for the zero-copy direct-io write path (client writes data, server reads it) is as follows: ======================================================================= | Kernel | FUSE server | | | "write(fd, buf, 1MB)" | | | | >sys_write() | | >fuse_file_write_iter() | | >fuse_send_one() | | [req->args->in_pages = true] | | [folios hold client write data] | | | | >fuse_uring_copy_to_ring() | | >copy_header_to_ring(IN_OUT) | | [memcpy fuse_in_header] | | >copy_header_to_ring(OP) | | [memcpy write_in header] | | | | >fuse_uring_args_to_ring() | | >setup_fuse_copy_state() | | [skip_folio_copy = true] | | | | >fuse_uring_set_up_zero_copy() | | [folio_get for each client folio] | | [build bio_vec array from folios] | | >io_buffer_register_bvec() | | [register pages at ent->zero_copy_index] | | [ent->zero_copied = true] | | | | >fuse_copy_args() | | [skip_folio_copy => return 0 | | for page arg, skip data copy] | | | | >copy_header_to_ring(RING_ENT) | | [memcpy ent_in_out] | | >io_uring_cmd_done() | | | | | [CQE received] | | | | [issue io_uring READ at | | ent->zero_copy_index] | | [reads directly from | |client's pages (ZERO_COPY)] | | | | [write data to backing | | store] | | [submit COMMIT AND FETCH] | | | >fuse_uring_commit_fetch() | | >fuse_uring_commit() | | >fuse_uring_copy_from_ring() | | >fuse_uring_req_end() | | >io_buffer_unregister(ent->zero_copy_index) | | [unregister pages from index] | | >fuse_zero_copy_release() | | [folio_put for each folio] | | [ent->zero_copied = false] | | >fuse_request_end() | | [wake up client] | The zero-copy read path is analogous. Some requests may have both page-backed args and non-page-backed args. For these requests, the page-backed args are zero-copied while the non-page-backed args are copied to the buffer selected from the buffer pool: zero-copy: pages registered via io_buffer_register_bvec() non-page-backed: copied to payload buffer via fuse_copy_args() For a request whose payload is zero-copied, the registration/unregistration path looks like: register: fuse_uring_set_up_zero_copy() folio_get() for each folio io_buffer_register_bvec(ent->zero_copy_index) unregister: fuse_uring_req_end() io_buffer_unregister(ent->zero_copy_index) -> fuse_zero_copy_release() callback folio_put() for each folio Please note that on abort for in-flight zero-copied requests that have been sent to userspace, the registered bvec slot remains occupied and its folios remain pinned until the io-uring ring is destroyed, at which point io-uring unregisters all buffers and the fuse_zero_copy_release() callback drops the folio references. Unregistering at teardown would require operating on the ring context directly, whose validity is hard to ascertain; this is deemed not worth the complexity for the abort race, since everything is freed when the ring is torn down. The throughput improvement from zero-copy depends on how much of the per-request latency is spent on data copying vs backing I/O. The gain comes from eliminating the payload-buffer memcpy, but accessing the zero-copied pages requires the server to issue the read/write as an IORING_OP_READ/WRITE_FIXED operation. The benefit is largest when the mempcy is a meaningful fraction of per-request latency while backing i/o is still noticable enough that the extra io-uring op's overhead doesn't dominate. Benchmarked with passthrough_hp (--nopassthrough, q_depth=8) on a 2-socket Intel Xeon Gold 6138 (40 cores / 80 threads), using fio (sync engine, bs=1M, O_DIRECT, numjobs=2, 30s run + 10s ramp, 3 runs) where direct-I/O throughput is against a RAM-backed (tmpfs) source (backing I/O is not the bottleneck): baseline registered-buf zero-copy (zc vs base) direct read ~5.1 GB/s ~5.4 GB/s ~8.9 GB/s (+75%) direct write ~3.4 GB/s ~4.8 GB/s ~5.1 GB/s (+50%) Reads end up higher than writes because the backing store reads faster than it writes (the baseline shows the same read>write gap, and the raw device does too). On a device-bound NVMe (~2 GB/s reads) the read gain shrinks to ~10-16% (and no measurable gains for writes), as backing I/O rather than the eliminated copy dominates latency. The benefit overall scales with how much of the per-request latency is the data copy versus backing I/O. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-07-31fuse: convert iomap ops to ->iomap_next()Joanne Koong1-1/+3
Convert fuse iomap_ops to the new ->iomap_next() callback. Each callback is generated with the DEFINE_IOMAP_ITER_NEXT()/DEFINE_IOMAP_ITER_NEXT_END() macros, which wrap the iomap_iter_next() helper to finish the previous mapping if needed and produce the next one. No functional changes are intended. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260729192737.3190206-19-joannelkoong@gmail.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-07-31fuse: use iomap helper to mark folio uptodateJoanne Koong1-1/+1
When fuse enables large folios, a large folio will be backed by iomap_folio_state that keeps track of uptodate and dirty state in an internal bitmap. Fuse writethrough and notify store paths currently set folio uptodate state with folio_mark_uptodate(), which touches only the folio-level flag, but on an iomap-backed folio, that leaves the uptodate bitmap out of sync. Use the iomap_folio_mark_uptodate() helper to update both the folio uptodate state and the iomap uptodate bitmap. Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260707220450.1200943-4-joannelkoong@gmail.com Acked-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-07-31fuse: don't clear folio uptodate on writethrough errorsJoanne Koong1-17/+1
In the writethrough path (fuse_send_write_pages()), if the write to the server failed or was a short write, the uptodate flag on the folios are cleared. As explained by Matthew in [1], this is dangerous because the folio may be mapped into userspace. The mm code has the invariant that a non-uptodate folio must never be visible to userspace (to avoid potentially leaking confidental information to userspace) and has checks in place for this that if violated can bring down the whole machine. Practically speaking, the effect of this change for the fuse writethrough error path is that if an application does a write and then the server fails to persist the data or only services a short write, the page cache folio keeps the data the application wrote instead of being reverted to the server's contents on the next read. The failure is still reported to the application synchronously through the short count / error return of the write() syscall. Folios that were only partially written are unaffected since they were never marked uptodate in the first place (fuse_fill_write_page() only marks a folio as uptodate if the whole folio was written to). [1] https://lore.kernel.org/linux-fsdevel/ajtPMgO65FA1TXhi@casper.infradead.org/ Suggested-by: Matthew Wilcox <willy@infradead.org> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260707220450.1200943-2-joannelkoong@gmail.com Acked-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-07-08fuse: use iomap helper to mark folio uptodateJoanne Koong1-1/+1
When fuse enables large folios, a large folio will be backed by iomap_folio_state that keeps track of uptodate and dirty state in an internal bitmap. Fuse writethrough and notify store paths currently set folio uptodate state with folio_mark_uptodate(), which touches only the folio-level flag, but on an iomap-backed folio, that leaves the uptodate bitmap out of sync. Use the iomap_folio_mark_uptodate() helper to update both the folio uptodate state and the iomap uptodate bitmap. Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-07-08fuse: don't clear folio uptodate on writethrough errorsJoanne Koong1-17/+1
In the writethrough path (fuse_send_write_pages()), if the write to the server failed or was a short write, the uptodate flag on the folios are cleared. As explained by Matthew in [1], this is dangerous because the folio may be mapped into userspace. The mm code has the invariant that a non-uptodate folio must never be visible to userspace (to avoid potentially leaking confidental information to userspace) and has checks in place for this that if violated can bring down the whole machine. Practically speaking, the effect of this change for the fuse writethrough error path is that if an application does a write and then the server fails to persist the data or only services a short write, the page cache folio keeps the data the application wrote instead of being reverted to the server's contents on the next read. The failure is still reported to the application synchronously through the short count / error return of the write() syscall. Folios that were only partially written are unaffected since they were never marked uptodate in the first place (fuse_fill_write_page() only marks a folio as uptodate if the whole folio was written to). [1] https://lore.kernel.org/linux-fsdevel/ajtPMgO65FA1TXhi@casper.infradead.org/ Suggested-by: Matthew Wilcox <willy@infradead.org> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-07-01fuse: call fuse_send_readpages explicitly from fuse_readaheadJoanne Koong1-11/+3
Move the call to fuse_send_readpages from the iomap ->submit_read method to the fuse readahead implementation. fuse_read_folio() does not need to call fuse_send_readpages() because it always does reads synchronously (the iomap->submit_read method for this was a no-op since data->ia is always NULL for fuse_read_folio()). This prepares for an iomap fix that will call ->submit_read after each iomap. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/20260629121750.3392300-3-hch@lst.de Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-06-18Merge tag 'fuse-update-7.2' of ↵Linus Torvalds1-151/+69
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse Pull fuse updates from Miklos Szeredi: - Fix lots of bugs, most from the late 6.x era, but some going back to 2.6.x - Add subsystems (io-uring, passthrough) and respective maintainers (Bernd, Joanne and Amir) - Separate transport and fs layers (Miklos) - Don't block on cat /dev/fuse (Joanne) - Perform some refactoring in fuse-uring (Joanne) - Don't use bounce-buffer for READDIR reply in virtio-fs (Matthew Ochs) - Clean up documentation (Randy) - Improve tracing (Amir) - Extend page cache invalidation after DIO (Cheng Ding) - Invalidate readdir cache on epoch change (Jun Wu) - Misc cleanups * tag 'fuse-update-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (81 commits) fuse-uring: clear ent->fuse_req in commit_fetch error path fuse-uring: use named constants for io-uring iovec indices fuse-uring: refactor setting up copy state for payload copying fuse-uring: use enum types for header copying fuse-uring: refactor io-uring header copying from ring fuse-uring: refactor io-uring header copying to ring fuse-uring: separate next request fetching from sending logic fuse: invalidate readdir cache on epoch bump virtio-fs: avoid double-free on failed queue setup fuse: invalidate page cache after DIO and async DIO writes fuse: set ff->flock only on success fuse: clean up interrupt reading fuse: remove stray newline in fuse_dev_do_read() fuse: use READ_ONCE in fuse_chan_num_background() fuse: dax: Move long delayed work on system_dfl_long_wq fuse: add fuse_request_sent tracepoint fuse: Add SPDX ID lines to some files fuse: use QSTR() instead of QSTR_INIT() in fuse_get_dentry fuse: convert page array allocation to kcalloc() fuse: use current creds for backing files ...
2026-06-15fuse: invalidate page cache after DIO and async DIO writesCheng Ding1-11/+46
This fixe does page cache invalidation after DIO and async DIO writes for both O_DIRECT and FOPEN_DIRECT_IO cases. Commit b359af8275a9 ("fuse: Invalidate the page cache after FOPEN_DIRECT_IO write") fixed xfstests generic/209 for DIO writes in the FOPEN_DIRECT_IO path. DIO writes without FOPEN_DIRECT_IO are already handled by generic_file_direct_write(). However, async DIO writes (xfstests generic/451) remain unhandled. After this fix: - Async write with FUSE_ASYNC_DIO: invalidate in fuse_aio_invalidate_worker() - Otherwise (Sync or async write without FUSE_ASYNC_DIO): - With FOPEN_DIRECT_IO: invalidate in fuse_direct_write_iter() - Without FOPEN_DIRECT_IO: invalidate in generic_file_direct_write() Workqueue is required for async write invalidation to prevent deadlock: calling it directly in the I/O end routine (which is in fuse worker thread context) can block on a folio lock held by a buffered I/O thread waiting for the same fuse worker thread. Co-developed-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Cheng Ding <cding@ddn.com> Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: set ff->flock only on successZhang Tianci1-1/+2
If FUSE_SETLK fails (e.g., due to EWOULDBLOCK), we shall not set FUSE_RELEASE_FLOCK_UNLOCK in fuse_file_release(). Reported-by: Li Yichao <liyichao.1@bytedance.com> Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: Add SPDX ID lines to some filesTim Bird1-3/+1
Some fuse source files are missing SPDX-License-Identifier lines. Add appropriate IDs to these files, and remove old license references from the headers. Signed-off-by: Tim Bird <tim.bird@sony.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: convert page array allocation to kcalloc()William Theesfeld1-1/+1
fuse_get_user_pages() allocates the temporary pages[] array used by iov_iter_extract_pages() with the open-coded kzalloc(n * sizeof(*p), ...) form. max_pages is derived from the inbound iov_iter and is not bounded at compile time, so the multiplication can overflow on sufficiently large iter counts; the resulting too-small allocation would then be written past by iov_iter_extract_pages(). Switch to kcalloc(), which carries the same zero-on-allocation semantics and adds the standard size_mul overflow check. No functional change for non-overflow inputs. Signed-off-by: William Theesfeld <william@theesfeld.net> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: create poll.cMiklos Szeredi1-119/+0
Move f_op->poll related functions to the new source file. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: remove fm arg of args->end callbackMiklos Szeredi1-13/+9
Only used by FUSE_INIT and CUSE_INIT, these can store the relevant pointer in their structs derived from fuse_args. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: don't access transport layer structs directly from the fs layerMiklos Szeredi1-3/+3
Add helpers (get and set functions mainly) that cleanly separate the layers. Remove #include "fuse_dev_i.h" from: - inode.c - file.c - control.c Remove #include "dev_uring_i.h" from inode.c. [Li Wang: drop redundant initializer in process_init_limits()] Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15fuse: move background queuing related members to fuse_chanMiklos Szeredi1-2/+3
Move: - max_background - num_background - active_background - bg_queue - bg_lock Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-06-15virtiofs: fix UAF on submount umountMiklos Szeredi1-1/+7
iput() called from fuse_release_end() can Oops if the super block has already been destroyed. Normally this is prevented by waiting for num_waiting to go down to zero before commencing with super block shutdown. This only works, however, for the last submount instance, as the wait counter is per connection, not per superblock. Revert to using synchronous release requests for the auto_submounts case, which is virtiofs only at this time. Reported-by: Aurélien Bombo <abombo@microsoft.com> Reported-by: Zhihao Cheng <chengzhihao1@huawei.com> Cc: Greg Kurz <gkurz@redhat.com> Closes: https://github.com/kata-containers/kata-containers/issues/12589 Fixes: 26e5c67deb2e ("fuse: fix livelock in synchronous file put from fuseblk workers") Cc: stable@vger.kernel.org Reviewed-by: Greg Kurz <gkurz@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-05-11fuse: fix writeback array overflow when max_pages is oneJunxi Qian1-1/+4
fuse_iomap_writeback_range() appends one folio pointer and one fuse_folio_desc for every dirty range that is merged into the current writeback request. The merge decision checks the byte budget against fc->max_pages and fc->max_write, but it does not check whether the folio and descriptor arrays still have another free slot. This is not sufficient for fuseblk, where the filesystem block size can be smaller than PAGE_SIZE. With writeback cache enabled and max_pages negotiated as one, contiguous sub-page dirty ranges can fit within the byte budget while spanning more than one folio. The next append can then write past the one-slot folios and descs arrays. Split the request when the number of already attached folios has reached fc->max_pages. This keeps the folio/descriptor slot accounting in sync with the send decision. Fixes: ef7e7cbb323f ("fuse: use iomap for writeback") Cc: stable@vger.kernel.org Reviewed-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Junxi Qian <qjx1298677004@gmail.com> Link: https://patch.msgid.link/20260506122415.205340-1-qjx1298677004@gmail.com Acked-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-04-15Merge tag 'fuse-update-7.1' of ↵Linus Torvalds1-7/+11
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse Pull fuse update from Miklos Szeredi: - Fix possible hang in virtiofs when cleaning up a DAX inode (Sergio Lopez) - Fix a warning when using large folio as the source of SPLICE_F_MOVE on the fuse device (Bernd) - Fix uninitialized value found by KMSAN (Luis Henriques) - Fix synchronous INIT hang (Miklos) - Fix race between inode initialization and FUSE_NOTIFY_INVAL_INODE (Horst) - Allow fd to be closed after passing fuse device fd to fsconfig(..., "fd", ...) (Miklos) - Support FSCONFIG_SET_FD for "fd" option (Miklos) - Misc fixes and cleanups * tag 'fuse-update-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (21 commits) fuse: support FSCONFIG_SET_FD for "fd" option fuse: clean up device cloning fuse: don't require /dev/fuse fd to be kept open during mount fuse: add refcount to fuse_dev fuse: create fuse_dev on /dev/fuse open instead of mount fuse: check connection state on notification fuse: fuse_dev_ioctl_clone() should wait for device file to be initialized fuse: fix inode initialization race fuse: abort on fatal signal during sync init fuse: fix uninit-value in fuse_dentry_revalidate() fuse: use offset_in_page() for page offset calculations fuse: use DIV_ROUND_UP() for page count calculations fuse: simplify logic in fuse_notify_store() and fuse_retrieve() fuse: validate outarg offset and size in notify store/retrieve fuse: Check for large folio with SPLICE_F_MOVE fuse: quiet down complaints in fuse_conn_limit_write fuse: drop unnecessary argument from fuse_lookup_init() fuse: fix premature writetrhough request for large folio fuse: refactor duplicate queue teardown operation virtiofs: add FUSE protocol validation ...
2026-04-13Merge tag 'vfs-7.1-rc1.integrity' of ↵Linus Torvalds1-2/+3
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs integrity updates from Christian Brauner: "This adds support to generate and verify integrity information (aka T10 PI) in the file system, instead of the automatic below the covers support that is currently used. The implementation is based on refactoring the existing block layer PI code to be reusable for this use case, and then adding relatively small wrappers for the file system use case. These are then used in iomap to implement the semantics, and wired up in XFS with a small amount of glue code. Compared to the baseline this does not change performance for writes, but increases read performance up to 15% for 4k I/O, with the benefit decreasing with larger I/O sizes as even the baseline maxes out the device quickly on my older enterprise SSD" * tag 'vfs-7.1-rc1.integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: xfs: support T10 protection information iomap: support T10 protection information iomap: support ioends for buffered reads iomap: add a bioset pointer to iomap_read_folio_ops ntfs3: remove copy and pasted iomap code iomap: allow file systems to hook into buffered read bio submission iomap: only call into ->submit_read when there is a read_ctx iomap: pass the iomap_iter to ->submit_read iomap: refactor iomap_bio_read_folio_range block: pass a maxlen argument to bio_iov_iter_bounce block: add fs_bio_integrity helpers block: make max_integrity_io_size public block: prepare generation / verification helpers for fs usage block: add a bdev_has_integrity_csum helper block: factor out a bio_integrity_setup_default helper block: factor out a bio_integrity_action helper
2026-03-20writeback: don't block sync for filesystems with no data integrity guaranteesJoanne Koong1-3/+1
Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot guarantee data persistence on sync (eg fuse). For superblocks with this flag set, sync kicks off writeback of dirty inodes but does not wait for the flusher threads to complete the writeback. This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings in wait_sb_inodes()"). The flag belongs at the superblock level because data integrity is a filesystem-wide property, not a per-inode one. Having this flag at the superblock level also allows us to skip having to iterate every dirty inode in wait_sb_inodes() only to skip each inode individually. Prior to this commit, mappings with no data integrity guarantees skipped waiting on writeback completion but still waited on the flusher threads to finish initiating the writeback. Waiting on the flusher threads is unnecessary. This commit kicks off writeback but does not wait on the flusher threads. This change properly addresses a recent report [1] for a suspend-to-RAM hang seen on fuse-overlayfs that was caused by waiting on the flusher threads to finish: Workqueue: pm_fs_sync pm_fs_sync_work_fn Call Trace: <TASK> __schedule+0x457/0x1720 schedule+0x27/0xd0 wb_wait_for_completion+0x97/0xe0 sync_inodes_sb+0xf8/0x2e0 __iterate_supers+0xdc/0x160 ksys_sync+0x43/0xb0 pm_fs_sync_work_fn+0x17/0xa0 process_one_work+0x193/0x350 worker_thread+0x1a1/0x310 kthread+0xfc/0x240 ret_from_fork+0x243/0x280 ret_from_fork_asm+0x1a/0x30 </TASK> On fuse this is problematic because there are paths that may cause the flusher thread to block (eg if systemd freezes the user session cgroups first, which freezes the fuse daemon, before invoking the kernel suspend. The kernel suspend triggers ->write_node() which on fuse issues a synchronous setattr request, which cannot be processed since the daemon is frozen. Or if the daemon is buggy and cannot properly complete writeback, initiating writeback on a dirty folio already under writeback leads to writeback_get_folio() -> folio_prepare_writeback() -> unconditional wait on writeback to finish, which will cause a hang). This commit restores fuse to its prior behavior before tmp folios were removed, where sync was essentially a no-op. [1] https://lore.kernel.org/linux-fsdevel/CAJnrk1a-asuvfrbKXbEwwDSctvemF+6zfhdnuzO65Pt8HsFSRw@mail.gmail.com/T/#m632c4648e9cafc4239299887109ebd880ac6c5c1 Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree") Reported-by: John <therealgraysky@proton.me> Cc: stable@vger.kernel.org Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260320005145.2483161-2-joannelkoong@gmail.com Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-03-10iomap: pass the iomap_iter to ->submit_readChristoph Hellwig1-2/+3
This provides additional context for file systems. Rename the fuse instance to match the method name while we're at it. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/20260223132021.292832-10-hch@lst.de Tested-by: Anuj Gupta <anuj20.g@samsung.com> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-03-03fuse: use DIV_ROUND_UP() for page count calculationsJoanne Koong1-1/+1
Use DIV_ROUND_UP() instead of manually computing round-up division calculations. Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Horst Birthelmer <hbirthelmer@ddn.com> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-03-03fuse: fix premature writetrhough request for large folioJingbo Xu1-6/+4
When large folio is enabled and the initial folio offset exceeds PAGE_SIZE, e.g. the position resides in the second page of a large folio, after the folio copying the offset (in the page) won't be updated to 0 even though the expected range is successfully copied until the end of the folio. In this case fuse_fill_write_pages() exits prematurelly before the request has reached the max_write/max_pages limit. Fix this by eliminating page offset entirely and use folio offset instead. Fixes: d60a6015e1a2 ("fuse: support large folios for writethrough writes") Reviewed-by: Horst Birthelmer <hbirthelmer@ddn.com> Reviewed-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-02-27fuse: mark DAX inode releases as blockingSergio Lopez1-0/+6
Commit 26e5c67deb2e ("fuse: fix livelock in synchronous file put from fuseblk workers") made fputs on closing files always asynchronous. As cleaning up DAX inodes may require issuing a number of synchronous request for releasing the mappings, completing the release request from the worker thread may lead to it hanging like this: [ 21.386751] Workqueue: events virtio_fs_requests_done_work [ 21.386769] Call trace: [ 21.386770] __switch_to+0xe4/0x140 [ 21.386780] __schedule+0x294/0x72c [ 21.386787] schedule+0x24/0x90 [ 21.386794] request_wait_answer+0x184/0x298 [ 21.386799] __fuse_simple_request+0x1f4/0x320 [ 21.386805] fuse_send_removemapping+0x80/0xa0 [ 21.386810] dmap_removemapping_list+0xac/0xfc [ 21.386814] inode_reclaim_dmap_range.constprop.0+0xd0/0x204 [ 21.386820] fuse_dax_inode_cleanup+0x28/0x5c [ 21.386825] fuse_evict_inode+0x120/0x190 [ 21.386834] evict+0x188/0x320 [ 21.386847] iput_final+0xb0/0x20c [ 21.386854] iput+0xa0/0xbc [ 21.386862] fuse_release_end+0x18/0x2c [ 21.386868] fuse_request_end+0x9c/0x2c0 [ 21.386872] virtio_fs_request_complete+0x150/0x384 [ 21.386879] virtio_fs_requests_done_work+0x18c/0x37c [ 21.386885] process_one_work+0x15c/0x2e8 [ 21.386891] worker_thread+0x278/0x480 [ 21.386898] kthread+0xd0/0xdc [ 21.386902] ret_from_fork+0x10/0x20 Here, the virtio-fs worker_thread is waiting on request_wait_answer() for a reply from the virtio-fs server that is already in the virtqueue but will never be processed since it's that same worker thread the one in charge of consuming the elements from the virtqueue. To address this issue, when relesing a DAX inode mark the operation as potentially blocking. Doing this will ensure these release requests are processed on a different worker thread. Signed-off-by: Sergio Lopez <slp@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-02-21Convert 'alloc_obj' family to use the new default GFP_KERNEL argumentLinus Torvalds1-2/+2
This was done entirely with mindless brute force, using git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' | xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/' to convert the new alloc_obj() users that had a simple GFP_KERNEL argument to just drop that argument. Note that due to the extreme simplicity of the scripting, any slightly more complex cases spread over multiple lines would not be triggered: they definitely exist, but this covers the vast bulk of the cases, and the resulting diff is also then easier to check automatically. For the same reason the 'flex' versions will be done as a separate conversion. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-02-21treewide: Replace kmalloc with kmalloc_obj for non-scalar typesKees Cook1-5/+5
This is the result of running the Coccinelle script from scripts/coccinelle/api/kmalloc_objs.cocci. The script is designed to avoid scalar types (which need careful case-by-case checking), and instead replace kmalloc-family calls that allocate struct or union object instances: Single allocations: kmalloc(sizeof(TYPE), ...) are replaced with: kmalloc_obj(TYPE, ...) Array allocations: kmalloc_array(COUNT, sizeof(TYPE), ...) are replaced with: kmalloc_objs(TYPE, COUNT, ...) Flex array allocations: kmalloc(struct_size(PTR, FAM, COUNT), ...) are replaced with: kmalloc_flex(*PTR, FAM, COUNT, ...) (where TYPE may also be *VAR) The resulting allocations no longer return "void *", instead returning "TYPE *". Signed-off-by: Kees Cook <kees@kernel.org>
2026-02-09fs: fuse: fix max() of incompatible typesArnd Bergmann1-2/+4
The 'max()' value of a 'long long' and an 'unsigned int' is problematic if the former is negative: In function 'fuse_wr_pages', inlined from 'fuse_perform_write' at fs/fuse/file.c:1347:27: include/linux/compiler_types.h:652:45: error: call to '__compiletime_assert_390' declared with attribute error: min(((pos + len - 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error 652 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^ Use a temporary variable to make it clearer what is going on here. Fixes: 0f5bb0cfb0b4 ("fs: use min() or umin() instead of min_t()") Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-02-09Merge tag 'vfs-7.0-rc1.misc' of ↵Linus Torvalds1-5/+3
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull misc vfs updates from Christian Brauner: "This contains a mix of VFS cleanups, performance improvements, API fixes, documentation, and a deprecation notice. Scalability and performance: - Rework pid allocation to only take pidmap_lock once instead of twice during alloc_pid(), improving thread creation/teardown throughput by 10-16% depending on false-sharing luck. Pad the namespace refcount to reduce false-sharing - Track file lock presence via a flag in ->i_opflags instead of reading ->i_flctx, avoiding false-sharing with ->i_readcount on open/close hot paths. Measured 4-16% improvement on 24-core open-in-a-loop benchmarks - Use a consume fence in locks_inode_context() to match the store-release/load-consume idiom, eliminating a hardware fence on some architectures - Annotate cdev_lock with __cacheline_aligned_in_smp to prevent false-sharing - Remove a redundant DCACHE_MANAGED_DENTRY check in __follow_mount_rcu() that never fires since the caller already verifies it, eliminating a 100% mispredicted branch - Fix a 100% mispredicted likely() in devcgroup_inode_permission() that became wrong after a prior code reorder Bug fixes and correctness: - Make insert_inode_locked() wait for inode destruction instead of skipping, fixing a corner case where two matching inodes could exist in the hash - Move f_mode initialization before file_ref_init() in alloc_file() to respect the SLAB_TYPESAFE_BY_RCU ordering contract - Add a WARN_ON_ONCE guard in try_to_free_buffers() for folios with no buffers attached, preventing a null pointer dereference when AS_RELEASE_ALWAYS is set but no release_folio op exists - Fix select restart_block to store end_time as timespec64, avoiding truncation of tv_sec on 32-bit architectures - Make dump_inode() use get_kernel_nofault() to safely access inode and superblock fields, matching the dump_mapping() pattern API modernization: - Make posix_acl_to_xattr() allocate the buffer internally since every single caller was doing it anyway. Reduces boilerplate and unnecessary error checking across ~15 filesystems - Replace deprecated simple_strtoul() with kstrtoul() for the ihash_entries, dhash_entries, mhash_entries, and mphash_entries boot parameters, adding proper error handling - Convert chardev code to use guard(mutex) and __free(kfree) cleanup patterns - Replace min_t() with min() or umin() in VFS code to avoid silently truncating unsigned long to unsigned int - Gate LOOKUP_RCU assertions behind CONFIG_DEBUG_VFS since callers already check the flag Deprecation: - Begin deprecating legacy BSD process accounting (acct(2)). The interface has numerous footguns and better alternatives exist (eBPF) Documentation: - Fix and complete kernel-doc for struct export_operations, removing duplicated documentation between ReST and source - Fix kernel-doc warnings for __start_dirop() and ilookup5_nowait() Testing: - Add a kunit test for initramfs cpio handling of entries with filesize > PATH_MAX Misc: - Add missing <linux/init_task.h> include in fs_struct.c" * tag 'vfs-7.0-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (28 commits) posix_acl: make posix_acl_to_xattr() alloc the buffer fs: make insert_inode_locked() wait for inode destruction initramfs_test: kunit test for cpio.filesize > PATH_MAX fs: improve dump_inode() to safely access inode fields fs: add <linux/init_task.h> for 'init_fs' docs: exportfs: Use source code struct documentation fs: move initializing f_mode before file_ref_init() exportfs: Complete kernel-doc for struct export_operations exportfs: Mark struct export_operations functions at kernel-doc exportfs: Fix kernel-doc output for get_name() acct(2): begin the deprecation of legacy BSD process accounting device_cgroup: remove branch hint after code refactor VFS: fix __start_dirop() kernel-doc warnings fs: Describe @isnew parameter in ilookup5_nowait() fs/namei: Remove redundant DCACHE_MANAGED_DENTRY check in __follow_mount_rcu fs: only assert on LOOKUP_RCU when built with CONFIG_DEBUG_VFS select: store end_time as timespec64 in restart block chardev: Switch to guard(mutex) and __free(kfree) namespace: Replace simple_strtoul with kstrtoul to parse boot params dcache: Replace simple_strtoul with kstrtoul in set_dhash_entries ...
2026-02-09Merge tag 'vfs-7.0-rc1.iomap' of ↵Linus Torvalds1-2/+2
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs iomap updates from Christian Brauner: - Erofs page cache sharing preliminaries: Plumb a void *private parameter through iomap_read_folio() and iomap_readahead() into iomap_iter->private, matching iomap DIO. Erofs uses this to replace a bogus kmap_to_page() call, as preparatory work for page cache sharing. - Fix for invalid folio access: Fix an invalid folio access when a folio without iomap_folio_state is fully submitted to the IO helper — the helper may call folio_end_read() at any time, so ctx->cur_folio must be invalidated after full submission. * tag 'vfs-7.0-rc1.iomap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: iomap: fix invalid folio access after folio_end_read() erofs: hold read context in iomap_iter if needed iomap: stash iomap read ctx in the private field of iomap_iter
2026-02-09Merge tag 'vfs-7.0-rc1.leases' of ↵Linus Torvalds1-0/+1
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs lease updates from Christian Brauner: "This contains updates for lease support to require filesystems to explicitly opt-in to lease support Currently kernel_setlease() falls through to generic_setlease() when a a filesystem does not define ->setlease(), silently granting lease support to every filesystem regardless of whether it is prepared for it. This is a poor default: most filesystems never intended to support leases, and the silent fallthrough makes it impossible to distinguish "supports leases" from "never thought about it". This inverts the default. It adds explicit .setlease = generic_setlease; assignments to every in-tree filesystem that should retain lease support, then changes kernel_setlease() to return -EINVAL when ->setlease is NULL. With the new default in place, simple_nosetlease() is redundant and is removed along with all references to it" * tag 'vfs-7.0-rc1.leases' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (25 commits) fuse: add setlease file operation fs: remove simple_nosetlease() filelock: default to returning -EINVAL when ->setlease operation is NULL xfs: add setlease file operation ufs: add setlease file operation udf: add setlease file operation tmpfs: add setlease file operation squashfs: add setlease file operation overlayfs: add setlease file operation orangefs: add setlease file operation ocfs2: add setlease file operation ntfs3: add setlease file operation nilfs2: add setlease file operation jfs: add setlease file operation jffs2: add setlease file operation gfs2: add a setlease file operation fat: add setlease file operation f2fs: add setlease file operation exfat: add setlease file operation ext4: add setlease file operation ...
2026-01-19fs/writeback: skip AS_NO_DATA_INTEGRITY mappings in wait_sb_inodes()Joanne Koong1-1/+3
Above the while() loop in wait_sb_inodes(), we document that we must wait for all pages under writeback for data integrity. Consequently, if a mapping, like fuse, traditionally does not have data integrity semantics, there is no need to wait at all; we can simply skip these inodes. This restores fuse back to prior behavior where syncs are no-ops. This fixes a user regression where if a system is running a faulty fuse server that does not reply to issued write requests, this causes wait_sb_inodes() to wait forever. Link: https://lkml.kernel.org/r/20260105211737.4105620-2-joannelkoong@gmail.com Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree") Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reported-by: Athul Krishna <athul.krishna.kr@protonmail.com> Reported-by: J. Neuschäfer <j.neuschaefer@gmx.net> Reviewed-by: Bernd Schubert <bschubert@ddn.com> Tested-by: J. Neuschäfer <j.neuschaefer@gmx.net> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Bernd Schubert <bschubert@ddn.com> Cc: Bonaccorso Salvatore <carnil@debian.org> Cc: Christian Brauner <brauner@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jan Kara <jack@suse.cz> Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-01-14iomap: stash iomap read ctx in the private field of iomap_iterHongbo Li1-2/+2
It's useful to get filesystem-specific information using the existing private field in the @iomap_iter passed to iomap_{begin,end} for advanced usage for iomap buffered reads, which is much like the current iomap DIO. For example, EROFS needs it to: - implement an efficient page cache sharing feature, since iomap needs to apply to anon inode page cache but we'd like to get the backing inode/fs instead, so filesystem-specific private data is needed to keep such information; - pass in both struct page * and void * for inline data to avoid kmap_to_page() usage (which is bogus). Signed-off-by: Hongbo Li <lihongbo22@huawei.com> Link: https://patch.msgid.link/20260109102856.598531-2-lihongbo22@huawei.com Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-01-13fuse: add setlease file operationJeff Layton1-0/+1
Add the setlease file_operation to fuse_file_operations, pointing to generic_setlease. A future patch will change the default behavior to reject lease attempts with -EINVAL when there is no setlease file operation defined. Add generic_setlease to retain the ability to set leases on this filesystem. Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260112130121.25965-1-jlayton@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-12-15fs: use min() or umin() instead of min_t()David Laight1-5/+3
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'. Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long' and so cannot discard significant bits. A couple of places need umin() because of loops like: nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE); for (i = 0; i < nfolios; i++) { struct folio *folio = page_folio(pages[i]); ... unsigned int len = umin(ret, PAGE_SIZE - start); ... ret -= len; ... } where the compiler doesn't track things well enough to know that 'ret' is never negative. The alternate loop: for (i = 0; ret > 0; i++) { struct folio *folio = page_folio(pages[i]); ... unsigned int len = min(ret, PAGE_SIZE - start); ... ret -= len; ... } would be equivalent and doesn't need 'nfolios'. Most of the 'unsigned long' actually come from PAGE_SIZE. Detected by an extra check added to min_t(). Signed-off-by: David Laight <david.laight.linux@gmail.com> Link: https://patch.msgid.link/20251119224140.8616-31-david.laight.linux@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-12-05Merge tag 'fuse-update-6.19' of ↵Linus Torvalds1-8/+29
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse Pull fuse updates from Miklos Szeredi: - Add mechanism for cleaning out unused, stale dentries; controlled via a module option (Luis Henriques) - Fix various bugs - Cleanups * tag 'fuse-update-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: Uninitialized variable in fuse_epoch_work() fuse: fix io-uring list corruption for terminated non-committed requests fuse: signal that a fuse inode should exhibit local fs behaviors fuse: Always flush the page cache before FOPEN_DIRECT_IO write fuse: Invalidate the page cache after FOPEN_DIRECT_IO write fuse: rename 'namelen' to 'namesize' fuse: use strscpy instead of strcpy fuse: refactor fuse_conn_put() to remove negative logic. fuse: new work queue to invalidate dentries from old epochs fuse: new work queue to periodically invalidate expired dentries dcache: export shrink_dentry_list() and add new helper d_dispose_if_unused() fuse: add WARN_ON and comment for RCU revalidate fuse: Fix whitespace for fuse_uring_args_to_ring() comment fuse: missing copy_finish in fuse-over-io-uring argument copies fuse: fix readahead reclaim deadlock
2025-11-13fuse: Always flush the page cache before FOPEN_DIRECT_IO writeBernd Schubert1-1/+1
This was done as condition on direct_io_allow_mmap, but I believe this is not right, as a file might be open two times - once with write-back enabled another time with FOPEN_DIRECT_IO. Signed-off-by: Bernd Schubert <bschubert@ddn.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2025-11-13fuse: Invalidate the page cache after FOPEN_DIRECT_IO writeBernd Schubert1-0/+9
generic_file_direct_write() also does this and has a large comment about. Reproducer here is xfstest's generic/209, which is exactly to have competing DIO write and cached IO read. Signed-off-by: Bernd Schubert <bschubert@ddn.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2025-11-12iomap: simplify ->read_folio_range() error handling for readsJoanne Koong1-8/+2
Instead of requiring that the caller calls iomap_finish_folio_read() even if the ->read_folio_range() callback returns an error, account for this internally in iomap instead, which makes the interface simpler and makes it match writeback's ->read_folio_range() error handling expectations. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20251111193658.3495942-6-joannelkoong@gmail.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-11-12iomap: optimize pending async writeback accountingJoanne Koong1-2/+2
Pending writebacks must be accounted for to determine when all requests have completed and writeback on the folio should be ended. Currently this is done by atomically incrementing ifs->write_bytes_pending for every range to be written back. Instead, the number of atomic operations can be minimized by setting ifs->write_bytes_pending to the folio size, internally tracking how many bytes are written back asynchronously, and then after sending off all the requests, decrementing ifs->write_bytes_pending by the number of bytes not written back asynchronously. Now, for N ranges written back, only N + 2 atomic operations are required instead of 2N + 2. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20251111193658.3495942-5-joannelkoong@gmail.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-11-11fuse: fix readahead reclaim deadlockJoanne Koong1-7/+19
Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed") skips allocating ff->release_args if the server does not implement open. However in doing so, fuse_prepare_release() now skips grabbing the reference on the inode, which makes it possible for an inode to be evicted from the dcache while there are inflight readahead requests. This causes a deadlock if the server triggers reclaim while servicing the readahead request and reclaim attempts to evict the inode of the file being read ahead. Since the folio is locked during readahead, when reclaim evicts the fuse inode and fuse_evict_inode() attempts to remove all folios associated with the inode from the page cache (truncate_inode_pages_range()), reclaim will block forever waiting for the lock since readahead cannot relinquish the lock because it is itself blocked in reclaim: >>> stack_trace(1504735) folio_wait_bit_common (mm/filemap.c:1308:4) folio_lock (./include/linux/pagemap.h:1052:3) truncate_inode_pages_range (mm/truncate.c:336:10) fuse_evict_inode (fs/fuse/inode.c:161:2) evict (fs/inode.c:704:3) dentry_unlink_inode (fs/dcache.c:412:3) __dentry_kill (fs/dcache.c:615:3) shrink_kill (fs/dcache.c:1060:12) shrink_dentry_list (fs/dcache.c:1087:3) prune_dcache_sb (fs/dcache.c:1168:2) super_cache_scan (fs/super.c:221:10) do_shrink_slab (mm/shrinker.c:435:9) shrink_slab (mm/shrinker.c:626:10) shrink_node (mm/vmscan.c:5951:2) shrink_zones (mm/vmscan.c:6195:3) do_try_to_free_pages (mm/vmscan.c:6257:3) do_swap_page (mm/memory.c:4136:11) handle_pte_fault (mm/memory.c:5562:10) handle_mm_fault (mm/memory.c:5870:9) do_user_addr_fault (arch/x86/mm/fault.c:1338:10) handle_page_fault (arch/x86/mm/fault.c:1481:3) exc_page_fault (arch/x86/mm/fault.c:1539:2) asm_exc_page_fault+0x22/0x27 Fix this deadlock by allocating ff->release_args and grabbing the reference on the inode when preparing the file for release even if the server does not implement open. The inode reference will be dropped when the last reference on the fuse file is dropped (see fuse_file_put() -> fuse_release_end()). Fixes: e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed") Cc: stable@vger.kernel.org Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reported-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2025-11-05fuse: use iomap for readaheadJoanne Koong1-96/+124
Do readahead in fuse using iomap. This gives us granular uptodate tracking for large folios, which optimizes how much data needs to be read in. If some portions of the folio are already uptodate (eg through a prior write), we only need to read in the non-uptodate portions. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-11-05fuse: use iomap for read_folioJoanne Koong1-24/+56
Read folio data into the page cache using iomap. This gives us granular uptodate tracking for large folios, which optimizes how much data needs to be read in. If some portions of the folio are already uptodate (eg through a prior write), we only need to read in the non-uptodate portions. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-09-23fuse: fix livelock in synchronous file put from fuseblk workersDarrick J. Wong1-1/+7
I observed a hang when running generic/323 against a fuseblk server. This test opens a file, initiates a lot of AIO writes to that file descriptor, and closes the file descriptor before the writes complete. Unsurprisingly, the AIO exerciser threads are mostly stuck waiting for responses from the fuseblk server: # cat /proc/372265/task/372313/stack [<0>] request_wait_answer+0x1fe/0x2a0 [fuse] [<0>] __fuse_simple_request+0xd3/0x2b0 [fuse] [<0>] fuse_do_getattr+0xfc/0x1f0 [fuse] [<0>] fuse_file_read_iter+0xbe/0x1c0 [fuse] [<0>] aio_read+0x130/0x1e0 [<0>] io_submit_one+0x542/0x860 [<0>] __x64_sys_io_submit+0x98/0x1a0 [<0>] do_syscall_64+0x37/0xf0 [<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53 But the /weird/ part is that the fuseblk server threads are waiting for responses from itself: # cat /proc/372210/task/372232/stack [<0>] request_wait_answer+0x1fe/0x2a0 [fuse] [<0>] __fuse_simple_request+0xd3/0x2b0 [fuse] [<0>] fuse_file_put+0x9a/0xd0 [fuse] [<0>] fuse_release+0x36/0x50 [fuse] [<0>] __fput+0xec/0x2b0 [<0>] task_work_run+0x55/0x90 [<0>] syscall_exit_to_user_mode+0xe9/0x100 [<0>] do_syscall_64+0x43/0xf0 [<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53 The fuseblk server is fuse2fs so there's nothing all that exciting in the server itself. So why is the fuse server calling fuse_file_put? The commit message for the fstest sheds some light on that: "By closing the file descriptor before calling io_destroy, you pretty much guarantee that the last put on the ioctx will be done in interrupt context (during I/O completion). Aha. AIO fgets a new struct file from the fd when it queues the ioctx. The completion of the FUSE_WRITE command from userspace causes the fuse server to call the AIO completion function. The completion puts the struct file, queuing a delayed fput to the fuse server task. When the fuse server task returns to userspace, it has to run the delayed fput, which in the case of a fuseblk server, it does synchronously. Sending the FUSE_RELEASE command sychronously from fuse server threads is a bad idea because a client program can initiate enough simultaneous AIOs such that all the fuse server threads end up in delayed_fput, and now there aren't any threads left to handle the queued fuse commands. Fix this by only using asynchronous fputs when closing files, and leave a comment explaining why. Cc: stable@vger.kernel.org # v2.6.38 Fixes: 5a18ec176c934c ("fuse: fix hang of single threaded fuseblk filesystem") Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>