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);
- mntget(mnt);
- dget(dentry);
+ path_get(&path);
- if (!autofs4_follow_mount(&mnt, &dentry))
+ if (!follow_down(&path))
goto done;
- /* This is an autofs submount, we can't expire it */
- if (is_autofs4_dentry(dentry))
- 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;
+
+ /*
+ * Otherwise it's an offset mount and we need to check
+ * if we can umount its mount, if there is one.
+ */
+ if (!d_mountpoint(path.dentry)) {
+ status = 0;
+ goto done;
+ }
+ }
/* Update the expiry counter if fs is busy */
if (!may_umount_tree(mnt)) {
status = 0;
done:
DPRINTK("returning = %d", status);
- dput(dentry);
- mntput(mnt);
+ path_put(&path);
return status;
}
}
/* Check if we can expire a direct mount (possibly a tree) */
-static struct dentry *autofs4_expire_direct(struct super_block *sb,
- struct vfsmount *mnt,
- struct autofs_sb_info *sbi,
- int how)
+struct dentry *autofs4_expire_direct(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
{
unsigned long timeout;
struct dentry *root = dget(sb->s_root);
* - it is unused by any user process
* - it has been unused for exp_timeout time
*/
-static struct dentry *autofs4_expire_indirect(struct super_block *sb,
- struct vfsmount *mnt,
- struct autofs_sb_info *sbi,
- int how)
+struct dentry *autofs4_expire_indirect(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
{
unsigned long timeout;
struct dentry *root = sb->s_root;
return ret;
}
-/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
- more to be done */
-int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
- struct autofs_sb_info *sbi, int __user *arg)
+int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
+ struct autofs_sb_info *sbi, int when)
{
struct dentry *dentry;
int ret = -EAGAIN;
- int do_now = 0;
-
- if (arg && get_user(do_now, arg))
- return -EFAULT;
- if (sbi->type & AUTOFS_TYPE_DIRECT)
- dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
+ if (autofs_type_trigger(sbi->type))
+ dentry = autofs4_expire_direct(sb, mnt, sbi, when);
else
- dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
+ dentry = autofs4_expire_indirect(sb, mnt, sbi, when);
if (dentry) {
struct autofs_info *ino = autofs4_dentry_ino(dentry);
return ret;
}
+/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
+ more to be done */
+int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
+ struct autofs_sb_info *sbi, int __user *arg)
+{
+ int do_now = 0;
+
+ if (arg && get_user(do_now, arg))
+ return -EFAULT;
+
+ return autofs4_do_expire_multi(sb, mnt, sbi, do_now);
+}
+