nilfs2: use iget for all metadata files
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Sun, 5 Sep 2010 03:20:59 +0000 (12:20 +0900)
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Sat, 23 Oct 2010 00:24:38 +0000 (09:24 +0900)
This makes use of iget5_locked to allocate or get inode for metadata
files to stop using own inode allocator.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
14 files changed:
fs/nilfs2/cpfile.c
fs/nilfs2/cpfile.h
fs/nilfs2/dat.c
fs/nilfs2/dat.h
fs/nilfs2/ifile.c
fs/nilfs2/ifile.h
fs/nilfs2/inode.c
fs/nilfs2/mdt.c
fs/nilfs2/mdt.h
fs/nilfs2/nilfs.h
fs/nilfs2/sufile.c
fs/nilfs2/sufile.h
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c

index 18737818db63c63875db8a414e7f415a0217f014..03de1da8795bdade10f1863dc640e8b165997798 100644 (file)
@@ -933,27 +933,40 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat)
 }
 
 /**
- * nilfs_cpfile_read - read cpfile inode
- * @cpfile: cpfile inode
- * @raw_inode: on-disk cpfile inode
- */
-int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode)
-{
-       return nilfs_read_inode_common(cpfile, raw_inode);
-}
-
-/**
- * nilfs_cpfile_new - create cpfile
- * @nilfs: nilfs object
+ * nilfs_cpfile_read - read or get cpfile inode
+ * @sb: super block instance
  * @cpsize: size of a checkpoint entry
+ * @raw_inode: on-disk cpfile inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize)
+int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
+                     struct nilfs_inode *raw_inode, struct inode **inodep)
 {
        struct inode *cpfile;
+       int err;
 
-       cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO, 0);
-       if (cpfile)
-               nilfs_mdt_set_entry_size(cpfile, cpsize,
-                                        sizeof(struct nilfs_cpfile_header));
-       return cpfile;
+       cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
+       if (unlikely(!cpfile))
+               return -ENOMEM;
+       if (!(cpfile->i_state & I_NEW))
+               goto out;
+
+       err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0);
+       if (err)
+               goto failed;
+
+       nilfs_mdt_set_entry_size(cpfile, cpsize,
+                                sizeof(struct nilfs_cpfile_header));
+
+       err = nilfs_read_inode_common(cpfile, raw_inode);
+       if (err)
+               goto failed;
+
+       unlock_new_inode(cpfile);
+ out:
+       *inodep = cpfile;
+       return 0;
+ failed:
+       iget_failed(cpfile);
+       return err;
 }
index bc0809e0ab43d15dc60efad9ed731dd870348c22..a242b9a314f9550ed9367cf1d60b1b40bc715403 100644 (file)
@@ -40,7 +40,7 @@ int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *);
 ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned,
                                size_t);
 
-int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode);
-struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize);
+int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
+                     struct nilfs_inode *raw_inode, struct inode **inodep);
 
 #endif /* _NILFS_CPFILE_H */
