diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-03-04 20:53:18 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2021-03-09 00:25:39 +0100 |
| commit | c375ac35c728ebd99d794b3c2b64a3ecb07f27b1 (patch) | |
| tree | 2b53ca250ced98370528ba4eaea86a2eef1b4b80 /src | |
| parent | 3601ea5bae9247add596e2c6920e80a236803964 (diff) | |
Write all block group headers sequentially.
Before this the code would write:
headers for blocks 0-127 (without group descriptors)
group descriptors for blocks 0-127 to all blocks on disk
headers for blocks 128-255
group descriptors for blocks 128-255 to all blocks on disk
...
Diffstat (limited to 'src')
| -rw-r--r-- | src/ext4_mkfs.c | 133 |
1 files changed, 68 insertions, 65 deletions
diff --git a/src/ext4_mkfs.c b/src/ext4_mkfs.c index 0dfc91f..b792eb5 100644 --- a/src/ext4_mkfs.c +++ b/src/ext4_mkfs.c @@ -298,75 +298,39 @@ static void fill_sb(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info) } -static int write_bgroup_block(struct ext4_blockdev *bd, - struct fs_aux_info *aux_info, - struct ext4_mkfs_info *info, - uint32_t blk) +static int write_bgroups(struct ext4_blockdev *bd, struct fs_aux_info *aux_info, + struct ext4_mkfs_info *info) { - int r = EOK; - uint32_t j; - struct ext4_block b; - + /* size of the group descriptor */ + uint32_t dsc_size = ext4_sb_get_desc_size(aux_info->sb); 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 + - j * info->blocks_per_group; - uint32_t blk_off = 0; + /* Calculate the group descriptors chunk that will be written to each block group */ - blk_off += aux_info->bg_desc_blocks; - if (has_superblock(info, j)) { - bg_start_block++; - blk_off += info->bg_desc_reserve_blocks; - } - - uint64_t dsc_blk = bg_start_block + blk; - - r = ext4_block_get_noread(bd, &b, dsc_blk); - if (r != EOK) - return r; - - memcpy(b.data, aux_info->bg_desc_blk, block_size); - - ext4_bcache_set_dirty(b.buf); - r = ext4_block_set(bd, &b); - if (r != EOK) - return r; + /* The whole set of group descriptors */ + void* all_bg_desc = ext4_calloc(1, aux_info->groups * dsc_size); + if (!all_bg_desc) { + return ENOMEM; } - return r; -} - -static int write_bgroups(struct ext4_blockdev *bd, struct fs_aux_info *aux_info, - struct ext4_mkfs_info *info) -{ - 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++) { + for (uint32_t i = 0; i < aux_info->groups; i++) { uint64_t bg_start_block = aux_info->first_data_block + 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); + struct ext4_bgroup* bg_desc = (struct ext4_bgroup *) (((char *) all_bg_desc) + i * 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)) + if (i == (aux_info->groups - 1)) { bg_free_blk -= aux_info->first_data_block; + } if (has_superblock(info, i)) { bg_start_block++; @@ -398,37 +362,76 @@ static int write_bgroups(struct ext4_blockdev *bd, struct fs_aux_info *aux_info, EXT4_BLOCK_GROUP_INODE_UNINIT); sb_free_blk += bg_free_blk; + } + /* Write the block group headers */ + + int r = EOK; + + struct ext4_block b; + + for (uint32_t i = 0; i < aux_info->groups; i++) { + uint64_t bg_start_block = aux_info->first_data_block + + aux_info->first_data_block + i * info->blocks_per_group; + uint32_t blk_off = 0; + + if (has_superblock(info, i)) { + bg_start_block++; + blk_off += info->bg_desc_reserve_blocks; + } + + /* Group descriptors */ + uint32_t remaining = aux_info->groups * dsc_size; + for (uint32_t j = 0; j < aux_info->bg_desc_blocks; j++) { + r = ext4_block_get_noread(bd, &b, bg_start_block + blk_off + j); + if (r != EOK) { + free(all_bg_desc); + return r; + } + uint32_t this_time = remaining < block_size ? remaining : block_size; + memcpy(b.data, ((char *) all_bg_desc) + j * block_size, this_time); + memset(b.data + this_time, 0, block_size - this_time); + remaining -= this_time; + ext4_bcache_set_dirty(b.buf); + r = ext4_block_set(bd, &b); + if (r != EOK) { + free(all_bg_desc); + return r; + } + } + + blk_off += aux_info->bg_desc_blocks; + + /* Empty block bitmap */ r = ext4_block_get_noread(bd, &b, bg_start_block + blk_off + 1); - if (r != EOK) + if (r != EOK) { + free(all_bg_desc); return r; + } memset(b.data, 0, block_size); ext4_bcache_set_dirty(b.buf); r = ext4_block_set(bd, &b); - if (r != EOK) + if (r != EOK) { + free(all_bg_desc); return r; + } + + /* Empty inode bitmap */ r = ext4_block_get_noread(bd, &b, bg_start_block + blk_off + 2); - if (r != EOK) + if (r != EOK) { + free(all_bg_desc); return r; + } memset(b.data, 0, block_size); ext4_bcache_set_dirty(b.buf); r = ext4_block_set(bd, &b); - if (r != EOK) + if (r != EOK) { + free(all_bg_desc); 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; + free(all_bg_desc); ext4_sb_set_free_blocks_cnt(aux_info->sb, sb_free_blk); return r; |
