Skip to content

Commit 1ad6ecf

Browse files
Eric SandeenLinus Torvalds
authored andcommitted
ext3: lighten up resize transaction requirements
When resizing online, setup_new_group_blocks attempts to reserve a potentially very large transaction, depending on the current filesystem geometry. For some journal sizes, there may not be enough room for this transaction, and the online resize will fail. The patch below resizes & restarts the transaction as necessary while setting up the new group, and should work with even the smallest journal. Tested with something like: [root@newbox ~]# dd if=/dev/zero of=fsfile bs=1024 count=32768 [root@newbox ~]# mkfs.ext3 -b 1024 fsfile 16384 [root@newbox ~]# mount -o loop fsfile mnt/ [root@newbox ~]# resize2fs /dev/loop0 resize2fs 1.40.2 (12-Jul-2007) Filesystem at /dev/loop0 is mounted on /root/mnt; on-line resizing required old desc_blocks = 1, new_desc_blocks = 1 Performing an on-line resize of /dev/loop0 to 32768 (1k) blocks. resize2fs: No space left on device While trying to add group #2 [root@newbox ~]# dmesg | tail -n 1 JBD: resize2fs wants too many credits (258 > 256) [root@newbox ~]# With the below change, it works. [[email protected]: coding-style fixes] Signed-off-by: Eric Sandeen <[email protected]> Acked-by: Andreas Dilger <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d58ae67 commit 1ad6ecf

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

fs/ext3/resize.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,34 @@ static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
153153
memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
154154
}
155155

156+
/*
157+
* If we have fewer than thresh credits, extend by EXT3_MAX_TRANS_DATA.
158+
* If that fails, restart the transaction & regain write access for the
159+
* buffer head which is used for block_bitmap modifications.
160+
*/
161+
static int extend_or_restart_transaction(handle_t *handle, int thresh,
162+
struct buffer_head *bh)
163+
{
164+
int err;
165+
166+
if (handle->h_buffer_credits >= thresh)
167+
return 0;
168+
169+
err = ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA);
170+
if (err < 0)
171+
return err;
172+
if (err) {
173+
err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA);
174+
if (err)
175+
return err;
176+
err = ext3_journal_get_write_access(handle, bh);
177+
if (err)
178+
return err;
179+
}
180+
181+
return 0;
182+
}
183+
156184
/*
157185
* Set up the block and inode bitmaps, and the inode table for the new group.
158186
* This doesn't need to be part of the main transaction, since we are only
@@ -175,8 +203,9 @@ static int setup_new_group_blocks(struct super_block *sb,
175203
int i;
176204
int err = 0, err2;
177205

178-
handle = ext3_journal_start_sb(sb, reserved_gdb + gdblocks +
179-
2 + sbi->s_itb_per_group);
206+
/* This transaction may be extended/restarted along the way */
207+
handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
208+
180209
if (IS_ERR(handle))
181210
return PTR_ERR(handle);
182211

@@ -203,6 +232,10 @@ static int setup_new_group_blocks(struct super_block *sb,
203232

204233
ext3_debug("update backup group %#04lx (+%d)\n", block, bit);
205234

235+
err = extend_or_restart_transaction(handle, 1, bh);
236+
if (err)
237+
goto exit_bh;
238+
206239
gdb = sb_getblk(sb, block);
207240
if (!gdb) {
208241
err = -EIO;
@@ -228,6 +261,10 @@ static int setup_new_group_blocks(struct super_block *sb,
228261

229262
ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit);
230263

264+
err = extend_or_restart_transaction(handle, 1, bh);
265+
if (err)
266+
goto exit_bh;
267+
231268
if (IS_ERR(gdb = bclean(handle, sb, block))) {
232269
err = PTR_ERR(bh);
233270
goto exit_bh;
@@ -249,6 +286,11 @@ static int setup_new_group_blocks(struct super_block *sb,
249286
struct buffer_head *it;
250287

251288
ext3_debug("clear inode block %#04lx (+%d)\n", block, bit);
289+
290+
err = extend_or_restart_transaction(handle, 1, bh);
291+
if (err)
292+
goto exit_bh;
293+
252294
if (IS_ERR(it = bclean(handle, sb, block))) {
253295
err = PTR_ERR(it);
254296
goto exit_bh;
@@ -257,6 +299,11 @@ static int setup_new_group_blocks(struct super_block *sb,
257299
brelse(it);
258300
ext3_set_bit(bit, bh->b_data);
259301
}
302+
303+
err = extend_or_restart_transaction(handle, 2, bh);
304+
if (err)
305+
goto exit_bh;
306+
260307
mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb),
261308
bh->b_data);
262309
ext3_journal_dirty_metadata(handle, bh);

0 commit comments

Comments
 (0)