18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
48c2ecf20Sopenharmony_ci * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
58c2ecf20Sopenharmony_ci * Copyright 2001-2006 Ian Kent <raven@themaw.net>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "autofs_i.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/* Check if a dentry can be expired */
118c2ecf20Sopenharmony_cistatic inline int autofs_can_expire(struct dentry *dentry,
128c2ecf20Sopenharmony_ci				    unsigned long timeout, unsigned int how)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	/* dentry in the process of being deleted */
178c2ecf20Sopenharmony_ci	if (ino == NULL)
188c2ecf20Sopenharmony_ci		return 0;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	if (!(how & AUTOFS_EXP_IMMEDIATE)) {
218c2ecf20Sopenharmony_ci		/* Too young to die */
228c2ecf20Sopenharmony_ci		if (!timeout || time_after(ino->last_used + timeout, jiffies))
238c2ecf20Sopenharmony_ci			return 0;
248c2ecf20Sopenharmony_ci	}
258c2ecf20Sopenharmony_ci	return 1;
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* Check a mount point for busyness */
298c2ecf20Sopenharmony_cistatic int autofs_mount_busy(struct vfsmount *mnt,
308c2ecf20Sopenharmony_ci			     struct dentry *dentry, unsigned int how)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct dentry *top = dentry;
338c2ecf20Sopenharmony_ci	struct path path = {.mnt = mnt, .dentry = dentry};
348c2ecf20Sopenharmony_ci	int status = 1;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	pr_debug("dentry %p %pd\n", dentry, dentry);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	path_get(&path);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (!follow_down_one(&path))
418c2ecf20Sopenharmony_ci		goto done;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (is_autofs_dentry(path.dentry)) {
448c2ecf20Sopenharmony_ci		struct autofs_sb_info *sbi = autofs_sbi(path.dentry->d_sb);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci		/* This is an autofs submount, we can't expire it */
478c2ecf20Sopenharmony_ci		if (autofs_type_indirect(sbi->type))
488c2ecf20Sopenharmony_ci			goto done;
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	/* Not a submount, has a forced expire been requested */
528c2ecf20Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED) {
538c2ecf20Sopenharmony_ci		status = 0;
548c2ecf20Sopenharmony_ci		goto done;
558c2ecf20Sopenharmony_ci	}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* Update the expiry counter if fs is busy */
588c2ecf20Sopenharmony_ci	if (!may_umount_tree(path.mnt)) {
598c2ecf20Sopenharmony_ci		struct autofs_info *ino;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		ino = autofs_dentry_ino(top);
628c2ecf20Sopenharmony_ci		ino->last_used = jiffies;
638c2ecf20Sopenharmony_ci		goto done;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	status = 0;
678c2ecf20Sopenharmony_cidone:
688c2ecf20Sopenharmony_ci	pr_debug("returning = %d\n", status);
698c2ecf20Sopenharmony_ci	path_put(&path);
708c2ecf20Sopenharmony_ci	return status;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* p->d_lock held */
748c2ecf20Sopenharmony_cistatic struct dentry *positive_after(struct dentry *p, struct dentry *child)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	if (child)
778c2ecf20Sopenharmony_ci		child = list_next_entry(child, d_child);
788c2ecf20Sopenharmony_ci	else
798c2ecf20Sopenharmony_ci		child = list_first_entry(&p->d_subdirs, struct dentry, d_child);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	list_for_each_entry_from(child, &p->d_subdirs, d_child) {
828c2ecf20Sopenharmony_ci		spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
838c2ecf20Sopenharmony_ci		if (simple_positive(child)) {
848c2ecf20Sopenharmony_ci			dget_dlock(child);
858c2ecf20Sopenharmony_ci			spin_unlock(&child->d_lock);
868c2ecf20Sopenharmony_ci			return child;
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci		spin_unlock(&child->d_lock);
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	return NULL;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/*
958c2ecf20Sopenharmony_ci * Calculate and dget next entry in the subdirs list under root.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cistatic struct dentry *get_next_positive_subdir(struct dentry *prev,
988c2ecf20Sopenharmony_ci					       struct dentry *root)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
1018c2ecf20Sopenharmony_ci	struct dentry *q;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	spin_lock(&sbi->lookup_lock);
1048c2ecf20Sopenharmony_ci	spin_lock(&root->d_lock);
1058c2ecf20Sopenharmony_ci	q = positive_after(root, prev);
1068c2ecf20Sopenharmony_ci	spin_unlock(&root->d_lock);
1078c2ecf20Sopenharmony_ci	spin_unlock(&sbi->lookup_lock);
1088c2ecf20Sopenharmony_ci	dput(prev);
1098c2ecf20Sopenharmony_ci	return q;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/*
1138c2ecf20Sopenharmony_ci * Calculate and dget next entry in top down tree traversal.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_cistatic struct dentry *get_next_positive_dentry(struct dentry *prev,
1168c2ecf20Sopenharmony_ci					       struct dentry *root)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
1198c2ecf20Sopenharmony_ci	struct dentry *p = prev, *ret = NULL, *d = NULL;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	if (prev == NULL)
1228c2ecf20Sopenharmony_ci		return dget(root);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	spin_lock(&sbi->lookup_lock);
1258c2ecf20Sopenharmony_ci	spin_lock(&p->d_lock);
1268c2ecf20Sopenharmony_ci	while (1) {
1278c2ecf20Sopenharmony_ci		struct dentry *parent;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci		ret = positive_after(p, d);
1308c2ecf20Sopenharmony_ci		if (ret || p == root)
1318c2ecf20Sopenharmony_ci			break;
1328c2ecf20Sopenharmony_ci		parent = p->d_parent;
1338c2ecf20Sopenharmony_ci		spin_unlock(&p->d_lock);
1348c2ecf20Sopenharmony_ci		spin_lock(&parent->d_lock);
1358c2ecf20Sopenharmony_ci		d = p;
1368c2ecf20Sopenharmony_ci		p = parent;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci	spin_unlock(&p->d_lock);
1398c2ecf20Sopenharmony_ci	spin_unlock(&sbi->lookup_lock);
1408c2ecf20Sopenharmony_ci	dput(prev);
1418c2ecf20Sopenharmony_ci	return ret;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/*
1458c2ecf20Sopenharmony_ci * Check a direct mount point for busyness.
1468c2ecf20Sopenharmony_ci * Direct mounts have similar expiry semantics to tree mounts.
1478c2ecf20Sopenharmony_ci * The tree is not busy iff no mountpoints are busy and there are no
1488c2ecf20Sopenharmony_ci * autofs submounts.
1498c2ecf20Sopenharmony_ci */
1508c2ecf20Sopenharmony_cistatic int autofs_direct_busy(struct vfsmount *mnt,
1518c2ecf20Sopenharmony_ci			      struct dentry *top,
1528c2ecf20Sopenharmony_ci			      unsigned long timeout,
1538c2ecf20Sopenharmony_ci			      unsigned int how)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	pr_debug("top %p %pd\n", top, top);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Forced expire, user space handles busy mounts */
1588c2ecf20Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED)
1598c2ecf20Sopenharmony_ci		return 0;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	/* If it's busy update the expiry counters */
1628c2ecf20Sopenharmony_ci	if (!may_umount_tree(mnt)) {
1638c2ecf20Sopenharmony_ci		struct autofs_info *ino;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		ino = autofs_dentry_ino(top);
1668c2ecf20Sopenharmony_ci		if (ino)
1678c2ecf20Sopenharmony_ci			ino->last_used = jiffies;
1688c2ecf20Sopenharmony_ci		return 1;
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* Timeout of a direct mount is determined by its top dentry */
1728c2ecf20Sopenharmony_ci	if (!autofs_can_expire(top, timeout, how))
1738c2ecf20Sopenharmony_ci		return 1;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	return 0;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/*
1798c2ecf20Sopenharmony_ci * Check a directory tree of mount points for busyness
1808c2ecf20Sopenharmony_ci * The tree is not busy iff no mountpoints are busy
1818c2ecf20Sopenharmony_ci */
1828c2ecf20Sopenharmony_cistatic int autofs_tree_busy(struct vfsmount *mnt,
1838c2ecf20Sopenharmony_ci			    struct dentry *top,
1848c2ecf20Sopenharmony_ci			    unsigned long timeout,
1858c2ecf20Sopenharmony_ci			    unsigned int how)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct autofs_info *top_ino = autofs_dentry_ino(top);
1888c2ecf20Sopenharmony_ci	struct dentry *p;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	pr_debug("top %p %pd\n", top, top);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* Negative dentry - give up */
1938c2ecf20Sopenharmony_ci	if (!simple_positive(top))
1948c2ecf20Sopenharmony_ci		return 1;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	p = NULL;
1978c2ecf20Sopenharmony_ci	while ((p = get_next_positive_dentry(p, top))) {
1988c2ecf20Sopenharmony_ci		pr_debug("dentry %p %pd\n", p, p);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		/*
2018c2ecf20Sopenharmony_ci		 * Is someone visiting anywhere in the subtree ?
2028c2ecf20Sopenharmony_ci		 * If there's no mount we need to check the usage
2038c2ecf20Sopenharmony_ci		 * count for the autofs dentry.
2048c2ecf20Sopenharmony_ci		 * If the fs is busy update the expiry counter.
2058c2ecf20Sopenharmony_ci		 */
2068c2ecf20Sopenharmony_ci		if (d_mountpoint(p)) {
2078c2ecf20Sopenharmony_ci			if (autofs_mount_busy(mnt, p, how)) {
2088c2ecf20Sopenharmony_ci				top_ino->last_used = jiffies;
2098c2ecf20Sopenharmony_ci				dput(p);
2108c2ecf20Sopenharmony_ci				return 1;
2118c2ecf20Sopenharmony_ci			}
2128c2ecf20Sopenharmony_ci		} else {
2138c2ecf20Sopenharmony_ci			struct autofs_info *ino = autofs_dentry_ino(p);
2148c2ecf20Sopenharmony_ci			unsigned int ino_count = READ_ONCE(ino->count);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci			/* allow for dget above and top is already dgot */
2178c2ecf20Sopenharmony_ci			if (p == top)
2188c2ecf20Sopenharmony_ci				ino_count += 2;
2198c2ecf20Sopenharmony_ci			else
2208c2ecf20Sopenharmony_ci				ino_count++;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci			if (d_count(p) > ino_count) {
2238c2ecf20Sopenharmony_ci				top_ino->last_used = jiffies;
2248c2ecf20Sopenharmony_ci				dput(p);
2258c2ecf20Sopenharmony_ci				return 1;
2268c2ecf20Sopenharmony_ci			}
2278c2ecf20Sopenharmony_ci		}
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Forced expire, user space handles busy mounts */
2318c2ecf20Sopenharmony_ci	if (how & AUTOFS_EXP_FORCED)
2328c2ecf20Sopenharmony_ci		return 0;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	/* Timeout of a tree mount is ultimately determined by its top dentry */
2358c2ecf20Sopenharmony_ci	if (!autofs_can_expire(top, timeout, how))
2368c2ecf20Sopenharmony_ci		return 1;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	return 0;
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic struct dentry *autofs_check_leaves(struct vfsmount *mnt,
2428c2ecf20Sopenharmony_ci					  struct dentry *parent,
2438c2ecf20Sopenharmony_ci					  unsigned long timeout,
2448c2ecf20Sopenharmony_ci					  unsigned int how)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct dentry *p;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	pr_debug("parent %p %pd\n", parent, parent);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	p = NULL;
2518c2ecf20Sopenharmony_ci	while ((p = get_next_positive_dentry(p, parent))) {
2528c2ecf20Sopenharmony_ci		pr_debug("dentry %p %pd\n", p, p);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci		if (d_mountpoint(p)) {
2558c2ecf20Sopenharmony_ci			/* Can we umount this guy */
2568c2ecf20Sopenharmony_ci			if (autofs_mount_busy(mnt, p, how))
2578c2ecf20Sopenharmony_ci				continue;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci			/* This isn't a submount so if a forced expire
2608c2ecf20Sopenharmony_ci			 * has been requested, user space handles busy
2618c2ecf20Sopenharmony_ci			 * mounts */
2628c2ecf20Sopenharmony_ci			if (how & AUTOFS_EXP_FORCED)
2638c2ecf20Sopenharmony_ci				return p;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci			/* Can we expire this guy */
2668c2ecf20Sopenharmony_ci			if (autofs_can_expire(p, timeout, how))
2678c2ecf20Sopenharmony_ci				return p;
2688c2ecf20Sopenharmony_ci		}
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci	return NULL;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci/* Check if we can expire a direct mount (possibly a tree) */
2748c2ecf20Sopenharmony_cistatic struct dentry *autofs_expire_direct(struct super_block *sb,
2758c2ecf20Sopenharmony_ci					   struct vfsmount *mnt,
2768c2ecf20Sopenharmony_ci					   struct autofs_sb_info *sbi,
2778c2ecf20Sopenharmony_ci					   unsigned int how)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct dentry *root = dget(sb->s_root);
2808c2ecf20Sopenharmony_ci	struct autofs_info *ino;
2818c2ecf20Sopenharmony_ci	unsigned long timeout;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (!root)
2848c2ecf20Sopenharmony_ci		return NULL;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	timeout = sbi->exp_timeout;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (!autofs_direct_busy(mnt, root, timeout, how)) {
2898c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
2908c2ecf20Sopenharmony_ci		ino = autofs_dentry_ino(root);
2918c2ecf20Sopenharmony_ci		/* No point expiring a pending mount */
2928c2ecf20Sopenharmony_ci		if (ino->flags & AUTOFS_INF_PENDING) {
2938c2ecf20Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
2948c2ecf20Sopenharmony_ci			goto out;
2958c2ecf20Sopenharmony_ci		}
2968c2ecf20Sopenharmony_ci		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
2978c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
2988c2ecf20Sopenharmony_ci		synchronize_rcu();
2998c2ecf20Sopenharmony_ci		if (!autofs_direct_busy(mnt, root, timeout, how)) {
3008c2ecf20Sopenharmony_ci			spin_lock(&sbi->fs_lock);
3018c2ecf20Sopenharmony_ci			ino->flags |= AUTOFS_INF_EXPIRING;
3028c2ecf20Sopenharmony_ci			init_completion(&ino->expire_complete);
3038c2ecf20Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
3048c2ecf20Sopenharmony_ci			return root;
3058c2ecf20Sopenharmony_ci		}
3068c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
3078c2ecf20Sopenharmony_ci		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
3088c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ciout:
3118c2ecf20Sopenharmony_ci	dput(root);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	return NULL;
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci/* Check if 'dentry' should expire, or return a nearby
3178c2ecf20Sopenharmony_ci * dentry that is suitable.
3188c2ecf20Sopenharmony_ci * If returned dentry is different from arg dentry,
3198c2ecf20Sopenharmony_ci * then a dget() reference was taken, else not.
3208c2ecf20Sopenharmony_ci */
3218c2ecf20Sopenharmony_cistatic struct dentry *should_expire(struct dentry *dentry,
3228c2ecf20Sopenharmony_ci				    struct vfsmount *mnt,
3238c2ecf20Sopenharmony_ci				    unsigned long timeout,
3248c2ecf20Sopenharmony_ci				    unsigned int how)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
3278c2ecf20Sopenharmony_ci	unsigned int ino_count;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* No point expiring a pending mount */
3308c2ecf20Sopenharmony_ci	if (ino->flags & AUTOFS_INF_PENDING)
3318c2ecf20Sopenharmony_ci		return NULL;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	/*
3348c2ecf20Sopenharmony_ci	 * Case 1: (i) indirect mount or top level pseudo direct mount
3358c2ecf20Sopenharmony_ci	 *	   (autofs-4.1).
3368c2ecf20Sopenharmony_ci	 *	   (ii) indirect mount with offset mount, check the "/"
3378c2ecf20Sopenharmony_ci	 *	   offset (autofs-5.0+).
3388c2ecf20Sopenharmony_ci	 */
3398c2ecf20Sopenharmony_ci	if (d_mountpoint(dentry)) {
3408c2ecf20Sopenharmony_ci		pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci		/* Can we umount this guy */
3438c2ecf20Sopenharmony_ci		if (autofs_mount_busy(mnt, dentry, how))
3448c2ecf20Sopenharmony_ci			return NULL;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci		/* This isn't a submount so if a forced expire
3478c2ecf20Sopenharmony_ci		 * has been requested, user space handles busy
3488c2ecf20Sopenharmony_ci		 * mounts */
3498c2ecf20Sopenharmony_ci		if (how & AUTOFS_EXP_FORCED)
3508c2ecf20Sopenharmony_ci			return dentry;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		/* Can we expire this guy */
3538c2ecf20Sopenharmony_ci		if (autofs_can_expire(dentry, timeout, how))
3548c2ecf20Sopenharmony_ci			return dentry;
3558c2ecf20Sopenharmony_ci		return NULL;
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
3598c2ecf20Sopenharmony_ci		pr_debug("checking symlink %p %pd\n", dentry, dentry);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci		/* Forced expire, user space handles busy mounts */
3628c2ecf20Sopenharmony_ci		if (how & AUTOFS_EXP_FORCED)
3638c2ecf20Sopenharmony_ci			return dentry;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		/*
3668c2ecf20Sopenharmony_ci		 * A symlink can't be "busy" in the usual sense so
3678c2ecf20Sopenharmony_ci		 * just check last used for expire timeout.
3688c2ecf20Sopenharmony_ci		 */
3698c2ecf20Sopenharmony_ci		if (autofs_can_expire(dentry, timeout, how))
3708c2ecf20Sopenharmony_ci			return dentry;
3718c2ecf20Sopenharmony_ci		return NULL;
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	if (simple_empty(dentry))
3758c2ecf20Sopenharmony_ci		return NULL;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/* Case 2: tree mount, expire iff entire tree is not busy */
3788c2ecf20Sopenharmony_ci	if (!(how & AUTOFS_EXP_LEAVES)) {
3798c2ecf20Sopenharmony_ci		/* Not a forced expire? */
3808c2ecf20Sopenharmony_ci		if (!(how & AUTOFS_EXP_FORCED)) {
3818c2ecf20Sopenharmony_ci			/* ref-walk currently on this dentry? */
3828c2ecf20Sopenharmony_ci			ino_count = READ_ONCE(ino->count) + 1;
3838c2ecf20Sopenharmony_ci			if (d_count(dentry) > ino_count)
3848c2ecf20Sopenharmony_ci				return NULL;
3858c2ecf20Sopenharmony_ci		}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		if (!autofs_tree_busy(mnt, dentry, timeout, how))
3888c2ecf20Sopenharmony_ci			return dentry;
3898c2ecf20Sopenharmony_ci	/*
3908c2ecf20Sopenharmony_ci	 * Case 3: pseudo direct mount, expire individual leaves
3918c2ecf20Sopenharmony_ci	 *	   (autofs-4.1).
3928c2ecf20Sopenharmony_ci	 */
3938c2ecf20Sopenharmony_ci	} else {
3948c2ecf20Sopenharmony_ci		struct dentry *expired;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		/* Not a forced expire? */
3978c2ecf20Sopenharmony_ci		if (!(how & AUTOFS_EXP_FORCED)) {
3988c2ecf20Sopenharmony_ci			/* ref-walk currently on this dentry? */
3998c2ecf20Sopenharmony_ci			ino_count = READ_ONCE(ino->count) + 1;
4008c2ecf20Sopenharmony_ci			if (d_count(dentry) > ino_count)
4018c2ecf20Sopenharmony_ci				return NULL;
4028c2ecf20Sopenharmony_ci		}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		expired = autofs_check_leaves(mnt, dentry, timeout, how);
4058c2ecf20Sopenharmony_ci		if (expired) {
4068c2ecf20Sopenharmony_ci			if (expired == dentry)
4078c2ecf20Sopenharmony_ci				dput(dentry);
4088c2ecf20Sopenharmony_ci			return expired;
4098c2ecf20Sopenharmony_ci		}
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci	return NULL;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci/*
4158c2ecf20Sopenharmony_ci * Find an eligible tree to time-out
4168c2ecf20Sopenharmony_ci * A tree is eligible if :-
4178c2ecf20Sopenharmony_ci *  - it is unused by any user process
4188c2ecf20Sopenharmony_ci *  - it has been unused for exp_timeout time
4198c2ecf20Sopenharmony_ci */
4208c2ecf20Sopenharmony_cistatic struct dentry *autofs_expire_indirect(struct super_block *sb,
4218c2ecf20Sopenharmony_ci					     struct vfsmount *mnt,
4228c2ecf20Sopenharmony_ci					     struct autofs_sb_info *sbi,
4238c2ecf20Sopenharmony_ci					     unsigned int how)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	unsigned long timeout;
4268c2ecf20Sopenharmony_ci	struct dentry *root = sb->s_root;
4278c2ecf20Sopenharmony_ci	struct dentry *dentry;
4288c2ecf20Sopenharmony_ci	struct dentry *expired;
4298c2ecf20Sopenharmony_ci	struct dentry *found;
4308c2ecf20Sopenharmony_ci	struct autofs_info *ino;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	if (!root)
4338c2ecf20Sopenharmony_ci		return NULL;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	timeout = sbi->exp_timeout;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	dentry = NULL;
4388c2ecf20Sopenharmony_ci	while ((dentry = get_next_positive_subdir(dentry, root))) {
4398c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
4408c2ecf20Sopenharmony_ci		ino = autofs_dentry_ino(dentry);
4418c2ecf20Sopenharmony_ci		if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
4428c2ecf20Sopenharmony_ci			spin_unlock(&sbi->fs_lock);
4438c2ecf20Sopenharmony_ci			continue;
4448c2ecf20Sopenharmony_ci		}
4458c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci		expired = should_expire(dentry, mnt, timeout, how);
4488c2ecf20Sopenharmony_ci		if (!expired)
4498c2ecf20Sopenharmony_ci			continue;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
4528c2ecf20Sopenharmony_ci		ino = autofs_dentry_ino(expired);
4538c2ecf20Sopenharmony_ci		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
4548c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
4558c2ecf20Sopenharmony_ci		synchronize_rcu();
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		/* Make sure a reference is not taken on found if
4588c2ecf20Sopenharmony_ci		 * things have changed.
4598c2ecf20Sopenharmony_ci		 */
4608c2ecf20Sopenharmony_ci		how &= ~AUTOFS_EXP_LEAVES;
4618c2ecf20Sopenharmony_ci		found = should_expire(expired, mnt, timeout, how);
4628c2ecf20Sopenharmony_ci		if (found != expired) { // something has changed, continue
4638c2ecf20Sopenharmony_ci			dput(found);
4648c2ecf20Sopenharmony_ci			goto next;
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci		if (expired != dentry)
4688c2ecf20Sopenharmony_ci			dput(dentry);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
4718c2ecf20Sopenharmony_ci		goto found;
4728c2ecf20Sopenharmony_cinext:
4738c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
4748c2ecf20Sopenharmony_ci		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
4758c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
4768c2ecf20Sopenharmony_ci		if (expired != dentry)
4778c2ecf20Sopenharmony_ci			dput(expired);
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci	return NULL;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cifound:
4828c2ecf20Sopenharmony_ci	pr_debug("returning %p %pd\n", expired, expired);
4838c2ecf20Sopenharmony_ci	ino->flags |= AUTOFS_INF_EXPIRING;
4848c2ecf20Sopenharmony_ci	init_completion(&ino->expire_complete);
4858c2ecf20Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
4868c2ecf20Sopenharmony_ci	return expired;
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ciint autofs_expire_wait(const struct path *path, int rcu_walk)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	struct dentry *dentry = path->dentry;
4928c2ecf20Sopenharmony_ci	struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
4938c2ecf20Sopenharmony_ci	struct autofs_info *ino = autofs_dentry_ino(dentry);
4948c2ecf20Sopenharmony_ci	int status;
4958c2ecf20Sopenharmony_ci	int state;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	/* Block on any pending expire */
4988c2ecf20Sopenharmony_ci	if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
4998c2ecf20Sopenharmony_ci		return 0;
5008c2ecf20Sopenharmony_ci	if (rcu_walk)
5018c2ecf20Sopenharmony_ci		return -ECHILD;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ciretry:
5048c2ecf20Sopenharmony_ci	spin_lock(&sbi->fs_lock);
5058c2ecf20Sopenharmony_ci	state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
5068c2ecf20Sopenharmony_ci	if (state == AUTOFS_INF_WANT_EXPIRE) {
5078c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
5088c2ecf20Sopenharmony_ci		/*
5098c2ecf20Sopenharmony_ci		 * Possibly being selected for expire, wait until
5108c2ecf20Sopenharmony_ci		 * it's selected or not.
5118c2ecf20Sopenharmony_ci		 */
5128c2ecf20Sopenharmony_ci		schedule_timeout_uninterruptible(HZ/10);
5138c2ecf20Sopenharmony_ci		goto retry;
5148c2ecf20Sopenharmony_ci	}
5158c2ecf20Sopenharmony_ci	if (state & AUTOFS_INF_EXPIRING) {
5168c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci		pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		status = autofs_wait(sbi, path, NFY_NONE);
5218c2ecf20Sopenharmony_ci		wait_for_completion(&ino->expire_complete);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci		pr_debug("expire done status=%d\n", status);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		if (d_unhashed(dentry))
5268c2ecf20Sopenharmony_ci			return -EAGAIN;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci		return status;
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	return 0;
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci/* Perform an expiry operation */
5368c2ecf20Sopenharmony_ciint autofs_expire_run(struct super_block *sb,
5378c2ecf20Sopenharmony_ci		      struct vfsmount *mnt,
5388c2ecf20Sopenharmony_ci		      struct autofs_sb_info *sbi,
5398c2ecf20Sopenharmony_ci		      struct autofs_packet_expire __user *pkt_p)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	struct autofs_packet_expire pkt;
5428c2ecf20Sopenharmony_ci	struct autofs_info *ino;
5438c2ecf20Sopenharmony_ci	struct dentry *dentry;
5448c2ecf20Sopenharmony_ci	int ret = 0;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	pkt.hdr.proto_version = sbi->version;
5498c2ecf20Sopenharmony_ci	pkt.hdr.type = autofs_ptype_expire;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	dentry = autofs_expire_indirect(sb, mnt, sbi, 0);
5528c2ecf20Sopenharmony_ci	if (!dentry)
5538c2ecf20Sopenharmony_ci		return -EAGAIN;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	pkt.len = dentry->d_name.len;
5568c2ecf20Sopenharmony_ci	memcpy(pkt.name, dentry->d_name.name, pkt.len);
5578c2ecf20Sopenharmony_ci	pkt.name[pkt.len] = '\0';
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
5608c2ecf20Sopenharmony_ci		ret = -EFAULT;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	spin_lock(&sbi->fs_lock);
5638c2ecf20Sopenharmony_ci	ino = autofs_dentry_ino(dentry);
5648c2ecf20Sopenharmony_ci	/* avoid rapid-fire expire attempts if expiry fails */
5658c2ecf20Sopenharmony_ci	ino->last_used = jiffies;
5668c2ecf20Sopenharmony_ci	ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
5678c2ecf20Sopenharmony_ci	complete_all(&ino->expire_complete);
5688c2ecf20Sopenharmony_ci	spin_unlock(&sbi->fs_lock);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	dput(dentry);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return ret;
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ciint autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
5768c2ecf20Sopenharmony_ci			   struct autofs_sb_info *sbi, unsigned int how)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	struct dentry *dentry;
5798c2ecf20Sopenharmony_ci	int ret = -EAGAIN;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	if (autofs_type_trigger(sbi->type))
5828c2ecf20Sopenharmony_ci		dentry = autofs_expire_direct(sb, mnt, sbi, how);
5838c2ecf20Sopenharmony_ci	else
5848c2ecf20Sopenharmony_ci		dentry = autofs_expire_indirect(sb, mnt, sbi, how);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	if (dentry) {
5878c2ecf20Sopenharmony_ci		struct autofs_info *ino = autofs_dentry_ino(dentry);
5888c2ecf20Sopenharmony_ci		const struct path path = { .mnt = mnt, .dentry = dentry };
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci		/* This is synchronous because it makes the daemon a
5918c2ecf20Sopenharmony_ci		 * little easier
5928c2ecf20Sopenharmony_ci		 */
5938c2ecf20Sopenharmony_ci		ret = autofs_wait(sbi, &path, NFY_EXPIRE);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci		spin_lock(&sbi->fs_lock);
5968c2ecf20Sopenharmony_ci		/* avoid rapid-fire expire attempts if expiry fails */
5978c2ecf20Sopenharmony_ci		ino->last_used = jiffies;
5988c2ecf20Sopenharmony_ci		ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
5998c2ecf20Sopenharmony_ci		complete_all(&ino->expire_complete);
6008c2ecf20Sopenharmony_ci		spin_unlock(&sbi->fs_lock);
6018c2ecf20Sopenharmony_ci		dput(dentry);
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	return ret;
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci/*
6088c2ecf20Sopenharmony_ci * Call repeatedly until it returns -EAGAIN, meaning there's nothing
6098c2ecf20Sopenharmony_ci * more to be done.
6108c2ecf20Sopenharmony_ci */
6118c2ecf20Sopenharmony_ciint autofs_expire_multi(struct super_block *sb, struct vfsmount *mnt,
6128c2ecf20Sopenharmony_ci			struct autofs_sb_info *sbi, int __user *arg)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	unsigned int how = 0;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (arg && get_user(how, arg))
6178c2ecf20Sopenharmony_ci		return -EFAULT;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	return autofs_do_expire_multi(sb, mnt, sbi, how);
6208c2ecf20Sopenharmony_ci}
621