From 749e93ee183cc95ae69caaea20ce696f955cfacb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20Br=C3=BCns?= Date: Tue, 20 Sep 2016 01:13:01 +0200 Subject: [PATCH] ext4: Respect group descriptor size when adjusting free counts MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Also adjust high 16/32 bits when free inode/block counts are modified. Signed-off-by: Stefan Brüns --- fs/ext4/ext4_common.c | 53 +++++++++++++++++++++++++++++++++---------- fs/ext4/ext4_write.c | 40 ++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 24 deletions(-) diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 90e7602e2a..1336068f9c 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -60,22 +60,51 @@ static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb) 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_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_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) @@ -958,7 +987,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, @@ -1033,7 +1062,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; } @@ -1092,9 +1121,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, @@ -1148,7 +1177,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); diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index 2c123e3646..d710a86d59 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -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(le32_to_cpu(*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); -- 2.39.5