diff --git a/lwext4/ext4_mkfs.c b/lwext4/ext4_mkfs.c index 2052edd..a332898 100644 --- a/lwext4/ext4_mkfs.c +++ b/lwext4/ext4_mkfs.c @@ -46,6 +46,22 @@ #define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y)) #define EXT4_ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y))) +struct fs_aux_info { + struct ext4_sblock *sb; + struct ext4_sblock *sb_block; + struct ext4_bgroup *bg_desc; + struct xattr_list_element *xattrs; + uint32_t first_data_block; + uint64_t len_blocks; + uint32_t inode_table_blocks; + uint32_t groups; + uint32_t bg_desc_blocks; + uint32_t default_i_flags; + uint32_t blocks_per_ind; + uint32_t blocks_per_dind; + uint32_t blocks_per_tind; +}; + static int sb2info(struct ext4_sblock *sb, struct ext4_mkfs_info *info) { if (to_le16(sb->magic) != EXT4_SUPERBLOCK_MAGIC) @@ -127,6 +143,56 @@ static uint32_t compute_journal_blocks(struct ext4_mkfs_info *info) return journal_blocks; } +static void create_fs_aux_info(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info) +{ + aux_info->first_data_block = (info->block_size > 1024) ? 0 : 1; + aux_info->len_blocks = info->len / info->block_size; + aux_info->inode_table_blocks = DIV_ROUND_UP(info->inodes_per_group * info->inode_size, + info->block_size); + aux_info->groups = DIV_ROUND_UP(aux_info->len_blocks - aux_info->first_data_block, + info->blocks_per_group); + aux_info->blocks_per_ind = info->block_size / sizeof(uint32_t); + aux_info->blocks_per_dind = aux_info->blocks_per_ind * aux_info->blocks_per_ind; + aux_info->blocks_per_tind = aux_info->blocks_per_dind * aux_info->blocks_per_dind; + + aux_info->bg_desc_blocks = + DIV_ROUND_UP(aux_info->groups * sizeof(struct ext4_bgroup), + info->block_size); + + aux_info->default_i_flags = EXT4_INODE_FLAG_NOATIME; + + uint32_t last_group_size = aux_info->len_blocks % info->blocks_per_group; + uint32_t last_header_size = 2 + aux_info->inode_table_blocks; + if (!(info->feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) || + ext4_sb_sparse(aux_info->groups - 1)) + last_header_size += 1 + aux_info->bg_desc_blocks + + info->bg_desc_reserve_blocks; + + if (last_group_size > 0 && last_group_size < last_header_size) { + aux_info->groups--; + aux_info->len_blocks -= last_group_size; + } + + /* The write_data* functions expect only block aligned calls. + * This is not an issue, except when we write out the super + * block on a system with a block size > 1K. So, we need to + * deal with that here. + */ + aux_info->sb_block = calloc(1, info->block_size); + ext4_assert(aux_info->sb_block); + + + if (info->block_size > 1024) + aux_info->sb = (struct ext4_sblock *)((char *)aux_info->sb_block + 1024); + else + aux_info->sb = aux_info->sb_block; + + aux_info->bg_desc = calloc(info->block_size, aux_info->bg_desc_blocks); + ext4_assert(aux_info->bg_desc); + + aux_info->xattrs = NULL; +} + int ext4_mkfs_read_info(struct ext4_blockdev *bd, struct ext4_mkfs_info *info) @@ -229,6 +295,9 @@ int ext4_mkfs(struct ext4_blockdev *bd, struct ext4_mkfs_info *info) !info->no_journal ? "yes" : "no"); ext4_dbg(DEBUG_MKFS, DBG_NONE "Label: %s\n", info->label); + struct fs_aux_info aux_info; + create_fs_aux_info(&aux_info, info); + /*TODO: write filesystem metadata*/ Finish: