162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
462306a36Sopenharmony_ci * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
562306a36Sopenharmony_ci * Copyright 2001-2006 Ian Kent <raven@themaw.net>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "autofs_i.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* Check if a dentry can be expired */
1162306a36Sopenharmony_cistatic inline int autofs_can_expire(struct dentry *dentry,
1262306a36Sopenharmony_ci				    unsigned long timeout, unsigned int how)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	/* dentry in the process of being deleted */
1762306a36Sopenharmony_ci	if (ino == NULL)
1862306a36Sopenharmony_ci		return 0;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	if (!(how & AUTOFS_EXP_IMMEDIATE)) {
2162306a36Sopenharmony_ci		/* Too young to die */
2262306a36Sopenharmony_ci		if (!timeout || time_after(ino->last_used + timeout, jiffies))
2362306a36Sopenharmony_ci			return 0;
2462306a36Sopenharmony_ci	}
2562306a36Sopenharmony_ci	return 1;
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* Check a mount point for busyness */
2962306a36Sopenharmony_cistatic int autofs_mount_busy(struct vfsmount *mnt,
3062306a36Sopenharmony_ci			     struct dentry *dentry, unsigned int how)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct dentry *top = dentry;
3362306a36Sopenharmony_ci	struct path path = {.mnt = mnt, .dentry = dentry};
3462306a36Sopenharmony_ci	int status = 1;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	pr_debug("dentry %p %pd\n", dentry, dentry);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	path_get(&path);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (!follow_down_one(&path))
4162306a36Sopenharmony_ci		goto done;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (is_autofs_dentry(path.dentry)) {
4462306a36Sopenharmony_ci		struct autofs_sb_info *sbi = autofs_sbi(path.dentry->d_sb);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		/* This is an autofs submount, we can't expire it */
4762306a36Sopenharmony_ci		if (autofs_type_indirect(sbi->type))
4862306a36Sopenharmony_ci			goto done;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* Not a submount, has a forced expire been requested */
5262306a36Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED) {
5362306a36Sopenharmony_ci		status = 0;
5462306a36Sopenharmony_ci		goto done;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* Update the expiry counter if fs is busy */
5862306a36Sopenharmony_ci	if (!may_umount_tree(path.mnt)) {
5962306a36Sopenharmony_ci		struct autofs_info *ino;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci		ino = autofs_dentry_ino(top);
6262306a36Sopenharmony_ci		ino->last_used = jiffies;
6362306a36Sopenharmony_ci		goto done;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	status = 0;
6762306a36Sopenharmony_cidone:
6862306a36Sopenharmony_ci	pr_debug("returning = %d\n", status);
6962306a36Sopenharmony_ci	path_put(&path);
7062306a36Sopenharmony_ci	return status;
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* p->d_lock held */
7462306a36Sopenharmony_cistatic struct dentry *positive_after(struct dentry *p, struct dentry *child)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	if (child)
7762306a36Sopenharmony_ci		child = list_next_entry(child, d_child);
7862306a36Sopenharmony_ci	else
7962306a36Sopenharmony_ci		child = list_first_entry(&p->d_subdirs, struct dentry, d_child);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	list_for_each_entry_from(child, &p->d_subdirs, d_child) {
8262306a36Sopenharmony_ci		spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
8362306a36Sopenharmony_ci		if (simple_positive(child)) {
8462306a36Sopenharmony_ci			dget_dlock(child);
8562306a36Sopenharmony_ci			spin_unlock(&child->d_lock);
8662306a36Sopenharmony_ci			return child;
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci		spin_unlock(&child->d_lock);
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	return NULL;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/*
9562306a36Sopenharmony_ci * Calculate and dget next entry in the subdirs list under root.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_cistatic struct dentry *get_next_positive_subdir(struct dentry *prev,
9862306a36Sopenharmony_ci					       struct dentry *root)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
10162306a36Sopenharmony_ci	struct dentry *q;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	spin_lock(&sbi->lookup_lock);
10462306a36Sopenharmony_ci	spin_lock(&root->d_lock);
10562306a36Sopenharmony_ci	q = positive_after(root, prev);
10662306a36Sopenharmony_ci	spin_unlock(&root->d_lock);
10762306a36Sopenharmony_ci	spin_unlock(&sbi->lookup_lock);
10862306a36Sopenharmony_ci	dput(prev);
10962306a36Sopenharmony_ci	return q;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/*
11362306a36Sopenharmony_ci * Calculate and dget next entry in top down tree traversal.
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_cistatic struct dentry *get_next_positive_dentry(struct dentry *prev,
11662306a36Sopenharmony_ci					       struct dentry *root)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
11962306a36Sopenharmony_ci	struct dentry *p = prev, *ret = NULL, *d = NULL;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	if (prev == NULL)
12262306a36Sopenharmony_ci		return dget(root);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	spin_lock(&sbi->lookup_lock);
12562306a36Sopenharmony_ci	spin_lock(&p->d_lock);
12662306a36Sopenharmony_ci	while (1) {
12762306a36Sopenharmony_ci		struct dentry *parent;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		ret = positive_after(p, d);
13062306a36Sopenharmony_ci		if (ret || p == root)
13162306a36Sopenharmony_ci			break;
13262306a36Sopenharmony_ci		parent = p->d_parent;
13362306a36Sopenharmony_ci		spin_unlock(&p->d_lock);
13462306a36Sopenharmony_ci		spin_lock(&parent->d_lock);
13562306a36Sopenharmony_ci		d = p;
13662306a36Sopenharmony_ci		p = parent;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci	spin_unlock(&p->d_lock);
13962306a36Sopenharmony_ci	spin_unlock(&sbi->lookup_lock);
14062306a36Sopenharmony_ci	dput(prev);
14162306a36Sopenharmony_ci	return ret;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/*
14562306a36Sopenharmony_ci * Check a direct mount point for busyness.
14662306a36Sopenharmony_ci * Direct mounts have similar expiry semantics to tree mounts.
14762306a36Sopenharmony_ci * The tree is not busy iff no mountpoints are busy and there are no
14862306a36Sopenharmony_ci * autofs submounts.
14962306a36Sopenharmony_ci */
15062306a36Sopenharmony_cistatic int autofs_direct_busy(struct vfsmount *mnt,
15162306a36Sopenharmony_ci			      struct dentry *top,
15262306a36Sopenharmony_ci			      unsigned long timeout,
15362306a36Sopenharmony_ci			      unsigned int how)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	pr_debug("top %p %pd\n", top, top);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Forced expire, user space handles busy mounts */
15862306a36Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED)
15962306a36Sopenharmony_ci		return 0;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* If it's busy update the expiry counters */
16262306a36Sopenharmony_ci	if (!may_umount_tree(mnt)) {
16362306a36Sopenharmony_ci		struct autofs_info *ino;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci		ino = autofs_dentry_ino(top);
16662306a36Sopenharmony_ci		if (ino)
16762306a36Sopenharmony_ci			ino->last_used = jiffies;
16862306a36Sopenharmony_ci		return 1;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	/* Timeout of a direct mount is determined by its top dentry */
17262306a36Sopenharmony_ci	if (!autofs_can_expire(top, timeout, how))
17362306a36Sopenharmony_ci		return 1;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/*
17962306a36Sopenharmony_ci * Check a directory tree of mount points for busyness
18062306a36Sopenharmony_ci * The tree is not busy iff no mountpoints are busy
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_cistatic int autofs_tree_busy(struct vfsmount *mnt,
18362306a36Sopenharmony_ci			    struct dentry *top,
18462306a36Sopenharmony_ci			    unsigned long timeout,
18562306a36Sopenharmony_ci			    unsigned int how)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct autofs_info *top_ino = autofs_dentry_ino(top);
18862306a36Sopenharmony_ci	struct dentry *p;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	pr_debug("top %p %pd\n", top, top);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	/* Negative dentry - give up */
19362306a36Sopenharmony_ci	if (!simple_positive(top))
19462306a36Sopenharmony_ci		return 1;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	p = NULL;
19762306a36Sopenharmony_ci	while ((p = get_next_positive_dentry(p, top))) {
19862306a36Sopenharmony_ci		pr_debug("dentry %p %pd\n", p, p);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci		/*
20162306a36Sopenharmony_ci		 * Is someone visiting anywhere in the subtree ?
20262306a36Sopenharmony_ci		 * If there's no mount we need to check the usage
20362306a36Sopenharmony_ci		 * count for the autofs dentry.
20462306a36Sopenharmony_ci		 * If the fs is busy update the expiry counter.
20562306a36Sopenharmony_ci		 */
20662306a36Sopenharmony_ci		if (d_mountpoint(p)) {
20762306a36Sopenharmony_ci			if (autofs_mount_busy(mnt, p, how)) {
20862306a36Sopenharmony_ci				top_ino->last_used = jiffies;
20962306a36Sopenharmony_ci				dput(p);
21062306a36Sopenharmony_ci				return 1;
21162306a36Sopenharmony_ci			}
21262306a36Sopenharmony_ci		} else {
21362306a36Sopenharmony_ci			struct autofs_info *ino = autofs_dentry_ino(p);
21462306a36Sopenharmony_ci			unsigned int ino_count = READ_ONCE(ino->count);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci			/* allow for dget above and top is already dgot */
21762306a36Sopenharmony_ci			if (p == top)
21862306a36Sopenharmony_ci				ino_count += 2;
21962306a36Sopenharmony_ci			else
22062306a36Sopenharmony_ci				ino_count++;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci			if (d_count(p) > ino_count) {
22362306a36Sopenharmony_ci				top_ino->last_used = jiffies;
22462306a36Sopenharmony_ci				dput(p);
22562306a36Sopenharmony_ci				return 1;
22662306a36Sopenharmony_ci			}
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	/* Forced expire, user space handles busy mounts */
23162306a36Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED)
23262306a36Sopenharmony_ci		return 0;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	/* Timeout of a tree mount is ultimately determined by its top dentry */
23562306a36Sopenharmony_ci	if (!autofs_can_expire(top, timeout, how))
23662306a36Sopenharmony_ci		return 1;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	return 0;
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic struct dentry *autofs_check_leaves(struct vfsmount *mnt,
24262306a36Sopenharmony_ci					  struct dentry *parent,
24362306a36Sopenharmony_ci					  unsigned long timeout,
24462306a36Sopenharmony_ci					  unsigned int how)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	struct dentry *p;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	pr_debug("parent %p %pd\n", parent, parent);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	p = NULL;
25162306a36Sopenharmony_ci	while ((p = get_next_positive_dentry(p, parent))) {
25262306a36Sopenharmony_ci		pr_debug("dentry %p %pd\n", p, p);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		if (d_mountpoint(p)) {
25562306a36Sopenharmony_ci			/* Can we umount this guy */
25662306a36Sopenharmony_ci			if (autofs_mount_busy(mnt, p, how))
25762306a36Sopenharmony_ci				continue;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci			/* This isn't a submount so if a forced expire
26062306a36Sopenharmony_ci			 * has been requested, user space handles busy
26162306a36Sopenharmony_ci			 * mounts */
26262306a36Sopenharmony_ci			if (how & AUTOFS_EXP_FORCED)
26362306a36Sopenharmony_ci				return p;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci			/* Can we expire this guy */
26662306a36Sopenharmony_ci			if (autofs_can_expire(p, timeout, how))
26762306a36Sopenharmony_ci				return p;
26862306a36Sopenharmony_ci		}
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci	return NULL;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/* Check if we can expire a direct mount (possibly a tree) */
27462306a36Sopenharmony_cistatic struct dentry *autofs_expire_direct(struct super_block *sb,
27562306a36Sopenharmony_ci					   struct vfsmount *mnt,
27662306a36Sopenharmony_ci					   struct autofs_sb_info *sbi,
27762306a36Sopenharmony_ci					   unsigned int how)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct dentry *root = dget(sb->s_root);
28062306a36Sopenharmony_ci	struct autofs_info *ino;
28162306a36Sopenharmony_ci	unsigned long timeout;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (!root)
28462306a36Sopenharmony_ci		return NULL;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	timeout = sbi->exp_timeout;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	if (!autofs_direct_busy(mnt, root, timeout, how)) {
28962306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
29062306a36Sopenharmony_ci		ino = autofs_dentry_ino(root);
29162306a36Sopenharmony_ci		/* No point expiring a pending mount */
29262306a36Sopenharmony_ci		if (ino->flags & AUTOFS_INF_PENDING) {
29362306a36Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
29462306a36Sopenharmony_ci			goto out;
29562306a36Sopenharmony_ci		}
29662306a36Sopenharmony_ci		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
29762306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
29862306a36Sopenharmony_ci		synchronize_rcu();
29962306a36Sopenharmony_ci		if (!autofs_direct_busy(mnt, root, timeout, how)) {
30062306a36Sopenharmony_ci			spin_lock(&sbi->fs_lock);
30162306a36Sopenharmony_ci			ino->flags |= AUTOFS_INF_EXPIRING;
30262306a36Sopenharmony_ci			init_completion(&ino->expire_complete);
30362306a36Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
30462306a36Sopenharmony_ci			return root;
30562306a36Sopenharmony_ci		}
30662306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
30762306a36Sopenharmony_ci		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
30862306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ciout:
31162306a36Sopenharmony_ci	dput(root);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	return NULL;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci/* Check if 'dentry' should expire, or return a nearby
31762306a36Sopenharmony_ci * dentry that is suitable.
31862306a36Sopenharmony_ci * If returned dentry is different from arg dentry,
31962306a36Sopenharmony_ci * then a dget() reference was taken, else not.
32062306a36Sopenharmony_ci */
32162306a36Sopenharmony_cistatic struct dentry *should_expire(struct dentry *dentry,
32262306a36Sopenharmony_ci				    struct vfsmount *mnt,
32362306a36Sopenharmony_ci				    unsigned long timeout,
32462306a36Sopenharmony_ci				    unsigned int how)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
32762306a36Sopenharmony_ci	unsigned int ino_count;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	/* No point expiring a pending mount */
33062306a36Sopenharmony_ci	if (ino->flags & AUTOFS_INF_PENDING)
33162306a36Sopenharmony_ci		return NULL;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/*
33462306a36Sopenharmony_ci	 * Case 1: (i) indirect mount or top level pseudo direct mount
33562306a36Sopenharmony_ci	 *	   (autofs-4.1).
33662306a36Sopenharmony_ci	 *	   (ii) indirect mount with offset mount, check the "/"
33762306a36Sopenharmony_ci	 *	   offset (autofs-5.0+).
33862306a36Sopenharmony_ci	 */
33962306a36Sopenharmony_ci	if (d_mountpoint(dentry)) {
34062306a36Sopenharmony_ci		pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		/* Can we umount this guy */
34362306a36Sopenharmony_ci		if (autofs_mount_busy(mnt, dentry, how))
34462306a36Sopenharmony_ci			return NULL;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci		/* This isn't a submount so if a forced expire
34762306a36Sopenharmony_ci		 * has been requested, user space handles busy
34862306a36Sopenharmony_ci		 * mounts */
34962306a36Sopenharmony_ci		if (how & AUTOFS_EXP_FORCED)
35062306a36Sopenharmony_ci			return dentry;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		/* Can we expire this guy */
35362306a36Sopenharmony_ci		if (autofs_can_expire(dentry, timeout, how))
35462306a36Sopenharmony_ci			return dentry;
35562306a36Sopenharmony_ci		return NULL;
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	if (d_is_symlink(dentry)) {
35962306a36Sopenharmony_ci		pr_debug("checking symlink %p %pd\n", dentry, dentry);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		/* Forced expire, user space handles busy mounts */
36262306a36Sopenharmony_ci		if (how & AUTOFS_EXP_FORCED)
36362306a36Sopenharmony_ci			return dentry;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci		/*
36662306a36Sopenharmony_ci		 * A symlink can't be "busy" in the usual sense so
36762306a36Sopenharmony_ci		 * just check last used for expire timeout.
36862306a36Sopenharmony_ci		 */
36962306a36Sopenharmony_ci		if (autofs_can_expire(dentry, timeout, how))
37062306a36Sopenharmony_ci			return dentry;
37162306a36Sopenharmony_ci		return NULL;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (autofs_empty(ino))
37562306a36Sopenharmony_ci		return NULL;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* Case 2: tree mount, expire iff entire tree is not busy */
37862306a36Sopenharmony_ci	if (!(how & AUTOFS_EXP_LEAVES)) {
37962306a36Sopenharmony_ci		/* Not a forced expire? */
38062306a36Sopenharmony_ci		if (!(how & AUTOFS_EXP_FORCED)) {
38162306a36Sopenharmony_ci			/* ref-walk currently on this dentry? */
38262306a36Sopenharmony_ci			ino_count = READ_ONCE(ino->count) + 1;
38362306a36Sopenharmony_ci			if (d_count(dentry) > ino_count)
38462306a36Sopenharmony_ci				return NULL;
38562306a36Sopenharmony_ci		}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci		if (!autofs_tree_busy(mnt, dentry, timeout, how))
38862306a36Sopenharmony_ci			return dentry;
38962306a36Sopenharmony_ci	/*
39062306a36Sopenharmony_ci	 * Case 3: pseudo direct mount, expire individual leaves
39162306a36Sopenharmony_ci	 *	   (autofs-4.1).
39262306a36Sopenharmony_ci	 */
39362306a36Sopenharmony_ci	} else {
39462306a36Sopenharmony_ci		struct dentry *expired;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci		/* Not a forced expire? */
39762306a36Sopenharmony_ci		if (!(how & AUTOFS_EXP_FORCED)) {
39862306a36Sopenharmony_ci			/* ref-walk currently on this dentry? */
39962306a36Sopenharmony_ci			ino_count = READ_ONCE(ino->count) + 1;
40062306a36Sopenharmony_ci			if (d_count(dentry) > ino_count)
40162306a36Sopenharmony_ci				return NULL;
40262306a36Sopenharmony_ci		}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		expired = autofs_check_leaves(mnt, dentry, timeout, how);
40562306a36Sopenharmony_ci		if (expired) {
40662306a36Sopenharmony_ci			if (expired == dentry)
40762306a36Sopenharmony_ci				dput(dentry);
40862306a36Sopenharmony_ci			return expired;
40962306a36Sopenharmony_ci		}
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci	return NULL;
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci/*
41562306a36Sopenharmony_ci * Find an eligible tree to time-out
41662306a36Sopenharmony_ci * A tree is eligible if :-
41762306a36Sopenharmony_ci *  - it is unused by any user process
41862306a36Sopenharmony_ci *  - it has been unused for exp_timeout time
41962306a36Sopenharmony_ci */
42062306a36Sopenharmony_cistatic struct dentry *autofs_expire_indirect(struct super_block *sb,
42162306a36Sopenharmony_ci					     struct vfsmount *mnt,
42262306a36Sopenharmony_ci					     struct autofs_sb_info *sbi,
42362306a36Sopenharmony_ci					     unsigned int how)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	unsigned long timeout;
42662306a36Sopenharmony_ci	struct dentry *root = sb->s_root;
42762306a36Sopenharmony_ci	struct dentry *dentry;
42862306a36Sopenharmony_ci	struct dentry *expired;
42962306a36Sopenharmony_ci	struct dentry *found;
43062306a36Sopenharmony_ci	struct autofs_info *ino;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	if (!root)
43362306a36Sopenharmony_ci		return NULL;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	timeout = sbi->exp_timeout;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	dentry = NULL;
43862306a36Sopenharmony_ci	while ((dentry = get_next_positive_subdir(dentry, root))) {
43962306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
44062306a36Sopenharmony_ci		ino = autofs_dentry_ino(dentry);
44162306a36Sopenharmony_ci		if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
44262306a36Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
44362306a36Sopenharmony_ci			continue;
44462306a36Sopenharmony_ci		}
44562306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		expired = should_expire(dentry, mnt, timeout, how);
44862306a36Sopenharmony_ci		if (!expired)
44962306a36Sopenharmony_ci			continue;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
45262306a36Sopenharmony_ci		ino = autofs_dentry_ino(expired);
45362306a36Sopenharmony_ci		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
45462306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
45562306a36Sopenharmony_ci		synchronize_rcu();
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		/* Make sure a reference is not taken on found if
45862306a36Sopenharmony_ci		 * things have changed.
45962306a36Sopenharmony_ci		 */
46062306a36Sopenharmony_ci		how &= ~AUTOFS_EXP_LEAVES;
46162306a36Sopenharmony_ci		found = should_expire(expired, mnt, timeout, how);
46262306a36Sopenharmony_ci		if (found != expired) { // something has changed, continue
46362306a36Sopenharmony_ci			dput(found);
46462306a36Sopenharmony_ci			goto next;
46562306a36Sopenharmony_ci		}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci		if (expired != dentry)
46862306a36Sopenharmony_ci			dput(dentry);
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
47162306a36Sopenharmony_ci		goto found;
47262306a36Sopenharmony_cinext:
47362306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
47462306a36Sopenharmony_ci		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
47562306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
47662306a36Sopenharmony_ci		if (expired != dentry)
47762306a36Sopenharmony_ci			dput(expired);
47862306a36Sopenharmony_ci	}
47962306a36Sopenharmony_ci	return NULL;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cifound:
48262306a36Sopenharmony_ci	pr_debug("returning %p %pd\n", expired, expired);
48362306a36Sopenharmony_ci	ino->flags |= AUTOFS_INF_EXPIRING;
48462306a36Sopenharmony_ci	init_completion(&ino->expire_complete);
48562306a36Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
48662306a36Sopenharmony_ci	return expired;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ciint autofs_expire_wait(const struct path *path, int rcu_walk)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct dentry *dentry = path->dentry;
49262306a36Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
49362306a36Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
49462306a36Sopenharmony_ci	int status;
49562306a36Sopenharmony_ci	int state;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	/* Block on any pending expire */
49862306a36Sopenharmony_ci	if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
49962306a36Sopenharmony_ci		return 0;
50062306a36Sopenharmony_ci	if (rcu_walk)
50162306a36Sopenharmony_ci		return -ECHILD;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ciretry:
50462306a36Sopenharmony_ci	spin_lock(&sbi->fs_lock);
50562306a36Sopenharmony_ci	state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
50662306a36Sopenharmony_ci	if (state == AUTOFS_INF_WANT_EXPIRE) {
50762306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
50862306a36Sopenharmony_ci		/*
50962306a36Sopenharmony_ci		 * Possibly being selected for expire, wait until
51062306a36Sopenharmony_ci		 * it's selected or not.
51162306a36Sopenharmony_ci		 */
51262306a36Sopenharmony_ci		schedule_timeout_uninterruptible(HZ/10);
51362306a36Sopenharmony_ci		goto retry;
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci	if (state & AUTOFS_INF_EXPIRING) {
51662306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci		pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci		status = autofs_wait(sbi, path, NFY_NONE);
52162306a36Sopenharmony_ci		wait_for_completion(&ino->expire_complete);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci		pr_debug("expire done status=%d\n", status);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		if (d_unhashed(dentry))
52662306a36Sopenharmony_ci			return -EAGAIN;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci		return status;
52962306a36Sopenharmony_ci	}
53062306a36Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	return 0;
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci/* Perform an expiry operation */
53662306a36Sopenharmony_ciint autofs_expire_run(struct super_block *sb,
53762306a36Sopenharmony_ci		      struct vfsmount *mnt,
53862306a36Sopenharmony_ci		      struct autofs_sb_info *sbi,
53962306a36Sopenharmony_ci		      struct autofs_packet_expire __user *pkt_p)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	struct autofs_packet_expire pkt;
54262306a36Sopenharmony_ci	struct autofs_info *ino;
54362306a36Sopenharmony_ci	struct dentry *dentry;
54462306a36Sopenharmony_ci	int ret = 0;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	pkt.hdr.proto_version = sbi->version;
54962306a36Sopenharmony_ci	pkt.hdr.type = autofs_ptype_expire;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	dentry = autofs_expire_indirect(sb, mnt, sbi, 0);
55262306a36Sopenharmony_ci	if (!dentry)
55362306a36Sopenharmony_ci		return -EAGAIN;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	pkt.len = dentry->d_name.len;
55662306a36Sopenharmony_ci	memcpy(pkt.name, dentry->d_name.name, pkt.len);
55762306a36Sopenharmony_ci	pkt.name[pkt.len] = '\0';
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
56062306a36Sopenharmony_ci		ret = -EFAULT;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	spin_lock(&sbi->fs_lock);
56362306a36Sopenharmony_ci	ino = autofs_dentry_ino(dentry);
56462306a36Sopenharmony_ci	/* avoid rapid-fire expire attempts if expiry fails */
56562306a36Sopenharmony_ci	ino->last_used = jiffies;
56662306a36Sopenharmony_ci	ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
56762306a36Sopenharmony_ci	complete_all(&ino->expire_complete);
56862306a36Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	dput(dentry);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	return ret;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ciint autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
57662306a36Sopenharmony_ci			   struct autofs_sb_info *sbi, unsigned int how)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	struct dentry *dentry;
57962306a36Sopenharmony_ci	int ret = -EAGAIN;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	if (autofs_type_trigger(sbi->type))
58262306a36Sopenharmony_ci		dentry = autofs_expire_direct(sb, mnt, sbi, how);
58362306a36Sopenharmony_ci	else
58462306a36Sopenharmony_ci		dentry = autofs_expire_indirect(sb, mnt, sbi, how);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	if (dentry) {
58762306a36Sopenharmony_ci		struct autofs_info *ino = autofs_dentry_ino(dentry);
58862306a36Sopenharmony_ci		const struct path path = { .mnt = mnt, .dentry = dentry };
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci		/* This is synchronous because it makes the daemon a
59162306a36Sopenharmony_ci		 * little easier
59262306a36Sopenharmony_ci		 */
59362306a36Sopenharmony_ci		ret = autofs_wait(sbi, &path, NFY_EXPIRE);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		spin_lock(&sbi->fs_lock);
59662306a36Sopenharmony_ci		/* avoid rapid-fire expire attempts if expiry fails */
59762306a36Sopenharmony_ci		ino->last_used = jiffies;
59862306a36Sopenharmony_ci		ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
59962306a36Sopenharmony_ci		complete_all(&ino->expire_complete);
60062306a36Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
60162306a36Sopenharmony_ci		dput(dentry);
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return ret;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci/*
60862306a36Sopenharmony_ci * Call repeatedly until it returns -EAGAIN, meaning there's nothing
60962306a36Sopenharmony_ci * more to be done.
61062306a36Sopenharmony_ci */
61162306a36Sopenharmony_ciint autofs_expire_multi(struct super_block *sb, struct vfsmount *mnt,
61262306a36Sopenharmony_ci			struct autofs_sb_info *sbi, int __user *arg)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	unsigned int how = 0;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	if (arg && get_user(how, arg))
61762306a36Sopenharmony_ci		return -EFAULT;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return autofs_do_expire_multi(sb, mnt, sbi, how);
62062306a36Sopenharmony_ci}
621