[PATCH v2 17/18] autofs: replace positive_after() with d_scan_positives()
From: NeilBrown
Date: Sat Aug 15 2026 - 00:36:26 EST
From: NeilBrown <neil@xxxxxxxxxx>
Now that d_scan_positives() is exported, autofs can use it.
An important difference from positive_after() is that d_scan_positives()
drop the ref to the "prev" dentry. This means that
get_next_positive_dentry() must take a reference to the new parent
when stepping up, using dget_parent(), but otherwise
allows that function to be significantly simplified.
The while() loop looks a little unbalanced as there is a dget_parent
without a dput. However when d_scan_positives() returns NULL, it will
have done a dput without a dget, which provides the required balance.
The dput(prev) at the end now doesn't (necessary) dput() the original
"prev", but instead dput()s the parent of the returned dentry.
Note that d_scan_positives() requires the caller to protect against
renames. autofs doesn't need to take any action because it doesn't
support rename at all.
Signed-off-by: NeilBrown <neil@xxxxxxxxxx>
---
fs/autofs/expire.c | 51 +++++++++++-----------------------------------
1 file changed, 12 insertions(+), 39 deletions(-)
diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index b6937c5936a5..277d9129754e 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -70,53 +70,26 @@ static int autofs_mount_busy(struct vfsmount *mnt,
return status;
}
-static struct dentry *positive_after(struct dentry *p, struct dentry *child)
-{
- d_for_each_positive_child_continue(child, p) {
- spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
- if (simple_positive(child)) {
- dget_dlock(child);
- spin_unlock(&child->d_lock);
- return child;
- }
- spin_unlock(&child->d_lock);
- }
- return NULL;
-}
-
/*
- * Calculate and dget next entry in the subdirs list under root.
- */
-static struct dentry *get_next_positive_subdir(struct dentry *prev,
- struct dentry *root)
-{
- struct dentry *q;
-
- q = positive_after(root, prev);
- dput(prev);
- return q;
-}
-
-/*
- * Calculate and dget next entry in top down tree traversal.
+ * Calculate and dget() next entry in top down tree traversal,
+ * and dput() the previous dentry. If there are no positive
+ * children, we stop up to the parent and look for next
+ * sibling.
+ * As autofs does not support rename, there is no risk
+ * for the parent changing before we step up.
*/
static struct dentry *get_next_positive_dentry(struct dentry *prev,
struct dentry *root)
{
- struct dentry *p = prev, *ret = NULL, *d = NULL;
+ struct dentry *ret = NULL;
if (prev == NULL)
return dget(root);
- while (1) {
- struct dentry *parent;
-
- ret = positive_after(p, d);
- if (ret || p == root)
- break;
- parent = p->d_parent;
- d = p;
- p = parent;
+ while ((ret = d_scan_positives(prev, ret, 0)) == NULL &&
+ prev != root) {
+ ret = prev;
+ prev = dget_parent(prev);
}
dput(prev);
return ret;
@@ -414,7 +387,7 @@ static struct dentry *autofs_expire_indirect(struct super_block *sb,
return NULL;
dentry = NULL;
- while ((dentry = get_next_positive_subdir(dentry, root))) {
+ while ((dentry = d_scan_positives(root, dentry, 0))) {
spin_lock(&sbi->fs_lock);
ino = autofs_dentry_ino(dentry);
if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
--
2.50.0.107.gf914562f5916.dirty