new inode method: ->free_inode()
[muen/linux.git] / fs / inode.c
index e9d97ad..627e176 100644 (file)
@@ -202,12 +202,28 @@ out:
 }
 EXPORT_SYMBOL(inode_init_always);
 
+void free_inode_nonrcu(struct inode *inode)
+{
+       kmem_cache_free(inode_cachep, inode);
+}
+EXPORT_SYMBOL(free_inode_nonrcu);
+
+static void i_callback(struct rcu_head *head)
+{
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       if (inode->free_inode)
+               inode->free_inode(inode);
+       else
+               free_inode_nonrcu(inode);
+}
+
 static struct inode *alloc_inode(struct super_block *sb)
 {
+       const struct super_operations *ops = sb->s_op;
        struct inode *inode;
 
-       if (sb->s_op->alloc_inode)
-               inode = sb->s_op->alloc_inode(sb);
+       if (ops->alloc_inode)
+               inode = ops->alloc_inode(sb);
        else
                inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);
 
@@ -215,22 +231,19 @@ static struct inode *alloc_inode(struct super_block *sb)
                return NULL;
 
        if (unlikely(inode_init_always(sb, inode))) {
-               if (inode->i_sb->s_op->destroy_inode)
-                       inode->i_sb->s_op->destroy_inode(inode);
-               else
-                       kmem_cache_free(inode_cachep, inode);
+               if (ops->destroy_inode) {
+                       ops->destroy_inode(inode);
+                       if (!ops->free_inode)
+                               return NULL;
+               }
+               inode->free_inode = ops->free_inode;
+               i_callback(&inode->i_rcu);
                return NULL;
        }
 
        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));
@@ -253,20 +266,19 @@ 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);
-       kmem_cache_free(inode_cachep, inode);
-}
-
 static void destroy_inode(struct inode *inode)
 {
+       const struct super_operations *ops = inode->i_sb->s_op;
+
        BUG_ON(!list_empty(&inode->i_lru));
        __destroy_inode(inode);
-       if (inode->i_sb->s_op->destroy_inode)
-               inode->i_sb->s_op->destroy_inode(inode);
-       else
-               call_rcu(&inode->i_rcu, i_callback);
+       if (ops->destroy_inode) {
+               ops->destroy_inode(inode);
+               if (!ops->free_inode)
+                       return;
+       }
+       inode->free_inode = ops->free_inode;
+       call_rcu(&inode->i_rcu, i_callback);
 }
 
 /**