Merge branch 'work.iget' into work.misc
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 8 Oct 2016 14:44:37 +0000 (10:44 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 8 Oct 2016 14:44:37 +0000 (10:44 -0400)
fs/inode.c

index 7e3ef3a..691c007 100644 (file)
@@ -1021,13 +1021,17 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
 {
        struct hlist_head *head = inode_hashtable + hash(sb, hashval);
        struct inode *inode;
-
+again:
        spin_lock(&inode_hash_lock);
        inode = find_inode(sb, head, test, data);
        spin_unlock(&inode_hash_lock);
 
        if (inode) {
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
                return inode;
        }
 
@@ -1064,6 +1068,10 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
        }
        return inode;
 
@@ -1091,12 +1099,16 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
 {
        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);
        if (inode) {
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
                return inode;
        }
 
@@ -1131,6 +1143,10 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
        }
        return inode;
 }
@@ -1266,10 +1282,16 @@ EXPORT_SYMBOL(ilookup5_nowait);
 struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
                int (*test)(struct inode *, void *), void *data)
 {
-       struct inode *inode = ilookup5_nowait(sb, hashval, test, data);
-
-       if (inode)
+       struct inode *inode;
+again:
+       inode = ilookup5_nowait(sb, hashval, test, data);
+       if (inode) {
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
+       }
        return inode;
 }
 EXPORT_SYMBOL(ilookup5);
@@ -1286,13 +1308,18 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
 {
        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);
 
-       if (inode)
+       if (inode) {
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
+       }
        return inode;
 }
 EXPORT_SYMBOL(ilookup);