logfs: get rid of magical inodes
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 7 Jun 2010 16:22:31 +0000 (12:22 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 9 Aug 2010 20:48:26 +0000 (16:48 -0400)
ordering problems at ->kill_sb() time are solved by doing iput()
of these suckers in ->put_super()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/logfs/inode.c
fs/logfs/journal.c
fs/logfs/logfs.h
fs/logfs/readwrite.c
fs/logfs/segment.c
fs/logfs/super.c

index f602e230e16282aa00d10c26c93b6c5cec0015ac..7811a2a359353d6eba4b7d61359eb4d6a1bc9d8a 100644 (file)
@@ -235,33 +235,21 @@ static struct inode *logfs_alloc_inode(struct super_block *sb)
  * purpose is to create a new inode that will not trigger the warning if such
  * an inode is still in use.  An ugly hack, no doubt.  Suggections for
  * improvement are welcome.
+ *
+ * AV: that's what ->put_super() is for...
  */
 struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino)
 {
        struct inode *inode;
 
-       inode = logfs_alloc_inode(sb);
+       inode = new_inode(sb);
        if (!inode)
                return ERR_PTR(-ENOMEM);
 
        inode->i_mode = S_IFREG;
        inode->i_ino = ino;
-       inode->i_sb = sb;
-
-       /* This is a blatant copy of alloc_inode code.  We'd need alloc_inode
-        * to be nonstatic, alas. */
-       {
-               struct address_space * const mapping = &inode->i_data;
-
-               mapping->a_ops = &logfs_reg_aops;
-               mapping->host = inode;
-               mapping->flags = 0;
-               mapping_set_gfp_mask(mapping, GFP_NOFS);
-               mapping->assoc_mapping = NULL;
-               mapping->backing_dev_info = &default_backing_dev_info;
-               inode->i_mapping = mapping;
-               inode->i_nlink = 1;
-       }
+       inode->i_data.a_ops = &logfs_reg_aops;
+       mapping_set_gfp_mask(&inode->i_data, GFP_NOFS);
 
        return inode;
 }
@@ -277,7 +265,7 @@ struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino)
 
        err = logfs_read_inode(inode);
        if (err) {
-               destroy_meta_inode(inode);
+               iput(inode);
                return ERR_PTR(err);
        }
        logfs_inode_setops(inode);
@@ -298,16 +286,6 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
        return ret;
 }
 
-void destroy_meta_inode(struct inode *inode)
-{
-       if (inode) {
-               if (inode->i_data.nrpages)
-                       truncate_inode_pages(&inode->i_data, 0);
-               logfs_clear_inode(inode);
-               kmem_cache_free(logfs_inode_cache, logfs_inode(inode));
-       }
-}
-
 /* called with inode_lock held */
 static void logfs_drop_inode(struct inode *inode)
 {
@@ -384,12 +362,22 @@ static int logfs_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
+static void logfs_put_super(struct super_block *sb)
+{
+       struct logfs_super *super = logfs_super(sb);
+       /* kill the meta-inodes */
+       iput(super->s_master_inode);
+       iput(super->s_segfile_inode);
+       iput(super->s_mapping_inode);
+}
+
 const struct super_operations logfs_super_operations = {
        .alloc_inode    = logfs_alloc_inode,
        .clear_inode    = logfs_clear_inode,
        .delete_inode   = logfs_delete_inode,
        .destroy_inode  = logfs_destroy_inode,
        .drop_inode     = logfs_drop_inode,
+       .put_super      = logfs_put_super,
        .write_inode    = logfs_write_inode,
        .statfs         = logfs_statfs,
        .sync_fs        = logfs_sync_fs,
index 4b0e0616b357d59ba89fda8f7450c24e85a2abba..f46ee8b0e135eb62d00e45dc30bbee31c61c213a 100644 (file)
@@ -889,8 +889,6 @@ void logfs_cleanup_journal(struct super_block *sb)
        struct logfs_super *super = logfs_super(sb);
 
        btree_grim_visitor32(&super->s_reserved_segments, 0, NULL);
-       destroy_meta_inode(super->s_master_inode);
-       super->s_master_inode = NULL;
 
        kfree(super->s_compressed_je);
        kfree(super->s_je);
index c838c4d721110db6d1c99df7880b7ccedd0ba89f..5e65171dad2389660701b9736a29d579aee3b524 100644 (file)
@@ -525,7 +525,6 @@ struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino);
 struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino);
 int logfs_init_inode_cache(void);
 void logfs_destroy_inode_cache(void);
-void destroy_meta_inode(struct inode *inode);
 void logfs_set_blocks(struct inode *inode, u64 no);
 /* these logically belong into inode.c but actually reside in readwrite.c */
 int logfs_read_inode(struct inode *inode);
index 0718d112a1a59a7f92e98469e0311fbaddf7cd7d..580d126d597de9a46118f8efe0c343f2bbe04c8d 100644 (file)
@@ -2272,7 +2272,6 @@ void logfs_cleanup_rw(struct super_block *sb)
 {
        struct logfs_super *super = logfs_super(sb);
 
-       destroy_meta_inode(super->s_segfile_inode);
        logfs_mempool_destroy(super->s_block_pool);
        logfs_mempool_destroy(super->s_shadow_pool);
 }
index a9657afb70ad1a562bdb36a2f789d8eda672deec..9d5187353255ddf630a44afcb5e7d020dc8dd25c 100644 (file)
@@ -929,5 +929,4 @@ void logfs_cleanup_areas(struct super_block *sb)
        for_each_area(i)
                free_area(super->s_area[i]);
        free_area(super->s_journal_area);
-       destroy_meta_inode(super->s_mapping_inode);
 }
index d651e10a1e9c1e589ed55269c0b1c9bab6488b83..5336155c5d8189c2d6f4f78d73bd1abb3056ff36 100644 (file)
@@ -342,24 +342,27 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
                goto fail;
        }
 
+       /* at that point we know that ->put_super() will be called */
        super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
        if (!super->s_erase_page)
-               goto fail;
+               return -ENOMEM;
        memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE);
 
        /* FIXME: check for read-only mounts */
        err = logfs_make_writeable(sb);
-       if (err)
-               goto fail1;
+       if (err) {
+               __free_page(super->s_erase_page);
+               return err;
+       }
 
        log_super("LogFS: Finished mounting\n");
        simple_set_mnt(mnt, sb);
        return 0;
 
-fail1:
-       __free_page(super->s_erase_page);
 fail:
-       iput(logfs_super(sb)->s_master_inode);
+       iput(super->s_master_inode);
+       iput(super->s_segfile_inode);
+       iput(super->s_mapping_inode);
        return -EIO;
 }
 
@@ -580,10 +583,14 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
        sb->s_flags |= MS_ACTIVE;
        err = logfs_get_sb_final(sb, mnt);
        if (err)
-               goto err1;
-       return 0;
+               deactivate_locked_super(sb);
+       return err;
 
 err1:
+       /* no ->s_root, no ->put_super() */
+       iput(super->s_master_inode);
+       iput(super->s_segfile_inode);
+       iput(super->s_mapping_inode);
        deactivate_locked_super(sb);
        return err;
 err0: