[PATCH v2 17/18] autofs: replace positive_after() with d_scan_positives()
NeilBrown <[email protected]>
| Newsgroups | org.kernel.vger.ceph-devel,org.kernel.vger.autofs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.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