aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/resize.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2007-10-16 18:38:25 -0400
committerTheodore Ts'o <tytso@mit.edu>2007-10-17 18:50:04 -0400
commit149041070deb2e83cd36dc60bc72975b3cbf5bbe (patch)
tree8691039d34be263f28f9e0845bb555737033efad /fs/ext4/resize.c
parent5b615287b37c32dc0c9dbeab13b19ac87828a5f7 (diff)
ext4: 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. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Mingming Cao <cmm@us.ibm.com> Acked-by: Andreas Dilger <adilger@clusterfs.com>
Diffstat (limited to 'fs/ext4/resize.c')
-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