diff options
author | Theodore Ts'o <tytso@mit.edu> | 2012-09-19 00:55:56 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-09-19 00:55:56 -0400 |
commit | 59e31c156a24d483bbd2ea07d4dc96043a55b6bc (patch) | |
tree | adb76b9f52a862c4a844be737c7f16c4a8dbaa81 /fs/ext4 | |
parent | c9b92530a723ac5ef8e352885a1862b18f31b2f5 (diff) |
ext4: fix online resizing when the # of block groups is constant
Commit 1c6bd7173d66b3 introduced a regression where an online resize
operation which did not change the number of block groups would fail,
i.e:
mke2fs -t /dev/vdc 60000
mount /dev/vdc
resize2fs /dev/vdc 60001
This was due to a bug in the logic regarding when to try converting
the filesystem to use meta_bg.
Also fix up a number of other minor issues with the online resizing
code: (a) Fix a sparse warning; (b) only check to make sure the device
is large enough once, instead of multiple times through the resize
loop.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/resize.c | 36 |
1 files changed, 14 insertions, 22 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3c9367b9bebd..ee985ca05100 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1772,23 +1772,18 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode) | |||
1772 | handle_t *handle; | 1772 | handle_t *handle; |
1773 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1773 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
1774 | struct ext4_super_block *es = sbi->s_es; | 1774 | struct ext4_super_block *es = sbi->s_es; |
1775 | struct ext4_inode_info *ei = 0; | 1775 | struct ext4_inode_info *ei = EXT4_I(inode); |
1776 | ext4_fsblk_t nr; | 1776 | ext4_fsblk_t nr; |
1777 | int i, ret, err = 0; | 1777 | int i, ret, err = 0; |
1778 | int credits = 1; | 1778 | int credits = 1; |
1779 | 1779 | ||
1780 | ext4_msg(sb, KERN_INFO, "Converting file system to meta_bg"); | 1780 | ext4_msg(sb, KERN_INFO, "Converting file system to meta_bg"); |
1781 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) { | 1781 | if (inode) { |
1782 | if (es->s_reserved_gdt_blocks) { | 1782 | if (es->s_reserved_gdt_blocks) { |
1783 | ext4_error(sb, "Unexpected non-zero " | 1783 | ext4_error(sb, "Unexpected non-zero " |
1784 | "s_reserved_gdt_blocks"); | 1784 | "s_reserved_gdt_blocks"); |
1785 | return -EPERM; | 1785 | return -EPERM; |
1786 | } | 1786 | } |
1787 | if (!inode) { | ||
1788 | ext4_error(sb, "Unexpected NULL resize_inode"); | ||
1789 | return -EPERM; | ||
1790 | } | ||
1791 | ei = EXT4_I(inode); | ||
1792 | 1787 | ||
1793 | /* Do a quick sanity check of the resize inode */ | 1788 | /* Do a quick sanity check of the resize inode */ |
1794 | if (inode->i_blocks != 1 << (inode->i_blkbits - 9)) | 1789 | if (inode->i_blocks != 1 << (inode->i_blkbits - 9)) |
@@ -1873,12 +1868,19 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) | |||
1873 | int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex; | 1868 | int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex; |
1874 | int meta_bg; | 1869 | int meta_bg; |
1875 | 1870 | ||
1871 | /* See if the device is actually as big as what was requested */ | ||
1872 | bh = sb_bread(sb, n_blocks_count - 1); | ||
1873 | if (!bh) { | ||
1874 | ext4_warning(sb, "can't read last block, resize aborted"); | ||
1875 | return -ENOSPC; | ||
1876 | } | ||
1877 | brelse(bh); | ||
1878 | |||
1876 | retry: | 1879 | retry: |
1877 | o_blocks_count = ext4_blocks_count(es); | 1880 | o_blocks_count = ext4_blocks_count(es); |
1878 | 1881 | ||
1879 | if (test_opt(sb, DEBUG)) | 1882 | ext4_msg(sb, KERN_INFO, "resizing filesystem from %llu " |
1880 | ext4_msg(sb, KERN_DEBUG, "resizing filesystem from %llu " | 1883 | "to %llu blocks", o_blocks_count, n_blocks_count); |
1881 | "to %llu blocks", o_blocks_count, n_blocks_count); | ||
1882 | 1884 | ||
1883 | if (n_blocks_count < o_blocks_count) { | 1885 | if (n_blocks_count < o_blocks_count) { |
1884 | /* On-line shrinking not supported */ | 1886 | /* On-line shrinking not supported */ |
@@ -1922,7 +1924,7 @@ retry: | |||
1922 | } | 1924 | } |
1923 | } | 1925 | } |
1924 | 1926 | ||
1925 | if ((!resize_inode && !meta_bg) || n_group == o_group) { | 1927 | if ((!resize_inode && !meta_bg) || n_blocks_count == o_blocks_count) { |
1926 | err = ext4_convert_meta_bg(sb, resize_inode); | 1928 | err = ext4_convert_meta_bg(sb, resize_inode); |
1927 | if (err) | 1929 | if (err) |
1928 | goto out; | 1930 | goto out; |
@@ -1937,14 +1939,6 @@ retry: | |||
1937 | } | 1939 | } |
1938 | } | 1940 | } |
1939 | 1941 | ||
1940 | /* See if the device is actually as big as what was requested */ | ||
1941 | bh = sb_bread(sb, n_blocks_count - 1); | ||
1942 | if (!bh) { | ||
1943 | ext4_warning(sb, "can't read last block, resize aborted"); | ||
1944 | return -ENOSPC; | ||
1945 | } | ||
1946 | brelse(bh); | ||
1947 | |||
1948 | /* extend the last group */ | 1942 | /* extend the last group */ |
1949 | if (n_group == o_group) | 1943 | if (n_group == o_group) |
1950 | add = n_blocks_count - o_blocks_count; | 1944 | add = n_blocks_count - o_blocks_count; |
@@ -2005,8 +1999,6 @@ out: | |||
2005 | free_flex_gd(flex_gd); | 1999 | free_flex_gd(flex_gd); |
2006 | if (resize_inode != NULL) | 2000 | if (resize_inode != NULL) |
2007 | iput(resize_inode); | 2001 | iput(resize_inode); |
2008 | if (test_opt(sb, DEBUG)) | 2002 | ext4_msg(sb, KERN_INFO, "resized filesystem to %llu", n_blocks_count); |
2009 | ext4_msg(sb, KERN_DEBUG, "resized filesystem to %llu", | ||
2010 | n_blocks_count); | ||
2011 | return err; | 2003 | return err; |
2012 | } | 2004 | } |