ext4_mkfs: add journal node creation support
authorgkostka <kostka.grzegorz@gmail.com>
Tue, 21 Feb 2017 20:30:54 +0000 (21:30 +0100)
committergkostka <kostka.grzegorz@gmail.com>
Tue, 21 Feb 2017 21:05:26 +0000 (22:05 +0100)
fs_test/lwext4_mkfs.c
include/ext4_mkfs.h
src/ext4.c
src/ext4_fs.c
src/ext4_mkfs.c

index 7579c8d05ff85bd4dc42dc9bf3bc0bcb62f8a9c4..ac6b4fa099ae459ae0c039ac108babb2b071a6e2 100644 (file)
@@ -56,6 +56,7 @@ static int fs_type = F_SET_EXT4;
 static struct ext4_fs fs;
 static struct ext4_mkfs_info info = {
        .block_size = 1024,
+       .journal = true,
 };
 
 static bool verbose = false;
index e22ff888beafa228f2d6956496a1c6df53b2889a..1cbe31ad6f3fe0cf985d2eb50e0e9162dd369d60 100644 (file)
@@ -63,7 +63,7 @@ struct ext4_mkfs_info {
        uint16_t feat_incompat;
        uint32_t bg_desc_reserve_blocks;
        uint16_t dsc_size;
-       uint8_t journal;
+       bool journal;
        const char *label;
 };
 
index e877f13703fccea5a3d5106fb7ef414fae070778..b3f4aefa1c8309df1726bdc66e45c1b95f06c554 100644 (file)
@@ -998,6 +998,8 @@ static int ext4_generic_open2(ext4_file *f, const char *path, int flags,
                        struct ext4_inode_ref child_ref;
                        r = ext4_fs_alloc_inode(fs, &child_ref,
                                        is_goal ? ftype : EXT4_DE_DIR);
+
+                       ext4_fs_inode_blocks_init(fs, &child_ref);
                        if (r != EOK)
                                break;
 
index e8b296da9e54f6b32887708a57fa3128e470c5c4..3427df36aeac57f8551cb29dcb0d5027496e3b6b 100644 (file)
@@ -805,13 +805,18 @@ int ext4_fs_put_inode_ref(struct ext4_inode_ref *ref)
 void ext4_fs_inode_blocks_init(struct ext4_fs *fs,
                               struct ext4_inode_ref *inode_ref)
 {
-       int i;
        struct ext4_inode *inode = inode_ref->inode;
 
-       for (i = 0; i < EXT4_INODE_BLOCKS; i++)
-               inode->blocks[i] = 0;
+       /* Reset blocks array. For inode which is not directory or file, just
+        * fill in blocks with 0 */
+       switch (ext4_inode_type(&fs->sb, inode_ref->inode)) {
+       case EXT4_INODE_MODE_FILE:
+       case EXT4_INODE_MODE_DIRECTORY:
+               break;
+       default:
+               return;
+       }
 
-       (void)fs;
 #if CONFIG_EXTENT_ENABLE
        /* Initialize extents if needed */
        if (ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS)) {
@@ -820,6 +825,8 @@ void ext4_fs_inode_blocks_init(struct ext4_fs *fs,
                /* Initialize extent root header */
                ext4_extent_tree_init(inode_ref);
        }
+
+       inode_ref->dirty = true;
 #endif
 }
 
@@ -850,7 +857,6 @@ int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref,
 {
        /* Check if newly allocated i-node will be a directory */
        bool is_dir;
-       uint32_t type;
        uint16_t inode_size = ext4_get16(&fs->sb, inode_size);
 
        is_dir = (filetype == EXT4_DE_DIR);
@@ -919,20 +925,7 @@ int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref,
                ext4_inode_set_extra_isize(&fs->sb, inode, size);
        }
 
-       /* Reset blocks array. For inode which is not directory or file, just
-        * fill in blocks with 0 */
-       type = ext4_inode_type(&fs->sb, inode_ref->inode);
-       if (type == EXT4_INODE_MODE_CHARDEV ||
-           type == EXT4_INODE_MODE_BLOCKDEV ||
-           type == EXT4_INODE_MODE_SOCKET ||
-           type == EXT4_INODE_MODE_SOFTLINK) {
-               for (int i = 0; i < EXT4_INODE_BLOCKS; i++)
-                       inode->blocks[i] = 0;
-
-       } else {
-               ext4_fs_inode_blocks_init(fs, inode_ref);
-       }
-
+       memset(inode->blocks, 0, sizeof(inode->blocks));
        inode_ref->dirty = true;
 
        return EOK;
index 7af33018b1ab27ec397f7d44aaa215f8f713c6d5..81867d6af237b41416cd85e0296d16aa473265d1 100644 (file)
@@ -273,6 +273,8 @@ static void fill_sb(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info)
 
        if (info->feat_compat & EXT4_FCOM_HAS_JOURNAL)
                sb->journal_inode_number = to_le32(EXT4_JOURNAL_INO);
+
+       sb->journal_backup_type = 1;
        sb->journal_dev = to_le32(0);
        sb->last_orphan = to_le32(0);
        sb->hash_seed[0] = to_le32(0x11111111);
@@ -541,6 +543,8 @@ static int alloc_inodes(struct ext4_fs *fs)
                case EXT4_GOOD_OLD_FIRST_INO:
                        filetype = EXT4_DE_DIR;
                        break;
+               default:
+                       break;
                }
 
                r = ext4_fs_alloc_inode(fs, &inode_ref, filetype);
