autofs: delete fs/autofs4 source files
[linux-2.6-block.git] / fs / autofs4 / expire.c
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
deleted file mode 100644 (file)
index 36f16b6..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- * Copyright 2001-2006 Ian Kent <raven@themaw.net>
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- */
-
-#include "autofs_i.h"
-
-static unsigned long now;
-
-/* Check if a dentry can be expired */
-static inline int autofs_can_expire(struct dentry *dentry,
-                                   unsigned long timeout, int do_now)
-{
-       struct autofs_info *ino = autofs_dentry_ino(dentry);
-
-       /* dentry in the process of being deleted */
-       if (ino == NULL)
-               return 0;
-
-       if (!do_now) {
-               /* Too young to die */
-               if (!timeout || time_after(ino->last_used + timeout, now))
-                       return 0;
-       }
-       return 1;
-}
-
-/* Check a mount point for busyness */
-static int autofs_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
-{
-       struct dentry *top = dentry;
-       struct path path = {.mnt = mnt, .dentry = dentry};
-       int status = 1;
-
-       pr_debug("dentry %p %pd\n", dentry, dentry);
-
-       path_get(&path);
-
-       if (!follow_down_one(&path))
-               goto done;
-
-       if (is_autofs_dentry(path.dentry)) {
-               struct autofs_sb_info *sbi = autofs_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;
-
-               ino = autofs_dentry_ino(top);
-               ino->last_used = jiffies;
-               goto done;
-       }
-
-       status = 0;
-done:
-       pr_debug("returning = %d\n", status);
-       path_put(&path);
-       return status;
-}
-
-/*
- * Calculate and dget next entry in the subdirs list under root.
- */
-static struct dentry *get_next_positive_subdir(struct dentry *prev,
-                                              struct dentry *root)
-{
-       struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
-       struct list_head *next;
-       struct dentry *q;
-
-       spin_lock(&sbi->lookup_lock);
-       spin_lock(&root->d_lock);
-
-       if (prev)
-               next = prev->d_child.next;
-       else {
-               prev = dget_dlock(root);
-               next = prev->d_subdirs.next;
-       }
-
-cont:
-       if (next == &root->d_subdirs) {
-               spin_unlock(&root->d_lock);
-               spin_unlock(&sbi->lookup_lock);
-               dput(prev);
-               return NULL;
-       }
-
-       q = list_entry(next, struct dentry, d_child);
-
-       spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
-       /* Already gone or negative dentry (under construction) - try next */
-       if (!d_count(q) || !simple_positive(q)) {
-               spin_unlock(&q->d_lock);
-               next = q->d_child.next;
-               goto cont;
-       }
-       dget_dlock(q);
-       spin_unlock(&q->d_lock);
-       spin_unlock(&root->d_lock);
-       spin_unlock(&sbi->lookup_lock);
-
-       dput(prev);
-
-       return q;
-}
-
-/*
- * Calculate and dget next entry in top down tree traversal.
- */
-static struct dentry *get_next_positive_dentry(struct dentry *prev,
-                                              struct dentry *root)
-{
-       struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
-       struct list_head *next;
-       struct dentry *p, *ret;
-
-       if (prev == NULL)
-               return dget(root);
-
-       spin_lock(&sbi->lookup_lock);
-relock:
-       p = prev;
-       spin_lock(&p->d_lock);
-again:
-       next = p->d_subdirs.next;
-       if (next == &p->d_subdirs) {
-               while (1) {
-                       struct dentry *parent;
-
-                       if (p == root) {
-                               spin_unlock(&p->d_lock);
-                               spin_unlock(&sbi->lookup_lock);
-                               dput(prev);
-                               return NULL;
-                       }
-
-                       parent = p->d_parent;
-                       if (!spin_trylock(&parent->d_lock)) {
-                               spin_unlock(&p->d_lock);
-                               cpu_relax();
-                               goto relock;
-                       }
-                       spin_unlock(&p->d_lock);
-                       next = p->d_child.next;
-                       p = parent;
-                       if (next != &parent->d_subdirs)
-                               break;
-               }
-       }
-       ret = list_entry(next, struct dentry, d_child);
-
-       spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
-       /* Negative dentry - try next */
-       if (!simple_positive(ret)) {
-               spin_unlock(&p->d_lock);
-               lock_set_subclass(&ret->d_lock.dep_map, 0, _RET_IP_);
-               p = ret;
-               goto again;
-       }
-       dget_dlock(ret);
-       spin_unlock(&ret->d_lock);
-       spin_unlock(&p->d_lock);
-       spin_unlock(&sbi->lookup_lock);
-
-       dput(prev);
-
-       return ret;
-}
-
-/*
- * 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 autofs_direct_busy(struct vfsmount *mnt,
-                             struct dentry *top,
-                             unsigned long timeout,
-                             int do_now)
-{
-       pr_debug("top %p %pd\n", top, top);
-
-       /* If it's busy update the expiry counters */
-       if (!may_umount_tree(mnt)) {
-               struct autofs_info *ino;
-
-               ino = autofs_dentry_ino(top);
-               if (ino)
-                       ino->last_used = jiffies;
-               return 1;
-       }
-
-       /* Timeout of a direct mount is determined by its top dentry */
-       if (!autofs_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
- */
-static int autofs_tree_busy(struct vfsmount *mnt,
-                           struct dentry *top,
-                           unsigned long timeout,
-                           int do_now)
-{
-       struct autofs_info *top_ino = autofs_dentry_ino(top);
-       struct dentry *p;
-
-       pr_debug("top %p %pd\n", top, top);
-
-       /* Negative dentry - give up */
-       if (!simple_positive(top))
-               return 1;
-
-       p = NULL;
-       while ((p = get_next_positive_dentry(p, top))) {
-               pr_debug("dentry %p %pd\n", p, p);
-
-               /*
-                * Is someone visiting anywhere in the subtree ?
-                * If there's no mount we need to check the usage
-                * count for the autofs dentry.
-                * If the fs is busy update the expiry counter.
-                */
-               if (d_mountpoint(p)) {
-                       if (autofs_mount_busy(mnt, p)) {
-                               top_ino->last_used = jiffies;
-                               dput(p);
-                               return 1;
-                       }
-               } else {
-                       struct autofs_info *ino = autofs_dentry_ino(p);
-                       unsigned int ino_count = atomic_read(&ino->count);
-
-                       /* allow for dget above and top is already dgot */
-                       if (p == top)
-                               ino_count += 2;
-                       else
-                               ino_count++;
-
-                       if (d_count(p) > ino_count) {
-                               top_ino->last_used = jiffies;
-                               dput(p);
-                               return 1;
-                       }
-               }
-       }
-
-       /* Timeout of a tree mount is ultimately determined by its top dentry */
-       if (!autofs_can_expire(top, timeout, do_now))
-               return 1;
-
-       return 0;
-}
-
-static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
-                                         struct dentry *parent,
-                                         unsigned long timeout,
-                                         int do_now)
-{
-       struct dentry *p;
-
-       pr_debug("parent %p %pd\n", parent, parent);
-
-       p = NULL;
-       while ((p = get_next_positive_dentry(p, parent))) {
-               pr_debug("dentry %p %pd\n", p, p);
-
-               if (d_mountpoint(p)) {
-                       /* Can we umount this guy */
-                       if (autofs_mount_busy(mnt, p))
-                               continue;
-
-                       /* Can we expire this guy */
-                       if (autofs_can_expire(p, timeout, do_now))
-                               return p;
-               }
-       }
-       return NULL;
-}
-
-/* Check if we can expire a direct mount (possibly a tree) */
-struct dentry *autofs_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);
-       int do_now = how & AUTOFS_EXP_IMMEDIATE;
-       struct autofs_info *ino;
-
-       if (!root)
-               return NULL;
-
-       now = jiffies;
-       timeout = sbi->exp_timeout;
-
-       if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
-               spin_lock(&sbi->fs_lock);
-               ino = autofs_dentry_ino(root);
-               /* No point expiring a pending mount */
-               if (ino->flags & AUTOFS_INF_PENDING) {
-                       spin_unlock(&sbi->fs_lock);
-                       goto out;
-               }
-               ino->flags |= AUTOFS_INF_WANT_EXPIRE;
-               spin_unlock(&sbi->fs_lock);
-               synchronize_rcu();
-               if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
-                       spin_lock(&sbi->fs_lock);
-                       ino->flags |= AUTOFS_INF_EXPIRING;
-                       init_completion(&ino->expire_complete);
-                       spin_unlock(&sbi->fs_lock);
-                       return root;
-               }
-               spin_lock(&sbi->fs_lock);
-               ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
-               spin_unlock(&sbi->fs_lock);
-       }
-out:
-       dput(root);
-
-       return NULL;
-}
-
-/* Check if 'dentry' should expire, or return a nearby
- * dentry that is suitable.
- * If returned dentry is different from arg dentry,
- * then a dget() reference was taken, else not.
- */
-static struct dentry *should_expire(struct dentry *dentry,
-                                   struct vfsmount *mnt,
-                                   unsigned long timeout,
-                                   int how)
-{
-       int do_now = how & AUTOFS_EXP_IMMEDIATE;
-       int exp_leaves = how & AUTOFS_EXP_LEAVES;
-       struct autofs_info *ino = autofs_dentry_ino(dentry);
-       unsigned int ino_count;
-
-       /* No point expiring a pending mount */
-       if (ino->flags & AUTOFS_INF_PENDING)
-               return NULL;
-
-       /*
-        * Case 1: (i) indirect mount or top level pseudo direct mount
-        *         (autofs-4.1).
-        *         (ii) indirect mount with offset mount, check the "/"
-        *         offset (autofs-5.0+).
-        */
-       if (d_mountpoint(dentry)) {
-               pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
-
-               /* Can we umount this guy */
-               if (autofs_mount_busy(mnt, dentry))
-                       return NULL;
-
-               /* Can we expire this guy */
-               if (autofs_can_expire(dentry, timeout, do_now))
-                       return dentry;
-               return NULL;
-       }
-
-       if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
-               pr_debug("checking symlink %p %pd\n", dentry, dentry);
-               /*
-                * A symlink can't be "busy" in the usual sense so
-                * just check last used for expire timeout.
-                */
-               if (autofs_can_expire(dentry, timeout, do_now))
-                       return dentry;
-               return NULL;
-       }
-
-       if (simple_empty(dentry))
-               return NULL;
-
-       /* Case 2: tree mount, expire iff entire tree is not busy */
-       if (!exp_leaves) {
-               /* Path walk currently on this dentry? */
-               ino_count = atomic_read(&ino->count) + 1;
-               if (d_count(dentry) > ino_count)
-                       return NULL;
-
-               if (!autofs_tree_busy(mnt, dentry, timeout, do_now))
-                       return dentry;
-       /*
-        * Case 3: pseudo direct mount, expire individual leaves
-        *         (autofs-4.1).
-        */
-       } else {
-               /* Path walk currently on this dentry? */
-               struct dentry *expired;
-
-               ino_count = atomic_read(&ino->count) + 1;
-               if (d_count(dentry) > ino_count)
-                       return NULL;
-
-               expired = autofs_check_leaves(mnt, dentry, timeout, do_now);
-               if (expired) {
-                       if (expired == dentry)
-                               dput(dentry);
-                       return expired;
-               }
-       }
-       return NULL;
-}
-
-/*
- * Find an eligible tree to time-out
- * A tree is eligible if :-
- *  - it is unused by any user process
- *  - it has been unused for exp_timeout time
- */
-struct dentry *autofs_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;
-       struct dentry *dentry;
-       struct dentry *expired;
-       struct dentry *found;
-       struct autofs_info *ino;
-
-       if (!root)
-               return NULL;
-
-       now = jiffies;
-       timeout = sbi->exp_timeout;
-
-       dentry = NULL;
-       while ((dentry = get_next_positive_subdir(dentry, root))) {
-               int flags = how;
-
-               spin_lock(&sbi->fs_lock);
-               ino = autofs_dentry_ino(dentry);
-               if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
-                       spin_unlock(&sbi->fs_lock);
-                       continue;
-               }
-               spin_unlock(&sbi->fs_lock);
-
-               expired = should_expire(dentry, mnt, timeout, flags);
-               if (!expired)
-                       continue;
-
-               spin_lock(&sbi->fs_lock);
-               ino = autofs_dentry_ino(expired);
-               ino->flags |= AUTOFS_INF_WANT_EXPIRE;
-               spin_unlock(&sbi->fs_lock);
-               synchronize_rcu();
-
-               /* Make sure a reference is not taken on found if
-                * things have changed.
-                */
-               flags &= ~AUTOFS_EXP_LEAVES;
-               found = should_expire(expired, mnt, timeout, how);
-               if (!found || found != expired)
-                       /* Something has changed, continue */
-                       goto next;
-
-               if (expired != dentry)
-                       dput(dentry);
-
-               spin_lock(&sbi->fs_lock);
-               goto found;
-next:
-               spin_lock(&sbi->fs_lock);
-               ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
-               spin_unlock(&sbi->fs_lock);
-               if (expired != dentry)
-                       dput(expired);
-       }
-       return NULL;
-
-found:
-       pr_debug("returning %p %pd\n", expired, expired);
-       ino->flags |= AUTOFS_INF_EXPIRING;
-       init_completion(&ino->expire_complete);
-       spin_unlock(&sbi->fs_lock);
-       return expired;
-}
-
-int autofs_expire_wait(const struct path *path, int rcu_walk)
-{
-       struct dentry *dentry = path->dentry;
-       struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs_dentry_ino(dentry);
-       int status;
-       int state;
-
-       /* Block on any pending expire */
-       if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
-               return 0;
-       if (rcu_walk)
-               return -ECHILD;
-
-retry:
-       spin_lock(&sbi->fs_lock);
-       state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
-       if (state == AUTOFS_INF_WANT_EXPIRE) {
-               spin_unlock(&sbi->fs_lock);
-               /*
-                * Possibly being selected for expire, wait until
-                * it's selected or not.
-                */
-               schedule_timeout_uninterruptible(HZ/10);
-               goto retry;
-       }
-       if (state & AUTOFS_INF_EXPIRING) {
-               spin_unlock(&sbi->fs_lock);
-
-               pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);
-
-               status = autofs_wait(sbi, path, NFY_NONE);
-               wait_for_completion(&ino->expire_complete);
-
-               pr_debug("expire done status=%d\n", status);
-
-               if (d_unhashed(dentry))
-                       return -EAGAIN;
-
-               return status;
-       }
-       spin_unlock(&sbi->fs_lock);
-
-       return 0;
-}
-
-/* Perform an expiry operation */
-int autofs_expire_run(struct super_block *sb,
-                     struct vfsmount *mnt,
-                     struct autofs_sb_info *sbi,
-                     struct autofs_packet_expire __user *pkt_p)
-{
-       struct autofs_packet_expire pkt;
-       struct autofs_info *ino;
-       struct dentry *dentry;
-       int ret = 0;
-
-       memset(&pkt, 0, sizeof(pkt));
-
-       pkt.hdr.proto_version = sbi->version;
-       pkt.hdr.type = autofs_ptype_expire;
-
-       dentry = autofs_expire_indirect(sb, mnt, sbi, 0);
-       if (!dentry)
-               return -EAGAIN;
-
-       pkt.len = dentry->d_name.len;
-       memcpy(pkt.name, dentry->d_name.name, pkt.len);
-       pkt.name[pkt.len] = '\0';
-       dput(dentry);
-
-       if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
-               ret = -EFAULT;
-
-       spin_lock(&sbi->fs_lock);
-       ino = autofs_dentry_ino(dentry);
-       /* avoid rapid-fire expire attempts if expiry fails */
-       ino->last_used = now;
-       ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
-       complete_all(&ino->expire_complete);
-       spin_unlock(&sbi->fs_lock);
-
-       return ret;
-}
-
-int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
-                          struct autofs_sb_info *sbi, int when)
-{
-       struct dentry *dentry;
-       int ret = -EAGAIN;
-
-       if (autofs_type_trigger(sbi->type))
-               dentry = autofs_expire_direct(sb, mnt, sbi, when);
-       else
-               dentry = autofs_expire_indirect(sb, mnt, sbi, when);
-
-       if (dentry) {
-               struct autofs_info *ino = autofs_dentry_ino(dentry);
-               const struct path path = { .mnt = mnt, .dentry = dentry };
-
-               /* This is synchronous because it makes the daemon a
-                * little easier
-                */
-               ret = autofs_wait(sbi, &path, NFY_EXPIRE);
-
-               spin_lock(&sbi->fs_lock);
-               /* avoid rapid-fire expire attempts if expiry fails */
-               ino->last_used = now;
-               ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
-               complete_all(&ino->expire_complete);
-               spin_unlock(&sbi->fs_lock);
-               dput(dentry);
-       }
-
-       return ret;
-}
-
-/*
- * Call repeatedly until it returns -EAGAIN, meaning there's nothing
- * more to be done.
- */
-int autofs_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 autofs_do_expire_multi(sb, mnt, sbi, do_now);
-}
-