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)
1  2 
fs/inode.c

diff --combined fs/inode.c
index 7e3ef3af3db9e35dc175608d83d3e7ab7d3f789a,d123fe4b6f7d4a9b69be1453354814574192ae9f..691c00747e725918cdc98e1f1414a42047f1baee
@@@ -345,7 -345,7 +345,7 @@@ EXPORT_SYMBOL(inc_nlink)
  void address_space_init_once(struct address_space *mapping)
  {
        memset(mapping, 0, sizeof(*mapping));
 -      INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
 +      INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC | __GFP_ACCOUNT);
        spin_lock_init(&mapping->tree_lock);
        init_rwsem(&mapping->i_mmap_rwsem);
        INIT_LIST_HEAD(&mapping->private_list);
@@@ -365,7 -365,6 +365,7 @@@ void inode_init_once(struct inode *inod
        INIT_HLIST_NODE(&inode->i_hash);
        INIT_LIST_HEAD(&inode->i_devices);
        INIT_LIST_HEAD(&inode->i_io_list);
 +      INIT_LIST_HEAD(&inode->i_wb_list);
        INIT_LIST_HEAD(&inode->i_lru);
        address_space_init_once(&inode->i_data);
        i_size_ordered_init(inode);
@@@ -508,7 -507,6 +508,7 @@@ void clear_inode(struct inode *inode
        BUG_ON(!list_empty(&inode->i_data.private_list));
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(inode->i_state & I_CLEAR);
 +      BUG_ON(!list_empty(&inode->i_wb_list));
        /* don't need i_lock here, no concurrent mods to i_state */
        inode->i_state = I_FREEING | I_CLEAR;
  }
@@@ -1021,13 -1019,17 +1021,17 @@@ struct inode *iget5_locked(struct super
  {
        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;
        }
  
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
        }
        return inode;
  
@@@ -1091,12 -1097,16 +1099,16 @@@ struct inode *iget_locked(struct super_
  {
        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;
        }
  
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
+               if (unlikely(inode_unhashed(inode))) {
+                       iput(inode);
+                       goto again;
+               }
        }
        return inode;
  }
@@@ -1266,10 -1280,16 +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 -1306,18 +1308,18 @@@ struct inode *ilookup(struct super_bloc
  {
        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);
@@@ -1619,13 -1644,6 +1646,13 @@@ bool atime_needs_update(const struct pa
  
        if (inode->i_flags & S_NOATIME)
                return false;
 +
 +      /* Atime updates will likely cause i_uid and i_gid to be written
 +       * back improprely if their true value is unknown to the vfs.
 +       */
 +      if (HAS_UNMAPPED_ID(inode))
 +              return false;
 +
        if (IS_NOATIME(inode))
                return false;
        if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
@@@ -1729,6 -1747,7 +1756,6 @@@ int dentry_needs_remove_privs(struct de
                mask |= ATTR_KILL_PRIV;
        return mask;
  }
 -EXPORT_SYMBOL(dentry_needs_remove_privs);
  
  static int __remove_privs(struct dentry *dentry, int kill)
  {
   */
  int file_remove_privs(struct file *file)
  {
 -      struct dentry *dentry = file->f_path.dentry;
 -      struct inode *inode = d_inode(dentry);
 +      struct dentry *dentry = file_dentry(file);
 +      struct inode *inode = file_inode(file);
        int kill;
        int error = 0;
  
        if (IS_NOSEC(inode))
                return 0;
  
 -      kill = file_needs_remove_privs(file);
 +      kill = dentry_needs_remove_privs(dentry);
        if (kill < 0)
                return kill;
        if (kill)