@@ -548,6 +552,14 @@ static int alloc_inodes(struct ext4_fs *fs)
                        return r;
 
                ext4_inode_set_mode(&fs->sb, inode_ref.inode, 0);
+
+               switch (i) {
+               case EXT4_ROOT_INO:
+               case EXT4_JOURNAL_INO:
+                       ext4_fs_inode_blocks_init(fs, &inode_ref);
+                       break;
+               }
+
                ext4_fs_put_inode_ref(&inode_ref);
        }
 
@@ -621,6 +633,70 @@ static int create_dirs(struct ext4_fs *fs)
        return r;
 }
 
+static int create_journal_inode(struct ext4_fs *fs,
+                               struct ext4_mkfs_info *info)
+{
+       int ret;
+       struct ext4_inode_ref inode_ref;
+       uint64_t blocks_count;
+
+       if (!info->journal)
+               return EOK;
+
+       ret = ext4_fs_get_inode_ref(fs, EXT4_JOURNAL_INO, &inode_ref);
+       if (ret != EOK)
+               return ret;
+
+       struct ext4_inode *inode = inode_ref.inode;
+
+       ext4_inode_set_mode(&fs->sb, inode, EXT4_INODE_MODE_FILE | 0600);
+       ext4_inode_set_links_cnt(inode, 1);
+
+       blocks_count = ext4_inode_get_blocks_count(&fs->sb, inode);
+
+       while (blocks_count++ < info->journal_blocks)
+       {
+               ext4_fsblk_t fblock;
+               ext4_lblk_t iblock;
+               struct ext4_block blk;
+
+               ret = ext4_fs_append_inode_dblk(&inode_ref, &fblock, &iblock);
+               if (ret != EOK)
+                       goto Finish;
+
+               if (iblock != 0)
+                       continue;
+
+               ret = ext4_block_get(fs->bdev, &blk, fblock);
+               if (ret != EOK)
+                       goto Finish;
+
+
+               struct jbd_sb * jbd_sb = (struct jbd_sb * )blk.data;
+               memset(jbd_sb, 0, sizeof(struct jbd_sb));
+
+               jbd_sb->header.magic = to_be32(JBD_MAGIC_NUMBER);
+               jbd_sb->header.blocktype = to_be32(JBD_SUPERBLOCK_V2);
+               jbd_sb->blocksize = to_be32(info->block_size);
+               jbd_sb->maxlen = to_be32(info->journal_blocks);
+               jbd_sb->nr_users = to_be32(1);
+               jbd_sb->first = to_be32(1);
+               jbd_sb->sequence = to_be32(1);
+
+               ext4_bcache_set_dirty(blk.buf);
+               ret = ext4_block_set(fs->bdev, &blk);
+               if (ret != EOK)
+                       goto Finish;
+       }
+
+       memcpy(fs->sb.journal_blocks, inode->blocks, sizeof(inode->blocks));
+
+       Finish:
+       ext4_fs_put_inode_ref(&inode_ref);
+
+       return ret;
+}
+
 int ext4_mkfs(struct ext4_fs *fs, struct ext4_blockdev *bd,
              struct ext4_mkfs_info *info, int fs_type)
 {
@@ -676,14 +752,19 @@ int ext4_mkfs(struct ext4_fs *fs, struct ext4_blockdev *bd,
                break;
        }
 
-       /*TODO: handle this features*/
+       /*TODO: handle this features some day...*/
        info->feat_incompat &= ~EXT4_FINCOM_META_BG;
        info->feat_incompat &= ~EXT4_FINCOM_FLEX_BG;
+       info->feat_incompat &= ~EXT4_FINCOM_64BIT;
+
        info->feat_ro_compat &= ~EXT4_FRO_COM_METADATA_CSUM;
+       info->feat_ro_compat &= ~EXT4_FRO_COM_GDT_CSUM;
+       info->feat_ro_compat &= ~EXT4_FRO_COM_DIR_NLINK;
+       info->feat_ro_compat &= ~EXT4_FRO_COM_EXTRA_ISIZE;
+       info->feat_ro_compat &= ~EXT4_FRO_COM_HUGE_FILE;
 
-       /*TODO: handle journal feature & inode*/
-       if (info->journal == 0)
-               info->feat_compat |= 0;
+       if (info->journal)
+               info->feat_compat |= EXT4_FCOM_HAS_JOURNAL;
 
        if (info->dsc_size == 0) {
 
@@ -723,8 +804,10 @@ int ext4_mkfs(struct ext4_fs *fs, struct ext4_blockdev *bd,
        ext4_dbg(DEBUG_MKFS, DBG_NONE "Label: %s\n", info->label);
 
        struct ext4_bcache bc;
+
        memset(&bc, 0, sizeof(struct ext4_bcache));
        ext4_block_set_lb_size(bd, info->block_size);
+
        r = ext4_bcache_init_dynamic(&bc, CONFIG_BLOCK_DEV_CACHE_SIZE,
                                      info->block_size);
        if (r != EOK)
@@ -759,6 +842,10 @@ int ext4_mkfs(struct ext4_fs *fs, struct ext4_blockdev *bd,
        if (r != EOK)
                goto fs_fini;
 
+       r = create_journal_inode(fs, info);
+       if (r != EOK)
+               goto fs_fini;
+
        fs_fini:
        ext4_fs_fini(fs);