resize.c (93f9052643409c13b3b5f76833865087351f55b8) | resize.c (1c6bd7173d66b3dfdefcedb38cabc1fb03997509) |
---|---|
1/* 2 * linux/fs/ext4/resize.c 3 * 4 * Support for resizing an ext4 filesystem while it is mounted. 5 * 6 * Copyright (C) 2001, 2002 Andreas Dilger <adilger@clusterfs.com> 7 * 8 * This could probably be made into a module, because it is not often in use. --- 1742 unchanged lines hidden (view full) --- 1751 return -ENOSPC; 1752 } 1753 brelse(bh); 1754 1755 err = ext4_group_extend_no_check(sb, o_blocks_count, add); 1756 return err; 1757} /* ext4_group_extend */ 1758 | 1/* 2 * linux/fs/ext4/resize.c 3 * 4 * Support for resizing an ext4 filesystem while it is mounted. 5 * 6 * Copyright (C) 2001, 2002 Andreas Dilger <adilger@clusterfs.com> 7 * 8 * This could probably be made into a module, because it is not often in use. --- 1742 unchanged lines hidden (view full) --- 1751 return -ENOSPC; 1752 } 1753 brelse(bh); 1754 1755 err = ext4_group_extend_no_check(sb, o_blocks_count, add); 1756 return err; 1757} /* ext4_group_extend */ 1758 |
1759 1760static int num_desc_blocks(struct super_block *sb, ext4_group_t groups) 1761{ 1762 return (groups + EXT4_DESC_PER_BLOCK(sb) - 1) / EXT4_DESC_PER_BLOCK(sb); 1763} 1764 |
|
1759/* | 1765/* |
1766 * Release the resize inode and drop the resize_inode feature if there 1767 * are no more reserved gdt blocks, and then convert the file system 1768 * to enable meta_bg 1769 */ 1770static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode) 1771{ 1772 handle_t *handle; 1773 struct ext4_sb_info *sbi = EXT4_SB(sb); 1774 struct ext4_super_block *es = sbi->s_es; 1775 struct ext4_inode_info *ei = 0; 1776 ext4_fsblk_t nr; 1777 int i, ret, err = 0; 1778 int credits = 1; 1779 1780 ext4_msg(sb, KERN_INFO, "Converting file system to meta_bg"); 1781 if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) { 1782 if (es->s_reserved_gdt_blocks) { 1783 ext4_error(sb, "Unexpected non-zero " 1784 "s_reserved_gdt_blocks"); 1785 return -EPERM; 1786 } 1787 if (!inode) { 1788 ext4_error(sb, "Unexpected NULL resize_inode"); 1789 return -EPERM; 1790 } 1791 ei = EXT4_I(inode); 1792 1793 /* Do a quick sanity check of the resize inode */ 1794 if (inode->i_blocks != 1 << (inode->i_blkbits - 9)) 1795 goto invalid_resize_inode; 1796 for (i = 0; i < EXT4_N_BLOCKS; i++) { 1797 if (i == EXT4_DIND_BLOCK) { 1798 if (ei->i_data[i]) 1799 continue; 1800 else 1801 goto invalid_resize_inode; 1802 } 1803 if (ei->i_data[i]) 1804 goto invalid_resize_inode; 1805 } 1806 credits += 3; /* block bitmap, bg descriptor, resize inode */ 1807 } 1808 1809 handle = ext4_journal_start_sb(sb, credits); 1810 if (IS_ERR(handle)) 1811 return PTR_ERR(handle); 1812 1813 err = ext4_journal_get_write_access(handle, sbi->s_sbh); 1814 if (err) 1815 goto errout; 1816 1817 EXT4_CLEAR_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE); 1818 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); 1819 sbi->s_es->s_first_meta_bg = 1820 cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count)); 1821 1822 err = ext4_handle_dirty_super(handle, sb); 1823 if (err) { 1824 ext4_std_error(sb, err); 1825 goto errout; 1826 } 1827 1828 if (inode) { 1829 nr = le32_to_cpu(ei->i_data[EXT4_DIND_BLOCK]); 1830 ext4_free_blocks(handle, inode, NULL, nr, 1, 1831 EXT4_FREE_BLOCKS_METADATA | 1832 EXT4_FREE_BLOCKS_FORGET); 1833 ei->i_data[EXT4_DIND_BLOCK] = 0; 1834 inode->i_blocks = 0; 1835 1836 err = ext4_mark_inode_dirty(handle, inode); 1837 if (err) 1838 ext4_std_error(sb, err); 1839 } 1840 1841errout: 1842 ret = ext4_journal_stop(handle); 1843 if (!err) 1844 err = ret; 1845 return ret; 1846 1847invalid_resize_inode: 1848 ext4_error(sb, "corrupted/inconsistent resize inode"); 1849 return -EINVAL; 1850} 1851 1852/* |
|
1760 * ext4_resize_fs() resizes a fs to new size specified by @n_blocks_count 1761 * 1762 * @sb: super block of the fs to be resized 1763 * @n_blocks_count: the number of blocks resides in the resized fs 1764 */ 1765int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) 1766{ 1767 struct ext4_new_flex_group_data *flex_gd = NULL; 1768 struct ext4_sb_info *sbi = EXT4_SB(sb); 1769 struct ext4_super_block *es = sbi->s_es; 1770 struct buffer_head *bh; 1771 struct inode *resize_inode = NULL; 1772 ext4_grpblk_t add, offset; 1773 unsigned long n_desc_blocks; 1774 unsigned long o_desc_blocks; | 1853 * ext4_resize_fs() resizes a fs to new size specified by @n_blocks_count 1854 * 1855 * @sb: super block of the fs to be resized 1856 * @n_blocks_count: the number of blocks resides in the resized fs 1857 */ 1858int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) 1859{ 1860 struct ext4_new_flex_group_data *flex_gd = NULL; 1861 struct ext4_sb_info *sbi = EXT4_SB(sb); 1862 struct ext4_super_block *es = sbi->s_es; 1863 struct buffer_head *bh; 1864 struct inode *resize_inode = NULL; 1865 ext4_grpblk_t add, offset; 1866 unsigned long n_desc_blocks; 1867 unsigned long o_desc_blocks; |
1775 unsigned long desc_blocks; | |
1776 ext4_group_t o_group; 1777 ext4_group_t n_group; 1778 ext4_fsblk_t o_blocks_count; | 1868 ext4_group_t o_group; 1869 ext4_group_t n_group; 1870 ext4_fsblk_t o_blocks_count; |
1871 ext4_fsblk_t n_blocks_count_retry = 0; |
|
1779 int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex; 1780 int meta_bg; 1781 | 1872 int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex; 1873 int meta_bg; 1874 |
1875retry: |
|
1782 o_blocks_count = ext4_blocks_count(es); 1783 1784 if (test_opt(sb, DEBUG)) 1785 ext4_msg(sb, KERN_DEBUG, "resizing filesystem from %llu " 1786 "to %llu blocks", o_blocks_count, n_blocks_count); 1787 1788 if (n_blocks_count < o_blocks_count) { 1789 /* On-line shrinking not supported */ 1790 ext4_warning(sb, "can't shrink FS - resize aborted"); 1791 return -EINVAL; 1792 } 1793 1794 if (n_blocks_count == o_blocks_count) 1795 /* Nothing need to do */ 1796 return 0; 1797 1798 ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset); 1799 ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset); 1800 | 1876 o_blocks_count = ext4_blocks_count(es); 1877 1878 if (test_opt(sb, DEBUG)) 1879 ext4_msg(sb, KERN_DEBUG, "resizing filesystem from %llu " 1880 "to %llu blocks", o_blocks_count, n_blocks_count); 1881 1882 if (n_blocks_count < o_blocks_count) { 1883 /* On-line shrinking not supported */ 1884 ext4_warning(sb, "can't shrink FS - resize aborted"); 1885 return -EINVAL; 1886 } 1887 1888 if (n_blocks_count == o_blocks_count) 1889 /* Nothing need to do */ 1890 return 0; 1891 1892 ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset); 1893 ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset); 1894 |
1801 n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) / 1802 EXT4_DESC_PER_BLOCK(sb); 1803 o_desc_blocks = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / 1804 EXT4_DESC_PER_BLOCK(sb); 1805 desc_blocks = n_desc_blocks - o_desc_blocks; | 1895 n_desc_blocks = num_desc_blocks(sb, n_group + 1); 1896 o_desc_blocks = num_desc_blocks(sb, sbi->s_groups_count); |
1806 1807 meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); 1808 1809 if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) { 1810 if (meta_bg) { 1811 ext4_error(sb, "resize_inode and meta_bg enabled " 1812 "simultaneously"); 1813 return -EINVAL; 1814 } | 1897 1898 meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); 1899 1900 if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) { 1901 if (meta_bg) { 1902 ext4_error(sb, "resize_inode and meta_bg enabled " 1903 "simultaneously"); 1904 return -EINVAL; 1905 } |
1815 if (le16_to_cpu(es->s_reserved_gdt_blocks) < desc_blocks) { 1816 ext4_warning(sb, 1817 "No reserved GDT blocks, can't resize"); 1818 return -EPERM; | 1906 if (n_desc_blocks > o_desc_blocks + 1907 le16_to_cpu(es->s_reserved_gdt_blocks)) { 1908 n_blocks_count_retry = n_blocks_count; 1909 n_desc_blocks = o_desc_blocks + 1910 le16_to_cpu(es->s_reserved_gdt_blocks); 1911 n_group = n_desc_blocks * EXT4_DESC_PER_BLOCK(sb); 1912 n_blocks_count = n_group * EXT4_BLOCKS_PER_GROUP(sb); 1913 n_group--; /* set to last group number */ |
1819 } | 1914 } |
1820 resize_inode = ext4_iget(sb, EXT4_RESIZE_INO); | 1915 1916 if (!resize_inode) 1917 resize_inode = ext4_iget(sb, EXT4_RESIZE_INO); |
1821 if (IS_ERR(resize_inode)) { 1822 ext4_warning(sb, "Error opening resize inode"); 1823 return PTR_ERR(resize_inode); 1824 } | 1918 if (IS_ERR(resize_inode)) { 1919 ext4_warning(sb, "Error opening resize inode"); 1920 return PTR_ERR(resize_inode); 1921 } |
1825 } else if (!meta_bg) { 1826 ext4_warning(sb, "File system features do not permit " 1827 "online resize"); 1828 return -EPERM; | |
1829 } 1830 | 1922 } 1923 |
1924 if ((!resize_inode && !meta_bg) || n_group == o_group) { 1925 err = ext4_convert_meta_bg(sb, resize_inode); 1926 if (err) 1927 goto out; 1928 if (resize_inode) { 1929 iput(resize_inode); 1930 resize_inode = NULL; 1931 } 1932 if (n_blocks_count_retry) { 1933 n_blocks_count = n_blocks_count_retry; 1934 n_blocks_count_retry = 0; 1935 goto retry; 1936 } 1937 } 1938 |
|
1831 /* See if the device is actually as big as what was requested */ 1832 bh = sb_bread(sb, n_blocks_count - 1); 1833 if (!bh) { 1834 ext4_warning(sb, "can't read last block, resize aborted"); 1835 return -ENOSPC; 1836 } 1837 brelse(bh); 1838 --- 32 unchanged lines hidden (view full) --- 1871 flexbg_size)) { 1872 if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) 1873 break; 1874 err = ext4_flex_group_add(sb, resize_inode, flex_gd); 1875 if (unlikely(err)) 1876 break; 1877 } 1878 | 1939 /* See if the device is actually as big as what was requested */ 1940 bh = sb_bread(sb, n_blocks_count - 1); 1941 if (!bh) { 1942 ext4_warning(sb, "can't read last block, resize aborted"); 1943 return -ENOSPC; 1944 } 1945 brelse(bh); 1946 --- 32 unchanged lines hidden (view full) --- 1979 flexbg_size)) { 1980 if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) 1981 break; 1982 err = ext4_flex_group_add(sb, resize_inode, flex_gd); 1983 if (unlikely(err)) 1984 break; 1985 } 1986 |
1987 if (!err && n_blocks_count_retry) { 1988 n_blocks_count = n_blocks_count_retry; 1989 n_blocks_count_retry = 0; 1990 free_flex_gd(flex_gd); 1991 flex_gd = NULL; 1992 goto retry; 1993 } 1994 |
|
1879out: 1880 if (flex_gd) 1881 free_flex_gd(flex_gd); 1882 if (resize_inode != NULL) 1883 iput(resize_inode); 1884 if (test_opt(sb, DEBUG)) | 1995out: 1996 if (flex_gd) 1997 free_flex_gd(flex_gd); 1998 if (resize_inode != NULL) 1999 iput(resize_inode); 2000 if (test_opt(sb, DEBUG)) |
1885 ext4_msg(sb, KERN_DEBUG, "resized filesystem from %llu " 1886 "upto %llu blocks", o_blocks_count, n_blocks_count); | 2001 ext4_msg(sb, KERN_DEBUG, "resized filesystem to %llu", 2002 n_blocks_count); |
1887 return err; 1888} | 2003 return err; 2004} |