cifs: fix misspelling of "forcedirectio"
[linux-flexiantxendom0-3.2.10.git] / fs / dcache.c
index 0c6d5c5..b80531c 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/hash.h>
 #include <linux/cache.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mount.h>
 #include <linux/file.h>
 #include <asm/uaccess.h>
 #include <linux/hardirq.h>
 #include <linux/bit_spinlock.h>
 #include <linux/rculist_bl.h>
+#include <linux/prefetch.h>
+#include <linux/ratelimit.h>
 #include "internal.h"
+#include "mount.h"
 
 /*
  * Usage:
@@ -99,29 +102,16 @@ static struct kmem_cache *dentry_cache __read_mostly;
 static unsigned int d_hash_mask __read_mostly;
 static unsigned int d_hash_shift __read_mostly;
 
-struct dcache_hash_bucket {
-       struct hlist_bl_head head;
-};
-static struct dcache_hash_bucket *dentry_hashtable __read_mostly;
+static struct hlist_bl_head *dentry_hashtable __read_mostly;
 
-static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
-                                       unsigned long hash)
+static inline struct hlist_bl_head *d_hash(const struct dentry *parent,
+                                       unsigned int hash)
 {
-       hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
-       hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS);
+       hash += (unsigned long) parent / L1_CACHE_BYTES;
+       hash = hash + (hash >> D_HASHBITS);
        return dentry_hashtable + (hash & D_HASHMASK);
 }
 
-static inline void spin_lock_bucket(struct dcache_hash_bucket *b)
-{
-       bit_spin_lock(0, (unsigned long *)&b->head.first);
-}
-
-static inline void spin_unlock_bucket(struct dcache_hash_bucket *b)
-{
-       __bit_spin_unlock(0, (unsigned long *)&b->head.first);
-}
-
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
@@ -147,6 +137,67 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 }
 #endif
 
+/*
+ * Compare 2 name strings, return 0 if they match, otherwise non-zero.
+ * The strings are both count bytes long, and count is non-zero.
+ */
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+
+#include <asm/word-at-a-time.h>
+/*
+ * NOTE! 'cs' and 'scount' come from a dentry, so it has a
+ * aligned allocation for this particular component. We don't
+ * strictly need the load_unaligned_zeropad() safety, but it
+ * doesn't hurt either.
+ *
+ * In contrast, 'ct' and 'tcount' can be from a pathname, and do
+ * need the careful unaligned handling.
+ */
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+                               const unsigned char *ct, size_t tcount)
+{
+       unsigned long a,b,mask;
+
+       if (unlikely(scount != tcount))
+               return 1;
+
+       for (;;) {
+               a = load_unaligned_zeropad(cs);
+               b = load_unaligned_zeropad(ct);
+               if (tcount < sizeof(unsigned long))
+                       break;
+               if (unlikely(a != b))
+                       return 1;
+               cs += sizeof(unsigned long);
+               ct += sizeof(unsigned long);
+               tcount -= sizeof(unsigned long);
+               if (!tcount)
+                       return 0;
+       }
+       mask = ~(~0ul << tcount*8);
+       return unlikely(!!((a ^ b) & mask));
+}
+
+#else
+
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+                               const unsigned char *ct, size_t tcount)
+{
+       if (scount != tcount)
+               return 1;
+
+       do {
+               if (*cs != *ct)
+                       return 1;
+               cs++;
+               ct++;
+               tcount--;
+       } while (tcount);
+       return 0;
+}
+
+#endif
+
 static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
@@ -167,8 +218,8 @@ static void d_free(struct dentry *dentry)
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
 
-       /* if dentry was never inserted into hash, immediate free is OK */
-       if (hlist_bl_unhashed(&dentry->d_hash))
+       /* if dentry was never visible to RCU, immediate free is OK */
+       if (!(dentry->d_flags & DCACHE_RCUACCESS))
                __d_free(&dentry->d_u.d_rcu);
        else
                call_rcu(&dentry->d_u.d_rcu, __d_free);
@@ -176,6 +227,7 @@ static void d_free(struct dentry *dentry)
 
 /**
  * dentry_rcuwalk_barrier - invalidate in-progress rcu-walk lookups
+ * @dentry: the target dentry
  * After this call, in-progress rcu-walk path lookup will fail. This
  * should be called after unhashing, and after changing d_inode (if
  * the dentry has not already been unhashed).
@@ -236,7 +288,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 }
 
 /*
- * dentry_lru_(add|del|move_tail) must be called with d_lock held.
+ * dentry_lru_(add|del|prune|move_tail) must be called with d_lock held.
  */
 static void dentry_lru_add(struct dentry *dentry)
 {
@@ -252,10 +304,14 @@ static void dentry_lru_add(struct dentry *dentry)
 static void __dentry_lru_del(struct dentry *dentry)
 {
        list_del_init(&dentry->d_lru);
+       dentry->d_flags &= ~DCACHE_SHRINK_LIST;
        dentry->d_sb->s_nr_dentry_unused--;
        dentry_stat.nr_unused--;
 }
 
+/*
+ * Remove a dentry with references from the LRU.
+ */
 static void dentry_lru_del(struct dentry *dentry)
 {
        if (!list_empty(&dentry->d_lru)) {
@@ -265,15 +321,32 @@ static void dentry_lru_del(struct dentry *dentry)
        }
 }
 
-static void dentry_lru_move_tail(struct dentry *dentry)
+/*
+ * Remove a dentry that is unreferenced and about to be pruned
+ * (unhashed and destroyed) from the LRU, and inform the file system.
+ * This wrapper should be called _prior_ to unhashing a victim dentry.
+ */
+static void dentry_lru_prune(struct dentry *dentry)
+{
+       if (!list_empty(&dentry->d_lru)) {
+               if (dentry->d_flags & DCACHE_OP_PRUNE)
+                       dentry->d_op->d_prune(dentry);
+
+               spin_lock(&dcache_lru_lock);
+               __dentry_lru_del(dentry);
+               spin_unlock(&dcache_lru_lock);
+       }
+}
+
+static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
 {
        spin_lock(&dcache_lru_lock);
        if (list_empty(&dentry->d_lru)) {
-               list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+               list_add_tail(&dentry->d_lru, list);
                dentry->d_sb->s_nr_dentry_unused++;
                dentry_stat.nr_unused++;
        } else {
-               list_move_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+               list_move_tail(&dentry->d_lru, list);
        }
        spin_unlock(&dcache_lru_lock);
 }
@@ -281,6 +354,7 @@ static void dentry_lru_move_tail(struct dentry *dentry)
 /**
  * d_kill - kill dentry and return parent
  * @dentry: dentry to kill
+ * @parent: parent dentry
  *
  * The dentry must already be unhashed and removed from the LRU.
  *
@@ -294,8 +368,12 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        __releases(parent->d_lock)
        __releases(dentry->d_inode->i_lock)
 {
-       dentry->d_parent = NULL;
        list_del(&dentry->d_u.d_child);
+       /*
+        * Inform try_to_ascend() that we are no longer attached to the
+        * dentry tree
+        */
+       dentry->d_flags |= DCACHE_DISCONNECTED;
        if (parent)
                spin_unlock(&parent->d_lock);
        dentry_iput(dentry);
@@ -307,6 +385,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        return parent;
 }
 
