/* 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; }
/* 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; }
/* 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; }