index 7091c4e0f04273dc1ef2dff88c19461af1b1320b..ab04a68f425d98e4fea9c8d08464b4c841f8c6c3 100644 (file)
@@ -463,39 +463,48 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
 }
 
 /**
- * nilfs_dat_read - read dat inode
- * @dat: dat inode
- * @raw_inode: on-disk dat inode
- */
-int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode)
-{
-       return nilfs_read_inode_common(dat, raw_inode);
-}
-
-/**
- * nilfs_dat_new - create dat file
- * @nilfs: nilfs object
+ * nilfs_dat_read - read or get dat inode
+ * @sb: super block instance
  * @entry_size: size of a dat entry
+ * @raw_inode: on-disk dat inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size)
+int nilfs_dat_read(struct super_block *sb, size_t entry_size,
+                  struct nilfs_inode *raw_inode, struct inode **inodep)
 {
        static struct lock_class_key dat_lock_key;
        struct inode *dat;
        struct nilfs_dat_info *di;
        int err;
 
-       dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di));
-       if (dat) {
-               err = nilfs_palloc_init_blockgroup(dat, entry_size);
-               if (unlikely(err)) {
-                       nilfs_mdt_destroy(dat);
-                       return NULL;
-               }
+       dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
+       if (unlikely(!dat))
+               return -ENOMEM;
+       if (!(dat->i_state & I_NEW))
+               goto out;
 
-               di = NILFS_DAT_I(dat);
-               lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
-               nilfs_palloc_setup_cache(dat, &di->palloc_cache);
-               nilfs_mdt_setup_shadow_map(dat, &di->shadow);
-       }
-       return dat;
+       err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
+       if (err)
+               goto failed;
+
+       err = nilfs_palloc_init_blockgroup(dat, entry_size);
+       if (err)
+               goto failed;
+
+       di = NILFS_DAT_I(dat);
+       lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
+       nilfs_palloc_setup_cache(dat, &di->palloc_cache);
+       nilfs_mdt_setup_shadow_map(dat, &di->shadow);
+
+       err = nilfs_read_inode_common(dat, raw_inode);
+       if (err)
+               goto failed;
+
+       unlock_new_inode(dat);
+ out:
+       *inodep = dat;
+       return 0;
+ failed:
+       iget_failed(dat);
+       return err;
 }
index d31c3aab0efefb7cb64bd7070feee322a17469a8..cbd8e973250304973b67370cd73236ab923866d1 100644 (file)
@@ -53,7 +53,7 @@ int nilfs_dat_freev(struct inode *, __u64 *, size_t);
 int nilfs_dat_move(struct inode *, __u64, sector_t);
 ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t);
 
-int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode);
-struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size);
+int nilfs_dat_read(struct super_block *sb, size_t entry_size,
+                  struct nilfs_inode *raw_inode, struct inode **inodep);
 
 #endif /* _NILFS_DAT_H */
index 922d9dd42c8fb352f6e024688c73f9ede88e6738..9f8a2da67f901f666a0180a21d0bd938a6506af8 100644 (file)
@@ -161,25 +161,46 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino,
 }
 
 /**
- * nilfs_ifile_new - create inode file
- * @sbi: nilfs_sb_info struct
+ * nilfs_ifile_read - read or get ifile inode
+ * @sb: super block instance
+ * @root: root object
  * @inode_size: size of an inode
+ * @raw_inode: on-disk ifile inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size)
+int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
+                    size_t inode_size, struct nilfs_inode *raw_inode,
+                    struct inode **inodep)
 {
        struct inode *ifile;
        int err;
 
-       ifile = nilfs_mdt_new(sbi->s_nilfs, sbi->s_super, NILFS_IFILE_INO,
-                             sizeof(struct nilfs_ifile_info));
-       if (ifile) {
-               err = nilfs_palloc_init_blockgroup(ifile, inode_size);
-               if (unlikely(err)) {
-                       nilfs_mdt_destroy(ifile);
-                       return NULL;
-               }
-               nilfs_palloc_setup_cache(ifile,
-                                        &NILFS_IFILE_I(ifile)->palloc_cache);
-       }
-       return ifile;
+       ifile = nilfs_iget_locked(sb, root, NILFS_IFILE_INO);
+       if (unlikely(!ifile))
+               return -ENOMEM;
+       if (!(ifile->i_state & I_NEW))
+               goto out;
+
+       err = nilfs_mdt_init(ifile, NILFS_MDT_GFP,
+                            sizeof(struct nilfs_ifile_info));
+       if (err)
+               goto failed;
+
+       err = nilfs_palloc_init_blockgroup(ifile, inode_size);
+       if (err)
+               goto failed;
+
+       nilfs_palloc_setup_cache(ifile, &NILFS_IFILE_I(ifile)->palloc_cache);
+
+       err = nilfs_read_inode_common(ifile, raw_inode);
+       if (err)
+               goto failed;
+
+       unlock_new_inode(ifile);
+ out:
+       *inodep = ifile;
+       return 0;
+ failed:
+       iget_failed(ifile);
+       return err;
 }
index cbca32e498f28204a9efc23866ae9280a3023812..59b6f2b51df6e7c7e1ef659e7a806f294bbc58ad 100644 (file)
@@ -49,6 +49,8 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **);
 int nilfs_ifile_delete_inode(struct inode *, ino_t);
 int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **);
 
-struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size);
+int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
+                    size_t inode_size, struct nilfs_inode *raw_inode,
+                    struct inode **inodep);
 
 #endif /* _NILFS_IFILE_H */
