Merge branch 'devel-stable' of master.kernel.org:/home/rmk/linux-2.6-arm
[firefly-linux-kernel-4.4.55.git] / fs / inode.c
index 5a0a898f55d1ce9559f11cab98763f57389dcfbb..da85e56378f3e1d98c241901171e24e83882f189 100644 (file)
@@ -257,6 +257,12 @@ static struct inode *alloc_inode(struct super_block *sb)
        return inode;
 }
 
+void free_inode_nonrcu(struct inode *inode)
+{
+       kmem_cache_free(inode_cachep, inode);
+}
+EXPORT_SYMBOL(free_inode_nonrcu);
+
 void __destroy_inode(struct inode *inode)
 {
        BUG_ON(inode_has_buffers(inode));
@@ -272,6 +278,13 @@ void __destroy_inode(struct inode *inode)
 }
 EXPORT_SYMBOL(__destroy_inode);
 
+static void i_callback(struct rcu_head *head)
+{
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       INIT_LIST_HEAD(&inode->i_dentry);
+       kmem_cache_free(inode_cachep, inode);
+}
+
 static void destroy_inode(struct inode *inode)
 {
        BUG_ON(!list_empty(&inode->i_lru));
@@ -279,7 +292,7 @@ static void destroy_inode(struct inode *inode)
        if (inode->i_sb->s_op->destroy_inode)
                inode->i_sb->s_op->destroy_inode(inode);
        else
-               kmem_cache_free(inode_cachep, (inode));
+               call_rcu(&inode->i_rcu, i_callback);
 }
 
 /*
@@ -432,6 +445,7 @@ void end_writeback(struct inode *inode)
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(inode->i_state & I_CLEAR);
        inode_sync_wait(inode);
+       /* don't need i_lock here, no concurrent mods to i_state */
        inode->i_state = I_FREEING | I_CLEAR;
 }
 EXPORT_SYMBOL(end_writeback);