aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/resize.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 484e5699f848..bd8a52bb3999 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -141,6 +141,32 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
141} 141}
142 142
143/* 143/*
144 * If we have fewer than thresh credits, extend by EXT4_MAX_TRANS_DATA.
145 * If that fails, restart the transaction & regain write access for the
146 * buffer head which is used for block_bitmap modifications.
147 */
148static int extend_or_restart_transaction(handle_t *handle, int thresh,
149 struct buffer_head *bh)
150{
151 int err;
152
153 if (handle->h_buffer_credits >= thresh)
154 return 0;
155
156 err = ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA);
157 if (err < 0)
158 return err;
159 if (err) {
160 if ((err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
161 return err;
162 if ((err = ext4_journal_get_write_access(handle, bh)))
163 return err;
164 }
165
166 return 0;
167}
168
169/*
144 * Set up the block and inode bitmaps, and the inode table for the new group. 170 * Set up the block and inode bitmaps, and the inode table for the new group.
145 * This doesn't need to be part of the main transaction, since we are only 171 * This doesn't need to be part of the main transaction, since we are only
146 * changing blocks outside the actual filesystem. We still do journaling to 172 * changing blocks outside the actual filesystem. We still do journaling to
@@ -162,8 +188,9 @@ static int setup_new_group_blocks(struct super_block *sb,
162 int i; 188 int i;
163 int err = 0, err2; 189 int err = 0, err2;
164 190
165 handle = ext4_journal_start_sb(sb, reserved_gdb + gdblocks + 191 /* This transaction may be extended/restarted along the way */
166 2 + sbi->s_itb_per_group); 192 handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
193
167 if (IS_ERR(handle)) 194 if (IS_ERR(handle))
168 return PTR_ERR(handle); 195 return PTR_ERR(handle);
169 196
@@ -190,6 +217,9 @@ static int setup_new_group_blocks(struct super_block *sb,
190 217
191 ext4_debug("update backup group %#04lx (+%d)\n", block, bit); 218 ext4_debug("update backup group %#04lx (+%d)\n", block, bit);
192 219
220 if ((err = extend_or_restart_transaction(handle, 1, bh)))
221 goto exit_bh;
222
193 gdb = sb_getblk(sb, block); 223 gdb = sb_getblk(sb, block);
194 if (!gdb) { 224 if (!gdb) {
195 err = -EIO; 225 err = -EIO;
@@ -215,6 +245,9 @@ static int setup_new_group_blocks(struct super_block *sb,
215 245
216 ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit); 246 ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit);
217 247
248 if ((err = extend_or_restart_transaction(handle, 1, bh)))
249 goto exit_bh;
250
218 if (IS_ERR(gdb = bclean(handle, sb, block))) { 251 if (IS_ERR(gdb = bclean(handle, sb, block))) {
219 err = PTR_ERR(bh); 252 err = PTR_ERR(bh);
220 goto exit_bh; 253 goto exit_bh;
@@ -236,6 +269,10 @@ static int setup_new_group_blocks(struct super_block *sb,
236 struct buffer_head *it; 269 struct buffer_head *it;
237 270
238 ext4_debug("clear inode block %#04lx (+%d)\n", block, bit); 271 ext4_debug("clear inode block %#04lx (+%d)\n", block, bit);
272
273 if ((err = extend_or_restart_transaction(handle, 1, bh)))
274 goto exit_bh;
275
239 if (IS_ERR(it = bclean(handle, sb, block))) { 276 if (IS_ERR(it = bclean(handle, sb, block))) {
240 err = PTR_ERR(it); 277 err = PTR_ERR(it);
241 goto exit_bh; 278 goto exit_bh;
@@ -244,6 +281,10 @@ static int setup_new_group_blocks(struct super_block *sb,
244 brelse(it); 281 brelse(it);
245 ext4_set_bit(bit, bh->b_data); 282 ext4_set_bit(bit, bh->b_data);
246 } 283 }
284
285 if ((err = extend_or_restart_transaction(handle, 2, bh)))
286 goto exit_bh;
287
247 mark_bitmap_end(input->blocks_count, EXT4_BLOCKS_PER_GROUP(sb), 288 mark_bitmap_end(input->blocks_count, EXT4_BLOCKS_PER_GROUP(sb),
248 bh->b_data); 289 bh->b_data);
249 ext4_journal_dirty_metadata(handle, bh); 290 ext4_journal_dirty_metadata(handle, bh);
@@ -271,7 +312,6 @@ exit_journal:
271 return err; 312 return err;
272} 313}
273 314
274
275/* 315/*
276 * Iterate through the groups which hold BACKUP superblock/GDT copies in an 316 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
277 * ext4 filesystem. The counters should be initialized to 1, 5, and 7 before 317 * ext4 filesystem. The counters should be initialized to 1, 5, and 7 before