From: Linus Torvalds Date: Tue, 21 Apr 2026 14:30:44 +0000 (-0700) Subject: Merge tag 'pull-dcache-busy-wait' of git://git.kernel.org/pub/scm/linux/kernel/git... X-Git-Tag: v7.1-rc1~62 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=292a2bcd172662c7f281a7d79b095c91101c2e32;p=thirdparty%2Flinux.git Merge tag 'pull-dcache-busy-wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs Pull dcache busy loop updates from Al Viro: "Fix livelocks in shrink_dcache_tree() If shrink_dcache_tree() finds a dentry in the middle of being killed by another thread, it has to wait until the victim finishes dying, gets detached from the tree and ceases to pin its parent. The way we used to deal with that amounted to busy-wait; unfortunately, it's not just inefficient but can lead to reliably reproducible hard livelocks. Solved by having shrink_dentry_tree() attach a completion to such dentry, with dentry_unlist() calling complete() on all objects attached to it. With a bit of care it can be done without growing struct dentry or adding overhead in normal case" * tag 'pull-dcache-busy-wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: get rid of busy-waiting in shrink_dcache_tree() dcache.c: more idiomatic "positives are not allowed" sanity checks struct dentry: make ->d_u anonymous for_each_alias(): helper macro for iterating through dentries of given inode --- 292a2bcd172662c7f281a7d79b095c91101c2e32 diff --cc Documentation/filesystems/porting.rst index d02aa57e44775,9a9babd9ec486..fdf074429cd3a --- a/Documentation/filesystems/porting.rst +++ b/Documentation/filesystems/porting.rst @@@ -1364,14 -1364,10 +1364,24 @@@ lifetime, consider using inode_set_cach --- +**mandatory** + +lookup_one_qstr_excl() is no longer exported - use start_creating() or +similar. ++ +--- + +** mandatory** + +lock_rename(), lock_rename_child(), unlock_rename() are no +longer available. Use start_renaming() or similar. + ++--- ++ + **recommended** + + If you really need to iterate through dentries for given inode, use + for_each_alias(dentry, inode) instead of hlist_for_each_entry; better + yet, see if any of the exported primitives could be used instead of + the entire loop. You still need to hold ->i_lock of the inode over + either form of manual loop. diff --cc fs/affs/amigaffs.c index ee512baf57e5a,91966b1f41f64..bed4fc805e8e6 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@@ -126,9 -126,9 +126,9 @@@ affs_fix_dcache(struct inode *inode, u3 { struct dentry *dentry; spin_lock(&inode->i_lock); - hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + for_each_alias(dentry, inode) { if (entry_ino == (u32)(long)dentry->d_fsdata) { - dentry->d_fsdata = (void *)inode->i_ino; + dentry->d_fsdata = (void *)(unsigned long)inode->i_ino; break; } } diff --cc fs/inode.c index 69e219f0cfcbe,9e1ab333d3825..6a3cbc7dcd28c --- a/fs/inode.c +++ b/fs/inode.c @@@ -750,10 -754,10 +750,10 @@@ void dump_mapping(const struct address_ return; } - dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias); + dentry_ptr = container_of(dentry_first, struct dentry, d_alias); if (get_kernel_nofault(dentry, dentry_ptr) || !dentry.d_parent || !dentry.d_name.name) { - pr_warn("aops:%ps ino:%lx invalid dentry:%px\n", + pr_warn("aops:%ps ino:%llx invalid dentry:%px\n", a_ops, ino, dentry_ptr); return; }