return freed;
 }
 
-static void __wait_on_freeing_inode(struct inode *inode);
+static void __wait_on_freeing_inode(struct inode *inode, bool locked);
 /*
  * Called with the inode lock held.
  */
 static struct inode *find_inode(struct super_block *sb,
                                struct hlist_head *head,
                                int (*test)(struct inode *, void *),
-                               void *data)
+                               void *data, bool locked)
 {
        struct inode *inode = NULL;
 
+       if (locked)
+               lockdep_assert_held(&inode_hash_lock);
+       else
+               lockdep_assert_not_held(&inode_hash_lock);
+
+       rcu_read_lock();
 repeat:
-       hlist_for_each_entry(inode, head, i_hash) {
+       hlist_for_each_entry_rcu(inode, head, i_hash) {
                if (inode->i_sb != sb)
                        continue;
                if (!test(inode, data))
                        continue;
                spin_lock(&inode->i_lock);
                if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
-                       __wait_on_freeing_inode(inode);
+                       __wait_on_freeing_inode(inode, locked);
                        goto repeat;
                }
                if (unlikely(inode->i_state & I_CREATING)) {
                        spin_unlock(&inode->i_lock);
+                       rcu_read_unlock();
                        return ERR_PTR(-ESTALE);
                }
                __iget(inode);
                spin_unlock(&inode->i_lock);
+               rcu_read_unlock();
                return inode;
        }
+       rcu_read_unlock();
        return NULL;
 }
 
  * iget_locked for details.
  */
 static struct inode *find_inode_fast(struct super_block *sb,
-                               struct hlist_head *head, unsigned long ino)
+                               struct hlist_head *head, unsigned long ino,
+                               bool locked)
 {
        struct inode *inode = NULL;
 
+       if (locked)
+               lockdep_assert_held(&inode_hash_lock);
+       else
+               lockdep_assert_not_held(&inode_hash_lock);
+
+       rcu_read_lock();
 repeat:
-       hlist_for_each_entry(inode, head, i_hash) {
+       hlist_for_each_entry_rcu(inode, head, i_hash) {
                if (inode->i_ino != ino)
                        continue;
                if (inode->i_sb != sb)
                        continue;
                spin_lock(&inode->i_lock);
                if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
-                       __wait_on_freeing_inode(inode);
+                       __wait_on_freeing_inode(inode, locked);
                        goto repeat;
                }
                if (unlikely(inode->i_state & I_CREATING)) {
                        spin_unlock(&inode->i_lock);
+                       rcu_read_unlock();
                        return ERR_PTR(-ESTALE);
                }
                __iget(inode);
                spin_unlock(&inode->i_lock);
+               rcu_read_unlock();
                return inode;
        }
+       rcu_read_unlock();
        return NULL;
 }
 
 
 again:
        spin_lock(&inode_hash_lock);
-       old = find_inode(inode->i_sb, head, test, data);
+       old = find_inode(inode->i_sb, head, test, data, true);
        if (unlikely(old)) {
                /*
                 * Uhhuh, somebody else created the same inode under us.
 }
 EXPORT_SYMBOL(iget5_locked);
 
+/**
+ * iget5_locked_rcu - obtain an inode from a mounted file system
+ * @sb:                super block of file system
+ * @hashval:   hash value (usually inode number) to get
+ * @test:      callback used for comparisons between inodes
+ * @set:       callback used to initialize a new struct inode
+ * @data:      opaque data pointer to pass to @test and @set
+ *
+ * This is equivalent to iget5_locked, except the @test callback must
+ * tolerate the inode not being stable, including being mid-teardown.
+ */
+struct inode *iget5_locked_rcu(struct super_block *sb, unsigned long hashval,
+               int (*test)(struct inode *, void *),
+               int (*set)(struct inode *, void *), void *data)
+{
+       struct hlist_head *head = inode_hashtable + hash(sb, hashval);
+       struct inode *inode, *new;
+
+again:
+       inode = find_inode(sb, head, test, data, false);
+       if (inode) {
+               if (IS_ERR(inode))
+                       return NULL;
+               wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
+               return inode;
+       }
+
+       new = alloc_inode(sb);
+       if (new) {
+               new->i_state = 0;
+               inode = inode_insert5(new, hashval, test, set, data);
+               if (unlikely(inode != new))
+                       destroy_inode(new);
+       }
+       return inode;
+}
+EXPORT_SYMBOL_GPL(iget5_locked_rcu);
+
 /**
  * iget_locked - obtain an inode from a mounted file system
  * @sb:                super block of file system
        struct hlist_head *head = inode_hashtable + hash(sb, ino);
        struct inode *inode;
 again:
-       spin_lock(&inode_hash_lock);
-       inode = find_inode_fast(sb, head, ino);
-       spin_unlock(&inode_hash_lock);
+       inode = find_inode_fast(sb, head, ino, false);
        if (inode) {
                if (IS_ERR(inode))
                        return NULL;
 
                spin_lock(&inode_hash_lock);
                /* We released the lock, so.. */
-               old = find_inode_fast(sb, head, ino);
+               old = find_inode_fast(sb, head, ino, true);
                if (!old) {
                        inode->i_ino = ino;
                        spin_lock(&inode->i_lock);
        struct inode *inode;
 
        spin_lock(&inode_hash_lock);
-       inode = find_inode(sb, head, test, data);
+       inode = find_inode(sb, head, test, data, true);
        spin_unlock(&inode_hash_lock);
 
        return IS_ERR(inode) ? NULL : inode;
        struct inode *inode;
 again:
        spin_lock(&inode_hash_lock);
-       inode = find_inode_fast(sb, head, ino);
+       inode = find_inode_fast(sb, head, ino, true);
        spin_unlock(&inode_hash_lock);
 
        if (inode) {
  * wake_up_bit(&inode->i_state, __I_NEW) after removing from the hash list
  * will DTRT.
  */
-static void __wait_on_freeing_inode(struct inode *inode)
+static void __wait_on_freeing_inode(struct inode *inode, bool locked)
 {
        wait_queue_head_t *wq;
        DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
        wq = bit_waitqueue(&inode->i_state, __I_NEW);
        prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
        spin_unlock(&inode->i_lock);
-       spin_unlock(&inode_hash_lock);
+       rcu_read_unlock();
+       if (locked)
+               spin_unlock(&inode_hash_lock);
        schedule();
        finish_wait(wq, &wait.wq_entry);
-       spin_lock(&inode_hash_lock);
+       if (locked)
+               spin_lock(&inode_hash_lock);
+       rcu_read_lock();
 }
 
 static __initdata unsigned long ihash_entries;