aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/balloc.c105
-rw-r--r--fs/ext4/ext4.h13
-rw-r--r--fs/ext4/ialloc.c20
3 files changed, 66 insertions, 72 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 8573e2bfb78a..735d9fcc72e6 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -102,74 +102,73 @@ static unsigned int num_blocks_in_group(struct super_block *sb,
102 return EXT4_BLOCKS_PER_GROUP(sb); 102 return EXT4_BLOCKS_PER_GROUP(sb);
103} 103}
104 104
105/* Initializes an uninitialized block bitmap if given, and returns the 105/* Initializes an uninitialized block bitmap */
106 * number of blocks free in the group. */ 106void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
107unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, 107 ext4_group_t block_group,
108 ext4_group_t block_group, struct ext4_group_desc *gdp) 108 struct ext4_group_desc *gdp)
109{ 109{
110 unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group); 110 unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
111 ext4_group_t ngroups = ext4_get_groups_count(sb);
112 unsigned group_blocks = num_blocks_in_group(sb, block_group);
113 struct ext4_sb_info *sbi = EXT4_SB(sb); 111 struct ext4_sb_info *sbi = EXT4_SB(sb);
114 112 ext4_fsblk_t start, tmp;
115 if (bh) { 113 int flex_bg = 0;
116 J_ASSERT_BH(bh, buffer_locked(bh)); 114
117 115 J_ASSERT_BH(bh, buffer_locked(bh));
118 /* If checksum is bad mark all blocks used to prevent allocation 116
119 * essentially implementing a per-group read-only flag. */ 117 /* If checksum is bad mark all blocks used to prevent allocation
120 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { 118 * essentially implementing a per-group read-only flag. */
121 ext4_error(sb, "Checksum bad for group %u", 119 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
122 block_group); 120 ext4_error(sb, "Checksum bad for group %u", block_group);
123 ext4_free_blks_set(sb, gdp, 0); 121 ext4_free_blks_set(sb, gdp, 0);
124 ext4_free_inodes_set(sb, gdp, 0); 122 ext4_free_inodes_set(sb, gdp, 0);
125 ext4_itable_unused_set(sb, gdp, 0); 123 ext4_itable_unused_set(sb, gdp, 0);
126 memset(bh->b_data, 0xff, sb->s_blocksize); 124 memset(bh->b_data, 0xff, sb->s_blocksize);
127 return 0; 125 return;
128 }
129 memset(bh->b_data, 0, sb->s_blocksize);
130 } 126 }
127 memset(bh->b_data, 0, sb->s_blocksize);
131 128
132 if (bh) { 129 for (bit = 0; bit < bit_max; bit++)
133 ext4_fsblk_t start, tmp; 130 ext4_set_bit(bit, bh->b_data);
134 int flex_bg = 0;
135 131
136 for (bit = 0; bit < bit_max; bit++) 132 start = ext4_group_first_block_no(sb, block_group);
137 ext4_set_bit(bit, bh->b_data);
138 133
139 start = ext4_group_first_block_no(sb, block_group); 134 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
135 flex_bg = 1;
140 136
141 if (EXT4_HAS_INCOMPAT_FEATURE(sb, 137 /* Set bits for block and inode bitmaps, and inode table */
142 EXT4_FEATURE_INCOMPAT_FLEX_BG)) 138 tmp = ext4_block_bitmap(sb, gdp);
143 flex_bg = 1; 139 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
140 ext4_set_bit(tmp - start, bh->b_data);
144 141
145 /* Set bits for block and inode bitmaps, and inode table */ 142 tmp = ext4_inode_bitmap(sb, gdp);
146 tmp = ext4_block_bitmap(sb, gdp); 143 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
147 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) 144 ext4_set_bit(tmp - start, bh->b_data);
148 ext4_set_bit(tmp - start, bh->b_data);
149 145
150 tmp = ext4_inode_bitmap(sb, gdp); 146 tmp = ext4_inode_table(sb, gdp);
147 for (; tmp < ext4_inode_table(sb, gdp) +
148 sbi->s_itb_per_group; tmp++) {
151 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) 149 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
152 ext4_set_bit(tmp - start, bh->b_data); 150 ext4_set_bit(tmp - start, bh->b_data);
153
154 tmp = ext4_inode_table(sb, gdp);
155 for (; tmp < ext4_inode_table(sb, gdp) +
156 sbi->s_itb_per_group; tmp++) {
157 if (!flex_bg ||
158 ext4_block_in_group(sb, tmp, block_group))
159 ext4_set_bit(tmp - start, bh->b_data);
160 }
161 /*
162 * Also if the number of blocks within the group is
163 * less than the blocksize * 8 ( which is the size
164 * of bitmap ), set rest of the block bitmap to 1
165 */
166 ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
167 bh->b_data);
168 } 151 }
169 return group_blocks - bit_max - 152 /*
170 ext4_group_used_meta_blocks(sb, block_group, gdp); 153 * Also if the number of blocks within the group is less than
154 * the blocksize * 8 ( which is the size of bitmap ), set rest
155 * of the block bitmap to 1
156 */
157 ext4_mark_bitmap_end(num_blocks_in_group(sb, block_group),
158 sb->s_blocksize * 8, bh->b_data);
171} 159}
172 160
161/* Return the number of free blocks in a block group. It is used when
162 * the block bitmap is uninitialized, so we can't just count the bits
163 * in the bitmap. */
164unsigned ext4_free_blocks_after_init(struct super_block *sb,
165 ext4_group_t block_group,
166 struct ext4_group_desc *gdp)
167{
168 return num_blocks_in_group(sb, block_group) -
169 num_base_meta_blocks(sb, block_group) -
170 ext4_group_used_meta_blocks(sb, block_group, gdp);
171}
173 172
174/* 173/*
175 * The free blocks are managed by bitmaps. A file system contains several 174 * The free blocks are managed by bitmaps. A file system contains several
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f7257aa6bf81..b0b7b67e439d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1763,12 +1763,13 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
1763extern int ext4_should_retry_alloc(struct super_block *sb, int *retries); 1763extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
1764struct buffer_head *ext4_read_block_bitmap(struct super_block *sb, 1764struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
1765 ext4_group_t block_group); 1765 ext4_group_t block_group);
1766extern unsigned ext4_init_block_bitmap(struct super_block *sb, 1766extern void ext4_init_block_bitmap(struct super_block *sb,
1767 struct buffer_head *bh, 1767 struct buffer_head *bh,
1768 ext4_group_t group, 1768 ext4_group_t group,
1769 struct ext4_group_desc *desc); 1769 struct ext4_group_desc *desc);
1770#define ext4_free_blocks_after_init(sb, group, desc) \ 1770extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
1771 ext4_init_block_bitmap(sb, NULL, group, desc) 1771 ext4_group_t block_group,
1772 struct ext4_group_desc *gdp);
1772ext4_fsblk_t ext4_inode_to_goal_block(struct inode *); 1773ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
1773 1774
1774/* dir.c */ 1775/* dir.c */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 9c63f273b550..b7a8130d0af4 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -816,7 +816,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
816 int ret2, err = 0; 816 int ret2, err = 0;
817 struct inode *ret; 817 struct inode *ret;
818 ext4_group_t i; 818 ext4_group_t i;
819 int free = 0;
820 static int once = 1; 819 static int once = 1;
821 ext4_group_t flex_group; 820 ext4_group_t flex_group;
822 821
@@ -950,26 +949,21 @@ got:
950 goto fail; 949 goto fail;
951 } 950 }
952 951
953 free = 0; 952 BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
954 ext4_lock_group(sb, group); 953 err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
954 brelse(block_bitmap_bh);
955
955 /* recheck and clear flag under lock if we still need to */ 956 /* recheck and clear flag under lock if we still need to */
957 ext4_lock_group(sb, group);
956 if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 958 if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
957 free = ext4_free_blocks_after_init(sb, group, gdp);
958 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 959 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
959 ext4_free_blks_set(sb, gdp, free); 960 ext4_free_blks_set(sb, gdp,
961 ext4_free_blocks_after_init(sb, group, gdp));
960 gdp->bg_checksum = ext4_group_desc_csum(sbi, group, 962 gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
961 gdp); 963 gdp);
962 } 964 }
963 ext4_unlock_group(sb, group); 965 ext4_unlock_group(sb, group);
964 966
965 /* Don't need to dirty bitmap block if we didn't change it */
966 if (free) {
967 BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
968 err = ext4_handle_dirty_metadata(handle,
969 NULL, block_bitmap_bh);
970 }
971
972 brelse(block_bitmap_bh);
973 if (err) 967 if (err)
974 goto fail; 968 goto fail;
975 } 969 }