index 5485dd12da643525ebab8822dc9860520c7dd850..5b3d43fb4e12c6995944848d245f522f73bd90cf 100644 (file)
@@ -506,16 +506,23 @@ static int nilfs_iget_set(struct inode *inode, void *opaque)
        return 0;
 }
 
-struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
-                        unsigned long ino)
+struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
+                               unsigned long ino)
 {
        struct nilfs_iget_args args = {
                .ino = ino, .root = root, .cno = 0, .for_gc = 0
        };
+
+       return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
+}
+
+struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
+                        unsigned long ino)
+{
        struct inode *inode;
        int err;
 
-       inode = iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
+       inode = nilfs_iget_locked(sb, root, ino);
        if (unlikely(!inode))
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
index 3bbd340a5136ae97362626488c53c4be4bee6419..44326cfe1fa9415d3fc52a1c84317ab1ca932a36 100644 (file)
@@ -444,8 +444,7 @@ static const struct inode_operations def_mdt_iops;
 static const struct file_operations def_mdt_fops;
 
 
-int nilfs_mdt_init(struct inode *inode, struct the_nilfs *nilfs,
-                  gfp_t gfp_mask, size_t objsz)
+int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz)
 {
        struct nilfs_mdt_info *mi;
 
@@ -453,13 +452,17 @@ int nilfs_mdt_init(struct inode *inode, struct the_nilfs *nilfs,
        if (!mi)
                return -ENOMEM;
 
-       mi->mi_nilfs = nilfs;
+       mi->mi_nilfs = NILFS_I_NILFS(inode);
        init_rwsem(&mi->mi_sem);
        inode->i_private = mi;
 
        inode->i_mode = S_IFREG;
        mapping_set_gfp_mask(inode->i_mapping, gfp_mask);
-       inode->i_mapping->backing_dev_info = nilfs->ns_bdi;
+       inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi;
+
+       inode->i_op = &def_mdt_iops;
+       inode->i_fop = &def_mdt_fops;
+       inode->i_mapping->a_ops = &def_mdt_aops;
 
        return 0;
 }
@@ -544,13 +547,10 @@ struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb,
        if (!inode)
                return NULL;
 
-       if (nilfs_mdt_init(inode, nilfs, NILFS_MDT_GFP, objsz) < 0) {
+       if (nilfs_mdt_init(inode, NILFS_MDT_GFP, objsz) < 0) {
                nilfs_destroy_inode(inode);
                return NULL;
        }
-       inode->i_op = &def_mdt_iops;
-       inode->i_fop = &def_mdt_fops;
-       inode->i_mapping->a_ops = &def_mdt_aops;
        return inode;
 }
 
index 1e0901c3fd6b12903d78e67bcdf44a1cc485ce2a..73ff7c055715ab583081d7c427d0ef88530e8db2 100644 (file)
@@ -85,8 +85,7 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long);
 int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);
 int nilfs_mdt_fetch_dirty(struct inode *);
 
-int nilfs_mdt_init(struct inode *inode, struct the_nilfs *nilfs,
-                  gfp_t gfp_mask, size_t objsz);
+int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz);
 struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t,
                            size_t);
 struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *,
index e9f457951e3245beaa9c6cae240f7c1d981d7495..2ca2ca5ca848ae9eba8b3c5f565c7c1921f67910 100644 (file)
@@ -244,6 +244,8 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 extern void nilfs_set_inode_flags(struct inode *);
 extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *);
 extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int);
+struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
+                               unsigned long ino);
 struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
                         unsigned long ino);
 extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
index 3c6cc6005c2e1676a0fec2c76f6da37c9d92cca7..599d9c27761eb98d74aebcbbeb7bb8f7cfe926e9 100644 (file)
@@ -635,46 +635,55 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 }
 
 /**
- * nilfs_sufile_read - read sufile inode
- * @sufile: sufile inode
+ * nilfs_sufile_read - read or get sufile inode
+ * @sb: super block instance
+ * @susize: size of a segment usage entry
  * @raw_inode: on-disk sufile inode
+ * @inodep: buffer to store the inode
  */
