ext4: Update ext2/3/4 superblock, group descriptor and inode structures
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/7 ext4: Update ext2/3/4 superblock, group descriptor and inode structures
Most importantly, the superblock provides the used group descriptor size, which is required for the EXT4_FEATURE_INCOMPAT_64BIT.
--- include/ext_common.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-)
include/ext_common.h +46 -4
@@ -99,6 +99,33 @@ struct ext2_sblock {char volume_name[16 ];char last_mounted_on[64 ];__le32 compression_info; +uint8_t prealloc_blocks; +uint8_t prealloc_dir_blocks; +__le16 reserved_gdt_blocks; +uint8_t journal_uuid[16 ]; +__le32 journal_inode; +__le32 journal_dev; +__le32 last_orphan; +__le32 hash_seed[4 ]; +uint8_t default_hash_version; +uint8_t journal_backup_type; +__le16 descriptor_size; +__le32 default_mount_options; +__le32 first_meta_block_group; +__le32 mkfs_time; +__le32 journal_blocks[17 ]; +__le32 total_blocks_high; +__le32 reserved_blocks_high; +__le32 free_blocks_high; +__le16 min_extra_inode_size; +__le16 want_extra_inode_size; +__le32 flags; +__le16 raid_stride; +__le16 mmp_interval; +__le64 mmp_block; +__le32 raid_stripe_width; +uint8_t log2_groups_per_flex; +uint8_t checksum_type; };struct ext2_block_group {
@@ -109,9 +136,23 @@ struct ext2_block_group {__le16 free_inodes;/* Free inodes count */ __le16 used_dir_cnt;/* Directories count */ __le16 bg_flags; -__le32 bg_reserved[2 ]; +__le32 bg_exclude_bitmap; +__le16 bg_block_id_csum; +__le16 bg_inode_id_csum;__le16 bg_itable_unused;/* Unused inodes count */ -__le16 bg_checksum;/* crc16(s_uuid+grouo_num+group_desc)*/ +__le16 bg_checksum;/* crc16(s_uuid+group_num+group_desc)*/ +/* following fields only exist if descriptor size is 64 */ +__le32 block_id_high; +__le32 inode_id_high; +__le32 inode_table_id_high; +__le16 free_blocks_high; +__le16 free_inodes_high; +__le16 used_dir_cnt_high; +__le16 bg_itable_unused_high; +__le32 bg_exclude_bitmap_high; +__le16 bg_block_id_csum_high; +__le16 bg_inode_id_csum_high; +__le32 bg_reserved; };/* The ext2 inode. */
@@ -125,7 +166,7 @@ struct ext2_inode {__le32 dtime;__le16 gid;__le16 nlinks; -__le32 blockcnt;/* Blocks of 512 bytes!! */ +__le32 blockcnt;/* Blocks of either 512 or block_size bytes */ __le32 flags;__le32 osd1;union {
@@ -136,10 +177,11 @@ struct ext2_inode {__le32 triple_indir_block; } blocks;char symlink[60 ]; +char inline_data[60 ]; } b;__le32 version;__le32 acl; -__le32 dir_acl; +__le32 size_high;/* previously dir_acl, but never used */ __le32 fragment_addr;__le32 osd2[3 ]; };
Signature · 1 line
2.10.0
PATCH 1/7 ext4: Update ext2/3/4 superblock, group descriptor and inode structures
Quoted 4 lines · Stefan Br?ns
Most importantly, the superblock provides the used group descriptor size, which is required for the
EXT4_FEATURE_INCOMPAT_64BIT.Signed-off-by Stefan Br?ns <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160923/55390174/attachment.sig>
PATCH 2/7 ext4: determine group descriptor size for 64bit feature
In reply to a message not in the archiveIf EXT4_FEATURE_INCOMPAT_64BIT is set, the descriptor can be read from the superblocks, otherwise it defaults to 32.
--- fs/ext4/ext4_common.c | 18 ++++++++++++++---- include/ext4fs.h | 2 ++ 2 files changed, 16 insertions(+), 4 deletions(-)
fs/ext4/ext4_common.c +14 -4
@@ -2233,13 +2233,23 @@ int ext4fs_mount(unsigned part_length) goto fail; } -if (le32_to_cpu (data->sblock.revision_level) ==0 ) +if (le32_to_cpu (data->sblock.revision_level) ==0 ) { fs->inodesz =128 ; -else + }else { +debug ("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: %08x\n" , +__le32_to_cpu (data->sblock.feature_compatibility), +__le32_to_cpu (data->sblock.feature_incompat), +__le32_to_cpu (data->sblock.feature_ro_compat)); + fs->inodesz =le16_to_cpu (data->sblock.inode_size); + fs->gdsize =le32_to_cpu (data->sblock.feature_incompat) & +EXT4_FEATURE_INCOMPAT_64BIT ? +le16_to_cpu (data->sblock.descriptor_size) :32 ; + } -debug ("EXT2 rev %d, inode_size %d\n" , -le32_to_cpu (data->sblock.revision_level), fs->inodesz); +debug ("EXT2 rev %d, inode_size %d, descriptor size %d\n" , +le32_to_cpu (data->sblock.revision_level), + fs->inodesz, fs->gdsize); data->diropen.data = data; data->diropen.ino =2 ;
include/ext4fs.h +2 -0
@@ -87,6 +87,8 @@ struct ext_filesystem {uint32_t inodesz;/* Sectors per Block */ uint32_t sect_perblk; +/* Group Descriptor size */ +uint16_t gdsize;/* Group Descriptor Block Number */ uint32_t gdtable_blkno;/* Total block groups of partition */
Signature · 1 line
2.10.0
PATCH 2/7 ext4: determine group descriptor size for 64bit feature
Quoted 4 lines · Stefan Br?ns
If
EXT4_FEATURE_INCOMPAT_64BITis set, the descriptor can be read from the superblocks, otherwise it defaults to 32.Signed-off-by Stefan Br?ns <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160923/914a74ba/attachment.sig>
PATCH 2/7 ext4: determine group descriptor size for 64bit feature
In reply to Stefan BrünsHi Stefan, Tom,
I'm using genext2fs command in Linux to generate my boot image for
kernel and its dtb, my command is like this:
$ genext2fs -b 32768 -B $((32*1024*1024/32768)) -d boot/ -i 8192 -U boot.img
In the latest version of U-Boot, the image from above command is
not able
to be mount. After debug, I found out that the root cause is that the genext2fs
does not have a initial value for revision_level in super block. After I do the mount
and umount for the image in Linux, the U-Boot then can mount the image.
Is it possible to still support the ext2 image generated by
genext2fs command in U-Boot?
Thanks,
- Kever
Quoted 54 lines · Stefan Br?ns
If
EXT4_FEATURE_INCOMPAT_64BITis set, the descriptor can be read from the superblocks, otherwise it defaults to 32.Signed-off-by Stefan Br?ns <[email protected]>--- fs/ext4/ext4_common.c | 18 ++++++++++++++---- include/ext4fs.h | 2 ++ 2 files changed, 16 insertions(+), 4 deletions(-)fs/ext4/ext4_common.c +14
-4@@ -2233,13 +2233,23 @@ int ext4fs_mount(unsigned part_length) goto fail; } -if (le32_to_cpu (data->sblock.revision_level) ==0 ) +if (le32_to_cpu (data->sblock.revision_level) ==0 ) { fs->inodesz =128 ; -else + }else { +debug ("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: %08x\n" , +__le32_to_cpu (data->sblock.feature_compatibility), +__le32_to_cpu (data->sblock.feature_incompat), +__le32_to_cpu (data->sblock.feature_ro_compat)); + fs->inodesz =le16_to_cpu (data->sblock.inode_size); + fs->gdsize =le32_to_cpu (data->sblock.feature_incompat) & +EXT4_FEATURE_INCOMPAT_64BIT ? +le16_to_cpu (data->sblock.descriptor_size) :32 ; + } -debug ("EXT2 rev %d, inode_size %d\n" , -le32_to_cpu (data->sblock.revision_level), fs->inodesz); +debug ("EXT2 rev %d, inode_size %d, descriptor size %d\n" , +le32_to_cpu (data->sblock.revision_level), + fs->inodesz, fs->gdsize); data->diropen.data = data; data->diropen.ino =2 ;include/ext4fs.h +2
-0@@ -87,6 +87,8 @@ struct ext_filesystem {uint32_t inodesz;/* Sectors per Block */ uint32_t sect_perblk; +/* Group Descriptor size */ +uint16_t gdsize;/* Group Descriptor Block Number */ uint32_t gdtable_blkno;/* Total block groups of partition */
PATCH 2/7 ext4: determine group descriptor size for 64bit feature
Hi Kever,
can you test the ext4 patch I just posted?
Kind regards,
Stefan
Signature · 3 lines
Stefan Br?ns / Bergstra?e 21 / 52062 Aachen home: +49 241 53809034 mobile: +49 151 50412019 work: +49 2405 49936-424
PATCH 3/7 ext4: Add helper functions for block group descriptor field access
In reply to a message not in the archiveThe helper functions encapsulate access of the block group descriptors, independent of group descriptor size. The helpers also deal with the endianess of the fields, and with split fields like free_blocks/ free_blocks_high.
--- fs/ext4/ext4_common.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4/ext4_common.h | 12 ++++++++ 2 files changed, 92 insertions(+)
fs/ext4/ext4_common.c +80 -0
@@ -47,6 +47,12 @@ struct ext2_inode *g_parent_inode;static int symlinknest;#if defined(CONFIG_EXT4_WRITE ) +struct ext2_block_group *ext4fs_get_group_descriptor + (const struct ext_filesystem *fs,uint32_t bg_idx) +{ +return (struct ext2_block_group *)(fs->gdtable + (bg_idx * fs->gdsize)); +} +static inline void ext4fs_sb_free_inodes_dec (struct ext2_sblock *sb) { sb->free_inodes =cpu_to_le32 (le32_to_cpu (sb->free_inodes) -1 );
@@ -72,6 +78,80 @@ static inline void ext4fs_bg_itable_unused_dec(struct ext2_block_group *bg) bg->bg_itable_unused =cpu_to_le16 (le16_to_cpu (bg->bg_itable_unused) -1 ); } +uint64_t ext4fs_sb_get_free_blocks (const struct ext2_sblock *sb) +{ +uint64_t free_blocks =le32_to_cpu (sb->free_blocks); + free_blocks += (uint64_t )le32_to_cpu (sb->free_blocks_high) <<32 ; +return free_blocks; +} + +void ext4fs_sb_set_free_blocks (struct ext2_sblock *sb,uint64_t free_blocks) +{ + sb->free_blocks =cpu_to_le32 (free_blocks &0xffffffff ); + sb->free_blocks_high =cpu_to_le16 (free_blocks >>32 ); +} + +uint32_t ext4fs_bg_get_free_blocks (const struct ext2_block_group *bg, +const struct ext_filesystem *fs) +{ +uint32_t free_blocks =le16_to_cpu (bg->free_blocks); +if (fs->gdsize ==64 ) + free_blocks +=le16_to_cpu (bg->free_blocks_high) <<16 ; +return free_blocks; +} + +static inline +uint32_t ext4fs_bg_get_free_inodes (const struct ext2_block_group *bg, +const struct ext_filesystem *fs) +{ +uint32_t free_inodes =le16_to_cpu (bg->free_inodes); +if (fs->gdsize ==64 ) + free_inodes +=le16_to_cpu (bg->free_inodes_high) <<16 ; +return free_inodes; +} + +static inline uint16_t ext4fs_bg_get_flags (const struct ext2_block_group *bg) +{ +return le16_to_cpu (bg->bg_flags); +} + +static inline void ext4fs_bg_set_flags (struct ext2_block_group *bg, +uint16_t flags) +{ + bg->bg_flags =cpu_to_le16 (flags); +} + +/* Block number of the block bitmap */ +uint64_t ext4fs_bg_get_block_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs) +{ +uint64_t block_nr =le32_to_cpu (bg->block_id); +if (fs->gdsize ==64 ) + block_nr += (uint64_t )le32_to_cpu (bg->block_id_high) <<32 ; +return block_nr; +} + +/* Block number of the inode bitmap */ +uint64_t ext4fs_bg_get_inode_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs) +{ +uint64_t block_nr =le32_to_cpu (bg->inode_id); +if (fs->gdsize ==64 ) + block_nr += (uint64_t )le32_to_cpu (bg->inode_id_high) <<32 ; +return block_nr; +} + +/* Block number of the inode table */ +uint64_t ext4fs_bg_get_inode_table_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs) +{ +uint64_t block_nr =le32_to_cpu (bg->inode_table_id); +if (fs->gdsize ==64 ) + block_nr += + (uint64_t )le32_to_cpu (bg->inode_table_id_high) <<32 ; +return block_nr; +} +uint32_t ext4fs_div_roundup (uint32_t size,uint32_t n) {uint32_t res = size / n;
fs/ext4/ext4_common.h +12 -0
@@ -74,5 +74,17 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode,unsigned int total_remaining_blocks, unsigned int *total_no_of_block);void put_ext4 (uint64_t off,void *buf,uint32_t size); +struct ext2_block_group *ext4fs_get_group_descriptor + (const struct ext_filesystem *fs,uint32_t bg_idx); +uint64_t ext4fs_bg_get_block_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs); +uint64_t ext4fs_bg_get_inode_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs); +uint64_t ext4fs_bg_get_inode_table_id (const struct ext2_block_group *bg, +const struct ext_filesystem *fs); +uint64_t ext4fs_sb_get_free_blocks (const struct ext2_sblock *sb); +void ext4fs_sb_set_free_blocks (struct ext2_sblock *sb,uint64_t free_blocks); +uint32_t ext4fs_bg_get_free_blocks (const struct ext2_block_group *bg, +const struct ext_filesystem *fs);#endif #endif
Signature · 1 line
2.10.0
PATCH 4/7 ext4: Use correct descriptor size when reading the block group descriptor
In reply to a message not in the archiveThe correct descriptor size must be used when calculating offsets, and also to read the correct amount of data.
--- fs/ext4/ext4_common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/ext4/ext4_common.c +4 -4
@@ -1525,20 +1525,20 @@ static int ext4fs_blockgrouplong int blkno;unsigned int blkoff, desc_per_blk;int log2blksz =get_fs ()->dev_desc->log2blksz; +int desc_size =get_fs ()->gdsize; - desc_per_blk =EXT2_BLOCK_SIZE (data) /sizeof (struct ext2_block_group ); + desc_per_blk =EXT2_BLOCK_SIZE (data) / desc_size; blkno =le32_to_cpu (data->sblock.first_data_block) +1 + group / desc_per_blk; - blkoff = (group % desc_per_blk) *sizeof (struct ext2_block_group ); + blkoff = (group % desc_per_blk) * desc_size;debug ("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n" , group, blkno, blkoff);return ext4fs_devread ((lbaint_t )blkno << (LOG2_BLOCK_SIZE (data) - log2blksz), - blkoff,sizeof (struct ext2_block_group ), - (char *)blkgrp); + blkoff, desc_size, (char *)blkgrp); }int ext4fs_read_inode (struct ext2_data *data,int ino,struct ext2_inode *inode)
Signature · 1 line
2.10.0
PATCH 4/7 ext4: Use correct descriptor size when reading the block group descriptor
Quoted 4 lines · Stefan Br?ns
The correct descriptor size must be used when calculating offsets, and also to read the correct amount of data.
Signed-off-by Stefan Br?ns <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160923/ff1098e7/attachment.sig>
PATCH 5/7 ext4: Use helper function to access group descriptor and its fields
In reply to a message not in the archiveThe descriptor size is variable, thus array indices are not generically applicable. The larger group descriptors also contain e.g. high parts of block numbers, which have to be read and written.
--- fs/ext4/ext4_common.c | 125 ++++++++++++++++++++------------------ fs/ext4/ext4_write.c | 165 +++++++++++++++++++++++++++----------------------- include/ext4fs.h | 1 - 3 files changed, 154 insertions(+), 137 deletions(-)
fs/ext4/ext4_common.c +65 -60
@@ -391,7 +391,7 @@ uint16_t ext4fs_checksum_update(uint32_t i)uint16_t crc =0 ;__le32 le32_i =cpu_to_le32 (i); - desc = (struct ext2_block_group *)&fs->bgd[i]; + desc =ext4fs_get_group_descriptor (fs, i);if (le32_to_cpu (fs->sb->feature_ro_compat) &EXT4_FEATURE_RO_COMPAT_GDT_CSUM ) {int offset = offsetof(struct ext2_block_group , bg_checksum);
@@ -931,39 +931,41 @@ uint32_t ext4fs_get_new_blk_no(void)char *zero_buffer =zalloc (fs->blksz);if (!journal_buffer || !zero_buffer) goto fail; -struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;if (fs->first_pass_bbmap ==0 ) {for (i =0 ; i < fs->no_blkgrp; i++) { -if (le16_to_cpu (bgd[i].free_blocks)) { -if (le16_to_cpu (bgd[i].bg_flags) &EXT4_BG_BLOCK_UNINIT ) { -uint16_t new_flags; -put_ext4 ((uint64_t )le32_to_cpu (bgd[i].block_id) * fs->blksz, - zero_buffer, fs->blksz); - new_flags =le16_to_cpu (bgd[i].bg_flags) & ~EXT4_BG_BLOCK_UNINIT ; - bgd[i].bg_flags =cpu_to_le16 (new_flags); +struct ext2_block_group *bgd =NULL ; + bgd =ext4fs_get_group_descriptor (fs, i); +if (ext4fs_bg_get_free_blocks (bgd, fs)) { +uint16_t bg_flags =ext4fs_bg_get_flags (bgd); +uint64_t b_bitmap_blk = +ext4fs_bg_get_block_id (bgd, fs); +if (bg_flags &EXT4_BG_BLOCK_UNINIT ) {memcpy (fs->blk_bmaps[i], zero_buffer, fs->blksz); +put_ext4 (b_bitmap_blk * fs->blksz, + fs->blk_bmaps[i], fs->blksz); + bg_flags &= ~EXT4_BG_BLOCK_UNINIT ; +ext4fs_bg_set_flags (bgd, bg_flags); } fs->curr_blkno =_get_new_blk_no (fs->blk_bmaps[i]);if (fs->curr_blkno ==-1 ) -/* if block bitmap is completely fill */ +/* block bitmap is completely filled */ continue ; fs->curr_blkno = fs->curr_blkno + (i * fs->blksz *8 ); fs->first_pass_bbmap++; -ext4fs_bg_free_blocks_dec (&bgd[i]); +ext4fs_bg_free_blocks_dec (bgd);ext4fs_sb_free_blocks_dec (fs->sb); - status =ext4fs_devread ( - (lbaint_t )le32_to_cpu (bgd[i].block_id) * - fs->sect_perblk,0 , - fs->blksz, + status =ext4fs_devread (b_bitmap_blk * + fs->sect_perblk, +0 , fs->blksz, journal_buffer);if (status ==0 ) goto fail;if (ext4fs_log_journal (journal_buffer, -le32_to_cpu (bgd[i].block_id))) + b_bitmap_blk)) goto fail; goto success; }else {
@@ -990,7 +992,9 @@ restart:if (bg_idx >= fs->no_blkgrp) goto fail; -if (bgd[bg_idx].free_blocks ==0 ) { +struct ext2_block_group *bgd =NULL ; + bgd =ext4fs_get_group_descriptor (fs, bg_idx); +if (ext4fs_bg_get_free_blocks (bgd, fs) ==0 ) {debug ("block group %u is full. Skipping\n" , bg_idx); fs->curr_blkno = (bg_idx +1 ) * blk_per_grp;if (fs->blksz ==1024 )
@@ -998,13 +1002,14 @@ restart: goto restart; } -if (le16_to_cpu (bgd[bg_idx].bg_flags) &EXT4_BG_BLOCK_UNINIT ) { -uint16_t new_flags; -put_ext4 ((uint64_t )le32_to_cpu (bgd[bg_idx].block_id) * fs->blksz, - zero_buffer, fs->blksz); +uint16_t bg_flags =ext4fs_bg_get_flags (bgd); +uint64_t b_bitmap_blk =ext4fs_bg_get_block_id (bgd, fs); +if (bg_flags &EXT4_BG_BLOCK_UNINIT ) {memcpy (fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); - new_flags =le16_to_cpu (bgd[bg_idx].bg_flags) & ~EXT4_BG_BLOCK_UNINIT ; - bgd[bg_idx].bg_flags =cpu_to_le16 (new_flags); +put_ext4 (b_bitmap_blk * fs->blksz, + zero_buffer, fs->blksz); + bg_flags &= ~EXT4_BG_BLOCK_UNINIT ; +ext4fs_bg_set_flags (bgd, bg_flags); } if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx],
@@ -1017,19 +1022,16 @@ restart:/* journal backup */ if (prev_bg_bitmap_index != bg_idx) { - status =ext4fs_devread ( - (lbaint_t )le32_to_cpu (bgd[bg_idx].block_id) - * fs->sect_perblk, + status =ext4fs_devread (b_bitmap_blk * fs->sect_perblk,0 , fs->blksz, journal_buffer);if (status ==0 ) goto fail; -if (ext4fs_log_journal (journal_buffer, -le32_to_cpu (bgd[bg_idx].block_id))) +if (ext4fs_log_journal (journal_buffer, b_bitmap_blk)) goto fail; prev_bg_bitmap_index = bg_idx; } -ext4fs_bg_free_blocks_dec (&bgd[bg_idx]); +ext4fs_bg_free_blocks_dec (bgd);ext4fs_sb_free_blocks_dec (fs->sb); goto success; }
@@ -1057,46 +1059,49 @@ int ext4fs_get_new_inode_no(void)char *zero_buffer =zalloc (fs->blksz);if (!journal_buffer || !zero_buffer) goto fail; -struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;int has_gdt_chksum =le32_to_cpu (fs->sb->feature_ro_compat) &EXT4_FEATURE_RO_COMPAT_GDT_CSUM ?1 :0 ;if (fs->first_pass_ibmap ==0 ) {for (i =0 ; i < fs->no_blkgrp; i++) { -if (bgd[i].free_inodes) { +uint32_t free_inodes; +struct ext2_block_group *bgd =NULL ; + bgd =ext4fs_get_group_descriptor (fs, i); + free_inodes =ext4fs_bg_get_free_inodes (bgd, fs); +if (free_inodes) { +uint16_t bg_flags =ext4fs_bg_get_flags (bgd); +uint64_t i_bitmap_blk = +ext4fs_bg_get_inode_id (bgd, fs);if (has_gdt_chksum) - bgd[i].bg_itable_unused = - bgd[i].free_inodes; -if (le16_to_cpu (bgd[i].bg_flags) &EXT4_BG_INODE_UNINIT ) { -int new_flags; -put_ext4 ((uint64_t )le32_to_cpu (bgd[i].inode_id) * fs->blksz, + bgd->bg_itable_unused = free_inodes; +if (bg_flags &EXT4_BG_INODE_UNINIT ) { +put_ext4 (i_bitmap_blk * fs->blksz, zero_buffer, fs->blksz); - new_flags =le16_to_cpu (bgd[i].bg_flags) & ~EXT4_BG_INODE_UNINIT ; - bgd[i].bg_flags =cpu_to_le16 (new_flags); + bg_flags &= ~EXT4_BG_INODE_UNINIT ; +ext4fs_bg_set_flags (bgd, bg_flags);memcpy (fs->inode_bmaps[i], zero_buffer, fs->blksz); } fs->curr_inode_no =_get_new_inode_no (fs->inode_bmaps[i]);if (fs->curr_inode_no ==-1 ) -/* if block bitmap is completely fill */ +/* inode bitmap is completely filled */ continue ; fs->curr_inode_no = fs->curr_inode_no + (i * inodes_per_grp); fs->first_pass_ibmap++; -ext4fs_bg_free_inodes_dec (&bgd[i]); +ext4fs_bg_free_inodes_dec (bgd);if (has_gdt_chksum) -ext4fs_bg_itable_unused_dec (&bgd[i]); +ext4fs_bg_itable_unused_dec (bgd);ext4fs_sb_free_inodes_dec (fs->sb); - status =ext4fs_devread ( - (lbaint_t )le32_to_cpu (bgd[i].inode_id) * - fs->sect_perblk,0 , - fs->blksz, + status =ext4fs_devread (i_bitmap_blk * + fs->sect_perblk, +0 , fs->blksz, journal_buffer);if (status ==0 ) goto fail;if (ext4fs_log_journal (journal_buffer, -le32_to_cpu (bgd[i].inode_id))) + i_bitmap_blk)) goto fail; goto success; }else
@@ -1108,12 +1113,16 @@ restart: fs->curr_inode_no++;/* get the blockbitmap index respective to blockno */ ibmap_idx = fs->curr_inode_no / inodes_per_grp; -if (le16_to_cpu (bgd[ibmap_idx].bg_flags) &EXT4_BG_INODE_UNINIT ) { -int new_flags; -put_ext4 ((uint64_t )le32_to_cpu (bgd[ibmap_idx].inode_id) * fs->blksz, +struct ext2_block_group *bgd = +ext4fs_get_group_descriptor (fs, ibmap_idx); +uint16_t bg_flags =ext4fs_bg_get_flags (bgd); +uint64_t i_bitmap_blk =ext4fs_bg_get_inode_id (bgd, fs); + +if (bg_flags &EXT4_BG_INODE_UNINIT ) { +put_ext4 (i_bitmap_blk * fs->blksz, zero_buffer, fs->blksz); - new_flags =le16_to_cpu (bgd[ibmap_idx].bg_flags) & ~EXT4_BG_INODE_UNINIT ; - bgd[ibmap_idx].bg_flags =cpu_to_le16 (new_flags); + bg_flags &= ~EXT4_BG_INODE_UNINIT ; +ext4fs_bg_set_flags (bgd, bg_flags);memcpy (fs->inode_bmaps[ibmap_idx], zero_buffer, fs->blksz); }
@@ -1128,22 +1137,18 @@ restart:/* journal backup */ if (prev_inode_bitmap_index != ibmap_idx) { -memset (journal_buffer,'\0' , fs->blksz); - status =ext4fs_devread ( - (lbaint_t )le32_to_cpu (bgd[ibmap_idx].inode_id) - * fs->sect_perblk, + status =ext4fs_devread (i_bitmap_blk * fs->sect_perblk,0 , fs->blksz, journal_buffer);if (status ==0 ) goto fail;if (ext4fs_log_journal (journal_buffer, -le32_to_cpu (bgd[ibmap_idx].inode_id))) +le32_to_cpu (bgd->inode_id))) goto fail; prev_inode_bitmap_index = ibmap_idx; } -ext4fs_bg_free_inodes_dec (&bgd[ibmap_idx]); +ext4fs_bg_free_inodes_dec (bgd);if (has_gdt_chksum) - bgd[ibmap_idx].bg_itable_unused = - bgd[ibmap_idx].free_inodes; + bgd->bg_itable_unused = bgd->free_inodes;ext4fs_sb_free_inodes_dec (fs->sb); goto success; }
@@ -1559,7 +1564,7 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)return 0 ; inodes_per_block =EXT2_BLOCK_SIZE (data) / fs->inodesz; - blkno =le32_to_cpu (blkgrp.inode_table_id) + + blkno =ext4fs_bg_get_inode_table_id (&blkgrp, fs) + (ino %le32_to_cpu (sblock->inodes_per_group)) / inodes_per_block; blkoff = (ino % inodes_per_block) * fs->inodesz;/* Read the inode. */
fs/ext4/ext4_write.c +89 -76
379 lines not on this page · raw message
include/ext4fs.h +0 -1
@@ -98,7 +98,6 @@ struct ext_filesystem {/* Superblock */ struct ext2_sblock *sb;/* Block group descritpor table */ -struct ext2_block_group *bgd;char *gdtable;/* Block Bitmap Related */
Signature · 1 line
2.10.0
PATCH 5/7 ext4: Use helper function to access group descriptor and its fields
Quoted 5 lines · Stefan Br?ns
The descriptor size is variable, thus array indices are not generically applicable. The larger group descriptors also contain e.g. high parts of block numbers, which have to be read and written.
Signed-off-by Stefan Br?ns <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160923/c45393a0/attachment-0001.sig>
PATCH 6/7 ext4: Respect group descriptor size when adjusting free counts
In reply to a message not in the archiveAlso adjust high 16/32 bits when free inode/block counts are modified.
--- fs/ext4/ext4_common.c | 53 +++++++++++++++++++++++++++++++++++++++------------ fs/ext4/ext4_write.c | 40 ++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 24 deletions(-)
fs/ext4/ext4_common.c +41 -12
@@ -58,24 +58,53 @@ static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb) sb->free_inodes =cpu_to_le32 (le32_to_cpu (sb->free_inodes) -1 ); } -static inline void ext4fs_bg_free_inodes_dec (struct ext2_block_group *bg) +static inline void ext4fs_bg_free_inodes_dec + (struct ext2_block_group *bg,const struct ext_filesystem *fs) { - bg->free_inodes =cpu_to_le16 (le16_to_cpu (bg->free_inodes) -1 ); +uint32_t free_inodes =le16_to_cpu (bg->free_inodes); +if (fs->gdsize ==64 ) + free_inodes +=le16_to_cpu (bg->free_inodes_high) <<16 ; + free_inodes--; + + bg->free_inodes =cpu_to_le16 (free_inodes &0xffff ); +if (fs->gdsize ==64 ) + bg->free_inodes_high =cpu_to_le16 (free_inodes >>16 ); } -static inline void ext4fs_bg_free_blocks_dec (struct ext2_block_group *bg) +static inline void ext4fs_bg_free_blocks_dec + (struct ext2_block_group *bg,const struct ext_filesystem *fs) { - bg->free_blocks =cpu_to_le16 (le16_to_cpu (bg->free_blocks) -1 ); +uint32_t free_blocks =le16_to_cpu (bg->free_blocks); +if (fs->gdsize ==64 ) + free_blocks +=le16_to_cpu (bg->free_blocks_high) <<16 ; + free_blocks--; + + bg->free_blocks =cpu_to_le16 (free_blocks &0xffff ); +if (fs->gdsize ==64 ) + bg->free_blocks_high =cpu_to_le16 (free_blocks >>16 ); }static inline void ext4fs_sb_free_blocks_dec (struct ext2_sblock *sb) { - sb->free_blocks =cpu_to_le32 (le32_to_cpu (sb->free_blocks) -1 ); +uint64_t free_blocks =le32_to_cpu (sb->free_blocks); + free_blocks += (uint64_t )le32_to_cpu (sb->free_blocks_high) <<32 ; + free_blocks--; + + sb->free_blocks =cpu_to_le32 (free_blocks &0xffffffff ); + sb->free_blocks_high =cpu_to_le16 (free_blocks >>32 ); } -static inline void ext4fs_bg_itable_unused_dec (struct ext2_block_group *bg) +static inline void ext4fs_bg_itable_unused_dec + (struct ext2_block_group *bg,const struct ext_filesystem *fs) { - bg->bg_itable_unused =cpu_to_le16 (le16_to_cpu (bg->bg_itable_unused) -1 ); +uint32_t free_inodes =le16_to_cpu (bg->bg_itable_unused); +if (fs->gdsize ==64 ) + free_inodes +=le16_to_cpu (bg->bg_itable_unused_high) <<16 ; + free_inodes--; + + bg->bg_itable_unused =cpu_to_le16 (free_inodes &0xffff ); +if (fs->gdsize ==64 ) + bg->bg_itable_unused_high =cpu_to_le16 (free_inodes >>16 ); }uint64_t ext4fs_sb_get_free_blocks (const struct ext2_sblock *sb)
@@ -956,7 +985,7 @@ uint32_t ext4fs_get_new_blk_no(void) fs->curr_blkno = fs->curr_blkno + (i * fs->blksz *8 ); fs->first_pass_bbmap++; -ext4fs_bg_free_blocks_dec (bgd); +ext4fs_bg_free_blocks_dec (bgd, fs);ext4fs_sb_free_blocks_dec (fs->sb); status = ext4fs_devread(b_bitmap_blk * fs->sect_perblk,
@@ -1031,7 +1060,7 @@ restart: prev_bg_bitmap_index = bg_idx; } -ext4fs_bg_free_blocks_dec (bgd); +ext4fs_bg_free_blocks_dec (bgd, fs);ext4fs_sb_free_blocks_dec (fs->sb); goto success; }
@@ -1090,9 +1119,9 @@ int ext4fs_get_new_inode_no(void) fs->curr_inode_no = fs->curr_inode_no + (i * inodes_per_grp); fs->first_pass_ibmap++; -ext4fs_bg_free_inodes_dec (bgd); +ext4fs_bg_free_inodes_dec (bgd, fs);if (has_gdt_chksum) -ext4fs_bg_itable_unused_dec (bgd); +ext4fs_bg_itable_unused_dec (bgd, fs);ext4fs_sb_free_inodes_dec (fs->sb); status = ext4fs_devread(i_bitmap_blk * fs->sect_perblk,
@@ -1146,7 +1175,7 @@ restart: goto fail; prev_inode_bitmap_index = ibmap_idx; } -ext4fs_bg_free_inodes_dec (bgd); +ext4fs_bg_free_inodes_dec (bgd, fs);if (has_gdt_chksum) bgd->bg_itable_unused = bgd->free_inodes;ext4fs_sb_free_inodes_dec (fs->sb);
fs/ext4/ext4_write.c +28 -12
@@ -38,14 +38,30 @@ static inline void ext4fs_sb_free_blocks_inc(struct ext2_sblock *sb) sb->free_blocks =cpu_to_le32 (le32_to_cpu (sb->free_blocks) +1 ); } -static inline void ext4fs_bg_free_inodes_inc (struct ext2_block_group *bg) +static inline void ext4fs_bg_free_inodes_inc + (struct ext2_block_group *bg,const struct ext_filesystem *fs) { - bg->free_inodes =cpu_to_le16 (le16_to_cpu (bg->free_inodes) +1 ); +uint32_t free_inodes =le16_to_cpu (bg->free_inodes); +if (fs->gdsize ==64 ) + free_inodes +=le16_to_cpu (bg->free_inodes_high) <<16 ; + free_inodes++; + + bg->free_inodes =cpu_to_le16 (free_inodes &0xffff ); +if (fs->gdsize ==64 ) + bg->free_inodes_high =cpu_to_le16 (free_inodes >>16 ); } -static inline void ext4fs_bg_free_blocks_inc (struct ext2_block_group *bg) +static inline void ext4fs_bg_free_blocks_inc + (struct ext2_block_group *bg,const struct ext_filesystem *fs) { - bg->free_blocks =cpu_to_le16 (le16_to_cpu (bg->free_blocks) +1 ); +uint32_t free_blocks =le16_to_cpu (bg->free_blocks); +if (fs->gdsize ==64 ) + free_blocks +=le16_to_cpu (bg->free_blocks_high) <<16 ; + free_blocks++; + + bg->free_blocks =cpu_to_le16 (free_blocks &0xffff ); +if (fs->gdsize ==64 ) + bg->free_blocks_high =cpu_to_le16 (free_blocks >>16 ); }static void ext4fs_update (void )
@@ -146,7 +162,7 @@ static void delete_single_indirect_block(struct ext2_inode *inode)ext4fs_reset_block_bmap (blknr, fs->blk_bmaps[bg_idx], bg_idx);/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -210,7 +226,7 @@ static void delete_double_indirect_block(struct ext2_inode *inode)ext4fs_reset_block_bmap (*di_buffer, fs->blk_bmaps[bg_idx], bg_idx); di_buffer++; -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -241,7 +257,7 @@ static void delete_double_indirect_block(struct ext2_inode *inode)/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx);ext4fs_reset_block_bmap (blknr, fs->blk_bmaps[bg_idx], bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -322,7 +338,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) tip_buffer++;/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -362,7 +378,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) tigp_buffer++;/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -394,7 +410,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)ext4fs_reset_block_bmap (blknr, fs->blk_bmaps[bg_idx], bg_idx);/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -481,7 +497,7 @@ static int ext4fs_delete_file(int inodeno)/* get block group descriptor table */ bgd =ext4fs_get_group_descriptor (fs, bg_idx); -ext4fs_bg_free_blocks_inc (bgd); +ext4fs_bg_free_blocks_inc (bgd, fs);ext4fs_sb_free_blocks_inc (fs->sb);/* journal backup */ if (prev_bg_bmap_idx != bg_idx) {
@@ -536,7 +552,7 @@ static int ext4fs_delete_file(int inodeno)/* update the respective inode bitmaps */ inodeno++;ext4fs_reset_inode_bmap (inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx); -ext4fs_bg_free_inodes_inc (bgd); +ext4fs_bg_free_inodes_inc (bgd, fs);ext4fs_sb_free_inodes_inc (fs->sb);/* journal backup */ memset (journal_buffer,'\0' , fs->blksz);
Signature · 1 line
2.10.0
PATCH 7/7 ext4: Revert rejection of 64bit enabled ext4 fs
In reply to a message not in the archiveEnable mounting of ext4 fs with 64bit feature, as it is supported now. These had been disabled in 6f94ab6656ceffb3f2a972c8de4c554502b6f2b7.
--- fs/ext4/ext4_common.c | 9 --------- 1 file changed, 9 deletions(-)
fs/ext4/ext4_common.c +0 -9
@@ -2337,15 +2337,6 @@ int ext4fs_mount(unsigned part_length)if (le16_to_cpu (data->sblock.magic) !=EXT2_MAGIC ) goto fail; -/* -* The 64bit feature was enabled when metadata_csum was enabled -* and we do not support metadata_csum (and cannot reliably find -* files when it is set. Refuse to mount. -*/ -if (le32_to_cpu (data->sblock.feature_incompat) &EXT4_FEATURE_INCOMPAT_64BIT ) { -printf ("Unsupported feature found (64bit, possibly metadata_csum), not mounting\n" ); - goto fail; - }if (le32_to_cpu (data->sblock.revision_level) ==0 ) { fs->inodesz =128 ;
Signature · 1 line
2.10.0
PATCH 7/7 ext4: Revert rejection of 64bit enabled ext4 fs
Quoted 4 lines · Stefan Br?ns
Enable mounting of ext4 fs with 64bit feature, as it is supported now. These had been disabled in
6f94ab6656ceffb3f2a972c8de4c554502b6f2b7.Signed-off-by Stefan Br?ns <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160923/cccc8bb6/attachment-0001.sig>