Revert "writeback: fix WB_SYNC_NONE writeback from umount"
[safe/jmp/linux-2.6] / fs / dcache.c
index 75659a6..d96047b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/swap.h>
 #include <linux/bootmem.h>
 #include <linux/fs_struct.h>
+#include <linux/hardirq.h>
 #include "internal.h"
 
 int sysctl_vfs_cache_pressure __read_mostly = 100;
@@ -256,6 +257,7 @@ kill_it:
        if (dentry)
                goto repeat;
 }
+EXPORT_SYMBOL(dput);
 
 /**
  * d_invalidate - invalidate a dentry
@@ -313,6 +315,7 @@ int d_invalidate(struct dentry * dentry)
        spin_unlock(&dcache_lock);
        return 0;
 }
+EXPORT_SYMBOL(d_invalidate);
 
 /* This should be called _only_ with dcache_lock held */
 
@@ -327,6 +330,7 @@ struct dentry * dget_locked(struct dentry *dentry)
 {
        return __dget_locked(dentry);
 }
+EXPORT_SYMBOL(dget_locked);
 
 /**
  * d_find_alias - grab a hashed alias of inode
@@ -383,6 +387,7 @@ struct dentry * d_find_alias(struct inode *inode)
        }
        return de;
 }
+EXPORT_SYMBOL(d_find_alias);
 
 /*
  *     Try to kill dentries associated with this inode.
@@ -407,6 +412,7 @@ restart:
        }
        spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_prune_aliases);
 
 /*
  * Throw away a dentry - free the inode, dput the parent.  This requires that
@@ -530,7 +536,7 @@ restart:
  */
 static void prune_dcache(int count)
 {
-       struct super_block *sb;
+       struct super_block *sb, *n;
        int w_count;
        int unused = dentry_stat.nr_unused;
        int prune_ratio;
@@ -539,13 +545,14 @@ static void prune_dcache(int count)
        if (unused == 0 || count == 0)
                return;
        spin_lock(&dcache_lock);
-restart:
        if (count >= unused)
                prune_ratio = 1;
        else
                prune_ratio = unused / count;
        spin_lock(&sb_lock);
-       list_for_each_entry(sb, &super_blocks, s_list) {
+       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                if (sb->s_nr_dentry_unused == 0)
                        continue;
                sb->s_count++;
@@ -584,14 +591,10 @@ restart:
                }
                spin_lock(&sb_lock);
                count -= pruned;
-               /*
-                * restart only when sb is no longer on the list and
-                * we have more work to do.
-                */
-               if (__put_super_and_need_restart(sb) && count > 0) {
-                       spin_unlock(&sb_lock);
-                       goto restart;
-               }
+               __put_super(sb);
+               /* more work left to do? */
+               if (count <= 0)
+                       break;
        }
        spin_unlock(&sb_lock);
        spin_unlock(&dcache_lock);
@@ -609,6 +612,7 @@ void shrink_dcache_sb(struct super_block * sb)
 {
        __shrink_dcache_sb(sb, NULL, 0);
 }
+EXPORT_SYMBOL(shrink_dcache_sb);
 
 /*
  * destroy a single subtree of dentries for unmount
@@ -791,6 +795,7 @@ positive:
        spin_unlock(&dcache_lock);
        return 1;
 }
+EXPORT_SYMBOL(have_submounts);
 
 /*
  * Search the dentry child list for the specified parent,
@@ -875,6 +880,7 @@ void shrink_dcache_parent(struct dentry * parent)
        while ((found = select_parent(parent)) != 0)
                __shrink_dcache_sb(sb, &found, 0);
 }
+EXPORT_SYMBOL(shrink_dcache_parent);
 
 /*
  * Scan `nr' dentries and return the number which remain.
@@ -967,6 +973,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 
        return dentry;
 }
+EXPORT_SYMBOL(d_alloc);
 
 struct dentry *d_alloc_name(struct dentry *parent, const char *name)
 {
@@ -977,6 +984,7 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
        q.hash = full_name_hash(q.name, q.len);
        return d_alloc(parent, &q);
 }
+EXPORT_SYMBOL(d_alloc_name);
 
 /* the caller must hold dcache_lock */
 static void __d_instantiate(struct dentry *dentry, struct inode *inode)
@@ -1010,6 +1018,7 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
        spin_unlock(&dcache_lock);
        security_d_instantiate(entry, inode);
 }
