aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/resize.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2007-10-17 02:30:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:01 -0400
commit1ad6ecf9146e85ccb4e0bce70b91a93f57145c72 (patch)
tree03e90fbc705f02773def014dbd4abda4dabb5dd9 /fs/ext3/resize.c
parentd58ae67813ff97030d2f47ff7d1e5f54e5d7c5b3 (diff)
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. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Eric Sandeen <sandeen@redhat.com> Acked-by: Andreas Dilger <adilger@clusterfs.com> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext3/resize.c')
-rw-r--r--fs/ext3/resize.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index a4693c0428b..771f7ada15d 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -154,6 +154,34 @@ static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
154} 154}
155 155
156/* 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 */
161static 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
184/*
157 * Set up the block and inode bitmaps, and the inode table for the new group. 185 * Set up the block and inode bitmaps, and the inode table for the new group.
158 * This doesn't need to be part of the main transaction, since we are only 186 * This doesn't need to be part of the main transaction, since we are only
159 * changing blocks outside the actual filesystem. We still do journaling to 187 * changing blocks outside the actual filesystem. We still do journaling to
@@ -175,8 +203,9 @@ static int setup_new_group_blocks(struct super_block *sb,
175 int i; 203 int i;
176 int err = 0, err2; 204 int err = 0, err2;
177 205
178 handle = ext3_journal_start_sb(sb, reserved_gdb + gdblocks + 206 /* This transaction may be extended/restarted along the way */
179 2 + sbi->s_itb_per_group); 207 handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
208
180 if (IS_ERR(handle)) 209 if (IS_ERR(handle))
181 return PTR_ERR(handle); 210 return PTR_ERR(handle);
182 211
@@ -203,6 +232,10 @@ static int setup_new_group_blocks(struct super_block *sb,
203 232
204 ext3_debug("update backup group %#04lx (+%d)\n", block, bit); 233 ext3_debug("update backup group %#04lx (+%d)\n", block, bit);
205 234
235 err = extend_or_restart_transaction(handle, 1, bh);
236 if (err)
237 goto exit_bh;
238
206 gdb = sb_getblk(sb, block); 239 gdb = sb_getblk(sb, block);
207 if (!gdb) { 240 if (!gdb) {
208 err = -EIO; 241 err = -EIO;
@@ -228,6 +261,10 @@ static int setup_new_group_blocks(struct super_block *sb,
228 261
229 ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit); 262 ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit);
230 263
264 err = extend_or_restart_transaction(handle, 1, bh);
265 if (err)
266 goto exit_bh;
267
231 if (IS_ERR(gdb = bclean(handle, sb, block))) { 268 if (IS_ERR(gdb = bclean(handle, sb, block))) {
232 err = PTR_ERR(bh); 269 err = PTR_ERR(bh);
233 goto exit_bh; 270 goto exit_bh;
@@ -249,6 +286,11 @@ static int setup_new_group_blocks(struct super_block *sb,
249 struct buffer_head *it; 286 struct buffer_head *it;
250 287
251 ext3_debug("clear inode block %#04lx (+%d)\n", block, bit); 288 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
252 if (IS_ERR(it = bclean(handle, sb, block))) { 294 if (IS_ERR(it = bclean(handle, sb, block))) {
253 err = PTR_ERR(it); 295 err = PTR_ERR(it);
254 goto exit_bh; 296 goto exit_bh;
@@ -257,6 +299,11 @@ static int setup_new_group_blocks(struct super_block *sb,
257 brelse(it); 299 brelse(it);
258 ext3_set_bit(bit, bh->b_data); 300 ext3_set_bit(bit, bh->b_data);
259 } 301 }
302
303 err = extend_or_restart_transaction(handle, 2, bh);
304 if (err)
305 goto exit_bh;
306
260 mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), 307 mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb),
261 bh->b_data); 308 bh->b_data);
262 ext3_journal_dirty_metadata(handle, bh); 309 ext3_journal_dirty_metadata(handle, bh);