| From 03c1c29053f678234dbd51bf3d65f3b7529021de Mon Sep 17 00:00:00 2001 |
| From: Yongqiang Yang <xiaoqiangnk@gmail.com> |
| Date: Wed, 5 Sep 2012 01:21:50 -0400 |
| Subject: ext4: ignore last group w/o enough space when resizing instead of BUG'ing |
| |
| From: Yongqiang Yang <xiaoqiangnk@gmail.com> |
| |
| commit 03c1c29053f678234dbd51bf3d65f3b7529021de upstream. |
| |
| If the last group does not have enough space for group tables, ignore |
| it instead of calling BUG_ON(). |
| |
| Reported-by: Daniel Drake <dsd@laptop.org> |
| Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com> |
| Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/resize.c | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| --- a/fs/ext4/resize.c |
| +++ b/fs/ext4/resize.c |
| @@ -200,8 +200,11 @@ static void free_flex_gd(struct ext4_new |
| * be a partial of a flex group. |
| * |
| * @sb: super block of fs to which the groups belongs |
| + * |
| + * Returns 0 on a successful allocation of the metadata blocks in the |
| + * block group. |
| */ |
| -static void ext4_alloc_group_tables(struct super_block *sb, |
| +static int ext4_alloc_group_tables(struct super_block *sb, |
| struct ext4_new_flex_group_data *flex_gd, |
| int flexbg_size) |
| { |
| @@ -226,6 +229,8 @@ static void ext4_alloc_group_tables(stru |
| (last_group & ~(flexbg_size - 1)))); |
| next_group: |
| group = group_data[0].group; |
| + if (src_group >= group_data[0].group + flex_gd->count) |
| + return -ENOSPC; |
| start_blk = ext4_group_first_block_no(sb, src_group); |
| last_blk = start_blk + group_data[src_group - group].blocks_count; |
| |
| @@ -235,7 +240,6 @@ next_group: |
| |
| start_blk += overhead; |
| |
| - BUG_ON(src_group >= group_data[0].group + flex_gd->count); |
| /* We collect contiguous blocks as much as possible. */ |
| src_group++; |
| for (; src_group <= last_group; src_group++) |
| @@ -300,6 +304,7 @@ next_group: |
| group_data[i].free_blocks_count); |
| } |
| } |
| + return 0; |
| } |
| |
| static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, |
| @@ -1729,7 +1734,8 @@ int ext4_resize_fs(struct super_block *s |
| */ |
| while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count, |
| flexbg_size)) { |
| - ext4_alloc_group_tables(sb, flex_gd, flexbg_size); |
| + if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) |
| + break; |
| err = ext4_flex_group_add(sb, resize_inode, flex_gd); |
| if (unlikely(err)) |
| break; |