diff options
Diffstat (limited to 'fs/ext4/balloc.c')
| -rw-r--r-- | fs/ext4/balloc.c | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 30494c5da843..9cc80b9cc8d8 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -43,6 +43,46 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | |||
| 43 | 43 | ||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block, | ||
| 47 | ext4_group_t block_group) | ||
| 48 | { | ||
| 49 | ext4_group_t actual_group; | ||
| 50 | ext4_get_group_no_and_offset(sb, block, &actual_group, 0); | ||
| 51 | if (actual_group == block_group) | ||
| 52 | return 1; | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | static int ext4_group_used_meta_blocks(struct super_block *sb, | ||
| 57 | ext4_group_t block_group) | ||
| 58 | { | ||
| 59 | ext4_fsblk_t tmp; | ||
| 60 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 61 | /* block bitmap, inode bitmap, and inode table blocks */ | ||
| 62 | int used_blocks = sbi->s_itb_per_group + 2; | ||
| 63 | |||
| 64 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | ||
| 65 | struct ext4_group_desc *gdp; | ||
| 66 | struct buffer_head *bh; | ||
| 67 | |||
| 68 | gdp = ext4_get_group_desc(sb, block_group, &bh); | ||
| 69 | if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), | ||
| 70 | block_group)) | ||
| 71 | used_blocks--; | ||
| 72 | |||
| 73 | if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), | ||
| 74 | block_group)) | ||
| 75 | used_blocks--; | ||
| 76 | |||
| 77 | tmp = ext4_inode_table(sb, gdp); | ||
| 78 | for (; tmp < ext4_inode_table(sb, gdp) + | ||
| 79 | sbi->s_itb_per_group; tmp++) { | ||
| 80 | if (!ext4_block_in_group(sb, tmp, block_group)) | ||
| 81 | used_blocks -= 1; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | return used_blocks; | ||
| 85 | } | ||
| 46 | /* Initializes an uninitialized block bitmap if given, and returns the | 86 | /* Initializes an uninitialized block bitmap if given, and returns the |
| 47 | * number of blocks free in the group. */ | 87 | * number of blocks free in the group. */ |
| 48 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | 88 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, |
| @@ -105,20 +145,34 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
| 105 | free_blocks = group_blocks - bit_max; | 145 | free_blocks = group_blocks - bit_max; |
| 106 | 146 | ||
| 107 | if (bh) { | 147 | if (bh) { |
| 108 | ext4_fsblk_t start; | 148 | ext4_fsblk_t start, tmp; |
| 149 | int flex_bg = 0; | ||
| 109 | 150 | ||
| 110 | for (bit = 0; bit < bit_max; bit++) | 151 | for (bit = 0; bit < bit_max; bit++) |
| 111 | ext4_set_bit(bit, bh->b_data); | 152 | ext4_set_bit(bit, bh->b_data); |
| 112 | 153 | ||
| 113 | start = ext4_group_first_block_no(sb, block_group); | 154 | start = ext4_group_first_block_no(sb, block_group); |
| 114 | 155 | ||
| 115 | /* Set bits for block and inode bitmaps, and inode table */ | 156 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, |
| 116 | ext4_set_bit(ext4_block_bitmap(sb, gdp) - start, bh->b_data); | 157 | EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
| 117 | ext4_set_bit(ext4_inode_bitmap(sb, gdp) - start, bh->b_data); | 158 | flex_bg = 1; |
| 118 | for (bit = (ext4_inode_table(sb, gdp) - start), | ||
| 119 | bit_max = bit + sbi->s_itb_per_group; bit < bit_max; bit++) | ||
| 120 | ext4_set_bit(bit, bh->b_data); | ||
| 121 | 159 | ||
| 160 | /* Set bits for block and inode bitmaps, and inode table */ | ||
| 161 | tmp = ext4_block_bitmap(sb, gdp); | ||
| 162 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | ||
| 163 | ext4_set_bit(tmp - start, bh->b_data); | ||
| 164 | |||
| 165 | tmp = ext4_inode_bitmap(sb, gdp); | ||
| 166 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | ||
| 167 | ext4_set_bit(tmp - start, bh->b_data); | ||
| 168 | |||
| 169 | tmp = ext4_inode_table(sb, gdp); | ||
| 170 | for (; tmp < ext4_inode_table(sb, gdp) + | ||
| 171 | sbi->s_itb_per_group; tmp++) { | ||
| 172 | if (!flex_bg || | ||
| 173 | ext4_block_in_group(sb, tmp, block_group)) | ||
| 174 | ext4_set_bit(tmp - start, bh->b_data); | ||
| 175 | } | ||
| 122 | /* | 176 | /* |
| 123 | * Also if the number of blocks within the group is | 177 | * Also if the number of blocks within the group is |
| 124 | * less than the blocksize * 8 ( which is the size | 178 | * less than the blocksize * 8 ( which is the size |
| @@ -126,8 +180,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
| 126 | */ | 180 | */ |
| 127 | mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); | 181 | mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); |
| 128 | } | 182 | } |
| 129 | 183 | return free_blocks - ext4_group_used_meta_blocks(sb, block_group); | |
| 130 | return free_blocks - sbi->s_itb_per_group - 2; | ||
| 131 | } | 184 | } |
| 132 | 185 | ||
| 133 | 186 | ||