+/*
+ * Unhash a dentry without inserting an RCU walk barrier or checking that
+ * dentry->d_lock is locked.  The caller must take care of that, if
+ * appropriate.
+ */
+static void __d_shrink(struct dentry *dentry)
+{
+       if (!d_unhashed(dentry)) {
+               struct hlist_bl_head *b;
+               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
+                       b = &dentry->d_sb->s_anon;
+               else
+                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
+
+               hlist_bl_lock(b);
+               __hlist_bl_del(&dentry->d_hash);
+               dentry->d_hash.pprev = NULL;
+               hlist_bl_unlock(b);
+       }
+}
+
 /**
  * d_drop - drop a dentry
  * @dentry: dentry to drop
@@ -324,28 +423,9 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
  */
 void __d_drop(struct dentry *dentry)
 {
-       if (!(dentry->d_flags & DCACHE_UNHASHED)) {
-               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) {
-                       bit_spin_lock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_init(&dentry->d_hash);
-                       __bit_spin_unlock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-               } else {
-                       struct dcache_hash_bucket *b;
-                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
-                       spin_lock_bucket(b);
-                       /*
-                        * We may not actually need to put DCACHE_UNHASHED
-                        * manipulations under the hash lock, but follow
-                        * the principle of least surprise.
-                        */
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_rcu(&dentry->d_hash);
-                       spin_unlock_bucket(b);
-                       dentry_rcuwalk_barrier(dentry);
-               }
+       if (!d_unhashed(dentry)) {
+               __d_shrink(dentry);
+               dentry_rcuwalk_barrier(dentry);
        }
 }
 EXPORT_SYMBOL(__d_drop);
@@ -359,6 +439,24 @@ void d_drop(struct dentry *dentry)
 EXPORT_SYMBOL(d_drop);
 
 /*
+ * d_clear_need_lookup - drop a dentry from cache and clear the need lookup flag
+ * @dentry: dentry to drop
+ *
+ * This is called when we do a lookup on a placeholder dentry that needed to be
+ * looked up.  The dentry should have been hashed in order for it to be found by
+ * the lookup code, but now needs to be unhashed while we do the actual lookup
+ * and clear the DCACHE_NEED_LOOKUP flag.
+ */
+void d_clear_need_lookup(struct dentry *dentry)
+{
+       spin_lock(&dentry->d_lock);
+       __d_drop(dentry);
+       dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
+       spin_unlock(&dentry->d_lock);
+}
+EXPORT_SYMBOL(d_clear_need_lookup);
+
+/*
  * Finish off a dentry we've decided to kill.
  * dentry->d_lock must be held, returns with it unlocked.
  * If ref is non-zero, then decrement the refcount too.
@@ -389,8 +487,12 @@ relock:
 
        if (ref)
                dentry->d_count--;
-       /* if dentry was on the d_lru list delete it from there */
-       dentry_lru_del(dentry);
+       /*
+        * if dentry was on the d_lru list delete it from there.
+        * inform the fs via d_prune that this dentry is about to be
+        * unhashed and destroyed.
+        */
+       dentry_lru_prune(dentry);
        /* if it was on the hash then remove it */
        __d_drop(dentry);
        return d_kill(dentry, parent);
@@ -447,8 +549,13 @@ repeat:
        if (d_unhashed(dentry))
                goto kill_it;
 
-       /* Otherwise leave it cached and ensure it's on the LRU */
-       dentry->d_flags |= DCACHE_REFERENCED;
+       /*
+        * If this dentry needs lookup, don't set the referenced flag so that it
+        * is more likely to be cleaned up by the dcache shrinker in case of
+        * memory pressure.
+        */
+       if (!d_need_lookup(dentry))
+               dentry->d_flags |= DCACHE_REFERENCED;
        dentry_lru_add(dentry);
 
        dentry->d_count--;
@@ -503,9 +610,11 @@ int d_invalidate(struct dentry * dentry)
         * would make it unreachable from the root,
         * we might still populate it if it was a
         * working directory or similar).
+        * We also need to leave mountpoints alone,
+        * directory or not.
         */
