]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
for_each_alias(): helper macro for iterating through dentries of given inode
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 24 Jan 2026 22:58:48 +0000 (17:58 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 2 Apr 2026 07:45:02 +0000 (03:45 -0400)
Most of the places using d_alias are loops iterating through all aliases for
given inode; introduce a helper macro (for_each_alias(dentry, inode))
and convert open-coded instances of such loop to it.

They are easier to read that way and it reduces the noise on the next steps.

You _must_ hold inode->i_lock over that thing.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Documentation/filesystems/porting.rst
fs/affs/amigaffs.c
fs/ceph/mds_client.c
fs/dcache.c
fs/exportfs/expfs.c
fs/nfs/dir.c
fs/notify/fsnotify.c
fs/ocfs2/dcache.c
fs/overlayfs/dir.c
fs/smb/client/inode.c
include/linux/dcache.h

index 52ff1d19405beb8add035c9b305ec8a18e134b7a..9a9babd9ec4869447582c29e68038bdd69ddee6f 100644 (file)
@@ -1361,3 +1361,13 @@ to match what strlen() would return if it was ran on the string.
 
 However, if the string is freely accessible for the duration of inode's
 lifetime, consider using inode_set_cached_link() instead.
+
+---
+
+**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.
index fd669daa4e7bc951d8d7959c7a5ab1b60b75c61a..91966b1f41f64c75aa6c756376bda2ecaff0af41 100644 (file)
@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
        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;
                        break;
index b1746273f1863a5ad75fbaa7d8d628aaaaebe12d..f839109fb66f26231203c9b7d9509f3bf7390a86 100644 (file)
@@ -4614,7 +4614,7 @@ static struct dentry* d_find_primary(struct inode *inode)
                goto out_unlock;
        }
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(alias, inode) {
                spin_lock(&alias->d_lock);
                if (!d_unhashed(alias) &&
                    (ceph_dentry(alias)->flags & CEPH_DENTRY_PRIMARY_LINK)) {
index 7ba1801d81329942a38268cd5c69d2e3e3f2f613..e069b6ec4ec049f286790e752833cb638ab07c6a 100644 (file)
@@ -790,7 +790,7 @@ void d_mark_dontcache(struct inode *inode)
        struct dentry *de;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(de, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(de, inode) {
                spin_lock(&de->d_lock);
                de->d_flags |= DCACHE_DONTCACHE;
                spin_unlock(&de->d_lock);
@@ -1040,7 +1040,7 @@ static struct dentry *__d_find_alias(struct inode *inode)
        if (S_ISDIR(inode->i_mode))
                return __d_find_any_alias(inode);
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(alias, inode) {
                spin_lock(&alias->d_lock);
                if (!d_unhashed(alias)) {
                        dget_dlock(alias);
@@ -1133,7 +1133,7 @@ void d_prune_aliases(struct inode *inode)
        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)
                d_dispose_if_unused(dentry, &dispose);
        spin_unlock(&inode->i_lock);
        shrink_dentry_list(&dispose);
index 6c9be60a3e48dc5e984a826029375550d1494835..f67b3ce672fccf7b123bdb5c6181382b90292b78 100644 (file)
@@ -52,7 +52,7 @@ find_acceptable_alias(struct dentry *result,
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(dentry, inode) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
index 2402f57c8e7d932c4656a1439f1deff7954e0dc4..5a0bd8113e3a3202a9ba30432277e88d401688a1 100644 (file)
@@ -1471,7 +1471,7 @@ static void nfs_clear_verifier_file(struct inode *inode)
        struct dentry *alias;
        struct inode *dir;
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(alias, inode) {
                spin_lock(&alias->d_lock);
                dir = d_inode_rcu(alias->d_parent);
                if (!dir ||
index 9995de1710e59696ef708763488e739a2428ef4f..b7198c4744e3a41187f0130928632dba432f3bd4 100644 (file)
@@ -76,7 +76,7 @@ void fsnotify_set_children_dentry_flags(struct inode *inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(alias, inode) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
index c4ba968e778bf1eb26d608c10a7337da00d8c4c5..e06774fd89d8230d79965a7da1507065906a3f02 100644 (file)
@@ -145,7 +145,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
        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) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
index ff3dbd1ca61f280d1495bb52182a2da9a6b28119..f8dfa534b5666da14820f9745daa981a4f0413d5 100644 (file)
@@ -904,7 +904,7 @@ static void ovl_drop_nlink(struct dentry *dentry)
 
        /* Try to find another, hashed alias */
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
+       for_each_alias(alias, inode) {
                if (alias != dentry && !d_unhashed(alias))
                        break;
        }
index 888f9e35f14b8add0809d40ad0918f37c0f3d983..e2b4ad9bd0bdbb627a0ae863644fb7738d27dd48 100644 (file)
@@ -1595,7 +1595,7 @@ inode_has_hashed_dentries(struct inode *inode)
        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 (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
index 898c60d21c92b1792c9b1543d11cecaf4e70bcf8..7f1dbc7121d7c72238e65add6311cc290474d63f 100644 (file)
@@ -615,4 +615,8 @@ void set_default_d_op(struct super_block *, const struct dentry_operations *);
 struct dentry *d_make_persistent(struct dentry *, struct inode *);
 void d_make_discardable(struct dentry *dentry);
 
+/* inode->i_lock must be held over that */
+#define for_each_alias(dentry, inode) \
+       hlist_for_each_entry(dentry, &(inode)->i_dentry, d_u.d_alias)
+
 #endif /* __LINUX_DCACHE_H */