*/
#include "ext4_config.h"
+#include "ext4_types.h"
+#include "ext4_misc.h"
+#include "ext4_errno.h"
+#include "ext4_debug.h"
+
#include "ext4_super.h"
#include "ext4_block_group.h"
#include "ext4_dir.h"
#include "ext4_dir_idx.h"
#include "ext4_fs.h"
#include "ext4_inode.h"
-#include "ext4_debug.h"
#include "ext4_ialloc.h"
#include "ext4_mkfs.h"
#include <string.h>
#include <stdlib.h>
-#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_bgroup *bg_desc;
+ uint8_t *bg_desc_blk;
struct xattr_list_element *xattrs;
uint32_t first_data_block;
uint64_t len_blocks;
static uint32_t compute_inodes(struct ext4_mkfs_info *info)
{
- return (uint32_t)DIV_ROUND_UP(info->len, info->block_size) / 4;
+ return (uint32_t)EXT4_DIV_ROUND_UP(info->len, info->block_size) / 4;
}
static uint32_t compute_inodes_per_group(struct ext4_mkfs_info *info)
{
- uint32_t blocks = (uint32_t)DIV_ROUND_UP(info->len, info->block_size);
- uint32_t block_groups = DIV_ROUND_UP(blocks, info->blocks_per_group);
- uint32_t inodes = DIV_ROUND_UP(info->inodes, block_groups);
+ uint32_t blocks = (uint32_t)EXT4_DIV_ROUND_UP(info->len, info->block_size);
+ uint32_t block_groups = EXT4_DIV_ROUND_UP(blocks, info->blocks_per_group);
+ uint32_t inodes = EXT4_DIV_ROUND_UP(info->inodes, block_groups);
inodes = EXT4_ALIGN(inodes, (info->block_size / info->inode_size));
/* After properly rounding up the number of inodes/group,
static uint32_t compute_journal_blocks(struct ext4_mkfs_info *info)
{
- uint32_t journal_blocks = (uint32_t)DIV_ROUND_UP(info->len,
+ uint32_t journal_blocks = (uint32_t)EXT4_DIV_ROUND_UP(info->len,
info->block_size) / 64;
if (journal_blocks < 1024)
journal_blocks = 1024;
{
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 *
+ aux_info->inode_table_blocks = EXT4_DIV_ROUND_UP(info->inodes_per_group *
info->inode_size, info->block_size);
- aux_info->groups = (uint32_t)DIV_ROUND_UP(aux_info->len_blocks -
+ aux_info->groups = (uint32_t)EXT4_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_dind * aux_info->blocks_per_dind;
aux_info->bg_desc_blocks =
- DIV_ROUND_UP(aux_info->groups * info->dsc_size,
+ EXT4_DIV_ROUND_UP(aux_info->groups * info->dsc_size,
info->block_size);
aux_info->default_i_flags = EXT4_INODE_FLAG_NOATIME;
if (!aux_info->sb)
return ENOMEM;
- aux_info->bg_desc = calloc(aux_info->groups, sizeof(struct ext4_bgroup));
- if (!aux_info->bg_desc)
+ aux_info->bg_desc_blk = calloc(1, info->block_size);
+ if (!aux_info->bg_desc_blk)
return ENOMEM;
aux_info->xattrs = NULL;
{
if (aux_info->sb)
free(aux_info->sb);
- if (aux_info->bg_desc)
- free(aux_info->bg_desc);
+ if (aux_info->bg_desc_blk)
+ free(aux_info->bg_desc_blk);
}
sb->flags = to_le32(EXT4_SUPERBLOCK_FLAGS_SIGNED_HASH);
}
-static void fill_bgroups(struct fs_aux_info *aux_info,
- struct ext4_mkfs_info *info)
-{
- uint32_t i;
- uint32_t bg_free_blk = 0;
- uint64_t sb_free_blk = 0;
+static int write_bgroup_block(struct ext4_blockdev *bd,
+ struct fs_aux_info *aux_info,
+ struct ext4_mkfs_info *info,
+ uint32_t blk)
+{
+ int r = EOK;
+ uint32_t j;
+ struct ext4_block b;
- for (i = 0; i < aux_info->groups; i++) {
+ uint32_t block_size = ext4_sb_get_block_size(aux_info->sb);
+ for (j = 0; j < aux_info->groups; j++) {
uint64_t bg_start_block = aux_info->first_data_block +
- aux_info->first_data_block + i * info->blocks_per_group;
+ j * info->blocks_per_group;
uint32_t blk_off = 0;
- bg_free_blk = info->blocks_per_group -
- aux_info->inode_table_blocks;
-
- bg_free_blk -= 2;
blk_off += aux_info->bg_desc_blocks;
-
- if (i == (aux_info->groups - 1))
- bg_free_blk -= aux_info->first_data_block;
-
- if (has_superblock(info, i)) {
+ if (has_superblock(info, j)) {
bg_start_block++;
blk_off += info->bg_desc_reserve_blocks;
- bg_free_blk -= info->bg_desc_reserve_blocks + 1;
- bg_free_blk -= aux_info->bg_desc_blocks;
}
- ext4_bg_set_block_bitmap(&aux_info->bg_desc[i], aux_info->sb,
- bg_start_block + blk_off + 1);
-
- ext4_bg_set_inode_bitmap(&aux_info->bg_desc[i], aux_info->sb,
- bg_start_block + blk_off + 2);
-
- ext4_bg_set_inode_table_first_block(&aux_info->bg_desc[i],
- aux_info->sb,
- bg_start_block + blk_off + 3);
-
- ext4_bg_set_free_blocks_count(&aux_info->bg_desc[i],
- aux_info->sb, bg_free_blk);
-
- ext4_bg_set_free_inodes_count(&aux_info->bg_desc[i],
- aux_info->sb, aux_info->sb->inodes_per_group);
+ uint64_t dsc_blk = bg_start_block + blk;
- ext4_bg_set_used_dirs_count(&aux_info->bg_desc[i], aux_info->sb,
- 0);
+ r = ext4_block_get_noread(bd, &b, dsc_blk);
+ if (r != EOK)
+ return r;
- ext4_bg_set_flag(&aux_info->bg_desc[i],
- EXT4_BLOCK_GROUP_BLOCK_UNINIT |
- EXT4_BLOCK_GROUP_INODE_UNINIT);
+ memcpy(b.data, aux_info->bg_desc_blk, block_size);
- sb_free_blk += bg_free_blk;
+ ext4_bcache_set_dirty(b.buf);
+ r = ext4_block_set(bd, &b);
+ if (r != EOK)
+ return r;
}
- ext4_sb_set_free_blocks_cnt(aux_info->sb, sb_free_blk);
+ return r;
}
-
static int write_bgroups(struct ext4_blockdev *bd, struct fs_aux_info *aux_info,
struct ext4_mkfs_info *info)
{
- int r;
- uint32_t i;
+ int r = EOK;
+
struct ext4_block b;
+ struct ext4_bgroup *bg_desc;
+
+ uint32_t i;
+ uint32_t bg_free_blk = 0;
+ uint64_t sb_free_blk = 0;
+ uint32_t block_size = ext4_sb_get_block_size(aux_info->sb);
+ uint32_t dsc_size = ext4_sb_get_desc_size(aux_info->sb);
+ uint32_t dsc_per_block = block_size / dsc_size;
+ uint32_t k = 0;
+
for (i = 0; i < aux_info->groups; i++) {
uint64_t bg_start_block = aux_info->first_data_block +
- + i * info->blocks_per_group;
+ aux_info->first_data_block + i * info->blocks_per_group;
uint32_t blk_off = 0;
+ bg_desc = (void *)(aux_info->bg_desc_blk + k * dsc_size);
+ bg_free_blk = info->blocks_per_group -
+ aux_info->inode_table_blocks;
+
+ bg_free_blk -= 2;
blk_off += aux_info->bg_desc_blocks;
+
+ if (i == (aux_info->groups - 1))
+ bg_free_blk -= aux_info->first_data_block;
+
if (has_superblock(info, i)) {
bg_start_block++;
blk_off += info->bg_desc_reserve_blocks;
+ bg_free_blk -= info->bg_desc_reserve_blocks + 1;
+ bg_free_blk -= aux_info->bg_desc_blocks;
}
- uint32_t block_size = ext4_sb_get_block_size(aux_info->sb);
- uint32_t dsc_pos = 0;
- uint32_t dsc_id = 0;
- uint32_t dsc_size = ext4_sb_get_desc_size(aux_info->sb);
- uint32_t dsc_blk_cnt = aux_info->bg_desc_blocks;
- uint64_t dsc_blk = bg_start_block;
+ ext4_bg_set_block_bitmap(bg_desc, aux_info->sb,
+ bg_start_block + blk_off + 1);
- while (dsc_blk_cnt--) {
- r = ext4_block_get(bd, &b, dsc_blk++);
- if (r != EOK)
- return r;
+ ext4_bg_set_inode_bitmap(bg_desc, aux_info->sb,
+ bg_start_block + blk_off + 2);
+
+ ext4_bg_set_inode_table_first_block(bg_desc,
+ aux_info->sb,
+ bg_start_block + blk_off + 3);
- dsc_pos = 0;
- while (dsc_pos + dsc_size <= block_size) {
- memcpy(b.data + dsc_pos,
- &aux_info->bg_desc[dsc_id],
- dsc_size);
+ ext4_bg_set_free_blocks_count(bg_desc, aux_info->sb,
+ bg_free_blk);
- dsc_pos += dsc_size;
- dsc_id++;
+ ext4_bg_set_free_inodes_count(bg_desc,
+ aux_info->sb, aux_info->sb->inodes_per_group);
- if (dsc_id == aux_info->groups)
- break;
- }
+ ext4_bg_set_used_dirs_count(bg_desc, aux_info->sb, 0);
- ext4_bcache_set_dirty(b.buf);
- r = ext4_block_set(bd, &b);
- if (r != EOK)
- return r;
+ ext4_bg_set_flag(bg_desc,
+ EXT4_BLOCK_GROUP_BLOCK_UNINIT |
+ EXT4_BLOCK_GROUP_INODE_UNINIT);
- if (dsc_id == aux_info->groups)
- break;
- }
+ sb_free_blk += bg_free_blk;
r = ext4_block_get_noread(bd, &b, bg_start_block + blk_off + 1);
if (r != EOK)
r = ext4_block_set(bd, &b);
if (r != EOK)
return r;
+
+ if (++k != dsc_per_block)
+ continue;
+
+ k = 0;
+ r = write_bgroup_block(bd, aux_info, info, i / dsc_per_block);
+ if (r != EOK)
+ return r;
+
}
+ r = write_bgroup_block(bd, aux_info, info, i / dsc_per_block);
+ if (r != EOK)
+ return r;
+ ext4_sb_set_free_blocks_cnt(aux_info->sb, sb_free_blk);
return r;
}
goto Finish;
fill_in_sb(&aux_info, info);
- fill_bgroups(&aux_info, info);
-
r = write_bgroups(bd, &aux_info, info);
if (r != EOK)