shithub: lwext4

Download patch

ref: 12af982ed6f006c0ff4b73a2dc266d139d490904
parent: 958b570b8fe80913ed607a15a3548cadac8a1195
author: gkostka <kostka.grzegorz@gmail.com>
date: Tue Feb 21 16:30:54 EST 2017

ext4_mkfs: add journal node creation support

--- a/fs_test/lwext4_mkfs.c
+++ b/fs_test/lwext4_mkfs.c
@@ -56,6 +56,7 @@
 static struct ext4_fs fs;
 static struct ext4_mkfs_info info = {
 	.block_size = 1024,
+	.journal = true,
 };
 
 static bool verbose = false;
--- a/include/ext4_mkfs.h
+++ b/include/ext4_mkfs.h
@@ -63,7 +63,7 @@
 	uint16_t feat_incompat;
 	uint32_t bg_desc_reserve_blocks;
 	uint16_t dsc_size;
-	uint8_t journal;
+	bool journal;
 	const char *label;
 };
 
--- a/src/ext4.c
+++ b/src/ext4.c
@@ -998,6 +998,8 @@
 			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;
 
--- a/src/ext4_fs.c
+++ b/src/ext4_fs.c
@@ -805,13 +805,18 @@
 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 @@
 		/* Initialize extent root header */
 		ext4_extent_tree_init(inode_ref);
 	}
+
+	inode_ref->dirty = true;
 #endif
 }
 
@@ -850,7 +857,6 @@
 {
 	/* 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 @@
 		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;
--- a/src/ext4_mkfs.c
+++ b/src/ext4_mkfs.c
@@ -273,6 +273,8 @@
 
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 		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 @@
 	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)
@@ -756,6 +839,10 @@
 		goto fs_fini;
 
 	r = create_dirs(fs);
+	if (r != EOK)
+		goto fs_fini;
+
+	r = create_journal_inode(fs, info);
 	if (r != EOK)
 		goto fs_fini;