-       if (dentry->d_count > 1) {
-               if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+       if (dentry->d_count > 1 && dentry->d_inode) {
+               if (S_ISDIR(dentry->d_inode->i_mode) || d_mountpoint(dentry)) {
                        spin_unlock(&dentry->d_lock);
                        return -EBUSY;
                }
@@ -541,10 +650,6 @@ repeat:
         */
        rcu_read_lock();
        ret = dentry->d_parent;
-       if (!ret) {
-               rcu_read_unlock();
-               goto out;
-       }
        spin_lock(&ret->d_lock);
        if (unlikely(ret != dentry->d_parent)) {
                spin_unlock(&ret->d_lock);
@@ -555,7 +660,6 @@ repeat:
        BUG_ON(!ret->d_count);
        ret->d_count++;
        spin_unlock(&ret->d_lock);
-out:
        return ret;
 }
 EXPORT_SYMBOL(dget_parent);
@@ -728,20 +832,22 @@ static void shrink_dentry_list(struct list_head *list)
 }
 
 /**
- * __shrink_dcache_sb - shrink the dentry LRU on a given superblock
- * @sb:                superblock to shrink dentry LRU.
- * @count:     number of entries to prune
- * @flags:     flags to control the dentry processing
+ * prune_dcache_sb - shrink the dcache
+ * @sb: superblock
+ * @count: number of entries to try to free
+ *
+ * Attempt to shrink the superblock dcache LRU by @count entries. This is
+ * done when we need more memory an called from the superblock shrinker
+ * function.
  *
- * If flags contains DCACHE_REFERENCED reference dentries will not be pruned.
+ * This function may fail to free any resources if all the dentries are in
+ * use.
  */
-static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
+void prune_dcache_sb(struct super_block *sb, int count)
 {
-       /* called from prune_dcache() and shrink_dcache_parent() */
        struct dentry *dentry;
        LIST_HEAD(referenced);
        LIST_HEAD(tmp);
-       int cnt = *count;
 
 relock:
        spin_lock(&dcache_lru_lock);
@@ -756,20 +862,15 @@ relock:
                        goto relock;
                }
 
-               /*
-                * If we are honouring the DCACHE_REFERENCED flag and the
-                * dentry has this flag set, don't free it.  Clear the flag
-                * and put it back on the LRU.
-                */
-               if (flags & DCACHE_REFERENCED &&
-                               dentry->d_flags & DCACHE_REFERENCED) {
+               if (dentry->d_flags & DCACHE_REFERENCED) {
                        dentry->d_flags &= ~DCACHE_REFERENCED;
                        list_move(&dentry->d_lru, &referenced);
                        spin_unlock(&dentry->d_lock);
                } else {
                        list_move_tail(&dentry->d_lru, &tmp);
+                       dentry->d_flags |= DCACHE_SHRINK_LIST;
                        spin_unlock(&dentry->d_lock);
-                       if (!--cnt)
+                       if (!--count)
                                break;
                }
                cond_resched_lock(&dcache_lru_lock);
@@ -779,83 +880,6 @@ relock:
        spin_unlock(&dcache_lru_lock);
 
        shrink_dentry_list(&tmp);
-
-       *count = cnt;
-}
-
-/**
- * prune_dcache - shrink the dcache
- * @count: number of entries to try to free
- *
- * Shrink the dcache. This is done when we need more memory, or simply when we
- * need to unmount something (at which point we need to unuse all dentries).
- *
- * This function may fail to free any resources if all the dentries are in use.
- */
-static void prune_dcache(int count)
-{
-       struct super_block *sb, *p = NULL;
-       int w_count;
-       int unused = dentry_stat.nr_unused;
-       int prune_ratio;
-       int pruned;
-
-       if (unused == 0 || count == 0)
-               return;
-       if (count >= unused)
-               prune_ratio = 1;
-       else
-               prune_ratio = unused / count;
-       spin_lock(&sb_lock);
-       list_for_each_entry(sb, &super_blocks, s_list) {
-               if (list_empty(&sb->s_instances))
-                       continue;
-               if (sb->s_nr_dentry_unused == 0)
-                       continue;
-               sb->s_count++;
-               /* Now, we reclaim unused dentrins with fairness.
-                * We reclaim them same percentage from each superblock.
-                * We calculate number of dentries to scan on this sb
-                * as follows, but the implementation is arranged to avoid
-                * overflows:
-                * number of dentries to scan on this sb =
-                * count * (number of dentries on this sb /
-                * number of dentries in the machine)
-                */
-               spin_unlock(&sb_lock);
-               if (prune_ratio != 1)
-                       w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1;
-               else
-                       w_count = sb->s_nr_dentry_unused;
-               pruned = w_count;
-               /*
-                * We need to be sure this filesystem isn't being unmounted,
-                * otherwise we could race with generic_shutdown_super(), and
-                * end up holding a reference to an inode while the filesystem
-                * is unmounted.  So we try to get s_umount, and make sure
-                * s_root isn't NULL.
-                */
-               if (down_read_trylock(&sb->s_umount)) {
-                       if ((sb->s_root != NULL) &&
-                           (!list_empty(&sb->s_dentry_lru))) {
-                               __shrink_dcache_sb(sb, &w_count,
-                                               DCACHE_REFERENCED);
-                               pruned -= w_count;
-                       }
-                       up_read(&sb->s_umount);
-               }
-               spin_lock(&sb_lock);
-               if (p)
-                       __put_super(p);
-               count -= pruned;
-               p = sb;
-               /* more work left to do? */
-               if (count <= 0)
-                       break;
-       }
-       if (p)
-               __put_super(p);
-       spin_unlock(&sb_lock);
 }
 
 /**
@@ -888,44 +912,28 @@ EXPORT_SYMBOL(shrink_dcache_sb);
 static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 {
        struct dentry *parent;
-       unsigned detached = 0;
 
        BUG_ON(!IS_ROOT(dentry));
 
-       /* detach this root from the system */
-       spin_lock(&dentry->d_lock);
-       dentry_lru_del(dentry);
-       __d_drop(dentry);
-       spin_unlock(&dentry->d_lock);
-
        for (;;) {
                /* descend to the first leaf in the current subtree */
-               while (!list_empty(&dentry->d_subdirs)) {
-                       struct dentry *loop;
-
-                       /* this is a branch with children - detach all of them
-                        * from the system in one go */
-                       spin_lock(&dentry->d_lock);
-                       list_for_each_entry(loop, &dentry->d_subdirs,
-                                           d_u.d_child) {
-                               spin_lock_nested(&loop->d_lock,
-                                               DENTRY_D_LOCK_NESTED);
-                               dentry_lru_del(loop);
-                               __d_drop(loop);
-                               spin_unlock(&loop->d_lock);
-                       }
-                       spin_unlock(&dentry->d_lock);
-
-                       /* move to the first child */
+               while (!list_empty(&dentry->d_subdirs))
                        dentry = list_entry(dentry->d_subdirs.next,
                                            struct dentry, d_u.d_child);
-               }
 
                /* consume the dentries from this leaf up through its parents
                 * until we find one with children or run out altogether */
                do {
                        struct inode *inode;
 
+                       /*
+                        * remove the dentry from the lru, and inform
+                        * the fs that this dentry is about to be
+                        * unhashed and destroyed.
+                        */
+                       dentry_lru_prune(dentry);
+                       __d_shrink(dentry);
+
                        if (dentry->d_count != 0) {
                                printk(KERN_ERR
                                       "BUG: Dentry %p{i=%lx,n=%s}"
@@ -946,14 +954,10 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                                list_del(&dentry->d_u.d_child);
                        } else {
                                parent = dentry->d_parent;
-                               spin_lock(&parent->d_lock);
                                parent->d_count--;
                                list_del(&dentry->d_u.d_child);
-                               spin_unlock(&parent->d_lock);
                        }
 
-                       detached++;
-
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
@@ -998,9 +1002,7 @@ void shrink_dcache_for_umount(struct super_block *sb)
 
        dentry = sb->s_root;
        sb->s_root = NULL;
-       spin_lock(&dentry->d_lock);
        dentry->d_count--;
-       spin_unlock(&dentry->d_lock);
        shrink_dcache_for_umount_subtree(dentry);
 
        while (!hlist_bl_empty(&sb->s_anon)) {
@@ -1010,6 +1012,35 @@ void shrink_dcache_for_umount(struct super_block *sb)
 }
 
 /*
+ * This tries to ascend one level of parenthood, but
+ * we can race with renaming, so we need to re-check
+ * the parenthood after dropping the lock and check
+ * that the sequence number still matches.
+ */
+static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq)
+{
+       struct dentry *new = old->d_parent;
+
+       rcu_read_lock();
+       spin_unlock(&old->d_lock);
+       spin_lock(&new->d_lock);
+
+       /*
+        * might go back up the wrong parent if we have had a rename
+        * or deletion
+        */
+       if (new != old->d_parent ||
+                (old->d_flags & DCACHE_DISCONNECTED) ||
+                (!locked && read_seqretry(&rename_lock, seq))) {
+               spin_unlock(&new->d_lock);
+               new = NULL;
+       }
+       rcu_read_unlock();
+       return new;
+}
+
+
+/*
  * Search for at least 1 mount point in the dentry's subdirs.
  * We descend to the next level whenever the d_subdirs
  * list is non-empty and continue searching.
@@ -1064,24 +1095,10 @@ resume:
         * All done at this level ... ascend and resume the search.
         */
        if (this_parent != parent) {
-               struct dentry *tmp;
-               struct dentry *child;
-
-               tmp = this_parent->d_parent;
-               rcu_read_lock();
-               spin_unlock(&this_parent->d_lock);
-               child = this_parent;
-               this_parent = tmp;
-               spin_lock(&this_parent->d_lock);
-               /* might go back up the wrong parent if we have had a rename
-                * or deletion */
-               if (this_parent != child->d_parent ||
-                        (!locked && read_seqretry(&rename_lock, seq))) {
-                       spin_unlock(&this_parent->d_lock);
-                       rcu_read_unlock();
+               struct dentry *child = this_parent;
+               this_parent = try_to_ascend(this_parent, locked, seq);
+               if (!this_parent)
                        goto rename_retry;
-               }
-               rcu_read_unlock();
                next = child->d_u.d_child.next;
                goto resume;
        }
@@ -1119,7 +1136,7 @@ EXPORT_SYMBOL(have_submounts);
  * drop the lock and return early due to latency
  * constraints.
  */
-static int select_parent(struct dentry * parent)
+static int select_parent(struct dentry *parent, struct list_head *dispose)
 {
        struct dentry *this_parent;
        struct list_head *next;
@@ -1141,17 +1158,21 @@ resume:
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 
-               /* 
-                * move only zero ref count dentries to the end 
-                * of the unused list for prune_dcache
+               /*
+                * move only zero ref count dentries to the dispose list.
+                *
+                * Those which are presently on the shrink list, being processed
+                * by shrink_dentry_list(), shouldn't be moved.  Otherwise the
+                * loop in shrink_dcache_parent() might not make any progress
+                * and loop forever.
                 */
-               if (!dentry->d_count) {
-                       dentry_lru_move_tail(dentry);
-                       found++;
-               } else {
+               if (dentry->d_count) {
                        dentry_lru_del(dentry);
+               } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
+                       dentry_lru_move_list(dentry, dispose);
+                       dentry->d_flags |= DCACHE_SHRINK_LIST;
+                       found++;
                }
-
                /*
                 * We can return to the caller if we have found some (this
                 * ensures forward progress). We'll be coming back to find
@@ -1179,24 +1200,10 @@ resume:
         * All done at this level ... ascend and resume the search.
         */
        if (this_parent != parent) {
-               struct dentry *tmp;
-               struct dentry *child;
-
-               tmp = this_parent->d_parent;
-               rcu_read_lock();
-               spin_unlock(&this_parent->d_lock);
-               child = this_parent;
-               this_parent = tmp;
-               spin_lock(&this_parent->d_lock);
-               /* might go back up the wrong parent if we have had a rename
-                * or deletion */
-               if (this_parent != child->d_parent ||
-                       (!locked && read_seqretry(&rename_lock, seq))) {
-                       spin_unlock(&this_parent->d_lock);
-                       rcu_read_unlock();
+               struct dentry *child = this_parent;
+               this_parent = try_to_ascend(this_parent, locked, seq);
+               if (!this_parent)
                        goto rename_retry;
-               }
-               rcu_read_unlock();
                next = child->d_u.d_child.next;
                goto resume;
        }
@@ -1222,48 +1229,19 @@ rename_retry:
  *
  * Prune the dcache to remove unused children of the parent dentry.
  */
 void shrink_dcache_parent(struct dentry * parent)
 {
-       struct super_block *sb = parent->d_sb;
+       LIST_HEAD(dispose);
        int found;
 
-       while ((found = select_parent(parent)) != 0)
-               __shrink_dcache_sb(sb, &found, 0);
+       while ((found = select_parent(parent, &dispose)) != 0)
+               shrink_dentry_list(&dispose);
 }
 EXPORT_SYMBOL(shrink_dcache_parent);
 
-/*
- * Scan `nr' dentries and return the number which remain.
- *
- * We need to avoid reentering the filesystem if the caller is performing a
- * GFP_NOFS allocation attempt.  One example deadlock is:
- *
- * ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache->
- * prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->put_inode->
- * ext2_discard_prealloc->ext2_free_blocks->lock_super->DEADLOCK.
- *
- * In this case we return -1 to tell the caller that we baled.
- */
-static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
-{
-       if (nr) {
-               if (!(gfp_mask & __GFP_FS))
-                       return -1;
-               prune_dcache(nr);
-       }
-
-       return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
-}
-
-static struct shrinker dcache_shrinker = {
-       .shrink = shrink_dcache_memory,
-       .seeks = DEFAULT_SEEKS,
-};
-
 /**
- * d_alloc     -       allocate a dcache entry
- * @parent: parent of entry to allocate
+ * __d_alloc   -       allocate a dcache entry
+ * @sb: filesystem it will belong to
  * @name: qstr of the name
  *
  * Allocates a dentry. It returns %NULL if there is insufficient memory
@@ -1271,7 +1249,7 @@ static struct shrinker dcache_shrinker = {
  * copied and the copy passed in may be reused after this call.
  */
  
-struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
+struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
 {
        struct dentry *dentry;
        char *dname;
@@ -1297,12 +1275,12 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        dname[name->len] = 0;
 
        dentry->d_count = 1;
-       dentry->d_flags = DCACHE_UNHASHED;
+       dentry->d_flags = 0;
        spin_lock_init(&dentry->d_lock);
        seqcount_init(&dentry->d_seq);
        dentry->d_inode = NULL;
-       dentry->d_parent = NULL;
-       dentry->d_sb = NULL;
+       dentry->d_parent = dentry;
+       dentry->d_sb = sb;
        dentry->d_op = NULL;
        dentry->d_fsdata = NULL;
        INIT_HLIST_BL_NODE(&dentry->d_hash);
@@ -1310,36 +1288,47 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        INIT_LIST_HEAD(&dentry->d_subdirs);
        INIT_LIST_HEAD(&dentry->d_alias);
        INIT_LIST_HEAD(&dentry->d_u.d_child);
-
-       if (parent) {
-               spin_lock(&parent->d_lock);
-               /*
-                * don't need child lock because it is not subject
-                * to concurrency here
-                */
-               __dget_dlock(parent);
-               dentry->d_parent = parent;
-               dentry->d_sb = parent->d_sb;
-               d_set_d_op(dentry, dentry->d_sb->s_d_op);
-               list_add(&dentry->d_u.d_child, &parent->d_subdirs);
-               spin_unlock(&parent->d_lock);
-       }
+       d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
        this_cpu_inc(nr_dentry);
 
        return dentry;
 }
+
+/**
+ * d_alloc     -       allocate a dcache entry
+ * @parent: parent of entry to allocate
+ * @name: qstr of the name
+ *
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
+ * available. On a success the dentry is returned. The name passed in is
+ * copied and the copy passed in may be reused after this call.
+ */
+struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
+{
+       struct dentry *dentry = __d_alloc(parent->d_sb, name);
+       if (!dentry)
+               return NULL;
+
+       spin_lock(&parent->d_lock);
+       /*
+        * don't need child lock because it is not subject
+        * to concurrency here
+        */
+       __dget_dlock(parent);
+       dentry->d_parent = parent;
+       list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+       spin_unlock(&parent->d_lock);
+
+       return dentry;
+}
 EXPORT_SYMBOL(d_alloc);
 
 struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
 {
-       struct dentry *dentry = d_alloc(NULL, name);
-       if (dentry) {
-               dentry->d_sb = sb;
-               d_set_d_op(dentry, dentry->d_sb->s_d_op);
-               dentry->d_parent = dentry;
+       struct dentry *dentry = __d_alloc(sb, name);
+       if (dentry)
                dentry->d_flags |= DCACHE_DISCONNECTED;
-       }
        return dentry;
 }
 EXPORT_SYMBOL(d_alloc_pseudo);
@@ -1357,8 +1346,8 @@ EXPORT_SYMBOL(d_alloc_name);
 
 void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
 {
-       BUG_ON(dentry->d_op);
-       BUG_ON(dentry->d_flags & (DCACHE_OP_HASH        |
+       WARN_ON_ONCE(dentry->d_op);
+       WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH  |
                                DCACHE_OP_COMPARE       |
                                DCACHE_OP_REVALIDATE    |
                                DCACHE_OP_DELETE ));
@@ -1373,6 +1362,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
                dentry->d_flags |= DCACHE_OP_REVALIDATE;
        if (op->d_delete)
                dentry->d_flags |= DCACHE_OP_DELETE;
+       if (op->d_prune)
+               dentry->d_flags |= DCACHE_OP_PRUNE;
 
 }
 EXPORT_SYMBOL(d_set_d_op);
@@ -1380,8 +1371,11 @@ EXPORT_SYMBOL(d_set_d_op);
 static void __d_instantiate(struct dentry *dentry, struct inode *inode)
 {
        spin_lock(&dentry->d_lock);
-       if (inode)
+       if (inode) {
+               if (unlikely(IS_AUTOMOUNT(inode)))
+                       dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
                list_add(&dentry->d_alias, &inode->i_dentry);
+       }
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
@@ -1490,33 +1484,51 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 
 EXPORT_SYMBOL(d_instantiate_unique);
 
-/**
- * d_alloc_root - allocate root dentry
- * @root_inode: inode to allocate the root for
- *
- * Allocate a root ("/") dentry for the inode given. The inode is
- * instantiated and returned. %NULL is returned if there is insufficient
- * memory or the inode passed is %NULL.
- */
-struct dentry * d_alloc_root(struct inode * root_inode)
+struct dentry *d_make_root(struct inode *root_inode)
 {
        struct dentry *res = NULL;
 
        if (root_inode) {
                static const struct qstr name = { .name = "/", .len = 1 };
 
-               res = d_alloc(NULL, &name);
-               if (res) {
-                       res->d_sb = root_inode->i_sb;
-                       d_set_d_op(res, res->d_sb->s_d_op);
-                       res->d_parent = res;
+               res = __d_alloc(root_inode->i_sb, &name);
+               if (res)
                        d_instantiate(res, root_inode);
-               }
+               else
+                       iput(root_inode);
        }
        return res;
 }
-EXPORT_SYMBOL(d_alloc_root);
+EXPORT_SYMBOL(d_make_root);
+
+static struct dentry * __d_find_any_alias(struct inode *inode)
+{
+       struct dentry *alias;
+
+       if (list_empty(&inode->i_dentry))
+               return NULL;
+       alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
+       __dget(alias);
+       return alias;
+}
+
+/**
+ * d_find_any_alias - find any alias for a given inode
+ * @inode: inode to find an alias for
+ *
+ * If any aliases exist for the given inode, take and return a
+ * reference for one of them.  If no aliases exist, return %NULL.
+ */
+struct dentry *d_find_any_alias(struct inode *inode)
+{
+       struct dentry *de;
+
+       spin_lock(&inode->i_lock);
+       de = __d_find_any_alias(inode);
+       spin_unlock(&inode->i_lock);
+       return de;
+}
+EXPORT_SYMBOL(d_find_any_alias);
 
 /**
  * d_obtain_alias - find or allocate a dentry for a given inode
@@ -1547,20 +1559,18 @@ struct dentry *d_obtain_alias(struct inode *inode)
        if (IS_ERR(inode))
                return ERR_CAST(inode);
 
-       res = d_find_alias(inode);
+       res = d_find_any_alias(inode);
        if (res)
                goto out_iput;
 
-       tmp = d_alloc(NULL, &anonstring);
+       tmp = __d_alloc(inode->i_sb, &anonstring);
        if (!tmp) {
                res = ERR_PTR(-ENOMEM);
                goto out_iput;
        }
-       tmp->d_parent = tmp; /* make sure dput doesn't croak */
-
 
        spin_lock(&inode->i_lock);
-       res = __d_find_alias(inode, 0);
+       res = __d_find_any_alias(inode);
        if (res) {
                spin_unlock(&inode->i_lock);
                dput(tmp);
@@ -1569,21 +1579,21 @@ struct dentry *d_obtain_alias(struct inode *inode)
 
        /* attach a disconnected dentry */
        spin_lock(&tmp->d_lock);
-       tmp->d_sb = inode->i_sb;
-       d_set_d_op(tmp, tmp->d_sb->s_d_op);
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
        list_add(&tmp->d_alias, &inode->i_dentry);
-       bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
-       tmp->d_flags &= ~DCACHE_UNHASHED;
+       hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
-       __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
+       hlist_bl_unlock(&tmp->d_sb->s_anon);
        spin_unlock(&tmp->d_lock);
        spin_unlock(&inode->i_lock);
+       security_d_instantiate(tmp, inode);
 
        return tmp;
 
  out_iput:
+       if (res && !IS_ERR(res))
+               security_d_instantiate(res, inode);
        iput(inode);
        return res;
 }
@@ -1609,6 +1619,9 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
 {
        struct dentry *new = NULL;
 
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+
        if (inode && S_ISDIR(inode->i_mode)) {
                spin_lock(&inode->i_lock);
                new = __d_find_alias(inode, 1);
@@ -1691,29 +1704,22 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
        }
 
        /*
-        * Negative dentry: instantiate it unless the inode is a directory and
-        * already has a dentry.
+        * We are going to instantiate this dentry, unhash it and clear the
+        * lookup flag so we can do that.
         */
-       spin_lock(&inode->i_lock);
-       if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) {
-               __d_instantiate(found, inode);
-               spin_unlock(&inode->i_lock);
-               security_d_instantiate(found, inode);
-               return found;
-       }
+       if (unlikely(d_need_lookup(found)))
+               d_clear_need_lookup(found);
 
        /*
-        * In case a directory already has a (disconnected) entry grab a
-        * reference to it, move it in place and use it.
+        * Negative dentry: instantiate it unless the inode is a directory and
+        * already has a dentry.
         */
-       new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-       __dget(new);
-       spin_unlock(&inode->i_lock);
-       security_d_instantiate(found, inode);
-       d_move(new, found);
-       iput(inode);
-       dput(found);
-       return new;
+       new = d_splice_alias(inode, found);
+       if (new) {
+               dput(found);
+               found = new;
+       }
+       return found;
 
 err_out:
        iput(inode);
@@ -1725,7 +1731,7 @@ EXPORT_SYMBOL(d_add_ci);
  * __d_lookup_rcu - search for a dentry (racy, store-free)
  * @parent: parent dentry
  * @name: qstr of name we wish to find
- * @seq: returns d_seq value at the point where the dentry was found
+ * @seqp: returns d_seq value at the point where the dentry was found
  * @inode: returns dentry->d_inode when the inode was found valid.
  * Returns: dentry, or NULL
  *
@@ -1748,13 +1754,14 @@ EXPORT_SYMBOL(d_add_ci);
  * child is looked up. Thus, an interlocking stepping of sequence lock checks
  * is formed, giving integrity down the path walk.
  */
-struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
-                               unsigned *seq, struct inode **inode)
+struct dentry *__d_lookup_rcu(const struct dentry *parent,
+                               const struct qstr *name,
+                               unsigned *seqp, struct inode **inode)
 {
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *dentry;
 
@@ -1776,9 +1783,10 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
         * false-negative result. d_lookup() protects against concurrent
         * renames using rename_lock seqlock.
         *
-        * See Documentation/vfs/dcache-locking.txt for more details.
+        * See Documentation/filesystems/path-lookup.txt for more details.
         */
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
+               unsigned seq;
                struct inode *i;
                const char *tname;
                int tlen;
@@ -1787,7 +1795,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
                        continue;
 
 seqretry:
-               *seq = read_seqcount_begin(&dentry->d_seq);
+               seq = read_seqcount_begin(&dentry->d_seq);
                if (dentry->d_parent != parent)
                        continue;
                if (d_unhashed(dentry))
@@ -1796,17 +1804,15 @@ seqretry:
                tname = dentry->d_name.name;
                i = dentry->d_inode;
                prefetch(tname);
-               if (i)
-                       prefetch(i);
                /*
                 * This seqcount check is required to ensure name and
                 * len are loaded atomically, so as not to walk off the
                 * edge of memory when walking. If we could load this
                 * atomically some other way, we could drop this check.
                 */
-               if (read_seqcount_retry(&dentry->d_seq, *seq))
+               if (read_seqcount_retry(&dentry->d_seq, seq))
                        goto seqretry;
-               if (parent->d_flags & DCACHE_OP_COMPARE) {
+               if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
                        if (parent->d_op->d_compare(parent, *inode,
                                                dentry, i,
                                                tlen, tname, name))
@@ -1821,6 +1827,7 @@ seqretry:
                 * order to do anything useful with the returned dentry
                 * anyway.
                 */
+               *seqp = seq;
                *inode = i;
                return dentry;
        }
@@ -1873,7 +1880,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *found = NULL;
        struct dentry *dentry;
@@ -1896,11 +1903,11 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
         * false-negative result. d_lookup() protects against concurrent
         * renames using rename_lock seqlock.
         *
-        * See Documentation/vfs/dcache-locking.txt for more details.
+        * See Documentation/filesystems/path-lookup.txt for more details.
         */
        rcu_read_lock();
        
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
                const char *tname;
                int tlen;
 
@@ -1970,7 +1977,7 @@ out:
 /**
  * d_validate - verify dentry provided from insecure source (deprecated)
  * @dentry: The dentry alleged to be valid child of @dparent
- * @parent: The parent dentry (known to be valid)
+ * @dparent: The parent dentry (known to be valid)
  *
  * An insecure source has sent us a dentry, here we verify it and dget() it.
  * This is used by ncpfs in its readdir implementation.
@@ -2051,13 +2058,13 @@ again:
 }
 EXPORT_SYMBOL(d_delete);
 
-static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b)
+static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
 {
        BUG_ON(!d_unhashed(entry));
-       spin_lock_bucket(b);
-       entry->d_flags &= ~DCACHE_UNHASHED;
-       hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
-       spin_unlock_bucket(b);
+       hlist_bl_lock(b);
+       entry->d_flags |= DCACHE_RCUACCESS;
+       hlist_bl_add_head_rcu(&entry->d_hash, b);
+       hlist_bl_unlock(b);
 }
 
 static void _d_rehash(struct dentry * entry)
@@ -2096,7 +2103,7 @@ EXPORT_SYMBOL(d_rehash);
  */
 void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
 {
-       BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+       BUG_ON(!mutex_is_locked(&dentry->d_parent->d_inode->i_mutex));
        BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */
 
        spin_lock(&dentry->d_lock);
@@ -2196,14 +2203,16 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry,
  * The hash value has to match the hash queue that the dentry is on..
  */
 /*
- * d_move - move a dentry
+ * __d_move - move a dentry
  * @dentry: entry to move
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.
+ * dcache entries should not be moved in this way. Caller must hold
+ * rename_lock, the i_mutex of the source and target directories,
+ * and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
  */
-void d_move(struct dentry * dentry, struct dentry * target)
+static void __d_move(struct dentry * dentry, struct dentry * target)
 {
        if (!dentry->d_inode)
                printk(KERN_WARNING "VFS: moving negative dcache entry\n");
@@ -2211,8 +2220,6 @@ void d_move(struct dentry * dentry, struct dentry * target)
        BUG_ON(d_ancestor(dentry, target));
        BUG_ON(d_ancestor(target, dentry));
 
-       write_seqlock(&rename_lock);
-
        dentry_lock_for_move(dentry, target);
 
        write_seqcount_begin(&dentry->d_seq);
@@ -2258,6 +2265,21 @@ void d_move(struct dentry * dentry, struct dentry * target)
        spin_unlock(&target->d_lock);
        fsnotify_d_move(dentry);
        spin_unlock(&dentry->d_lock);
+}
+
+/*
+ * d_move - move a dentry
+ * @dentry: entry to move
+ * @target: new dentry
+ *
+ * Update the dcache to reflect the move of a file name. Negative
+ * dcache entries should not be moved in this way. See the locking
+ * requirements for __d_move.
+ */
+void d_move(struct dentry *dentry, struct dentry *target)
+{
+       write_seqlock(&rename_lock);
+       __d_move(dentry, target);
        write_sequnlock(&rename_lock);
 }
 EXPORT_SYMBOL(d_move);
@@ -2285,7 +2307,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
  * This helper attempts to cope with remotely renamed directories
  *
  * It assumes that the caller is already holding
- * dentry->d_parent->d_inode->i_mutex and the inode->i_lock
+ * dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock
  *
  * Note: If ever the locking in lock_rename() changes, then please
  * remember to update this too...
@@ -2300,11 +2322,6 @@ static struct dentry *__d_unalias(struct inode *inode,
        if (alias->d_parent == dentry->d_parent)
                goto out_unalias;
 
-       /* Check for loops */
-       ret = ERR_PTR(-ELOOP);
-       if (d_ancestor(alias, dentry))
-               goto out_err;
-
        /* See lock_rename() */
        ret = ERR_PTR(-EBUSY);
        if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
@@ -2314,7 +2331,7 @@ static struct dentry *__d_unalias(struct inode *inode,
                goto out_err;
        m2 = &alias->d_parent->d_inode->i_mutex;
 out_unalias:
-       d_move(alias, dentry);
+       __d_move(alias, dentry);
        ret = alias;
 out_err:
        spin_unlock(&inode->i_lock);
@@ -2375,7 +2392,8 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
  * @inode: inode to bind to the dentry, to which aliases may be attached
  *
  * Introduces an dentry into the tree, substituting an extant disconnected
- * root directory alias in its place if there is one
+ * root directory alias in its place if there is one. Caller must hold the
+ * i_mutex of the parent directory.
  */
 struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
 {
@@ -2399,17 +2417,35 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
                alias = __d_find_alias(inode, 0);
                if (alias) {
                        actual = alias;
-                       /* Is this an anonymous mountpoint that we could splice
-                        * into our tree? */
-                       if (IS_ROOT(alias)) {
+                       write_seqlock(&rename_lock);
+
+                       if (d_ancestor(alias, dentry)) {
+                               /* Check for loops */
+                               actual = ERR_PTR(-ELOOP);
+                               spin_unlock(&inode->i_lock);
+                       } else if (IS_ROOT(alias)) {
+                               /* Is this an anonymous mountpoint that we
+                                * could splice into our tree? */
                                __d_materialise_dentry(dentry, alias);
+                               write_sequnlock(&rename_lock);
                                __d_drop(alias);
                                goto found;
+                       } else {
+                               /* Nope, but we must(!) avoid directory
+                                * aliasing. This drops inode->i_lock */
+                               actual = __d_unalias(inode, dentry, alias);
                        }
-                       /* Nope, but we must(!) avoid directory aliasing */
-                       actual = __d_unalias(inode, dentry, alias);
-                       if (IS_ERR(actual))
+                       write_sequnlock(&rename_lock);
+                       if (IS_ERR(actual)) {
+                               if (PTR_ERR(actual) == -ELOOP)
+                                       pr_warn_ratelimited(
+                                               "VFS: Lookup of '%s' in %s %s"
+                                               " would have caused loop\n",
+                                               dentry->d_name.name,
+                                               inode->i_sb->s_type->name,
+                                               inode->i_sb->s_id);
                                dput(alias);
+                       }
                        goto out_nolock;
                }
        }
@@ -2455,20 +2491,19 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
 /**
  * prepend_path - Prepend path string to a buffer
  * @path: the dentry/vfsmount to report
- * @root: root vfsmnt/dentry (may be modified by this function)
+ * @root: root vfsmnt/dentry
  * @buffer: pointer to the end of the buffer
  * @buflen: pointer to buffer length
  *
  * Caller holds the rename_lock.
- *
- * If path is not reachable from the supplied root, then the value of
- * root is changed (without modifying refcounts).
  */
-static int prepend_path(const struct path *path, struct path *root,
+static int prepend_path(const struct path *path,
+                       const struct path *root,
                        char **buffer, int *buflen)
 {
        struct dentry *dentry = path->dentry;
        struct vfsmount *vfsmnt = path->mnt;
+       struct mount *mnt = real_mount(vfsmnt);
        bool slash = false;
        int error = 0;
 
@@ -2478,11 +2513,11 @@ static int prepend_path(const struct path *path, struct path *root,
 
                if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
                        /* Global root? */
-                       if (vfsmnt->mnt_parent == vfsmnt) {
+                       if (!mnt_has_parent(mnt))
                                goto global_root;
-                       }
-                       dentry = vfsmnt->mnt_mountpoint;
-                       vfsmnt = vfsmnt->mnt_parent;
+                       dentry = mnt->mnt_mountpoint;
+                       mnt = mnt->mnt_parent;
+                       vfsmnt = &mnt->mnt;
                        continue;
                }
                parent = dentry->d_parent;
@@ -2499,10 +2534,10 @@ static int prepend_path(const struct path *path, struct path *root,
                dentry = parent;
        }
 
-out:
        if (!error && !slash)
                error = prepend(buffer, buflen, "/", 1);
 
+out:
        br_read_unlock(vfsmount_lock);
        return error;
 
@@ -2516,15 +2551,17 @@ global_root:
                WARN(1, "Root dentry has weird name <%.*s>\n",
                     (int) dentry->d_name.len, dentry->d_name.name);
        }
-       root->mnt = vfsmnt;
-       root->dentry = dentry;
+       if (!slash)
+               error = prepend(buffer, buflen, "/", 1);
+       if (!error)
+               error = real_mount(vfsmnt)->mnt_ns ? 1 : 2;
        goto out;
 }
 
 /**
  * __d_path - return the path of a dentry
  * @path: the dentry/vfsmount to report
- * @root: root vfsmnt/dentry (may be modified by this function)
+ * @root: root vfsmnt/dentry
  * @buf: buffer to return value in
  * @buflen: buffer length
  *
@@ -2535,10 +2572,10 @@ global_root:
  *
  * "buflen" should be positive.
  *
- * If path is not reachable from the supplied root, then the value of
- * root is changed (without modifying refcounts).
+ * If the path is not reachable from the supplied root, return %NULL.
  */
-char *__d_path(const struct path *path, struct path *root,
+char *__d_path(const struct path *path,
+              const struct path *root,
               char *buf, int buflen)
 {
        char *res = buf + buflen;
@@ -2549,7 +2586,28 @@ char *__d_path(const struct path *path, struct path *root,
        error = prepend_path(path, root, &res, &buflen);
        write_sequnlock(&rename_lock);
 
-       if (error)
+       if (error < 0)
+               return ERR_PTR(error);
+       if (error > 0)
+               return NULL;
+       return res;
+}
+
+char *d_absolute_path(const struct path *path,
+              char *buf, int buflen)
+{
+       struct path root = {};
+       char *res = buf + buflen;
+       int error;
+
+       prepend(&res, &buflen, "\0", 1);
+       write_seqlock(&rename_lock);
+       error = prepend_path(path, &root, &res, &buflen);
+       write_sequnlock(&rename_lock);
+
+       if (error > 1)
+               error = -EINVAL;
+       if (error < 0)
                return ERR_PTR(error);
        return res;
 }
@@ -2557,8 +2615,9 @@ char *__d_path(const struct path *path, struct path *root,
 /*
  * same as __d_path but appends "(deleted)" for unlinked files.
  */
-static int path_with_deleted(const struct path *path, struct path *root,
-                                char **buf, int *buflen)
+static int path_with_deleted(const struct path *path,
+                            const struct path *root,
+                            char **buf, int *buflen)
 {
        prepend(buf, buflen, "\0", 1);
        if (d_unlinked(path->dentry)) {
@@ -2595,7 +2654,6 @@ char *d_path(const struct path *path, char *buf, int buflen)
 {
        char *res = buf + buflen;
        struct path root;
-       struct path tmp;
        int error;
 
        /*
@@ -2610,9 +2668,8 @@ char *d_path(const struct path *path, char *buf, int buflen)
 
        get_fs_root(current->fs, &root);
        write_seqlock(&rename_lock);
-       tmp = root;
-       error = path_with_deleted(path, &tmp, &res, &buflen);
-       if (error)
+       error = path_with_deleted(path, &root, &res, &buflen);
+       if (error < 0)
                res = ERR_PTR(error);
        write_sequnlock(&rename_lock);
        path_put(&root);
@@ -2633,7 +2690,6 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
 {
        char *res = buf + buflen;
        struct path root;
-       struct path tmp;
        int error;
 
        if (path->dentry->d_op && path->dentry->d_op->d_dname)
@@ -2641,9 +2697,8 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
 
        get_fs_root(current->fs, &root);
        write_seqlock(&rename_lock);
-       tmp = root;
-       error = path_with_deleted(path, &tmp, &res, &buflen);
-       if (!error && !path_equal(&tmp, &root))
+       error = path_with_deleted(path, &root, &res, &buflen);
+       if (error > 0)
                error = prepend_unreachable(&res, &buflen);
        write_sequnlock(&rename_lock);
        path_put(&root);
@@ -2774,19 +2829,18 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
        write_seqlock(&rename_lock);
        if (!d_unlinked(pwd.dentry)) {
                unsigned long len;
-               struct path tmp = root;
                char *cwd = page + PAGE_SIZE;
                int buflen = PAGE_SIZE;
 
                prepend(&cwd, &buflen, "\0", 1);
-               error = prepend_path(&pwd, &tmp, &cwd, &buflen);
+               error = prepend_path(&pwd, &root, &cwd, &buflen);
                write_sequnlock(&rename_lock);
 
-               if (error)
+               if (error < 0)
                        goto out;
 
                /* Unreachable from current root */
-               if (!path_equal(&tmp, &root)) {
+               if (error > 0) {
                        error = prepend_unreachable(&cwd, &buflen);
                        if (error)
                                goto out;
@@ -2852,31 +2906,6 @@ 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;
-
-       br_read_lock(vfsmount_lock);
-       if (mnt != path2->mnt) {
-               for (;;) {
-                       if (mnt->mnt_parent == mnt) {
-                               br_read_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);
-       br_read_unlock(vfsmount_lock);
-       return res;
-}
-EXPORT_SYMBOL(path_is_under);
-
 void d_genocide(struct dentry *root)
 {
        struct dentry *this_parent;
@@ -2915,28 +2944,14 @@ resume:
                spin_unlock(&dentry->d_lock);
        }
        if (this_parent != root) {
-               struct dentry *tmp;
-               struct dentry *child;
-
-               tmp = this_parent->d_parent;
+               struct dentry *child = this_parent;
                if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
                        this_parent->d_flags |= DCACHE_GENOCIDE;
                        this_parent->d_count--;
                }
-               rcu_read_lock();
-               spin_unlock(&this_parent->d_lock);
-               child = this_parent;
-               this_parent = tmp;
-               spin_lock(&this_parent->d_lock);
-               /* might go back up the wrong parent if we have had a rename
-                * or deletion */
-               if (this_parent != child->d_parent ||
-                        (!locked && read_seqretry(&rename_lock, seq))) {
-                       spin_unlock(&this_parent->d_lock);
-                       rcu_read_unlock();
+               this_parent = try_to_ascend(this_parent, locked, seq);
+               if (!this_parent)
                        goto rename_retry;
-               }
-               rcu_read_unlock();
                next = child->d_u.d_child.next;
                goto resume;
        }
@@ -2994,7 +3009,7 @@ __setup("dhash_entries=", set_dhash_entries);
 
 static void __init dcache_init_early(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* If hashes are distributed across NUMA nodes, defer
         * hash allocation until vmalloc space is available.
@@ -3004,7 +3019,7 @@ static void __init dcache_init_early(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        HASH_EARLY,
@@ -3012,13 +3027,13 @@ static void __init dcache_init_early(void)
                                        &d_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+       for (loop = 0; loop < (1U << d_hash_shift); loop++)
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 static void __init dcache_init(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* 
         * A constructor could be added for stable state like the lists,
@@ -3027,8 +3042,6 @@ static void __init dcache_init(void)
         */
        dentry_cache = KMEM_CACHE(dentry,
                SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
-       
-       register_shrinker(&dcache_shrinker);
 
        /* Hash may have been set up in dcache_init_early */
        if (!hashdist)
@@ -3036,7 +3049,7 @@ static void __init dcache_init(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        0,
@@ -3044,8 +3057,8 @@ static void __init dcache_init(void)
                                        &d_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+       for (loop = 0; loop < (1U << d_hash_shift); loop++)
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 /* SLAB cache for __getname() consumers */