/* Check a mount point for busyness */
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
	struct dentry *top = dentry;
	struct path path = {.mnt = mnt, .dentry = dentry};
	int status = 1;

	DPRINTK("dentry %p %.*s",
		dentry, (int)dentry->d_name.len, dentry->d_name.name);

	path_get(&path);

	if (!follow_down_one(&path))
		goto done;

	if (is_autofs4_dentry(path.dentry)) {
		struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);

		/* This is an autofs submount, we can't expire it */
		if (autofs_type_indirect(sbi->type))
			goto done;
	}

	/* Update the expiry counter if fs is busy */
	if (!may_umount_tree(path.mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		ino->last_used = jiffies;
		goto done;
	}

	status = 0;
done:
	DPRINTK("returning = %d", status);
	path_put(&path);
	return status;
}
/* Check a mount point for busyness return 1 if not busy, otherwise */
static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
{
	int status = 0;

	DPRINTK("dentry %p %.*s",
		dentry, (int)dentry->d_name.len, dentry->d_name.name);

	mntget(mnt);
	dget(dentry);

	if (!autofs4_follow_mount(&mnt, &dentry))
		goto done;

	/* This is an autofs submount, we can't expire it */
	if (is_autofs4_dentry(dentry))
		goto done;

	/* The big question */
	if (may_umount_tree(mnt) == 0)
		status = 1;
done:
	DPRINTK("returning = %d", status);
	mntput(mnt);
	dput(dentry);
	return status;
}
Exemple #3
0
/* Check a mount point for busyness */
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
	struct dentry *top = dentry;
	int status = 1;

	DPRINTK("dentry %p %.*s",
		dentry, (int)dentry->d_name.len, dentry->d_name.name);

	mntget(mnt);
	dget(dentry);

	if (!autofs4_follow_mount(&mnt, &dentry))
		goto done;

	/* This is an autofs submount, we can't expire it */
	if (is_autofs4_dentry(dentry))
		goto done;

	/* Update the expiry counter if fs is busy */
	if (!may_umount_tree(mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		ino->last_used = jiffies;
		goto done;
	}

	status = 0;
done:
	DPRINTK("returning = %d", status);
	mntput(mnt);
	dput(dentry);
	return status;
}
Exemple #4
0
/* must hold ftfs_southbound lock */
int __ftfs_private_umount(void)
{
	if (may_umount_tree(ftfs_vfs)) {
		kern_unmount(ftfs_vfs);
		return 0;
	}
	return -EBUSY;
}
/* Check a mount point for busyness */
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
	struct dentry *top = dentry;
	int status = 1;

	DPRINTK("dentry %p %.*s",
		dentry, (int)dentry->d_name.len, dentry->d_name.name);

	mntget(mnt);
	dget(dentry);

	if (!follow_down(&mnt, &dentry))
		goto done;

	if (is_autofs4_dentry(dentry)) {
		struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);

		/* This is an autofs submount, we can't expire it */
		if (autofs_type_indirect(sbi->type))
			goto done;

		/*
		 * Otherwise it's an offset mount and we need to check
		 * if we can umount its mount, if there is one.
		 */
		if (!d_mountpoint(dentry))
			goto done;
	}

	/* Update the expiry counter if fs is busy */
	if (!may_umount_tree(mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		ino->last_used = jiffies;
		goto done;
	}

	status = 0;
done:
	DPRINTK("returning = %d", status);
	dput(dentry);
	mntput(mnt);
	return status;
}
static int autofs4_direct_busy(struct vfsmount *mnt,
				struct dentry *top,
				unsigned long timeout,
				int do_now)
{
	DPRINTK("top %p %.*s",
		top, (int) top->d_name.len, top->d_name.name);

	
	if (!may_umount_tree(mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		if (ino)
			ino->last_used = jiffies;
		return 1;
	}

	
	if (!autofs4_can_expire(top, timeout, do_now))
		return 1;

	return 0;
}
/*
 * Check a direct mount point for busyness.
 * Direct mounts have similar expiry semantics to tree mounts.
 * The tree is not busy iff no mountpoints are busy and there are no
 * autofs submounts.
 */
static int autofs4_direct_busy(struct vfsmount *mnt,
				struct dentry *top,
				unsigned long timeout,
				int do_now)
{
	DPRINTK("top %p %.*s",
		top, (int) top->d_name.len, top->d_name.name);

	/* If it's busy update the expiry counters */
	if (!may_umount_tree(mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		if (ino)
			ino->last_used = jiffies;
		return 1;
	}

	/* Timeout of a direct mount is determined by its top dentry */
	if (!autofs4_can_expire(top, timeout, do_now))
		return 1;

	return 0;
}
/* Check a directory tree of mount points for busyness
 * The tree is not busy iff no mountpoints are busy
 * Return 1 if the tree is busy or 0 otherwise
 */
static int autofs4_check_tree(struct vfsmount *mnt,
	       		      struct dentry *top,
			      unsigned long timeout,
			      int do_now)
{
	struct dentry *this_parent = top;
	struct list_head *next;

	DPRINTK("parent %p %.*s",
		top, (int)top->d_name.len, top->d_name.name);

	/* Negative dentry - give up */
	if (!simple_positive(top))
		return 0;

	/* Timeout of a tree mount is determined by its top dentry */
	if (!autofs4_can_expire(top, timeout, do_now))
		return 0;

	/* Is someone visiting anywhere in the tree ? */
	if (may_umount_tree(mnt))
		return 0;

	spin_lock(&dcache_lock);
repeat:
	next = this_parent->d_subdirs.next;
resume:
	while (next != &this_parent->d_subdirs) {
		struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);

		/* Negative dentry - give up */
		if (!simple_positive(dentry)) {
			next = next->next;
			continue;
		}

		DPRINTK("dentry %p %.*s",
			dentry, (int)dentry->d_name.len, dentry->d_name.name);

		if (!simple_empty_nolock(dentry)) {
			this_parent = dentry;
			goto repeat;
		}

		dentry = dget(dentry);
		spin_unlock(&dcache_lock);

		if (d_mountpoint(dentry)) {
			/* First busy => tree busy */
			if (!autofs4_check_mount(mnt, dentry)) {
				dput(dentry);
				return 0;
			}
		}

		dput(dentry);
		spin_lock(&dcache_lock);
		next = next->next;
	}

	if (this_parent != top) {
		next = this_parent->d_u.d_child.next;
		this_parent = this_parent->d_parent;
		goto resume;
	}
	spin_unlock(&dcache_lock);

	return 1;
}