-int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode)
+int nilfs_sufile_read(struct super_block *sb, size_t susize,
+                     struct nilfs_inode *raw_inode, struct inode **inodep)
 {
-       struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
+       struct inode *sufile;
+       struct nilfs_sufile_info *sui;
        struct buffer_head *header_bh;
        struct nilfs_sufile_header *header;
        void *kaddr;
-       int ret;
+       int err;
 
-       ret = nilfs_read_inode_common(sufile, raw_inode);
-       if (ret < 0)
-               return ret;
+       sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
+       if (unlikely(!sufile))
+               return -ENOMEM;
+       if (!(sufile->i_state & I_NEW))
+               goto out;
 
-       ret = nilfs_sufile_get_header_block(sufile, &header_bh);
-       if (!ret) {
-               kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
-               header = kaddr + bh_offset(header_bh);
-               sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
-               kunmap_atomic(kaddr, KM_USER0);
-               brelse(header_bh);
-       }
-       return ret;
-}
+       err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui));
+       if (err)
+               goto failed;
 
-/**
- * nilfs_sufile_new - create sufile
- * @nilfs: nilfs object
- * @susize: size of a segment usage entry
- */
-struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize)
-{
-       struct inode *sufile;
+       nilfs_mdt_set_entry_size(sufile, susize,
+                                sizeof(struct nilfs_sufile_header));
+
+       err = nilfs_read_inode_common(sufile, raw_inode);
+       if (err)
+               goto failed;
+
+       err = nilfs_sufile_get_header_block(sufile, &header_bh);
+       if (err)
+               goto failed;
 
-       sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO,
-                              sizeof(struct nilfs_sufile_info));
-       if (sufile)
-               nilfs_mdt_set_entry_size(sufile, susize,
-                                        sizeof(struct nilfs_sufile_header));
-       return sufile;
+       sui = NILFS_SUI(sufile);
+       kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+       header = kaddr + bh_offset(header_bh);
+       sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
+       kunmap_atomic(kaddr, KM_USER0);
+       brelse(header_bh);
+
+       unlock_new_inode(sufile);
+ out:
+       *inodep = sufile;
+       return 0;
+ failed:
+       iget_failed(sufile);
+       return err;
 }
index 15163b8aff7d74384744839dcdadd05d83ea2931..203f6102a62feb954dda06b78ce611c742c4692e 100644 (file)
@@ -61,8 +61,8 @@ void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
 void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
                               struct buffer_head *);
 
-int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode);
-struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize);
+int nilfs_sufile_read(struct super_block *sb, size_t susize,
+                     struct nilfs_inode *raw_inode, struct inode **inodep);
 
 /**
  * nilfs_sufile_scrap - make a segment garbage
index 5893cb27c90921e6b83756070640024109e387d9..39e7d7f8eda06b9f10b6cd08eb057d2a8c8c2c4e 100644 (file)
@@ -356,6 +356,10 @@ static void nilfs_put_super(struct super_block *sb)
                up_write(&nilfs->ns_sem);
        }
 
+       iput(nilfs->ns_sufile);
+       iput(nilfs->ns_cpfile);
+       iput(nilfs->ns_dat);
+
        destroy_nilfs(nilfs);
        sbi->s_super = NULL;
        sb->s_fs_info = NULL;
@@ -403,10 +407,6 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
        if (root->ifile)
                goto reuse; /* already attached checkpoint */
 
-       root->ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size);
-       if (!root->ifile)
-               goto failed;
-
        down_read(&nilfs->ns_segctor_sem);
        err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp,
                                          &bh_cp);
@@ -421,8 +421,10 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
                }
                goto failed;
        }
-       err = nilfs_read_inode_common(root->ifile, &raw_cp->cp_ifile_inode);
-       if (unlikely(err))
+
+       err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size,
+                              &raw_cp->cp_ifile_inode, &root->ifile);
+       if (err)
                goto failed_bh;
 
        atomic_set(&root->inodes_count, le64_to_cpu(raw_cp->cp_inodes_count));
