[PATCH v2 17/18] autofs: replace positive_after() with d_scan_positives()

NeilBrown <[email protected]>
Newsgroups gmane.linux.file-systems,gmane.linux.kernel.autofs,gmane.linux.kernel,gmane.comp.file-systems.ceph.devel,gmane.comp.file-systems.coda.general,gmane.linux.nfs
Message-ID <[email protected]>
From: NeilBrown <[email protected]>

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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.