summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
11 daysdrm/vmwgfx: drop dma_buf reference on foreign-fd prime importZack Rusin
ttm_prime_fd_to_handle() returns -ENOSYS when the imported fd's dma_buf->ops do not match the ttm_object_device's ops, but does so without releasing the reference acquired by dma_buf_get(). Any unprivileged renderD client passing a non-vmwgfx prime fd through the DRM_VMW_GB_SURFACE_REF{,_EXT} path leaks one dma_buf reference per call and indefinitely pins the foreign exporter's GEM resources. Funnel the error path through the existing dma_buf_put() so the reference is always dropped. Fixes: 65981f7681ab ("drm/ttm: Add a minimal prime implementation for ttm base objects") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Zack Rusin <zack.rusin@broadcom.com> Reviewed-by: Ian Forbes <ian.forbes@broadcom.com> Link: https://patch.msgid.link/20260505222728.519626-6-zack.rusin@broadcom.com
11 daysdrm/vmwgfx: take fman->lock around fence list mutation in fifo_downZack Rusin
vmw_fence_fifo_down() drops fman->lock to wait on a fence and, on timeout, mutates fman->fence_list via list_del_init() and signals the fence without re-acquiring the lock. __vmw_fences_update() walks and removes entries from the same list under fman->lock from any other waiter, the fence-IRQ thread, or vmw_fences_update(), so the unlocked list_del_init() can corrupt the list head. Re-take fman->lock before manipulating fence->head and use dma_fence_signal_locked(). Wrap the locked signalling in dma_fence_begin_signalling() / dma_fence_end_signalling() so the lockdep annotation that dma_fence_signal() previously provided is preserved (the same pattern as __vmw_fences_update()). dma_fence_put() is moved outside the lock to avoid a recursive acquire from vmw_fence_obj_destroy(), which also takes fman->lock. Fixes: ae2a104058e2 ("vmwgfx: Implement fence objects") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Zack Rusin <zack.rusin@broadcom.com> Reviewed-by: Ian Forbes <ian.forbes@broadcom.com> Link: https://patch.msgid.link/20260505222728.519626-5-zack.rusin@broadcom.com
11 daysdrm/vmwgfx: clamp dirty-page range with min, not maxZack Rusin
vmw_bo_dirty_transfer_to_res() and vmw_bo_dirty_clear() compute the intersection of a resource's page range with the BO's tracked dirty range, but clamp res_end against dirty->end with max() instead of min(). When dirty->end exceeds the resource end, the loop walks past the resource's pages, calls vmw_resource_dirty_update() for ranges owned by other resources sharing the same backing MOB and clears their pending dirty bits via bitmap_clear(). The result is silent loss of writeback for unrelated resources whenever two resources share a MOB. Use min() in both functions so the loop is bounded to the intersection of the resource and dirty ranges. Fixes: b7468b15d271 ("drm/vmwgfx: Implement an infrastructure for write-coherent resources") Fixes: 965544150d1c ("drm/vmwgfx: Refactor cursor handling") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Zack Rusin <zack.rusin@broadcom.com> Reviewed-by: Ian Forbes <ian.forbes@broadcom.com> Link: https://patch.msgid.link/20260505222728.519626-4-zack.rusin@broadcom.com
11 daysdrm/vmwgfx: reject DX_BIND_QUERY without a DX contextZack Rusin
vmw_cmd_dx_bind_query() unconditionally dereferences sw_context->dx_ctx_node->ctx. Userspace can trigger a NULL pointer dereference from any render-node fd by submitting an execbuf with dx_context_handle == SVGA3D_INVALID_ID and a SVGA_3D_CMD_DX_BIND_QUERY opcode in the command stream: dx_ctx_node is left NULL and the kernel oopses on the assignment. The same NULL is then re-read in vmw_resources_reserve() via vmw_context_get_dx_query_mob(). All sibling DX handlers fail-close on a missing dx_ctx_node using VMW_GET_CTX_NODE(). Use the same pattern here, returning -EINVAL up front before any relocation state is published. Fixes: 9c079b8ce8bf ("drm/vmwgfx: Adapt execbuf to the new validation api") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Zack Rusin <zack.rusin@broadcom.com> Reviewed-by: Ian Forbes <ian.forbes@broadcom.com> Link: https://patch.msgid.link/20260505222728.519626-3-zack.rusin@broadcom.com
11 daysdrm/vmwgfx: fix guest_memory_dirty bitfield clobbered as sizeZack Rusin
Two sites in vmwgfx_resource.c assign boolean literals to res->guest_memory_size, which is an unsigned long allocation-size field; the intended target is the adjacent res->guest_memory_dirty bitfield. After the assignments the field holds 0 or 1 instead of the resource's MOB allocation size: - vmw_resource_release() writes 0 (false), and - vmw_resource_unbind_list() writes 1 (true). Subsequent revalidation paths read guest_memory_size when computing the dirty page range (vmw_bo_dirty_transfer_to_res()) and the buffer allocation size (vmw_resource_buf_alloc()), producing zero-length walks or wrap-around ranges that read or write past the MOB bitmap. The dirty-tracking intent of the original code (mark the resource as dirtied since the last sync) is also lost, since guest_memory_dirty is never updated. Rename both assignments to guest_memory_dirty. Fixes: 668b206601c5 ("drm/vmwgfx: Stop using raw ttm_buffer_object's") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Zack Rusin <zack.rusin@broadcom.com> Reviewed-by: Ian Forbes <ian.forbes@broadcom.com> Link: https://patch.msgid.link/20260505222728.519626-2-zack.rusin@broadcom.com
11 daysMerge patch series "fs: add failfs"Christian Brauner
Christian Brauner <brauner@kernel.org> says: nullfs provides a permanently empty and immutable directory. Lookups fail with ENOENT. The directory can be opened, read, stat, mounted upon. It behaves like nothing is there. Add its counterpart failfs where the semantics are not "there is nothing here" but "nothing is supported here". Every operation that reaches the filesystem fails with EOPNOTSUPP. Even statfs()/fstatfs() fail so the filesystem cannot be discovered through an fd to it. EOPNOTSUPP rather than a permission errno keeps that coherent. There is no permission model in which anything could ever be allowed and EACCES or EPERM would merely suggest that different credentials might succeed while EIO would suggest corruption. It also makes hitting the failfs boundary mostly quite dinstinguishable. A task anchoring its lookups at real directory file descriptors may be able to tell a failfs refusal from an ordinary permission failure. I wouldn't go so far as guaranteeing that but it should mostly work. The root cannot be opened at all not even with O_PATH. It is never reached by a lookup in a parent directory. The only way to a path-walk terminal at the root is a jump through a /proc/<pid>/{root,cwd} magic link or by mountpoint traversal. The root also refuses ->d_weak_revalidate() which the VFS calls for jumped terminals. That closes every remaining way to reference it. An O_PATH open is refused and name_to_handle_at() cannot encode it into a file handle, and following a magic link into it fails. A plain readlink() of such a link still works and shows "failfs:/". There is a single instance of failfs mounted during early boot via kern_mount() making it logically distinct from every mount namespace. Since the mount is a member of no mount namespace mounting onto it fails. So nothing can ever be mounted on top of it. It cannot be cloned via OPEN_TREE_CLONE and it does not show up in statmount()/listmount() or /proc/<pid>/mountinfo. The filesystem is not registered so it is not visible in /proc/filesystems and cannot be mounted from userspace. This lets tasks shed their filesystem state completely. A process with its root directory or working directory in failfs must anchor every path lookup at an explicit file descriptor or is doomed to fail any lookup. Absolute paths, absolute symlinks, and AT_FDCWD-relative lookups simply fail. Followup patches will expose it via a new FD_FAILFS_ROOT file descriptor sentinel understood by fchdir() and the new fchroot() system call. Fun fact, because of how dynamic binary execution work with PT_INTERP this also currently prevents execution of dynamic binaries because loaders have absolute paths (see selftests). * patches from https://patch.msgid.link/20260724-work-failfs-v2-0-485dabbae185@kernel.org: 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 Link: https://patch.msgid.link/20260724-work-failfs-v2-0-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysDocumentation: add failfs documentationChristian Brauner
Document the failfs semantics, the FD_FAILFS_ROOT sentinel, the fchroot() entry requirements, and the ways back out. Link: https://patch.msgid.link/20260724-work-failfs-v2-7-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysselftests/filesystems: add failfs selftestsChristian Brauner
Test the failfs semantics and both new entry points: - fchdir(FD_FAILFS_ROOT): * working directory lookups and getcwd() fail * other sentinels are rejected * the state is recoverable while the root is untouched - fchroot() with regular fds: * chroot parity * CAP_SYS_CHROOT required * ENOTDIR/EBADF/EINVAL checks - fchroot(FD_FAILFS_ROOT): * absolute lookups, stat, statfs and opens of the root including O_PATH fail with EOPNOTSUPP * dirfd-anchored I/O keeps working * ".." walks clamp at the top of the mount tree * /proc magic links resolve but can't be stat through * absolute symlinks fail while relative symlinks keep resolving - Unprivileged entry requires no_new_privs and is rejected for chrooted callers and for a shared fs_struct - entering makes the task count as chrooted so user namespace creation fails - Nothing can be mounted on top of failfs and OPEN_TREE_CLONE is rejected; the overmount test runs in a private mount namespace so a regression cannot touch the host root - setns() to a kept mount namespace fd restores root and working directory - The failfs root is inherited across fork() and absolute exec fails - Exec by fd of a dynamically linked binary fails on opening its absolute PT_INTERP interpreter The exec tests run the exec in a child so a wrongly successful exec cannot replace the test image and masquerade as a pass. Link: https://patch.msgid.link/20260724-work-failfs-v2-6-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysarch: hookup fchroot() system callChristian Brauner
Wire up the fchroot() system call as number 472 on (nearly) all architectures and sync the mirrored copies of the syscall tables and the asm-generic unistd.h under tools/. Link: https://patch.msgid.link/20260724-work-failfs-v2-5-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: support FD_FAILFS_ROOT in fchroot()Christian Brauner
Allow a process to move its root directory into failfs via fchroot(FD_FAILFS_ROOT). From that point on every absolute path lookup and every absolute symlink fails with EOPNOTSUPP. Combined with fchdir(FD_FAILFS_ROOT) this leaves the process with lookups anchored at explicit directory file descriptors only. It is the fs_struct equivalent of RESOLVE_BENEATH. This allows taks to drop their filesystem state completely. Callers with CAP_SYS_CHROOT in their user namespace may always do this, mirroring chroot(2). Unprivileged callers are subject to three requirements (which may be loosened later): (1) no_new_privs must be set After entering failfs suid binaries on regular mounts remain reachable via inherited directory file descriptors or the working directory. A setuid program executing with an unusable root directory might be tricked by this. I'm not 100% convinced that this is needed but it feels more secure initially and it also forces more no_new_privs on userspace. So win-win imo. (2) The caller must not already be chrooted. The root directory is what confines .. resolution. The failfs root can never be reached by walking up a real mount tree. A task whose root is failfs has no .. barrier left below the top of its mount tree. A .. walk from any real directory fd it still holds climbs to the mount-namespace root. Which is kinda the point if you want to do fd-based lookup only. If failfs prevented you from doing that then it doesn't make a lot of sense. A task that a privileged manager chrooted into a subtree could use chroot()ing into failfs as a way to allow for an inherited fd to resolve it again. So reject already-chrooted callers closing that issue without losing anything for the intended self-sandboxing use case. (3) The caller must not share its fs_struct. Requirement (1) is checked on the calling thread, but the root lives in the fs_struct which may be shared via CLONE_FS. A sibling thread without no_new_privs could then execute a setuid binary with the failfs root and defeat (1). setns() to a mount or user namespace refuses a shared fs_struct for the same kind of reason, so do the same here and require fs->users == 1. no_new_privs is inherited across clone() and can never be cleared, so any CLONE_FS child created afterwards carries it too and the guarantee holds. Privileged callers (CAP_SYS_CHROOT) are not subject to these requirements and may share the fs_struct. They can already chroot and exec a setuid binary today, so failfs hands them nothing new. Backing out is currently hard, but that is a property of the current implementation and not a promise. current_chrooted() treats a failfs root as chrooted so for now the task cannot create user namespaces to regain CAP_SYS_CHROOT and chroot()/fchroot() back out require CAP_SYS_CHROOT. This is not guaranteed though. current_chrooted() may change, or an unprivileged no_new_privs task could be allowed to chroot to a real directory, either of which would loosen this. So don't treat it as a permanent one-way door. The remaining way out today is setns() to a mount namespace file descriptor which requires CAP_SYS_ADMIN over the target namespace plus CAP_SYS_CHROOT and CAP_SYS_ADMIN in the caller's user namespace and resets both root and working directory. A task that closes or never had such file descriptors and restricts *chdir()/*chroot()/setns() via seccomp currently cannot get back out. Link: https://patch.msgid.link/20260724-work-failfs-v2-4-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: add fchroot()Christian Brauner
Add a file descriptor based counterpart to chroot(2). This has been overdue for a long time. It is the natural companion to fchdir() and avoids re-resolving a path that the caller already holds a file descriptor to. No TOCTOU between resolving the target and changing the root. It composes with modern fd-based APIs meaning it works with O_PATH file descriptors and file descriptors to detached mount trees created via open_tree(OPEN_TREE_CLONE). The permission model is identical to chroot(2). The caller must have CAP_SYS_CHROOT in its user namespace, must pass MAY_EXEC | MAY_CHDIR permission checks on the target directory, and LSMs are consulted via the same security_path_chroot() hook. The system call takes a flags argument for future extensibility which must currently be zero. Link: https://patch.msgid.link/20260724-work-failfs-v2-3-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: support FD_FAILFS_ROOT in fchdir()Christian Brauner
Add a new file descriptor sentinel FD_FAILFS_ROOT following FD_PIDFS_ROOT and FD_NSFS_ROOT and teach fchdir() to accept it. A process calling fchdir(FD_FAILFS_ROOT) moves its working directory into failfs. Every AT_FDCWD-relative lookup afterwards fails with EOPNOTSUPP including "." and ".." and getcwd() reports the working directory as unreachable from the process root by returning a path prefixed with "(unreachable)". Lookups relative to explicit directory file descriptors are unaffected. The sentinel is the only way in. No privilege or gating is required. Setting the working directory to a directory in which every operation fails grants nothing and loses nothing that closing file descriptors couldn't lose. An unlinked working directory behaves the same way today modulo errno. The working directory also plays no role in confining ".." resolution so no boundary is weakened. Link: https://patch.msgid.link/20260724-work-failfs-v2-2-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: add failfsChristian Brauner
nullfs provides a permanently empty and immutable directory. Lookups fail with ENOENT. The directory can be opened, read, stat, mounted upon. It behaves like nothing is there. Add its counterpart failfs where the semantics are not "there is nothing here" but "nothing is supported here". Every operation that reaches the filesystem fails with EOPNOTSUPP. Even statfs()/fstatfs() fail so the filesystem cannot be discovered through an fd to it. EOPNOTSUPP rather than a permission errno keeps that coherent. There is no permission model in which anything could ever be allowed and EACCES or EPERM would merely suggest that different credentials might succeed while EIO would suggest corruption. It also makes hitting the failfs boundary mostly quite dinstinguishable. A task anchoring its lookups at real directory file descriptors may be able to tell a failfs refusal from an ordinary permission failure. I wouldn't go so far as guaranteeing that but it should mostly work. No path lookup can open the root, not even with O_PATH. It is never reached by a lookup in a parent directory. The only way to a path-walk terminal at the root is a jump through a /proc/<pid>/{root,cwd} magic link or by mountpoint traversal. The root also refuses ->d_weak_revalidate() which the VFS calls for jumped terminals. That covers the jump-based references too: an O_PATH open is refused, name_to_handle_at() cannot encode it into a file handle, and following a magic link into it fails. A plain readlink() of such a link still works and shows "failfs:/". There is a single instance of failfs mounted during early boot via kern_mount() making it logically distinct from every mount namespace. Since the mount is a member of no mount namespace mounting onto it fails. So nothing can ever be mounted on top of it. It cannot be cloned via OPEN_TREE_CLONE and it does not show up in statmount()/listmount() or /proc/<pid>/mountinfo. The filesystem is not registered so it is not visible in /proc/filesystems and cannot be mounted from userspace. This lets tasks shed their filesystem state completely. A process with its root directory or working directory in failfs must anchor every path lookup at an explicit file descriptor or is doomed to fail any lookup. Absolute paths, absolute symlinks, and AT_FDCWD-relative lookups simply fail. Followup patches will expose it via a new FD_FAILFS_ROOT file descriptor sentinel understood by fchdir() and the new fchroot() system call. Link: https://patch.msgid.link/20260724-work-failfs-v2-1-485dabbae185@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfat: Fix persisting directory entries on fsync(2) of the root directoryChristian Brauner
Buffers containing the directory entries of a directory's children are tracked in the directory inode's metadata bh list. Before commit 525da4f40a7c ("fat: Fix missed inode writeback during fsync(2)") fsync(2) of a directory wrote that list out unconditionally via mmb_fsync_noflush(). Now the list is written by fat_sync_inode_metadata() which __writeback_single_inode() only invokes when the inode has I_METADATA_WRITEBACK set. The root inode never gets I_METADATA_WRITEBACK - __fat_write_inode() returns early for it since the root directory has no directory entry of its own - and fat_sync_inode_metadata() returns early for it as well. Hence fsync(2) on the root directory returns success without writing out the directory entries of its children. Set I_METADATA_WRITEBACK for the root inode in __fat_write_inode() and make fat_sync_inode_metadata() only skip the nonexistent directory entry for the root inode but still sync the metadata bh list. Fixes: 525da4f40a7c ("fat: Fix missed inode writeback during fsync(2)") Reported-by: Sashiko <sashiko-bot@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfat: Propagate inode buffer write errors from fat_sync_inode_metadata()Christian Brauner
fat_sync_inode_metadata() ignores the result of writing the buffer containing the inode's directory entry. Before commit 525da4f40a7c ("fat: Fix missed inode writeback during fsync(2)") a write error was propagated to fsync(2) via __fat_write_inode() -> sync_dirty_buffer(), now fsync(2) reports success even though the inode's directory entry could not be written. Check buffer_write_io_error() after sync_dirty_buffer() like the other ->sync_inode_metadata implementations do. Fixes: 525da4f40a7c ("fat: Fix missed inode writeback during fsync(2)") Reported-by: Sashiko <sashiko-bot@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfat: Fix lost inode update in do_msdos_rename() with DIRSYNCChristian Brauner
Commit e668e0668181 ("fat: Replace fat_sync_inode() with sync_inode_metadata()") hoisted mark_inode_dirty() in front of the IS_DIRSYNC conditional in all converted callers except for the main rename path of do_msdos_rename(). There old_inode is generally still clean when the target directory has DIRSYNC set and, unlike fat_sync_inode(), sync_inode_metadata() does nothing for a clean inode. Thus the directory entry at the new location is never updated with the contents of old_inode: it stays the way msdos_add_entry() created it, with start cluster 0 and size 0 (or, when the rename replaced an existing target, it keeps describing the deleted target). Since old_inode is also never marked dirty, later writeback doesn't update the entry either and the stale directory entry ends up on disk even on a clean unmount, so the renamed file loses its contents. Mark old_inode dirty before calling sync_inode_metadata() like all the other call sites do. Fixes: e668e0668181 ("fat: Replace fat_sync_inode() with sync_inode_metadata()") Reported-by: Sashiko <sashiko-bot@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysmmc: moxart: use platform helpers for resource and IRQRosen Penev
Replace of_address_to_resource() and the following devm_ioremap_resource() with a single devm_platform_get_and_ioremap_resource() call in moxart_probe(). This requests the register region and maps it once, which is equivalent to the previous devm_ioremap_resource() behavior, and drops the now-redundant separate resource lookup. Similarly replace irq_of_parse_and_map() with platform_get_irq(), which returns a negative errno on failure (including -EPROBE_DEFER) instead of 0, and tighten the error check to irq < 0. Both substitutions are equivalent for a DT-backed platform device. The remaining OF usage (mmc_of_parse() and the of_device_id table) is covered by already-included headers, so linux/of_address.h and linux/of_irq.h are dropped. No functional change; the MMC register window is requested and mapped exactly once, so there is no overlapping region claim. Built for ARM (allmodconfig + CONFIG_MMC_MOXART) with LLVM=1; drivers/mmc/host/moxart-mmc.o compiles cleanly. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev <rosenp@gmail.com> Signed-off-by: Ulf Hansson <ulfh@kernel.org>
11 dayswifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT eventBaochen Qiang
Add ath12k_dp_peer_fixup_peer_id() and call it from the HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For devices where the firmware allocates the MLD peer ID, this is the point at which all data structures that were left with ATH12K_MLO_PEER_ID_PENDING or ATH12K_MLO_PEER_ID_INVALID get their real ID: - dp_peer->peer_id is updated and the dp_peer is published into dp_hw->dp_peers[]; - every existing dp_link_peer in dp_peer->link_peers[] gets its ml_id set to the same value; - ahsta->ml_peer_id is updated to the same value so peer_assoc, sta_state and cleanup paths see a consistent ID. Devices with host_alloc_ml_id == true also receive the same HTT event, but the firmware-reported ID always matches the host-allocated one and everything has already been populated by ath12k_dp_peer_create(); Skips the helper entirely on those devices. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221039 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-8-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: defer dp_peer registration when firmware allocates MLD peer IDBaochen Qiang
For chips with host_alloc_ml_id=true (QCN9274 etc.), the host allocates the MLD peer ID up front; ath12k_dp_peer_create() publishes the dp_peer into dp_hw->dp_peers[] using that ID immediately. WCN7850/QCC2072 does not work that way: the firmware picks the ID and only tells the host afterwards via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP, so the publication has to be delayed until the event arrives. Introduce ATH12K_MLO_PEER_ID_PENDING (0xFFFE) as a sentinel for "is_mlo, but ID not yet known". On the firmware-allocates path: - ath12k_mac_op_sta_state(NOTEXIST->NONE) skips ath12k_peer_ml_alloc() and stores PENDING in ahsta->ml_peer_id and dp_params.peer_id; - ath12k_dp_peer_create() skips dp_peer registration until a real ID is known; - ath12k_peer_create() leaves peer->ml_id at INVALID so consumer sites do not treat PENDING as a real ID; - ath12k_peer_ml_free() and ath12k_mac_dp_peer_cleanup() skip the dp_peers[] write and the free_ml_peer_id_map clear when host_alloc_ml_id is false or the ID is still PENDING. The HTT handler change that resolves the PENDING ID is added in a follow-up patch. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-7-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: do not advertise MLD peer ID for firmware-allocate devicesBaochen Qiang
ath12k_peer_assoc_h_mlo() unconditionally sets ml->peer_id_valid and copies ahsta->ml_peer_id (with the ATH12K_PEER_ML_ID_VALID bookkeeping bit masked off) into the WMI_PEER_ASSOC_CMDID ML params, which causes ath12k_wmi_send_peer_assoc_cmd() to set ATH12K_WMI_FLAG_MLO_PEER_ID_VALID. This needs to be gated on chips where the firmware allocates the MLD peer ID: - WCN7850/QCC2072 firmware always picks the ID itself and does not honor a host-supplied one, so the value would be silently ignored anyway; - QCC2072 firmware additionally crashes during MLO disconnect when ATH12K_WMI_FLAG_MLO_PEER_ID_VALID was set in the preceding peer assoc, so the bit must not be sent at all. Branch on ah->host_alloc_ml_id: - When true (QCN9274 etc.), behavior is unchanged: peer_id_valid is set and the raw ahsta->ml_peer_id (without the VALID bit) is sent down. - When false (WCN7850, QCC2072), peer_id_valid stays unset and ml_peer_id is sent as 0. The firmware ignores both fields and reports the ID it allocated through HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP. The early-return on ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID only applies on the host-alloc path, since on the firmware-alloc path the value is ATH12K_MLO_PEER_ID_PENDING here, not INVALID. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-6-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: introduce host_alloc_ml_id hardware parameterBaochen Qiang
Different ath12k devices diverge on who allocates MLD peer id: WCN7850/QCC2072 have the firmware allocate it and notify the host via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP event; While others let the host allocate it and pass it down through WMI_PEER_ASSOC_CMDID with ATH12K_WMI_FLAG_MLO_PEER_ID_VALID set. Currently ath12k host allocates this ID and sends it to firmware by default for all devices. This breaks WCN7850/QCC2072, because the host maintained ID may be different from the firmware-allocated one. Consequently data path may fail to find the dp peer and drop some received packets. From user point of view, this results in bugs reported in [1] or the 4-way handshake timeout issue. Add host_alloc_ml_id flag to struct ath12k_hw_params (and a copy on struct ath12k_hw for hot-path access) so subsequent patches can branch on it. Set true for QCN9274/IPQ5332/IPQ5424, false for WCN7850/QCC2072. The flag will be consumed by subsequent patches. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Link: https://bugzilla.kernel.org/show_bug.cgi?id=221039 # 1 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-5-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAPBaochen Qiang
Firmware on chips that allocate the MLD peer ID itself (WCN7850 and QCC2072) reports the assignment back to the host through HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP. The message carries the chosen MLD peer id, the MLD MAC address etc. Add the message type, the on-the-wire struct, the field masks and a handler that parses them out. The host-side state update (publishing the dp peer into ath12k_dp_hw::dp_peers[], propagating the ID to ath12k_dp_link_peer::ml_id and ath12k_sta::ml_peer_id) is added in a follow-up patch; Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-4-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_idBaochen Qiang
Several pieces of host bookkeeping for MLD peer IDs encode the same fact in different ways: - ath12k_sta::ml_peer_id stores the raw ID in [0, ATH12K_MAX_MLO_PEERS); - ath12k_dp_peer::peer_id, ath12k_dp_link_peer::ml_id and the index used on ath12k_dp_hw::dp_peers[] always carry the ATH12K_PEER_ML_ID_VALID bit (BIT(13)) when the ID is real; - WMI_MLO_PEER_ASSOC_PARAMS::ml_peer_id sent down to firmware is raw, without the bookkeeping bit. The mismatch leaks into call sites that have to remember to OR the bit in (ath12k_peer_create(), ath12k_mac_op_sta_state()) or remember not to (ath12k_peer_assoc_h_mlo()). Make ath12k_sta::ml_peer_id carry the VALID bit when valid, the same way ath12k_dp_peer::peer_id and ath12k_dp_link_peer::ml_id do: - ath12k_peer_ml_alloc() OR-s the bit in once on the way out; the internal bitmap stays raw [0, ATH12K_MAX_MLO_PEERS); - ath12k_peer_create() and ath12k_mac_op_sta_state() drop the explicit OR; - ath12k_peer_assoc_h_mlo() masks the bit off when populating the WMI ml_peer_id; While there, introduce ath12k_peer_ml_free() to mirror ath12k_peer_ml_alloc(), which helps avoid code duplication. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-3-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: factor out peer assoc send-and-wait into a helperBaochen Qiang
ath12k_bss_assoc(), ath12k_mac_station_assoc() and ath12k_sta_rc_update_wk() all open-code the same sequence: reinit the peer_assoc_done completion, send the peer assoc WMI command, then wait for the firmware confirmation event. The reinit_completion() was buried in ath12k_peer_assoc_prepare(), far from the wait_for_completion_timeout() that consumes it, making the reinit/send/wait sequence hard to follow, and the three open-coded copies are easy to get out of sync. Move the sequence into a new helper ath12k_mac_peer_assoc() and call it from all three sites. The reinit, send and wait now live together so the completion's lifecycle is easy to read. While at it, ath12k_sta_rc_update_wk() previously warned but still waited the full timeout when the peer assoc command failed to send. Now a send failure returns immediately and skips the pointless 1 second wait, matching the other two callers. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-2-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayswifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()Baochen Qiang
ath12k_mac_dp_peer_cleanup() clears the ML peer ID slot on the free_ml_peer_id_map bitmap by indexing it with dp_peer->peer_id. That is wrong: dp_peer->peer_id for an MLO peer always carries the ATH12K_PEER_ML_ID_VALID bit (BIT(13)), so clear_bit() is invoked with index >= 0x2000, which is far outside the bitmap of ATH12K_MAX_MLO_PEERS (256) bits and corrupts memory adjacent to ah->free_ml_peer_id_map. The intended bitmap entry also never gets cleared, so subsequent ath12k_peer_ml_alloc() calls eventually run out of IDs. The ID without the VALID bit is what ath12k_peer_ml_alloc() returned and is stored in ahsta->ml_peer_id. Use that instead. While there, also reset ahsta->ml_peer_id to ATH12K_MLO_PEER_ID_INVALID so the bitmap and ahsta->ml_peer_id stay in sync. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Fixes: ee16dcf573d5 ("wifi: ath12k: Define ath12k_dp_peer structure & APIs for create & delete") Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-1-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
11 dayscpufreq: powernow-k8: Fix possible memory leak in powernowk8_cpu_init()Abdun Nihaal
The memory allocated for data->powernow_table inside powernow_k8_cpu_init_acpi() or find_psb_table() is not freed in one of the error paths in powernowk8_cpu_init(). Fix that by adding a kfree(). Fixes: 1ff6e97f1d99 ("[CPUFREQ] cpumask: avoid playing with cpus_allowed in powernow-k8.c") Cc: stable@vger.kernel.org Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com> Link: https://patch.msgid.link/20260727093553.98246-1-nihaal@cse.iitm.ac.in Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
11 daysmmc: host: Remove redundant dev_err()/dev_err_probe()Pan Chuang
Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() and devm_request_threaded_irq() automatically log detailed error messages on failure. Remove the now-redundant driver-specific dev_err() and dev_err_probe() calls. Signed-off-by: Pan Chuang <panchuang@vivo.com> Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulfh@kernel.org>
11 dayspinctrl: qcom: ipq9650: fix audio_sec_mclk_in1/out1 group pinsTaceddin Sancak
The audio_sec_mclk_in1 and audio_sec_mclk_out1 groups both list "gpio37", but in the pingroup table those functions are muxed on gpio39, while gpio37 provides the audio_sec_mclk_in0/out0 variants. This makes both functions unusable: selecting them on gpio39 is rejected by the pinmux core because the group is not listed for the function, and selecting them on gpio37 trips the WARN_ON() in msm_pinmux_set_mux() and fails with -EINVAL because that group cannot mux them. Point both groups at gpio39, matching the pingroup table. This also mirrors the primary audio MCLK pair, where the mclk0 and mclk1 variants live on separate pins (gpio53 and gpio51 respectively). Fixes: 3c8e7ba0e399 ("pinctrl: qcom: Introduce IPQ9650 TLMM driver") Assisted-by: Claude:claude-fable-5 Signed-off-by: Taceddin Sancak <ts.solidarity@gmail.com> Acked-by: Linus Walleij <linusw@kernel.org> Reviewed-by: Kathiravan Thirumoorthy <kathiravan.thirumoorthy@oss.qualcomm.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Link: https://patch.msgid.link/20260718002146.698973-1-ts.solidarity@gmail.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
11 daysPull zisofs bh leak fix.Jan Kara
11 daysisofs: release zisofs block pointer buffer headYichong Chen
zisofs_fill_pages() reads the compressed block pointer table. The error paths release the current buffer_head, the loop also releases the old buffer_head when it advances. However, the success path leaves the last buffer_head referenced. Release it before returning success. Fixes: 59bc055211b8 ("zisofs: Implement reading of compressed files when PAGE_CACHE_SIZE > compress block size") Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Link: https://patch.msgid.link/20260721091152.1450622-1-chenyichong@uniontech.com Signed-off-by: Jan Kara <jack@suse.cz>
11 dayspowercap: intel_rapl_tpmi: Handle PMU registration failure during probeSumeet Pawnikar
intel_rapl_tpmi_probe() invokes rapl_package_add_pmu() but ignores its return value, so a PMU registration failure would leave the driver reporting probe success despite the PMU being absent, with no log trace. Since PMU registration is an optional auxiliary feature for perf energy counters, its failure should not break the primary powercap functionality. Check the return value and log a warning to ensure graceful degradation. Fixes: 963a9ad3c589 ("powercap: intel_rapl_tpmi: Enable PMU support") Signed-off-by: Sumeet Pawnikar <sumeet4linux@gmail.com> [ rjw: Changed the log level of the new message to "info" ] Link: https://patch.msgid.link/20260723172321.5960-1-sumeet4linux@gmail.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
11 daysMerge patch series "fs: Fix missed inode write during fsync"Christian Brauner
Jan Kara <jack@suse.cz> says: The series strives to make sure sync_inode_metadata() -> writeback_single_inode() will end up to properly persisting not only the inode but also all metadata associated with the inode. This is beneficial for several reasons: 1) This removes the need for separate mmb_fsync() implementations. Filesystems can just use simple_fsync(). 2) This makes sure all metadata is written for IS_SYNC / IS_DIRSYNC inodes. Currently most filesystems just write inode itself. 3) This fixes races when multiple fsyncs race for a while where mmb_sync() could return before all buffers were really persisted (now I_SYNC state flag properly serializes everything). To be able to achieve this we add new .sync_inode_metadata superblock operation which gets called from __writeback_single_inode() and new I_METADATA_WRITEBACK state flag (putting everything into .write_inode is possible but it looked too ugly so I've decided for the new operation). This scheme with I_METADATA_WRITEBACK state flag also fixes the problem that when WB_SYNC_NONE writeback happened between write(2) and fsync(2), fsync(2) would fail to properly persist the inode. Note that this problem isn't specific to filesystems using the generic metadata bh tracking. This patch set doesn't fix such filesystems as it is already big enough but the universality of this problem among simple filesystems is another reason why I've chosen the new superblock operation instead of trying to somehow hack up metadata bh tracking infrastructure. * patches from https://patch.msgid.link/20260727101509.21667-1-jack@suse.cz: 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 ext4: Allocate mapping_metadata_bhs struct on demand fs: Fix missed inode writeback when racing with __writeback_single_inode fs: Fix possible UAF in mark_buffer_write_io_error() affs: Drop support for metadata bh tracking Link: https://patch.msgid.link/20260727101509.21667-1-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysvfs: Remove mmb_fsync()Jan Kara
Now that everybody has been converted from mmb_fsync() (and it's variant mmb_fsync_noflush()) to simple_fsync(), we can delete these calls. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-40-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfat: Replace fat_sync_inode() with sync_inode_metadata()Jan Kara
Use generic sync_inode_metadata() instead of fat_sync_inode() for persisting inode metadata changes for DIRSYNC inodes. This slightly simplifies code and also addresses a theoretical race where fat_sync_inode() could return before all metadata buffers associated with the inode were properly written out when racing with fsync(2). Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-39-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfat: Fix missed inode writeback during fsync(2)Jan Kara
FAT could fail to properly write out inode on fsync(2) due to races with WB_SYNC_NONE writeback. Several racing fsyncs could also result in some fsync returning earlier than all metadata buffers were properly persisted. Fix these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback. The slight disadvantage of this approach is that when fsync(2) of an inode races with rename(2) of the inode, the window during which inode isn't properly persisted becomes wider. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-38-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext4: Fix data integrity writeout issues in nojournal modeJan Kara
Several racing fsyncs on ext4 in nojournal mode could result in some fsync returning earlier than all metadata buffers were properly persisted. Also ext4_fsync() in nojournal mode was somewhat inefficient because it was always writing out the inode regardless whether it was dirty or not. Fix these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback in nojournal mode. This also somewhat simplifies the nojournal mode fsync handling. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-37-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysminix: Fix data integrity writeout issuesJan Kara
Minix could fail to properly write out inode on fsync(2) due to races with WB_SYNC_NONE writeback. Several racing fsyncs could also result in some fsync returning earlier than all metadata buffers were properly persisted. Furthermore DIRSYNC handling missed writing inode related metadata. Fix all these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-36-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysbfs: Fix data integrity writeout issuesJan Kara
BFS could fail to properly write out inode on fsync(2) due to races with WB_SYNC_NONE writeback. Several racing fsyncs could also result in some fsync returning earlier than all metadata buffers were properly persisted. Fix all these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-35-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysudf: Fold udf_update_inode() into udf_write_inode()Jan Kara
There is no point in udf_update_inode() anymore as it has a single caller. Just fold udf_update_inode() into it. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-34-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysudf: Use sync_inode_metadata() in udf_evict_inode()Jan Kara
Instead of opencoding inode update in udf_evict_inode() just use sync_inode_metadata(). Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-33-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysudf: Drop udf_sync_inode()Jan Kara
The only place using udf_sync_inode() is now inode_getblk() for flushing IS_SYNC inodes after write and page_mkwrite allocating blocks. For write the flushing is actually taken care of by generic_write_sync() so it isn't needed here. For page_mkwrite it does have effect however none of the other filesystems seem to bother with flushing IS_SYNC inode on page fault and properly synchronizing such writeback with standard inode writeback would be slightly complex due to locking constraints. So just drop IS_SYNC inode handling from inode_getblk(). Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-32-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysudf: Use sync_inode_metadata() to writeout IS_SYNC inodeJan Kara
When setting inode size we directly writeout inode in udf_setsize(). This misses proper writeout of other inode related metadata. Use sync_inode_metadata() instead and move the flushing to udf_setattr() to avoid it for udf_evict_inode() where it would be pointless. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-31-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysudf: Fix data integrity writeout issuesJan Kara
UDF could fail to properly write out inode on fsync(2) due to races with WB_SYNC_NONE writeback. Several racing fsyncs could also result in some fsync returning earlier than all metadata buffers were properly persisted. Fix all these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-30-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext2: Fix data integrity writeout issuesJan Kara
Ext2 could fail to properly write out inode on fsync(2) due to races with WB_SYNC_NONE writeback. Several racing fsyncs could also result in some fsync returning earlier than all metadata buffers were properly persisted. Finally DIRSYNC handling was not properly persisting all inode related metadata. Fix all these issues by using new .sync_inode_metadata method which makes sure all inode related metadata is written to disk during any WB_SYNC_ALL writeback. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-29-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext2: Avoid unnecessary inode buffer writeback for sync(2)Jan Kara
For sync(2) the generic code calls sync_blockdev_nowait() and later sync_blockdev() to persist all metadata buffers. Thus there's no need for ext2_write_inode() to do that which speeds up sync(2) writeback. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-28-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext2: Drop __ext2_write_inode()Jan Kara
Fold special helper __ext2_write_inode() into ext2_write_inode() and just learn the single caller of __ext2_write_inode() to pass proper wbc instead. No functional changes. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-27-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext2: Fix lost inode updates for IS_SYNC inodesJan Kara
ext2_setsize() and ext2_xattr_set2() had a construct like: if (IS_SYNC(inode)) { sync_inode_metadata(inode, 1); } else { mark_inode_dirty(inode); } which leads to lost inode updates for IS_SYNC inodes because sync_inode_metadata() does anything only if the inode is already dirty and hence inode updates may be simply lost. Fix the problem by unconditionally marking the inode dirty and *then* call sync_inode_metadata(). CC: stable@vger.kernel.org Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-26-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: Provide way for filesystem to wait for metadata writebackJan Kara
Currently, inode and in general metadata writeback is handled in a lazy manner. When inode is dirty, __writeback_single_inode() calls .write_inode method which for lots of filesystems just copies inode metadata into the underlying block buffer. Writeback of other metadata associated with the inode (as well as buffers underlying inodes) is usually handled completely separately and implicitely during writeback of block device inode. This is good for efficiency of WB_SYNC_NONE writeback or sync(2). However it becomes problematic for situations where we want to make sure inode and its metadata is really persistent on disk. fsync(2) is the most pronounced example of this and thus we have grown a special file operation and various helper functions to assist with this task. However fsync(2) is not the only case, For example directories with DIRSYNC flag need similar functionality and current use of sync_inode_metadata() for this task in filesystems generally misses writeout of necessary metadata. Furthermore even fsync(2) handling as implemented by simple_fsync() or similar helpers is racy and can fail to properly persist the inode. The problem is that WB_SYNC_NONE writeback can copy inode metadata into underlying buffer and clean inode dirty bits. Following fsync(2) will see inode is clean and will fail to make sure underlying buffer is written out. When multiple fsync(2) calls race, there's also another type of race involving mmb_fsync(). There the problem is buffers already submitted to the disk are no longer tracked in the mmb list and so racing mmb_sync() can return before all of the IO completes. Provide a new inode state bit I_METADATA_WRITEBACK tracking whether writeback of inode related metadata may be needed for successful data integrity sync and if this bit is set __writeback_single_inode() for data integrity writeback will call new superblock operation .sync_inode_metadata whose task is to make sure all metadata associated with the inode (including the inode itself) is properly persisted. This will allow filesystems to address the data integrity issues described above and at the same time somewhat simplify our fsync implementations. Issues with racing fsync(2) calls will be addressed by synchronization on I_SYNC inode state which is set while calling .sync_inode_metadata, issues with missed inode buffer writeback are fixed by filesystems looking up corresponding buffer head and writing it out if needed. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-25-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysext4: Allocate mapping_metadata_bhs struct on demandJan Kara
Currently every ext4 inode gets mapping_metadata_bhs struct although it is only needed when running without a journal and only for inodes where any metadata was dirtied. Allocate mapping_metadata_bhs struct on demand when dirtying the first metadata buffer for the inode. Acked-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-24-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
11 daysfs: Fix missed inode writeback when racing with __writeback_single_inodeJan Kara
When mmb_fsync_noflush() or simple_fsync_noflush() race with another writeback of the same inode, they can see inode dirty bits are already clear and skip inode writeback although the racing __writeback_single_inode() didn't yet get to writing anything. This can result in fsync(2) returning without properly persisting the inode. We already have I_SYNC bit for this synchronization and writeback_single_inode() properly uses it so just fix mmb_fsync_noflush() and simple_fsync_noflush() to take it into account as well. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260727104923.3828017-23-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>