diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index bb4969ce87..3588799b27 100644 --- a/src/afs/LINUX/osi_compat.h +++ b/src/afs/LINUX/osi_compat.h @@ -776,4 +776,46 @@ afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs) #endif } +/* + * afs_d_alias_foreach - Iterate over dentry aliases of an inode. Use like this: + * + * afs_d_alias_lock(inode); + * afs_d_alias_foreach(dentry, inode, node) { + * spin_lock(&dentry->d_lock); + * dentry->d_foo = bar; + * spin_unlock(&dentry->d_lock); + * } + * afs_d_alias_unlock(inode); + * + * 'node' is a struct hlist_node, and is only used when D_ALIAS_IS_HLIST && + * !HLIST_ITERATOR_NO_NODE. + * + * afs_d_alias_foreach_reverse is the same, but traverses the list in the + * reverse direction when possible (non-D_ALIAS_IS_HLIST). For + * D_ALIAS_IS_HLIST, Linux doesn't provide macros for going in reverse (struct + * hlist_head doesn't point directly to the end of the list), so just traverse + * forwards. + * + * @pre afs_d_alias_lock(inode) held + */ +#if defined(D_ALIAS_IS_HLIST) + +# if defined(HLIST_ITERATOR_NO_NODE) +# define afs_d_alias_foreach(dentry, inode, node) \ + hlist_for_each_entry((dentry), &((inode)->i_dentry), d_alias) +# else +# define afs_d_alias_foreach(dentry, inode, node) \ + hlist_for_each_entry((dentry), (node), &((inode)->i_dentry), d_alias) +# endif /* HLIST_ITERATOR_NO_NODE */ +# define afs_d_alias_foreach_reverse afs_d_alias_foreach + +#else /* D_ALIAS_IS_HLIST */ + +# define afs_d_alias_foreach(dentry, inode, node) \ + list_for_each_entry((dentry), &((inode)->i_dentry), d_alias) +# define afs_d_alias_foreach_reverse(dentry, inode, node) \ + list_for_each_entry_reverse((dentry), &((inode)->i_dentry), d_alias) + +#endif /* D_ALIAS_IS_HLIST */ + #endif /* AFS_LINUX_OSI_COMPAT_H */ diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index b42f3c2aed..38fd3b4b8d 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -26,15 +26,7 @@ TryEvictDirDentries(struct inode *inode) afs_d_alias_lock(inode); restart: -#if defined(D_ALIAS_IS_HLIST) -# if defined(HLIST_ITERATOR_NO_NODE) - hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { -# else - hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { -# endif -#else - list_for_each_entry(dentry, &inode->i_dentry, d_alias) { -#endif + afs_d_alias_foreach(dentry, inode, p) { spin_lock(&dentry->d_lock); if (d_unhashed(dentry)) { spin_unlock(&dentry->d_lock); diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 2c5439dfd0..89f771afc5 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -994,16 +994,7 @@ canonical_dentry(struct inode *ip) afs_d_alias_lock(ip); -#if defined(D_ALIAS_IS_HLIST) -# if defined(HLIST_ITERATOR_NO_NODE) - hlist_for_each_entry(cur, &ip->i_dentry, d_alias) { -# else - hlist_for_each_entry(cur, p, &ip->i_dentry, d_alias) { -# endif -#else - list_for_each_entry_reverse(cur, &ip->i_dentry, d_alias) { -#endif - + afs_d_alias_foreach_reverse(cur, ip, p) { if (!vcp->target_link || cur == vcp->target_link) { ret = cur; break;