+EXPORT_SYMBOL(d_instantiate);
 
 /**
  * d_instantiate_unique - instantiate a non-aliased dentry
@@ -1106,6 +1115,7 @@ struct dentry * d_alloc_root(struct inode * root_inode)
        }
        return res;
 }
+EXPORT_SYMBOL(d_alloc_root);
 
 static inline struct hlist_head *d_hash(struct dentry *parent,
                                        unsigned long hash)
@@ -1209,7 +1219,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                        BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
                        spin_unlock(&dcache_lock);
                        security_d_instantiate(new, inode);
-                       d_rehash(dentry);
                        d_move(new, dentry);
                        iput(inode);
                } else {
@@ -1223,6 +1232,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                d_add(dentry, inode);
        return new;
 }
+EXPORT_SYMBOL(d_splice_alias);
 
 /**
  * d_add_ci - lookup or allocate new dentry with case-exact name
@@ -1312,6 +1322,7 @@ err_out:
        iput(inode);
        return ERR_PTR(error);
 }
+EXPORT_SYMBOL(d_add_ci);
 
 /**
  * d_lookup - search for a dentry
@@ -1355,6 +1366,7 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
        } while (read_seqretry(&rename_lock, seq));
        return dentry;
 }
+EXPORT_SYMBOL(d_lookup);
 
 struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
 {
@@ -1481,6 +1493,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
 out:
        return 0;
 }
+EXPORT_SYMBOL(d_validate);
 
 /*
  * When a file is deleted, we have two options:
@@ -1513,6 +1526,7 @@ void d_delete(struct dentry * dentry)
        spin_lock(&dentry->d_lock);
        isdir = S_ISDIR(dentry->d_inode->i_mode);
        if (atomic_read(&dentry->d_count) == 1) {
+               dentry->d_flags &= ~DCACHE_CANT_MOUNT;
                dentry_iput(dentry);
                fsnotify_nameremove(dentry, isdir);
                return;
@@ -1526,6 +1540,7 @@ void d_delete(struct dentry * dentry)
 
        fsnotify_nameremove(dentry, isdir);
 }
+EXPORT_SYMBOL(d_delete);
 
 static void __d_rehash(struct dentry * entry, struct hlist_head *list)
 {
@@ -1554,6 +1569,7 @@ void d_rehash(struct dentry * entry)
        spin_unlock(&entry->d_lock);
        spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_rehash);
 
 /*
  * When switching names, the actual string doesn't strictly have to
@@ -1700,6 +1716,7 @@ void d_move(struct dentry * dentry, struct dentry * target)
        d_move_locked(dentry, target);
        spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_move);
 
 /**
  * d_ancestor - search for an ancestor
@@ -1866,6 +1883,7 @@ shouldnt_be_hashed:
        spin_unlock(&dcache_lock);
        BUG();
 }
+EXPORT_SYMBOL_GPL(d_materialise_unique);
 
 static int prepend(char **buffer, int *buflen, const char *str, int namelen)
 {
@@ -1910,7 +1928,7 @@ char *__d_path(const struct path *path, struct path *root,
 
        spin_lock(&vfsmount_lock);
        prepend(&end, &buflen, "\0", 1);
-       if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+       if (d_unlinked(dentry) &&
                (prepend(&end, &buflen, " (deleted)", 10) != 0))
                        goto Elong;
 
@@ -2003,6 +2021,7 @@ char *d_path(const struct path *path, char *buf, int buflen)
        path_put(&root);
        return res;
 }
+EXPORT_SYMBOL(d_path);
 
 /*
  * Helper function for dentry_operations.d_dname() members
@@ -2035,7 +2054,7 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen)
 
        spin_lock(&dcache_lock);
        prepend(&end, &buflen, "\0", 1);
-       if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+       if (d_unlinked(dentry) &&
                (prepend(&end, &buflen, "//deleted", 9) != 0))
                        goto Elong;
        if (buflen < 1)
@@ -2097,9 +2116,8 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
        read_unlock(&current->fs->lock);
 
        error = -ENOENT;
-       /* Has the current directory has been unlinked? */
        spin_lock(&dcache_lock);
-       if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
+       if (!d_unlinked(pwd.dentry)) {
                unsigned long len;
                struct path tmp = root;
                char * cwd;
@@ -2170,6 +2188,30 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
        return result;
 }
 
+int path_is_under(struct path *path1, struct path *path2)
+{
+       struct vfsmount *mnt = path1->mnt;
+       struct dentry *dentry = path1->dentry;
+       int res;
+       spin_lock(&vfsmount_lock);
+       if (mnt != path2->mnt) {
+               for (;;) {
+                       if (mnt->mnt_parent == mnt) {
+                               spin_unlock(&vfsmount_lock);
+                               return 0;
+                       }
+                       if (mnt->mnt_parent == path2->mnt)
+                               break;
+                       mnt = mnt->mnt_parent;
+               }
+               dentry = mnt->mnt_mountpoint;
+       }
+       res = is_subdir(dentry, path2->dentry);
+       spin_unlock(&vfsmount_lock);
+       return res;
+}
+EXPORT_SYMBOL(path_is_under);
+
 void d_genocide(struct dentry *root)
 {
        struct dentry *this_parent = root;
@@ -2227,6 +2269,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
        }
        return ino;
 }
+EXPORT_SYMBOL(find_inode_number);
 
 static __initdata unsigned long dhash_entries;
 static int __init set_dhash_entries(char *str)
@@ -2296,6 +2339,7 @@ static void __init dcache_init(void)
 
 /* SLAB cache for __getname() consumers */
 struct kmem_cache *names_cachep __read_mostly;
+EXPORT_SYMBOL(names_cachep);
 
 EXPORT_SYMBOL(d_genocide);
 
@@ -2325,26 +2369,3 @@ void __init vfs_caches_init(unsigned long mempages)
        bdev_cache_init();
        chrdev_init();
 }
-
-EXPORT_SYMBOL(d_alloc);
-EXPORT_SYMBOL(d_alloc_root);
-EXPORT_SYMBOL(d_delete);
-EXPORT_SYMBOL(d_find_alias);
-EXPORT_SYMBOL(d_instantiate);
-EXPORT_SYMBOL(d_invalidate);
-EXPORT_SYMBOL(d_lookup);
-EXPORT_SYMBOL(d_move);
-EXPORT_SYMBOL_GPL(d_materialise_unique);
-EXPORT_SYMBOL(d_path);
-EXPORT_SYMBOL(d_prune_aliases);
-EXPORT_SYMBOL(d_rehash);
-EXPORT_SYMBOL(d_splice_alias);
-EXPORT_SYMBOL(d_add_ci);
-EXPORT_SYMBOL(d_validate);
-EXPORT_SYMBOL(dget_locked);
-EXPORT_SYMBOL(dput);
-EXPORT_SYMBOL(find_inode_number);
-EXPORT_SYMBOL(have_submounts);
-EXPORT_SYMBOL(names_cachep);
-EXPORT_SYMBOL(shrink_dcache_parent);
-EXPORT_SYMBOL(shrink_dcache_sb);