summaryrefslogtreecommitdiff
path: root/fs
AgeCommit message (Collapse)AuthorFilesLines
2026-08-19ntfs: Remove references to page->__folio_indexMatthew Wilcox (Oracle)1-6/+8
Pages don't have indexes, folios have indexes. Correct this in ntfs_read_compressed_block() and also remove a use of page->mapping while I'm in here. Also convert the calls to unlock_page() and flush_dcache_page(). Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Hyunchul Lee <hyc.lee@gmail.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Use zero_user_segment() in handle_bounds_compressed_page()Matthew Wilcox (Oracle)1-10/+8
This fixes handle_bounds_compressed_page() on highmem memory as page_address() does not work on memory which has been kmap_local(), only on kmap() memory. Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Remove use of __folio_index in handle_bounds_compressed_page()Matthew Wilcox (Oracle)1-2/+4
Nobody is supposed to use page->__folio_index. Use page_offset() instead, and simplify by working exclusively in loff_t instead of mixing up loff_t and pgoff_t. Link: https://lore.kernel.org/all/20260608210618.3437216-3-willy@infradead.org/ Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Co-developed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Inline zero_partial_compressed_page()Matthew Wilcox (Oracle)1-22/+12
zero_partial_compressed_page() has one caller and the next commit will make changes to it that make it inelegant to split across two functions. Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Fix min_len for compressed/sparse attributes in ↵Alexandro Calo1-0/+5
ntfs_non_resident_attr_value_is_valid() Here the attribute validator computes a single min_len = 64 (as the end of initialized_size) for all non-resident attributes regardless of the flags field. This is correct for regular non-resident attributes but for sparse or compressed non-resident attributes the fixed header is 8 bytes longer, it includes a compressed_size field at bytes 64-71, min_len should be 72. Since the validator lets a sparse/compressed attr_record be less than the correct length, caller's accesses to compressed_size (e.g., ntfs_read_locked_inode() or ntfs_attr_update_mapping_pairs()) can extend past the attribute declared boundary. This can cause OOB reads or OOB writes past the MFT record buffer if the attribute is positioned near the end of the MFT record. The compressed_size field is accessed from: - ntfs_read_locked_inode() - ntfs_read_locked_attr_inode() - ntfs_attr_open() - ntfs_attr_update_mapping_pairs() ntfs_attr_make_non_resident() seems to be safe. Fixing this by raising min_len for sparse/compressed attributes in the validator. The OOB reads and the OOB writes require a crafted filesystem image, which is not in the kernel threat model, anyway, fixing memory errors would be nice to keep things secure. Signed-off-by: Alexandro Calo <alexandro.calo@nozominetworks.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: rewrite EA stream before updating metadataNamjae Jeon1-19/+46
Updating an EA removes the old record and appends its replacement. Build the complete $EA stream in memory and rewrite it from offset zero, rather than committing a compacted stream followed by a separate append. generic/642 shows that the append path can leave an invalid record layout on disk, including when a new EA entry is added. When removing an EA, write the compacted stream before updating $EA_INFORMATION and restore the original pair if the metadata update fails. When the final EA entry is removed the $EA/$EA_INFORMATION pair is torn down. If removing $EA_INFORMATION fails after $EA has already been removed, the original $EA is restored so the two attributes stay consistent. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: remove empty EA attribute pairNamjae Jeon1-0/+9
Removing the final xattr leaves an empty $EA stream. An empty $EA attribute paired with $EA_INFORMATION is not a valid EA chain and ntfsck reports it as corrupt. Remove both attributes when the final EA entry is deleted. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: validate final EA attribute sizeNamjae Jeon1-2/+15
A replacement first removes the existing EA record, then adds the replacement. Check the size of that final $EA stream before mutating the current stream. This avoids committing the shortened $EA stream or $EA_INFORMATION before discovering that the replacement exceeds the AttrDef size limit. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-18Merge tag 'x86_cache_for_v7.3_rc1' of ↵Linus Torvalds5-439/+739
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 resource control updates from Borislav Petkov: - How refreshing: no new features but a whole pile of fixes to more or less serious issues reported by Sashiko along with miscellaneous cleanups all over the place. All except one by Reinette Chatre, the one by Tony Luck. * tag 'x86_cache_for_v7.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: fs/resctrl: Inform user space when status buffer overflowed fs/resctrl: Communicate resource group deleted error via last_cmd_status fs/resctrl: Add last_cmd_status support for writes to max_threshold_occupancy fs/resctrl: Change last_cmd_status custom during input parsing fs/resctrl: Use accurate and symmetric exit flows fs/resctrl: Pass error reading event through to user space fs/resctrl: Use accurate type for rdt_resource::rid fs/resctrl: Change pattern used to track number of entries in enum resctrl_conf_type x86/resctrl: Protect against bad shift fs/resctrl: Use correct format specifier for printing error pointers fs/resctrl: Fix UAF from worker threads when domains are removed x86/resctrl: Ensure domain fully initialized before placed on RCU list fs/resctrl: Prevent deadlock and use-after-free in info file handlers fs/resctrl: Prevent use-after-free in rdtgroup_kn_put() fs/resctrl: Fix deadlock on errors during mount fs/resctrl: Move functions to avoid forward references in subsequent fixes x86,fs/resctrl: Document safe RCU list traversal
2026-08-18fuse: wake one waiter per freed slot when raising max_backgroundBaokun Li1-1/+2
fuse_get_req() parks background allocations on fch->blocked_waitq via wait_event_state_exclusive(), so each wakeup releases exactly one waiter. fuse_chan_max_background_set() clears fch->blocked when the new limit exceeds num_background, but the accompanying wake_up() releases a single waiter regardless of how many slots just became available. Raising max_background from 10 to 100 therefore admits one request instead of ninety. The remaining waiters are not permanently stranded — the "else if (!fch->blocked)" branch in fuse_request_end() wakes one more per completion — but that only helps while requests keep completing. Consider a fixed pool of threads doing readahead or async direct I/O with the quota exhausted: every thread is either in flight or parked, and each completion wakes one waiter while freeing one slot, a net change of zero. num_background oscillates around the old limit and the added quota is never taken up. Waking one waiter per freed slot also preserves submission order: once fch->blocked is clear, new callers of fuse_get_req() skip the waitqueue entirely, overtaking waiters that parked before the limit was raised. Use wake_up_nr() with the number of slots that just became available. Since the wakeup is guarded by !fch->blocked, num_background is strictly below max_background, so the count is at least 1 and never degenerates into wake_up_all(). Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-By: Horst Birthelmer <hbirthelmer@ddn.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: use min_not_zero() in fuse_init_server_timeout()Sang-Heon Jeon1-9/+3
fuse_init_server_timeout() limits timeout to fuse_max_req_timeout with the same logic as min_not_zero(), and returns early exactly when the computed timeout would be zero. So use min_not_zero() instead and return when the computed timeout is zero. No functional change. Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> Reviewed-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: copy request headers via a stack buffer for io-uringXiang Mei1-4/+8
The fuse-io-uring transport copies req->in.h out to the ring in fuse_uring_copy_to_ring() and req->out.h back in fuse_uring_commit(). Both headers live inside the fuse_request slab object, whose cache (fuse_req_cachep) is created without a usercopy whitelist, so copying them directly to/from userspace trips CONFIG_HARDENED_USERCOPY and panics: usercopy: Kernel memory exposure attempt detected from SLUB object 'fuse_request' (offset 56, size 40)! kernel BUG at mm/usercopy.c:102! Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI RIP: 0010:usercopy_abort (mm/usercopy.c:90) Call Trace: __check_heap_object (mm/slub.c:8268) __check_object_size (mm/usercopy.c:197 mm/usercopy.c:258 mm/usercopy.c:223) copy_header_to_ring (fs/fuse/dev_uring.c:618) fuse_uring_prepare_send (fs/fuse/dev_uring.c:776 fs/fuse/dev_uring.c:785) fuse_uring_send_in_task (fs/fuse/dev_uring.c:1306) tctx_task_work_run (io_uring/tw.c:96) 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:2685) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Bounce both headers through an on-stack copy so the usercopy touches stack memory, not the slab object. Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") Cc: stable@vger.kernel.org Reported-by: Weiming Shi <bestswngs@gmail.com> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Xiang Mei <xmei5@asu.edu> Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Reviewed-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: give wakeup hints to the scheduler for synchronous requestsXuewen Yan2-6/+19
When a synchronous FUSE request is sent, the in-kernel client queues it on fiq->pending and wakes the userspace daemon sleeping in fuse_dev_do_read()->wait_event_interruptible_exclusive(fiq->waitq, ...). The client then blocks in request_wait_answer() waiting for the reply, so the waker is about to go to sleep: this is exactly the pattern that WF_SYNC is meant to optimise. As Peter Zijlstra explained in the earlier discussion [1], WF_SYNC is a hint that the waker is about to sleep and the waker and wakee share data, so stacking the woken thread on the current CPU is beneficial for cache locality instead of searching for an idle one. Add a wake_up_sync() wrapper for task on the synchronous request path. Performance: On an Android big.LITTLE device where the FUSE daemon (MediaProvider) runs as a background service on the little cores while foreground applications run on the big cores, the synchronous wakeup hint lets the scheduler pull the daemon thread onto the big core that is issuing the request, where the request data is cache-hot. Measured by qixiaoyu [2] on a 2000-picture zip decompression to /sdcard: ------------------------------------------ | Default | patched | Improvement | ------------------------------------------ | 13.0 s | 7.0 s | 46% | ------------------------------------------ Server thread wall duration: 3583 ms -> 1276 ms Server runs on big core: 5% -> 79% The original 4K-file copy/compress/decompress workload [1] on the same kind of device showed a ~28% improvement (13.8s -> 9.9s). Note: Miklos reported [2] that on his test box he could not observe an actual migration from wake_up_interruptible_sync(); the benefit appears to be most visible on asymmetric topologies (big.LITTLE, where the daemon normally lives on a little core) and on workloads dominated by small synchronous requests. No regression was reported on the symmetric- SMP test setups tried. The earlier version of this change [1] added a `bool sync` argument to all three hooks of `struct fuse_iqueue_ops` and threaded it through virtio_fs as well. Miklos questioned the interface churn, and the patch has been stalled since. Re-work it so the exported interface is left alone. The hint is carried in a new FR_SYNC_WAKEUP bit of the existing `fuse_req->flags` bitfield (an `unsigned long`, so no layout change): - __fuse_request_send() sets the flag before fuse_send_one(). - fuse_dev_queue_req() consumes it with test_and_clear_bit() and forwards the result to fuse_dev_wake_and_unlock(), which then picks wake_up_sync() or wake_up(). - The forget, interrupt and resend paths pass `false` explicitly, preserving their original wake_up() behaviour. Only /dev/fuse ever wakes fiq->waitq; virtio_fs and fuse_uring dispatch through their own transport and never call wake_up(), so threading `sync` through their ops would just add an unused argument. test_and_clear_bit() makes the flag a one-shot hint that cannot leak into a future requeue, and no extra cleanup is needed in fuse_request_end()/fuse_put_request(). [1] https://lore.kernel.org/lkml/1638780405-38026-1-git-send-email-quic_pragalla@quicinc.com/ [2] https://lore.kernel.org/lkml/20221222093407.GA1141@mi-HP-ProDesk-680-G4-MT/ This work is based on "Pradeep P V K <quic_pragalla@quicinc.com>" and "Pavankumar Kondeti <quic_pkondeti@quicinc.com>" Assisted-by: TRAE:GLM-5.2 Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: check for NULL root inode in fuse_fill_super_submountBaokun Li1-0/+2
fuse_iget() can return NULL when its inode allocation fails, but fuse_fill_super_submount() passed the result straight to get_fuse_inode() and decremented fi->nlookup without checking it: root = fuse_iget(sb, parent_fi->nodeid, ...); fi = get_fuse_inode(root); fi->nlookup--; Inside fuse_iget() the inode allocation can fail and return NULL. The submount root takes the iget5_locked() path, whose alloc_inode() can fail under memory pressure (the auto-submount branch can fail the same way in new_inode() or fuse_alloc_submount_lookup()): inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); if (!inode) return NULL; A NULL root makes get_fuse_inode() a container_of() on NULL and the nlookup decrement a write to a bogus address, oopsing the mount. With CONFIG_KASAN the following null pointer dereference is reported when the root inode allocation of an auto-submount fails (e.g. under memory pressure): ================================================================== BUG: KASAN: null-ptr-deref in fuse_get_tree_submount+0x656/0x8b0 Read of size 8 at addr 00000000000002b0 by task ls/942 CPU: 0 PID: 942 Comm: ls Tainted: G W 6.6 #15 Call Trace: <TASK> fuse_get_tree_submount+0x656/0x8b0 vfs_get_tree+0x48/0x140 fc_mount+0x13/0x50 fuse_dentry_automount+0x7a/0xb0 __traverse_mounts+0xca/0x330 step_into+0x339/0xac0 path_lookupat+0xc5/0x2f0 filename_lookup+0x163/0x2a0 vfs_statx+0xd5/0x200 do_statx+0x83/0xd0 __x64_sys_statx+0xa0/0xc0 do_syscall_64+0x37/0x90 entry_SYSCALL_64_after_hwframe+0x78/0xe2 </TASK> ================================================================== Return -ENOMEM instead; the caller tears down the partially built superblock on error, matching the other error returns in this function. Fixes: 1866d779d5d2 ("fuse: Allow fuse_fill_super_common() for submounts") Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fuse: reject a duplicate fd= mount optionBaokun Li1-0/+3
fuse_opt_fd() stored the fuse device in ctx->fud and bumped its refcount unconditionally: ctx->fud = fuse_dev_grab(file); If fd= is given twice (two fsconfig FSCONFIG_SET_FD calls), the second call overwrites ctx->fud and grabs the new device, while the reference taken on the first device is never released - a permanent refcount leak that pins the first fuse_dev until reboot. Reject a second fd= outright. ctx is zeroed on allocation, so a non-NULL ctx->fud reliably means the option was already processed. Fixes: d42eb23b2ef9 ("fuse: don't require /dev/fuse fd to be kept open during mount") Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-18fs/ntfs3: validate ef->size covers the record's name and valueWeiming Shi1-9/+12
When an EA record has a non-zero ef->size, ntfs_read_ea() only checks that the record fits in the remaining buffer (ea_size > bytes), not that ef->size is large enough to hold the record's own name_len + 1 + elength. A crafted image can pass validation with, e.g., ef->size = 24 but elength = 0xffff. ntfs_get_ea() then trusts elength and copies it out of the undersized record, reading past the kmalloc(info->size) allocation and leaking heap memory to userspace via getxattr(): BUG: KASAN: slab-out-of-bounds in ntfs_get_ea (fs/ntfs3/xattr.c:302) Read of size 65535 at addr ffff888100794550 by task exploit __asan_memcpy (mm/kasan/shadow.c:105) ntfs_get_ea (fs/ntfs3/xattr.c:302) ntfs_getxattr (fs/ntfs3/xattr.c:848) __vfs_getxattr (fs/xattr.c:441) vfs_getxattr (fs/xattr.c:474) do_getxattr (fs/xattr.c:800) path_getxattrat (fs/xattr.c:868) do_syscall_64 (arch/x86/entry/syscall_64.c:94) The buggy address is located 80 bytes inside of allocated 84-byte region in cache kmalloc-96 Compute the size the record needs and require ef->size to cover it. Fixes: 0e8235d28f3a ("fs/ntfs3: Check fields while reading") Reported-by: Xiang Mei <xmei5@asu.edu> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Weiming Shi <bestswngs@gmail.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
2026-08-18fs/ntfs3: fix out-of-bounds read in read_log_rec_buf()Konstantin Komarov1-1/+9
read_log_rec_buf() copies a log record into a caller buffer starting at u32 off = lsn_to_page_off(log, lsn) + log->record_header_len; log->record_header_len (and log->data_off, used for the following pages) comes verbatim from the on-disk restart area and is only checked for 8-byte alignment in is_rst_area_valid(), so off can exceed log->page_size. "tail = log->page_size - off" then underflows and memcpy() reads past the page_size-sized buffer returned by read_log_page(), spilling adjacent slab memory into the replay buffer. This is reachable by mounting a crafted NTFS image: BUG: KASAN: slab-out-of-bounds in read_log_rec_buf+0x216/0x580 Read of size 64 at addr ffff88800a877ff8 by task exploit/127 read_log_rec_buf fs/ntfs3/fslog.c:2299 log_replay fs/ntfs3/fslog.c:4216 ntfs_loadlog_and_replay fs/ntfs3/fsntfs.c:324 ntfs_fill_super fs/ntfs3/super.c:1392 get_tree_bdev_flags fs/super.c:1694 __x64_sys_mount fs/namespace.c:4360 The buggy address is located 4088 bytes to the right of the 4096-byte region [ffff88800a876000, ffff88800a877000) Reject an in-page offset outside the current page before the copy. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Assisted-by: Claude:claude-opus-4-8 Reported-by: Xiang Mei <xmei5@asu.edu> Signed-off-by: Weiming Shi <bestswngs@gmail.com> [almaz.alexandrovich@paragon-software.com: replaced the >= sign with >] Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
2026-08-18cuse: wait for pending RCU callbacks on module exitBaokun Li1-0/+5
Since commit 053fc4f755ad ("fuse: fix UAF in rcu pathwalks"), fuse_conn_put() frees the fuse_conn through call_rcu() rather than synchronously. For cuse, fc->release is cuse_fc_release(), which lives in the cuse module. If the module is removed before the RCU grace period ends, the callback jumps into freed module memory: userspace / module unload | RCU softirq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ close(/dev/cuse) | cuse_channel_release() | fuse_dev_release() | fuse_conn_put(fch->conn) | call_rcu(delayed_release) ------+---> callback queued | rmmod cuse | cuse_exit() | cuse_channel_destroy() | ... | return | | <module text freed> | | rcu_do_batch() | delayed_release() | fc->release() | -> cuse_fc_release() | ^^^ freed text! The freed module text is unmapped by vfree(), so the jump into the stale callback triggers a page-fault Oops. If the virtual address is subsequently reused, the callback could execute unrelated code (undefined behaviour). Fix this by calling rcu_barrier() in cuse_exit() so that any pending fuse_conn release callback completes before the module is removed. Fixes: 053fc4f755ad ("fuse: fix UAF in rcu pathwalks") Signed-off-by: Baokun Li <libaokun@linux.alibaba.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-18fuse: fix invalidate lock leak on setattr writeback failureBaokun Li1-5/+4
fuse_do_setattr() takes filemap_invalidate_lock() for a DAX truncate (fault_blocked = true) and releases it at the out:/error: labels. But when a writeback flush is also needed, a write_inode_now() failure returns directly and leaks the lock, so any later fault or truncate on the file stalls on the stale rwsem. For example, truncate(2) on a setuid file reaches fuse_do_setattr() with both ATTR_SIZE and ATTR_MODE set: truncate(2) └─ do_truncate() ├─ dentry_needs_remove_privs() # S_ISUID └─ notify_change() # KILL_SUID -> ATTR_MODE └─ fuse_setattr() # no killpriv: │ # ia_valid |= ATTR_MODE └─ fuse_do_setattr() ├─ filemap_invalidate_lock() # IS_DAX && is_truncate └─ write_inode_now() # is_wb && ATTR_MODE └─ if (err) # e.g. daemon -> -EIO return err # <- lock leaked Fix this by adding an unlock label that releases the lock before returning the error, and use it for the fuse_dax_break_layouts() failure path as well. Fixes: 6ae330cad6ef ("virtiofs: serialize truncate/punch_hole and dax fault path") Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17Merge tag 'libcrypto-updates-for-linus' of ↵Linus Torvalds2-3/+3
git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux Pull crypto library updates from Eric Biggers: "Add library APIs for most AES encryption modes that are used in the kernel (ECB, CBC, CBC-CTS, CTR, XCTR, XTS, GCM, CCM). These AES modes have many in-kernel users that are currently using the crypto_skcipher or crypto_aead APIs. These existing APIs are difficult to use and inefficient. Until now, the lack of proper library support for these has been the main gap in the crypto library. This set of changes is the next stage of addressing it: - Implement the new APIs on top of the existing support for single-block AES in the library. - Fully document the new APIs. - Migrate the only user of the old AES-GCM library API to the new, more flexible API; then remove the old API and its implementation. - Wire up the new APIs to the traditional crypto API by adding crypto_skcipher and crypto_aead algorithms. This makes the new APIs be covered by the traditional crypto API's self-tests. It also makes them be already used for real on systems that don't have architecture-optimized code for these modes. But most importantly, this is a prerequisite for migrating the architecture-optimized code for these AES modes (i.e. arch/*/crypto/aes*) into the library, which as usual will eliminate a lot of redundant "glue" code. Note that unlike some of the other algorithms that have been migrated to the library, e.g. SHA-512, for these AES modes there was too much to get done in one cycle. Nor did it make sense to handle these modes one at a time, because they tend to be coupled together or depend on each other, especially in the architecture-optimized AES code. Thus, most of the benefits (reductions in lines of code, performance improvements, etc.) will follow in later cycles when architecture-optimized code is migrated into the library and users of crypto_skcipher and crypto_aead are updated to use the new APIs. The design of the new APIs was informed by writing proof-of-concept patches for many kernel subsystems currently accessing these same algorithms via crypto_skcipher or crypto_aead (patches 18-33 of https://lore.kernel.org/r/20260707053503.209874-1-ebiggers@kernel.org/). While those patches will be resent for real later, the total diffstat for them was negative 1905 lines. So clearly the new APIs are quite a bit easier to use and align better with what users actually need. Besides the new AES encryption APIs, there are also a few changes for improved AES-CMAC key and context zeroization" * tag 'libcrypto-updates-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux: mac80211: fils_aead: Use __cleanup() instead of memzero_explicit() Bluetooth: SMP: clear the aes_cmac_key when done smb: clear the aes_cmac_key and aes_cmac_ctx when done lib/crypto: aes-cmac: Add zeroization functions lib/crypto: aesgcm: Remove old AES-GCM library x86/sev: Remove obsolete virtual address check x86/sev: Use new AES-GCM library crypto: aes - Add CCM support using library crypto: aes - Add GCM support using library crypto: aes - Add XTS support using library crypto: aes - Add CTR and XCTR support using library crypto: aes - Add CBC and CBC-CTS support using library crypto: aes - Add ECB support using library lib/crypto: aes: Add CCM support lib/crypto: aes: Add GCM support lib/crypto: aes: Add XTS support lib/crypto: aes: Add CTR and XCTR support lib/crypto: aes: Add CBC and CBC-CTS support lib/crypto: aes: Add ECB support crypto: xts - Split out __xts_verify_key() helper
2026-08-17Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linuxLinus Torvalds23-990/+328
Pull fscrypt updates from Eric Biggers: "The main change this cycle is a significant simplification that's been overdue for a while now: standardizing on a single file contents encryption implementation in ext4 and f2fs, instead of having two. Specifically, the original filesystem-layer file contents encryption implementation is removed, and the blk-crypto implementation is now used unconditionally. blk-crypto delegates either to inline crypto hardware or to the CPU via blk-crypto-fallback. The latter is functionally equivalent to the original filesystem-layer code. The blk-crypto implementation already existed, but previously it was used only when the filesystem was mounted with "-o inlinecrypt". Now, "-o inlinecrypt" just selects whether inline crypto hardware is used. To allow maintaining that user control over hardware use, the blk-crypto API is extended with a new flag BLK_CRYPTO_CFG_ALLOW_HW. Overall, this removes quite a bit of redundant code from ext4, f2fs, and fs/crypto/. It should make things easier for ongoing filesystem efforts such as iomap support, large folios, and btrfs encryption (btrfs had already been planning to use blk-crypto exclusively.) There are two small behavior changes of note: - Direct I/O now works on encrypted files even without "-o inlinecrypt", rather than falling back to buffered I/O. This is effectively a bugfix, though I'll continue to keep an eye out for any user that may have been depending on the buffered I/O fallback. - IV_INO_LBLK_32 policies are no longer supported in certain cases that didn't make sense and have no known uses. This has been in linux-next since July 22 with no reported issues. All encryption xfstests pass on ext4 and f2fs. As usual I've also been using it on a system with an fscrypt-encrypted home directory. Of course, the blk-crypto code paths also aren't new and were already being used on many systems via the inlinecrypt mount option. In addition to the main change described above, there are a few other cleanups such as using lock guards for mutexes, improving documentation, and removing a workaround for outdated gcc versions" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: (29 commits) blk-crypto: Update docs for blk-crypto-fallback motivation blk-crypto: Remove unused function blk_crypto_config_supported() fscrypt: Update docs for data path fscrypt: Remove unused function fscrypt_finalize_bounce_page() f2fs: Update outdated comment in f2fs_write_begin() fs: Update outdated comment for SB_INLINECRYPT fscrypt: Update encryption policy version docs fscrypt: Replace some variable-size memsets with fixed-size fscrypt: Add safety checks to non-block-based en/decryption fscrypt: Merge bio.c and inline_crypt.c into block.c fscrypt: Remove unused functions and workqueue fscrypt: Remove fs-layer zeroout code fscrypt: Remove fscrypt_dio_supported() fscrypt: Replace calls to fscrypt_inode_uses_inline_crypto() fs/buffer: Remove fs-layer decryption code f2fs: Remove fs-layer file contents en/decryption code ext4: Further de-generalize the bio postprocessing code ext4: Make ext4_bio_write_folio() return void ext4: Remove fs-layer file contents en/decryption code Documentation: fscrypt: Update docs for inlinecrypt ...
2026-08-17Merge tag 'nilfs2-v7.3-tag1' of ↵Linus Torvalds17-88/+205
git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/nilfs2 Pull nilfs2 updates from Viacheslav Dubeyko: "This contains fixes of syzbot reported issue and various fixes in NILFS2 functionality: - Reject super-root inode sizes whose computed on-disk footprint exceeds the filesystem block size (David Lee) - Replace WARN_ON() in nilfs_cpfile_delete_checkpoints() with returning -EIO and reporting a filesystem error via nilfs_error() in the case of corrupted checkpoint count on the storage medium (Igor Putko) - Fixed a potential infinite loop in nilfs_clean_segments() reported by syzbot (Joshua Crofts) In nilfs_clean_segments(), if err is non-zero, logic logs the error and sleeps but doesn't abort when it encounters a terminal error like -EROFS. This causes the thread to loop forever. Fix this by breaking out of the loop if nilfs_segctor_construct() returns -EROFS. - Fix small grammar mistake in the description for nilfs2 recovery code (Manoj K M) - Multiple fixes by Ryusuke Konishi: - fix the list corruption issue recently detected by syzbot, that can occur when out-of-range values are intentionally passed to certain GC ioctl parameters - fix a flaw in the original B-tree implementation related to truncation and resolves the reported out-of-bounds memory access issue - fix an issue reported by syzbot where a kernel BUG could be triggered depending on timing after filesystem corruption is detected - fix an issue where a WARN_ON check is triggered by sufile functions within the log writer after the filesystem degrades to read-only mode - Check for sorted keys when reading btree node blocks into the cache (Wang Jianjian) This prevents unexpected errors during the block number assignment phase in log writing caused by key order inconsistencies, as well as the kernel warnings reported by syzbot" * tag 'nilfs2-v7.3-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/nilfs2: nilfs2: standardize the inode number type to u64 nilfs2: enhance btree node keys check nilfs2: suppress false positive WARN_ONs for sufile after an FS error nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch nilfs2: prevent out-of-bounds read in super root block parsing nilfs2: fix infinite loop in nilfs_clean_segments() nilfs2: fix slab-out-of-bounds in nilfs_direct_propagate after truncation Documentation: fix grammar in description of nilfs2 recovery code nilfs2: handle corrupted checkpoint count gracefully during deletion nilfs2: reject invalid block index in GC ioctl
2026-08-17Merge tag 'hfs-v7.3-tag1' of ↵Linus Torvalds17-162/+590
git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/hfs Pull HFS updates from Viacheslav Dubeyko: "This contains several fixes in HFS/HFS+ of syzbot reported issues and HFS/HFS+ fixes of xfstests failures. - b-tree bitmap corruption check (Aditya Prakash Srivastava) During b-tree open (hfs_btree_open()), the code verifies that the allocation map bit for the tree header (node 0) is set. If not, it indicates a corrupted map record/bitmap and mounts the volume as read-only (SB_RDONLY) to prevent further damage. - Validate catalog CNIDs before instantiating inodes (David Maximiliano Hermitte) The hfs_cat_find_brec() first resolves a catalog thread record by CNID and then looks up the corresponding catalog record by parent/name. On a corrupted filesystem image, the second lookup may find a record whose CNID does not match the CNID that was requested. Finally, corrupted catalog records are rejected. - Validate B-tree record offset table (Jiaming Zhang) A crafted HFS+ image can contain a corrupted B-tree node. The node descriptor may contain a record count that does not fit in the node, and record offsets may be unordered, unaligned, outside the node, or point into the offset table itself. Validate num_recs against the node size before walking the record offset table. Reject record ranges that are unordered, unaligned, outside the node, or overlapping the offset table. Reject invalid record indexes before reading their offset entries, and avoid decrementing an already-zero leaf_count. - Refactoring of hfsplus_delete_cat() logic (Kyle Zeng). The hfsplus_delete_cat() is called with str == NULL when the last open reference to an unlinked HFS+ hardlink backing inode is closed. In that case, the function finds the catalog thread by CNID and rebuilds the catalog key from thread.nodeName. A corrupted image can therefore provide an oversized thread name length and make hfs_bnode_read() write past the catalog search-key allocation. Read the CNID record through hfsplus_brec_read_cat(), which bounds the record read to sizeof(hfsplus_cat_entry) and verifies that a thread record's size exactly matches nodeName.length. - Cleanup in KUnit test (Mohammad Shahid) The kfree() safely handles NULL pointers, so the explicit NULL check in free_mock_str_env() before calling kfree() is unnecessary. The rest contain fixes of generic/564 xfstests' test-case failure for the case of HFS+ file system, syzbot reported issue in hfs_mdb_commit() and hfs_mdb_close() methods of HFS file system, and reworking the MDB locking scheme in HFS file system" * tag 'hfs-v7.3-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/hfs: hfsplus: validate extent record length before writing it back hfsplus: validate B-tree record offset table hfs: rework MDB locking scheme fs: hfsplus: remove redundant NULL check before kfree() hfs: port HFS+ b-tree bitmap corruption check hfs: don't re-dirty MDB buffers after a write failure hfsplus: fix error code when writing beyond volume capacity hfs: fix error code when writing beyond volume capacity hfsplus: validate thread record before delete key rebuild hfs: validate catalog CNIDs before instantiating inodes
2026-08-17Merge tag 'gfs2-for-7.3' of ↵Linus Torvalds9-221/+35
git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Andreas Gruenbacher: - Don't cache unreferenced glocks: when a glock is no longer referenced (for example, because the inode it protects is evicted), it is now released as soon as possible instead of leaving it around until memory pressure or an unmount forces it out. For some workloads, this saves a lot of memory and speeds up unmounts significantly. - Harden gfs2_glock_hold() by making sure the caller holds a reference and fix a related race in checking for the liveliness of glocks between gdlm_bast() and gfs2_glock_cb(). * tag 'gfs2-for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: harden gfs2_glock_hold gfs2: Remove the glock lru list and shrinker gfs2: Skip dlm unlocks earlier gfs2: Don't cache unreferenced glocks gfs2: Enable automatic glock hash table shrinking
2026-08-17Merge tag 'xfs-merge-7.3' of git://git.kernel.org:/pub/scm/fs/xfs/xfs-linuxLinus Torvalds25-346/+492
Pull xfs updates from Carlos Maiolino: "There are no big standing out features on this window, so this mostly consists on bug fixes and code refactoring. The only user visible change that stands out is the support for FALLOC_FL_WRITE_ZEROES added to this" * tag 'xfs-merge-7.3' of git://git.kernel.org:/pub/scm/fs/xfs/xfs-linux: (23 commits) xfs: validate attr entry pointer before field access xfs: check split_sectors validity before bio_split call xfs: use file target for post-log fsync fallback flush xfs: restore nofs context unconditionally in xfs_trans_roll xfs: add lockless xfs_buf_readahead_map fast path xfs: move buffer locking out of xfs_find_get_buf xfs: merge xfs_buf_reverify into xfs_buf_read_map xfs: use goto based error unwinding in xfs_buf_read_map xfs: don't reverify buffers in xfs_buf_readahead_map xfs: use WRITE_ONCE to update b_flags xfs: hide b_flags manipulation from code outside of xfs_buf.c xfs: remove _XBF_LOGRECOVERY xfs: remove spurious XBF_DONE clearing on readahead validation failure xfs: split out a lower-level xfs_buf_get_map helper from xfs_find_get_buf xfs: consolidate buffer locking in xfs_buf_get_map xfs: don't get a pag reference in xfs_buf_get_map xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int xfs: mark internal metadir file creation helpers static xfs: create rtgroup metadir inodes using xfs_metadir_create_file xfs: create quota metadir inodes using xfs_metadir_create_file ...
2026-08-17f2fs: fix to avoid pinfile fragment on fragment:{block, segment} modeChao Yu4-11/+18
pinfile fallocate() conflicts w/ mode=fragment:{block,segment} mount option, result in fragment blocks in pinfile, it violate semantics of pinfile introduced in commit f5a53edcf01e ("f2fs: support aligned pinned file"). mkfs.f2fs -f /dev/vdb mount -t f2fs -o mode=fragment:block /dev/vdb /mnt/f2fs/ dd if=/dev/zero of=/mnt/f2fs/file bs=1M count=3900 sync touch /mnt/f2fs/pinfile f2fs_io pinfile set /mnt/f2fs/pinfile f2fs_io fallocate 0 0 $((1024*1024*16)) /mnt/f2fs/pinfile sync f2fs_io fiemap 0 $((1024*1024*16)) /mnt/f2fs/pinfile [Before] fallocate failed: No space left on device Fiemap: offset = 0 len = 16777216 logical addr. physical addr. length flags 0 0000000000000000 00000000d7200000 0000000000004000 00001000 1 0000000000004000 00000000d7207000 0000000000001000 00001000 2 0000000000005000 00000000d720c000 0000000000002000 00001000 3 0000000000007000 00000000d7211000 0000000000001000 00001000 4 0000000000008000 00000000d7214000 0000000000001000 00001000 5 0000000000009000 00000000d7218000 0000000000001000 00001000 6 000000000000a000 00000000d721d000 0000000000001000 00001000 7 000000000000b000 00000000d721f000 0000000000004000 00001000 ... 96 00000000000f1000 00000000d73e9000 0000000000004000 00001000 97 00000000000f5000 00000000d73f1000 0000000000003000 00001000 98 00000000000f8000 00000000d73f5000 0000000000004000 00001000 99 00000000000fc000 00000000d73fa000 0000000000001000 00001000 100 00000000000fd000 00000000d73ff000 0000000000001000 00001001 [After] fallocated a file: i_size=16777216, i_blocks=32808 Fiemap: offset = 0 len = 16777216 logical addr. physical addr. length flags 0 0000000000000000 0000000018a00000 0000000000400000 00001000 1 0000000000400000 0000000019000000 0000000000400000 00001000 2 0000000000800000 0000000032400000 0000000000200000 00001000 3 0000000000a00000 0000000038000000 0000000000200000 00001000 4 0000000000c00000 0000000039c00000 0000000000200000 00001000 5 0000000000e00000 0000000044c00000 0000000000200000 00001001 Let's ignore mode=fragment:{block,segment} mount option while fallocate() on pinfile. Fixes: 6691d940b0e0 ("f2fs: introduce fragment allocation mode mount option") Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17f2fs: cleanup w/ f2fs_need_rand_{blk, seg, seg_blk}Chao Yu4-9/+18
No logic changes. Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17f2fs: fix to shrink gc_lock coverage in f2fs_gc_range()Chao Yu4-14/+28
In f2fs_allocate_pinning_section(), we will hold gc_lock before calling f2fs_gc_range() to migrate section in conventional zone, we may suffer worse case because we may need to traverse and migrate multiple sections if we failed to move blocks in section due to lot of reasons: ENOMEM, fail to migrate block of pinfile, racing on i_gc_rwsem. To avoid hold gc_lock for long time to block checkpoint, let's hold the lock and only try to migrate one section. Cc: Daeho Jeong <daehojeong@google.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17f2fs: fix to reclaim space in f2fs_allocate_pinning_section()Chao Yu1-3/+6
It needs to trigger checkpoint to free space reclaimed by f2fs_gc_range(), otherwise, fallocate() on pinfile will fail easily even there is slash space in conventional zone. [Testcase] nullblk_create.sh 512 2 1024 1024 mkfs.f2fs /dev/nullb0 -f -m mount /dev/nullb0 /mnt/f2fs/ touch /mnt/f2fs/pinfile f2fs_io pinfile set /mnt/f2fs/pinfile mkdir /mnt/f2fs/dir/ for((i=0;i<3934;i++)) do { dd if=/dev/zero of=/mnt/f2fs/dir/$i bs=1M count=1;} done sync for((i=0;i<3934;i+=2)) do { rm /mnt/f2fs/dir/$i;} done for((i=0;i<1950;i++)) do { rm /mnt/f2fs/dir/$i;} done sync f2fs_io fallocate 0 0 $((1024*1024*1024)) /mnt/f2fs/pinfile sync stat /mnt/f2fs/pinfile f2fs_io fiemap 0 $((1024*1024*1024)) /mnt/f2fs/pinfile [Before] fallocate failed: Resource temporarily unavailable File: /mnt/f2fs/pinfile Size: 109051904 Blocks: 213208 IO Block: 4096 regular file Device: 250,0 Inode: 4 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-08-12 20:04:02.264000000 +0800 Modify: 2026-08-12 20:04:26.784000000 +0800 Change: 2026-08-12 20:04:26.784000000 +0800 Birth: - root@localhost:~# root@localhost:~# root@localhost:~# root@localhost:~# f2fs_io fiemap 0 $((1024*1024*1024)) /mnt/f2fs/pinfile Fiemap: offset = 0 len = 1073741824 logical addr. physical addr. length flags 0 0000000000000000 0000000002e00000 0000000000200000 00001000 1 0000000000200000 000000002dc00000 0000000000400000 00001000 2 0000000000600000 000000002e400000 0000000000600000 00001000 3 0000000000c00000 000000007a400000 0000000005c00000 00001001 [After] File: /mnt/f2fs/pinfile Size: 1073741824 Blocks: 2099216 IO Block: 4096 regular file Device: 250,0 Inode: 4 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-08-12 19:47:49.428000000 +0800 Modify: 2026-08-12 19:49:06.808000000 +0800 Change: 2026-08-12 19:49:06.808000000 +0800 Birth: - Fiemap: offset = 0 len = 1073741824 logical addr. physical addr. length flags 0 0000000000000000 0000000002e00000 0000000000200000 00001000 1 0000000000200000 000000003aa00000 0000000000400000 00001000 2 0000000000600000 000000003b400000 0000000000200000 00001000 3 0000000000800000 000000007a200000 0000000005e00000 00001000 4 0000000006600000 0000000002800000 0000000000200000 00001000 5 0000000006800000 0000000003200000 0000000000400000 00001000 6 0000000006c00000 0000000003000000 0000000000200000 00001000 7 0000000006e00000 0000000003600000 0000000037200000 00001000 8 000000003e000000 000000003b200000 0000000000200000 00001000 9 000000003e200000 000000003a800000 0000000000200000 00001000 10 000000003e400000 000000003ae00000 0000000000400000 00001000 11 000000003e800000 000000003b600000 0000000001800000 00001001 Cc: stable@kernel.org Fixes: 9703d69d9d15 ("f2fs: support file pinning for zoned devices") Cc: Daeho Jeong <daehojeong@google.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17Merge tag 'vfs-7.3-rc1.sync' of ↵Linus Torvalds38-357/+398
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs writeback updates from Christian Brauner: "This makes sync_inode_metadata() and writeback_single_inode() persist not only the inode but all metadata associated with it. A new .sync_inode_metadata superblock operation is called from __writeback_single_inode(). Alongside it a new I_METADATA_WRITEBACK state flag is added. Filesystems no longer need their own mmb_fsync() implementations and can just use simple_fsync(). All metadata is now written for IS_SYNC and IS_DIRSYNC inodes. Races where several fsyncs raced and mmb_sync() could return before all buffers were really persisted are fixed since I_SYNC now serializes properly. The I_METADATA_WRITEBACK scheme also fixes the case where a WB_SYNC_NONE writeback landing between write(2) and fsync(2) left fsync(2) failing to persist the inode. That problem is not specific to filesystems using the generic metadata bh tracking, and the ones that do not are left alone. ext2, udf, bfs, minix, fat and ext4 in nojournal mode have their data integrity writeout fixed and are converted. affs drops metadata bh tracking and mmb_fsync() is removed. A few other fixes came out of this: - a UAF in mark_buffer_write_io_error() - missed inode writeback when racing with __writeback_single_inode() - ext4 allocating the mapping_metadata_bhs struct on demand - three fat fixes: a lost inode update in do_msdos_rename() with DIRSYNC, inode buffer write errors not propagating out of fat_sync_inode_metadata() and directory entries not being persisted on fsync(2) of the root directory" * tag 'vfs-7.3-rc1.sync' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (24 commits) writeback: Export __inode_attach_wb() fat: Fix persisting directory entries on fsync(2) of the root directory fat: Propagate inode buffer write errors from fat_sync_inode_metadata() fat: Fix lost inode update in do_msdos_rename() with DIRSYNC vfs: Remove mmb_fsync() fat: Replace fat_sync_inode() with sync_inode_metadata() fat: Fix missed inode writeback during fsync(2) ext4: Fix data integrity writeout issues in nojournal mode minix: Fix data integrity writeout issues bfs: Fix data integrity writeout issues udf: Fold udf_update_inode() into udf_write_inode() udf: Use sync_inode_metadata() in udf_evict_inode() udf: Drop udf_sync_inode() udf: Use sync_inode_metadata() to writeout IS_SYNC inode udf: Fix data integrity writeout issues ext2: Fix data integrity writeout issues ext2: Avoid unnecessary inode buffer writeback for sync(2) ext2: Drop __ext2_write_inode() ext2: Fix lost inode updates for IS_SYNC inodes fs: Provide way for filesystem to wait for metadata writeback ...
2026-08-17Merge tag 'vfs-7.3-rc1.super' of ↵Linus Torvalds17-266/+629
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs superblock updates from Christian Brauner: - Make it possible to share a block device between multiple filesystems. erofs can mount read-only blob devices shared between many superblocks, but because we only tracked a single superblock a freeze, thaw, removal or sync on such a device was never propagated to all the superblocks using it, and there was no way to find them. Add an efficient table to lookup all superblocks using a given block device. - A bunch of pre-existing fixes fell out of this work: A block-device freeze racing a btrfs device change could leave the whole filesystem stuck frozen. A bdev_freeze() issued by "dmsetup suspend" or an LVM snapshot resolves that holder to freeze the filesystem. and bdev_thaw() resolves it again to thaw. A freeze landing while btrfs is adding, removing or replacing a device freezes the filesystem. The membership change then drops that link. So the matching thaw could no longer find the superblock. Forbid freezing a device for the duration of a membership change, modelled on deny_write_access()/allow_write_access(). * tag 'vfs-7.3-rc1.super' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (24 commits) super: fix dying superblock warning messages block: reject block device inodes with i_rdev == 0 in lookup_bdev() selftests/filesystems: add ustat() coverage fs: look up the superblock via the device table in user_get_super() super: make fs_holder_ops private f2fs: open via dedicated fs bdev helpers erofs: open via dedicated fs bdev helpers fs: tolerate per-superblock freeze errors on shared devices fs: look up superblocks via the device table in fs_holder_ops ext4: open via dedicated fs bdev helpers btrfs: open via dedicated fs bdev helpers xfs: port to fs_bdev_file_open_by_path() fs: add dedicated block device open helpers for filesystems fs: maintain a global device-to-superblock table ocfs2: don't reset s_dev on dismount ext4: use anonymous devices for KUnit test superblocks fs, block: move blk_mode_t and fop_flags_t into <linux/types.h> super: take lock after last reference count super: convert s_count to refcount_t s_passive btrfs: deny freezing devices undergoing a replace ...
2026-08-17Merge tag 'vfs-7.3-rc1.ovl' of ↵Linus Torvalds5-15/+32
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull overlayfs updates from Christian Brauner: "This lets the merged overlayfs mount itself be idmapped through mount_setattr(MOUNT_ATTR_IDMAP), in addition to the already supported idmapped lower and upper layers. The same overlay tree can then be exposed under a different ownership view. Overlayfs already normalizes every underlying id through the relevant layer idmap when ovl_copyattr() copies attributes into the overlay inode. So the overlay inode's i_uid and i_gid are overlay-final ids. The overlay mount idmap composes on top of that and is applied at the overlay-inode boundary only while the underlying layers keep being accessed with the mounter's credentials through their own (possibly idmapped) mounts. So this only changes how the caller sees the overlay inode and never widens the mounter's access to the layers. The second, mounter-credential check in ovl_permission() against the real inode stays on the layer idmap. Most paths need no change because the VFS applies the mount idmap to the overlay inode before overlayfs runs or after it returns at the syscall boundary. Overlayfs only has to change where it bypasses the generic path. This also included is a fix for a double end_creating() on the overlayfs casefold-mismatch path" * tag 'vfs-7.3-rc1.ovl' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: ovl: fix double end_creating() on the casefold-mismatch path ovl: document security.capability idmapping on the xattr forward paths selftests/filesystems/overlayfs: test idmapped overlay mounts selftests/filesystems/overlayfs: fix set_layers_via_fds link error docs: document idmapped overlay mounts ovl: allow idmapping overlay mounts ovl: handle idmapped mounts in ovl_set_acl() ovl: handle idmapped mounts in ovl_getattr() ovl: handle idmapped mounts in ovl_setattr() ovl: handle idmapped mounts in ovl_permission() ovl: handle idmapped mounts in ovl_create_object() and ovl_tmpfile()
2026-08-17Merge tag 'vfs-7.3-rc1.netfs' of ↵Linus Torvalds8-1038/+8
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull cachefiles ondemand removal from Christian Brauner: "This sunsets cachefiles ondemand mode. It was an effort to make fscache usable as a kernel cache for lazy pulling. EROFS over fscache was its only in-tree user. fscache has since become netfslib-oriented while EROFS never acts as a network filesystem and EROFS over fscache has been removed. So this cleans up the netfs, fscache and cachefiles side as well" * tag 'vfs-7.3-rc1.netfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: cachefiles,netfs: sunset ondemand mode
2026-08-17Merge tag 'vfs-7.3-rc1.mount' of ↵Linus Torvalds1-3/+7
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull mount updates from Christian Brauner: - Make the legacy mount API notify pollers of propagation changes. Changing propagation via change_mnt_propagation() or with MOVE_MOUNT_SET_GROUP update the propagation relationship of the target mount. But unlike mount_setattr() neither path touched the affected mount namespace. So pollers of /proc/<pid>/mountinfo were never woken. - Also remove a redundant panic() in mnt_init() * tag 'vfs-7.3-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: mount: remove redundant panic() in mnt_init() fs/namespace: notify pollers of legacy propagation changes
2026-08-17Merge tag 'vfs-7.3-rc1.misc' of ↵Linus Torvalds61-235/+271
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull misc vfs updates from Christian Brauner: "Bigger cleanups: - The lockref dead-count handling is tidied up. The open-coded check for a count below zero as the dead marker relies on information the caller should not have. - make put_mnt_ns() leave mounts connected. Destroying a mount namespace disconnected its mounts from their mount points. So a file descriptor still open on the parent of a mount point could be used to peek under it. Locked mounts were already kept connected to prevent exactly that. But a mount is only locked when its tree is copied across a user namespace boundary. So a mount namespace set up by a privileged component had no locked mounts and its mounts were disconnected. Passing UMOUNT_CONNECTED keeps every mount connected and prevents that bug. - vfs_prepare_mode() passes S_IFDIR for directories. I meant to fix that ago but didn't get to it. So now someone finally did it. This kills the exception where the mode could be 0 when a directory was created whereas every other creation operation passed it explicitly already. - move long delayed work for ufs, jffs2, hfsplus, hfs and affs from the per-cpu system_long_wq to the new unbound system_dfl_long_wq. None of that work relies on per-cpu state and the work item is enqueued with queue_delayed_work() whose timer is global anyway. So it may as well benefit from scheduler task placement. Smaller fixes and cleanups: - unlock_buffer() and journal_end_buffer_io_sync() use clear_and_wake_up_bit() - the pipe page pools are unified into a single per-pipe pool and the extra wake_up(rd_wait) is limited to EPOLLET consumers - eventpoll now computes its timer slack lazily in ep_poll() - shrink_dcache_for_umount() keeps making progress on busy roots - excess xarray nodes are freed in clear_inode() - romfs detects hard link cycles - the user path of nested backing files is fixed - pidfd holds exec_update_lock around the namespace ioctl - non-memcg-aware nr_cached_objects is skipped during memcg slab shrink - iomap_write_iter() always returns status - mangle_path() is renamed to seq_mangle_path() - inode timestamp accessors are annotated - new regression test for pipe->poll_usage. - a few documentation, kernel-doc and selftest fixes" * tag 'vfs-7.3-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (67 commits) selftests/namespaces: Fix racy pipe handshake in timens and pidns_separate selftests/epoll: add a regression test for pipe->poll_usage pipe: only enable the extra wake_up(rd_wait) for EPOLLET consumers pidfd: hold exec_update_lock around namespace ioctl fs: fix user path of nested backing files fs: remove stale inode_insert5() kernel-doc parameter fs: fix switch/case indentation in sysfs() syscall fs: document semantics of kstat::{uid,gid} fields dcache: keep shrink_dcache_for_umount() making progress on busy roots seq_file: rename mangle_path to seq_mangle_path nstree: add/fix struct ns_id_req kernel-doc member fields dcache: use lockref routines for dead count checks lockref: tidy up dead count handling initramfs: fix typo in reserve_initrd_mem comment fs/pipe: unify the page pools into a single per-pipe pool fs: annotate inode timestamp accessors eventpoll: compute timer slack lazily in ep_poll() selftests/filesystems: add mntns cleanup test put_mnt_ns(): leave mounts connected affs: Move long delayed work on system_dfl_long_wq ...
2026-08-17Merge tag 'vfs-7.3-rc1.lookup' of ↵Linus Torvalds47-166/+297
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs lookup updates from Christian Brauner: "This refactors lookup_open() and adds vfs_lookup_open() for nfsd. mnt_want_write() and parent locking are moved into lookup_open() itself. audit_inode_child() is also now called in lookup_open() on failure. That is the calling convention in vfs_create() and vfs_mkdir(), but lookup_open() made no such call when atomic_open() should have created a file and did not. And neither did the regular ->create() path fwiw. This also contains work to remove the unneeded excl argument from the ->create() inode op" * tag 'vfs-7.3-rc1.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fs/namei.c: fix coding style in atomic_open() and lookup_open() fs/namei.c: fix kerneldoc of atomic_open() and vfs_lookup_open() fs/namei.c: update stale comments in lookup_open() Remove excl arg to ->create inode_operation fs/namei.c: update kerneldoc of atomic_open() vfs: call audit_inode_child() in lookup_open() on failure vfs: move create error && negative dentry case in lookup_open() up VFS: add vfs_lookup_open() for nfsd VFS: move delegated_inode retry loop into lookup_open() VFS: move mnt_want_write() and locking into lookup_open()
2026-08-17Merge tag 'vfs-7.3-rc1.kthread' of ↵Linus Torvalds13-51/+159
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull kthread vfs updates from Christian Brauner: "This stops kernel threads from sharing filesystem state with userspace. This work is about 3 cycles old and has been in -next for about that time. When the kernel boots init_task creates PID 1 and then kthreadd. From that point every kthread and PID 1 share the same fs_struct. That is why pivot_root() has to rewrite the fs_struct of all kthreads. The rewriting exists so that kthreads can use init's filesystem state when they want to. It also means userspace can move the ground out from under the kernel. PID 1 now gets a completely separate fs_struct. All kthreads are anchored in a private SB_KERNMOUNT instance of nullfs that cannot be mounted on and cannot be used to follow other mounts. Userspace init can no longer affect kthread filesystem state and kthreads can no longer affect userspace fs state without explicit opting in to that. Path lookup from a kthread now fails by default. It makes it deliberately hard to offload security sensitive operations into init's filesystem state from a kthread. Places that legitimately need to look something up there opt in through the new scoped_with_init_fs() which temporarily overrides the caller's fs_struct with init's. usermodehelpers remain the only kernel tasks that genuinely share init's filesystem state, since they execute random binaries in the root filesystem (excellent...). The visible result is that /proc/2/root is a nullfs with an empty mountinfo while /proc/1/root is the real root" * tag 'vfs-7.3-rc1.kthread' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (26 commits) initramfs_test: use test init/exit hooks to override init fs fs: stop rewriting paths for PF_EXITING | PF_DUMPCORE fs: stop rewriting kthread fs structs fs: start all kthreads in nullfs nullfs: make nullfs multi-instance devtmpfs: create private mount namespace fs: add umh argument to struct kernel_clone_args fs: stop sharing fs_struct between init_task and pid 1 af_unix: use scoped_with_init_fs() for coredump socket lookup initramfs: use scoped_with_init_fs() for rootfs unpacking pnfs/blocklayout: use scoped_with_init_fs() for SCSI device lookup ksmbd: use scoped_with_init_fs() for VFS path operations ksmbd: use scoped_with_init_fs() for filesystem info path lookup ksmbd: use scoped_with_init_fs() for share path resolution fs: use scoped_with_init_fs() for kernel_read_file_from_path_initns() coredump: use scoped_with_init_fs() for coredump path resolution btrfs: use scoped_with_init_fs() for update_dev_time() scsi: target: use scoped_with_init_fs() for APTPL metadata scsi: target: use scoped_with_init_fs() for ALUA metadata crypto: ccp: use scoped_with_init_fs() for SEV file access ...
2026-08-17Merge tag 'vfs-7.3-rc1.kfunc' of ↵Linus Torvalds1-0/+37
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs bpf access updates from Christian Brauner: "This adds a bpf_sock_read_xattr() kfunc so a BPF LSM program can read a user.* extended attribute from a socket's sockfs inode locklessly. userspace already uses user.* xattrs on sockets to implement socket rate limiting and to tag sockets for other purposes such as a varlink registry. There has been no efficient way for a BPF program to read those labels back. With this a listening socket marked from userspace with fsetxattr() can be read back during bind or connect and acted upon on the connecting socket. That lets userspace mark sockets and later rediscover them or implement policy on them" * tag 'vfs-7.3-rc1.kfunc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: selftests/bpf: Add test for bpf_sock_read_xattr() kfunc fs: Add bpf_sock_read_xattr() kfunc to read socket xattrs
2026-08-17Merge tag 'vfs-7.3-rc1.iomap' of ↵Linus Torvalds26-140/+404
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-17Merge tag 'vfs-7.3-rc1.fat' of ↵Linus Torvalds1-0/+3
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull FAT update from Christian Brauner: "This rejects names longer than NAME_MAX in msdos_format_name(). The VFS only enforces PATH_MAX rather than the length of an individual component. open() on such a path component reported success for a name far longer than NAME_MAX" * tag 'vfs-7.3-rc1.fat' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fat: reject name longer than NAME_MAX in msdos_format_name()
2026-08-17Merge tag 'vfs-7.3-rc1.failfs' of ↵Linus Torvalds6-3/+224
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull failfs filesystem from Christian Brauner: "Add failfs and expose a FD_FAILFS_ROOT sentinel. This allows userspace to shed their filesystem state completely. A process with its root or working directory in failfs must anchor every path lookup at an explicit file descriptor. Absolute paths, absolute symlinks and AT_FDCWD-relative lookups simply fail. Failfs is the counterpart to nullfs. nullfs says adds a permanently empty, immutable directory whose lookups fail with ENOENT but which can be opened, read, stat'd and mounted upon. Failfs on the other hand fails every operation. The root cannot be opened at all. A single instance is mounted during early boot via kern_mount(), which makes it logically distinct from every mount namespace. This is accompanied by a new fchroot() system call which makes chrooting via a file descriptor a first class concept. It's possible to chroot into failfs as an unprivileged user provided the task has no new privileges set" * tag 'vfs-7.3-rc1.failfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: Documentation: add failfs documentation selftests/filesystems: add failfs selftests arch: hookup fchroot() system call fs: support FD_FAILFS_ROOT in fchroot() fs: add fchroot() fs: support FD_FAILFS_ROOT in fchdir() fs: add failfs
2026-08-17nfs: fix ENXIO on O_CREAT open of existing symlink over NFSv3Michael Nemanov1-0/+7
When open(2) is called with O_CREAT on a path that already exists as a symlink, over an NFSv3 mount with a cold dcache, the kernel returns ENXIO instead of following the symlink to its target. Reproducer script (MNT is an NFSv3 mount, kernel is 7.1-rc6): MNT=/mnt/export ln -sf /tmp/target $MNT/mylink echo 3 | sudo tee /proc/sys/vm/drop_caches # cold dcache python3 - <<'EOF' import os fd = os.open('/mnt/export/mylink', os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o666) os.close(fd) EOF Expected: success (follow symlink, open target) Actual: OSError: [Errno 6] No such device or address The bug does not trigger when the dcache is warm (e.g. after a prior stat(2)), because lookup_open() then finds a positive dentry and skips atomic_open entirely, leaving symlink resolution to the VFS. Root cause: nfs_atomic_open_v23(), registered as inode->i_op->atomic_open for NFSv3, handles O_CREAT by sending a CREATE UNCHECKED RPC. As implemented in nfsd3_create_file() (fs/nfsd/nfs3proc.c) and as required by RFC 1813 (3.3.8), when the name already exists as a non-regular file the server returns NFS3_OK with the existing object's file handle rather than NFS3ERR_EXIST causing nfs_do_create() to return 0 with the dentry now pointing to a symlink. The code then unconditionally calls finish_open(), which dispatches through inode->i_fop->open(). Symlink inodes never have i_fop set — the VFS initialises it to &no_open_fops because POSIX requires open(2) to follow symlinks, never open them directly. no_open() returns -ENXIO. Fix: After nfs_do_create() succeeds, verify the returned inode is a regular file before calling finish_open(). If the object is not regular, return finish_no_open(file, NULL) so the VFS follows the symlink through the normal open path. NULL is passed because nfs_do_create() instantiates the inode on the dentry already owned by the caller; passing dentry back would cause atomic_open() to dput() it a second time. !S_ISREG() is used rather than S_ISLNK() to cover any other non-regular types a server might return. Changes in v2: - Pass NULL to finish_no_open() per Trond's feedback. Fixes: 7c6c5249f061 ("NFS: add atomic_open for NFSv3 to handle O_TRUNC correctly.") Link: https://lore.kernel.org/linux-nfs/20260614122911.3485467-1-michael.nemanov@vastdata.com/ (v1) Signed-off-by: Michael Nemanov <michael.nemanov@vastdata.com> Tested-by: Michael Nemanov <michael.nemanov@vastdata.com> [trond.myklebust@hammerspace.com: use d_is_reg() to catch negative dentries] Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4: Fix incorrect argument passed to nfs4_delete_lease() in nfs4_add_lease()Zhansong Gao1-1/+3
When nfs4_add_lease() races with a delegation return, it calls nfs4_delete_lease() to clean up. Previously, it passed priv, which can legitimately be NULL. Passing a NULL priv eventually leads to a NULL pointer dereference in generic_setlease(). Fixes: e93a5e9306a5 ("NFSv4: Add support for application leases underpinned by a delegation") Signed-off-by: Zhansong Gao <zhsgao@hotmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17lockd: fix NULL dereference on lockowner allocation failureShuangpeng Bai1-0/+3
nlmclnt_locks_init_private() installs NLM file lock operations even when nlmclnt_find_lockowner() fails to allocate a lockowner. nlmclnt_proc() then returns -ENOMEM, but the VFS still tears down the partially initialized file_lock and calls locks_release_private(). That invokes nlmclnt_locks_release_private(), which dereferences fl->fl_u.nfs_fl.owner and crashes because the owner was never installed. Clear fl_ops before attempting to initialize the NLM private state, and install the NLM lock operations only after a lockowner has been allocated successfully. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS: fix delegation_hash_table leak when nfs4_server_common_setup() failsNate Prodromou1-5/+12
nfs4_server_common_setup() allocates server->delegation_hash_table first, but server->destroy - the only path that frees the table via nfs4_destroy_server() - is not assigned until the very end of the function. If any intermediate step fails (the is_ds_only_client() check, nfs4_init_session(), nfs4_get_rootfh(), or nfs_probe_server()), the function returns with server->destroy still NULL, so the caller's nfs_free_server() skips the destroy callback and the hash table is leaked (4 KiB per attempt with the default delegation watermark). This is trivially reachable from userspace: every failed NFSv4 mount leaks one allocation. A client that persistently retries a mount that cannot succeed leaks kernel memory without bound. Observed in production where a Longhorn backup poller retried mount.nfs4 against an NFSv3-only server roughly 10 times per second, leaking ~3.4 GiB of unreclaimable slab (kmalloc-rnd-13-4k) per day; the node accumulated 12 GiB of leaked slab before the source was identified via the kmem:kmalloc tracepoint (call_site=nfs4_delegation_hash_alloc). Reproducer: # server exports NFSv3 only (or export path absent for v4) while :; do mount -t nfs4 <server>:/missing /mnt; done # watch SUnreclaim in /proc/meminfo grow 4 KiB per iteration Free the table on the error paths between the allocation and the assignment of server->destroy. Fixes: f5b3108e6a14 ("NFS: use a hash table for delegation lookup") Cc: stable@vger.kernel.org Signed-off-by: Nate Prodromou <nate@prodromou.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4/flexfiles: support loosely coupled data serversJeuk Kim8-14/+24
A flexfiles storage device is tightly coupled to the MDS only when the decoded ds_versions[0].tightly_coupled flag is set (RFC 8435, sections 2.3 and 4.1). The client currently ignores that flag and treats every data server as tightly coupled, which breaks I/O to loosely coupled DSes. Two things force that assumption on an NFSv4.1+ DS: 1) nfs4_set_ds_client() always sets NFS_CS_PNFS on the new client, so EXCHANGE_ID is sent with EXCHGID4_FLAG_USE_PNFS_DS. 2) nfs4_init_ds_session() then calls is_ds_client() and returns -ENODEV if the reply does not carry EXCHGID4_FLAG_USE_PNFS_DS. A loosely coupled DS is just a normal NFS server and does not act in the pNFS DS role, so the client must not require it to advertise that role. Thread the ds_versions[0].tightly_coupled flag from the flexfiles driver down to the DS connect path. When it is false, skip both the NFS_CS_PNFS flag and the is_ds_client() check. The file layout driver always passes true because NFSv4.1 file layout data servers use the pNFS DS role. Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4/flexfiles: fix NULL dereference for NFSv4.0 data serversJeuk Kim2-6/+13
flexfiles accepts NFSv4.0 data servers, but two NFSv4 code paths assume the data server client has a session. Unlike NFSv4.1+, an NFSv4.0 client has no session (clp->cl_session is NULL; it uses clp->cl_slot_tbl), so I/O to a v4.0 flexfiles DS oopses: - nfs4_init_ds_session() dereferences clp->cl_session->session_state while seeding the DS lease. It also only seeds cl_lease_time when NFS4_SESSION_INITING is set; without a session that never happens, so cl_lease_time stays 0 and nfs4_renew_state() busy-loops, requeuing every 5 seconds. Seed the lease whenever there is no session and return before touching session state. - ff_layout_async_handle_error_v4() dereferences clp->cl_session->fc_slot_table on every DS I/O error. Fall back to the v4.0 transport slot table (clp->cl_slot_tbl) when there is no session. Fixes: a7878ca14008 ("nfs: flexfilelayout: remove v3-only data server limitation") Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4: pin the superblock for active state ownersJia Zhu1-7/+33
NFSv4 open state can outlive the file and dentry that created it. This was observed in production when NFSv4 state recovery, such as after a server reboot or lease expiration, raced with unmount. The race requires recovery to hold an open state reference while the last open file is closed and the filesystem is unmounted, allowing the superblock's active reference to drop to zero between refcount_inc(&state->count) and nfs4_put_open_state(): state manager umount nfs4_run_state_manager() nfs4_do_reclaim() nfs4_reclaim_open_state() refcount_inc(&state->count) ... close last file generic_shutdown_super() "Busy inodes after unmount" nfs_free_server() nfs4_put_open_state() iput(inode) evict() nfs_clear_inode() nfs_zap_acl_cache() The "VFS: Busy inodes after unmount" warning is the visible symptom of that lifetime mismatch: superblock teardown proceeds even though the NFS open state still pins an inode. After umount has freed the server, the state manager can then run nfs4_put_open_state() for the last open-state reference. The resulting iput(inode) can evict an NFS inode with freed server data, causing crashes at nfs_zap_acl_cache(). This can be reproduced by delaying the reclaim path before nfs4_put_open_state(), then closing the last file and unmounting the NFS mount. Pin the superblock while a state owner is active, and drop the pin when the owner becomes idle again, so the NFS server stays alive until all open state associated with the owner has been released. Assisted-by: Codex:GPT-5 Signed-off-by: Jia Zhu <zhujia.zj@bytedance.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS/localio: issue commit inline when not in a memory-reclaim contextMike Snitzer1-1/+13
Extend the memory-reclaim-context test used for LOCALIO reads and writes to the commit (fsync) path. As with data IO, bouncing every commit through the dedicated !WQ_MEM_RECLAIM nfslocaliod_workqueue is only required when the submitting context is a memory-reclaim context: nfs_local_run_commit() calls vfs_fsync_range(), which may flush the underlying filesystem's own !WQ_MEM_RECLAIM workqueue, and doing so from a WQ_MEM_RECLAIM worker or a PF_MEMALLOC task trips check_flush_dependency(). The writeback path does exercise this: nfs_write_inode() (the ->write_inode super_op) runs under wb_workfn on the WQ_MEM_RECLAIM bdi_wq and reaches nfs_local_commit() via __nfs_commit_inode(), so that case must keep deferring. Application-context commits -- fsync (nfs_file_fsync), O_DIRECT (nfs_direct), and copy/clone (nfs42) -- are not in a reclaim context and now run the fsync inline via nfs_local_defer_io(), avoiding the per-commit workqueue hop. Completion (nfs_commit_release_pages -> nfs_commit_end) then runs synchronously in the submitting context; higher layers already cope with this, as __nfs_commit_inode() dispatches the commit async and waits for it separately via wait_on_commit(). Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>