summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Brüns <stefan.bruens@rwth-aachen.de>2016-09-20 02:13:01 +0300
committerDongjin Kim <tobetter@gmail.com>2020-02-10 16:44:41 +0300
commitff84b64861a2ce4e26be481b6854bbce35232b23 (patch)
treefc9f4e52c381e4d0df5668058c22bc72e8fc1caa
parent4a68406f3a3f3a1b57af59074d1139f3e020d090 (diff)
downloadu-boot-ff84b64861a2ce4e26be481b6854bbce35232b23.tar.xz
ext4: Respect group descriptor size when adjusting free counts
Also adjust high 16/32 bits when free inode/block counts are modified. Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
-rw-r--r--fs/ext4/ext4_common.c53
-rw-r--r--fs/ext4/ext4_write.c40
2 files changed, 69 insertions, 24 deletions
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 7e496dc6ee..a37911ffd4 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -59,22 +59,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)
@@ -966,7 +995,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,
@@ -1041,7 +1070,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;
}
@@ -1100,9 +1129,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,
@@ -1156,7 +1185,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 8343ab1d6d..b863412850 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -41,14 +41,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)
@@ -149,7 +165,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) {
@@ -213,7 +229,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) {
@@ -244,7 +260,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) {
@@ -325,7 +341,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) {
@@ -365,7 +381,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) {
@@ -397,7 +413,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) {
@@ -484,7 +500,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) {
@@ -539,7 +555,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);