@@ -895,7 +897,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        if (err) {
                printk(KERN_ERR "NILFS: error loading last checkpoint "
                       "(checkpoint number=%llu).\n", (unsigned long long)cno);
-               goto failed_nilfs;
+               goto failed_unload;
        }
 
        if (!(sb->s_flags & MS_RDONLY)) {
@@ -924,6 +926,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
  failed_checkpoint:
        nilfs_put_root(fsroot);
 
+ failed_unload:
+       iput(nilfs->ns_sufile);
+       iput(nilfs->ns_cpfile);
+       iput(nilfs->ns_dat);
+
  failed_nilfs:
        destroy_nilfs(nilfs);
 
index b7666bc042562c6ef918a01ab1e8fa9fae7c7b90..4d6763e28eb5ed518ec871771d567923d07ef85a 100644 (file)
@@ -92,11 +92,6 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
 void destroy_nilfs(struct the_nilfs *nilfs)
 {
        might_sleep();
-       if (nilfs_loaded(nilfs)) {
-               nilfs_mdt_destroy(nilfs->ns_sufile);
-               nilfs_mdt_destroy(nilfs->ns_cpfile);
-               nilfs_mdt_destroy(nilfs->ns_dat);
-       }
        if (nilfs_init(nilfs)) {
                brelse(nilfs->ns_sbh[0]);
                brelse(nilfs->ns_sbh[1]);
@@ -104,11 +99,13 @@ void destroy_nilfs(struct the_nilfs *nilfs)
        kfree(nilfs);
 }
 
-static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block)
+static int nilfs_load_super_root(struct the_nilfs *nilfs,
+                                struct super_block *sb, sector_t sr_block)
 {
        struct buffer_head *bh_sr;
        struct nilfs_super_root *raw_sr;
        struct nilfs_super_block **sbp = nilfs->ns_sbp;
+       struct nilfs_inode *rawi;
        unsigned dat_entry_size, segment_usage_size, checkpoint_size;
        unsigned inode_size;
        int err;
@@ -125,34 +122,22 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block)
 
        inode_size = nilfs->ns_inode_size;
 
-       err = -ENOMEM;
-       nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size);
-       if (unlikely(!nilfs->ns_dat))
+       rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size);
+       err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat);
+       if (err)
                goto failed;
 
-       nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size);
-       if (unlikely(!nilfs->ns_cpfile))
+       rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size);
+       err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile);
+       if (err)
                goto failed_dat;
 
-       nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size);
-       if (unlikely(!nilfs->ns_sufile))
+       rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size);
+       err = nilfs_sufile_read(sb, segment_usage_size, rawi,
+                               &nilfs->ns_sufile);
+       if (err)
                goto failed_cpfile;
 
-       err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data +
-                            NILFS_SR_DAT_OFFSET(inode_size));
-       if (unlikely(err))
-               goto failed_sufile;
-
-       err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data +
-                               NILFS_SR_CPFILE_OFFSET(inode_size));
-       if (unlikely(err))
-               goto failed_sufile;
-
-       err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data +
-                               NILFS_SR_SUFILE_OFFSET(inode_size));
-       if (unlikely(err))
-               goto failed_sufile;
-
        raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
        nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime);
 
@@ -160,14 +145,11 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block)
        brelse(bh_sr);
        return err;
 
- failed_sufile:
-       nilfs_mdt_destroy(nilfs->ns_sufile);
-
  failed_cpfile:
-       nilfs_mdt_destroy(nilfs->ns_cpfile);
+       iput(nilfs->ns_cpfile);
 
  failed_dat:
-       nilfs_mdt_destroy(nilfs->ns_dat);
+       iput(nilfs->ns_dat);
        goto failed;
 }
 
@@ -290,7 +272,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
                        goto scan_error;
        }
 
-       err = nilfs_load_super_root(nilfs, ri.ri_super_root);
+       err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root);
        if (unlikely(err)) {
                printk(KERN_ERR "NILFS: error loading super root.\n");
                goto failed;
@@ -358,9 +340,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
        goto failed;
 
  failed_unload:
-       nilfs_mdt_destroy(nilfs->ns_cpfile);
-       nilfs_mdt_destroy(nilfs->ns_sufile);
-       nilfs_mdt_destroy(nilfs->ns_dat);
+       iput(nilfs->ns_cpfile);
+       iput(nilfs->ns_sufile);
+       iput(nilfs->ns_dat);
 
  failed:
        nilfs_clear_recovery_info(&ri);
@@ -782,7 +764,7 @@ void nilfs_put_root(struct nilfs_root *root)
                rb_erase(&root->rb_node, &nilfs->ns_cptree);
                spin_unlock(&nilfs->ns_cptree_lock);
                if (root->ifile)
-                       nilfs_mdt_destroy(root->ifile);
+                       iput(root->ifile);
 
                kfree(root);
        }