A remount to a read-write filesystem is not safe when there's tree-log to be replayed. Files that could be opened until now might be affected by the changes in the tree-log.
A regular mount is needed to replay the log so the filesystem presents the consistent view with the pending changes included.
CC: stable@vger.kernel.org # 4.4+ Signed-off-by: David Sterba dsterba@suse.com --- fs/btrfs/super.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 580ba7db67e5..a2554c651548 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) }
if (btrfs_super_log_root(fs_info->super_copy) != 0) { + btrfs_warn(f_info, + "mount required to replay tree-log, cannot remount read-write"); ret = -EINVAL; goto restore; }
On 2/6/20 12:12 AM, David Sterba wrote:
A remount to a read-write filesystem is not safe when there's tree-log to be replayed. Files that could be opened until now might be affected by the changes in the tree-log.
A regular mount is needed to replay the log so the filesystem presents the consistent view with the pending changes included.
CC: stable@vger.kernel.org # 4.4+ Signed-off-by: David Sterba dsterba@suse.com
fs/btrfs/super.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 580ba7db67e5..a2554c651548 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) } if (btrfs_super_log_root(fs_info->super_copy) != 0) {
btrfs_warn(f_info,
^^^^ fs_info,
Thanks, Anand
}"mount required to replay tree-log, cannot remount read-write"); ret = -EINVAL; goto restore;
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on kdave/for-next] [also build test ERROR on v5.5] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/David-Sterba/btrfs-log-message-when... base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next config: h8300-randconfig-a001-20200206 (attached as .config) compiler: h8300-linux-gcc (GCC) 7.5.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.5.0 make.cross ARCH=h8300
If you fix the issue, kindly add following tag Reported-by: kbuild test robot lkp@intel.com
All errors (new ones prefixed by >>):
In file included from fs/btrfs/delayed-inode.h:17:0, from fs/btrfs/super.c:30: fs/btrfs/super.c: In function 'btrfs_remount':
fs/btrfs/super.c:1837:15: error: 'f_info' undeclared (first use in this function); did you mean 'fs_info'?
btrfs_warn(f_info, ^ fs/btrfs/ctree.h:3035:15: note: in definition of macro 'btrfs_warn' btrfs_printk(fs_info, KERN_WARNING fmt, ##args) ^~~~~~~ fs/btrfs/super.c:1837:15: note: each undeclared identifier is reported only once for each function it appears in btrfs_warn(f_info, ^ fs/btrfs/ctree.h:3035:15: note: in definition of macro 'btrfs_warn' btrfs_printk(fs_info, KERN_WARNING fmt, ##args) ^~~~~~~
vim +1837 fs/btrfs/super.c
1747 1748 static int btrfs_remount(struct super_block *sb, int *flags, char *data) 1749 { 1750 struct btrfs_fs_info *fs_info = btrfs_sb(sb); 1751 struct btrfs_root *root = fs_info->tree_root; 1752 unsigned old_flags = sb->s_flags; 1753 unsigned long old_opts = fs_info->mount_opt; 1754 unsigned long old_compress_type = fs_info->compress_type; 1755 u64 old_max_inline = fs_info->max_inline; 1756 u32 old_thread_pool_size = fs_info->thread_pool_size; 1757 u32 old_metadata_ratio = fs_info->metadata_ratio; 1758 int ret; 1759 1760 sync_filesystem(sb); 1761 btrfs_remount_prepare(fs_info); 1762 1763 if (data) { 1764 void *new_sec_opts = NULL; 1765 1766 ret = security_sb_eat_lsm_opts(data, &new_sec_opts); 1767 if (!ret) 1768 ret = security_sb_remount(sb, new_sec_opts); 1769 security_free_mnt_opts(&new_sec_opts); 1770 if (ret) 1771 goto restore; 1772 } 1773 1774 ret = btrfs_parse_options(fs_info, data, *flags); 1775 if (ret) 1776 goto restore; 1777 1778 btrfs_remount_begin(fs_info, old_opts, *flags); 1779 btrfs_resize_thread_pool(fs_info, 1780 fs_info->thread_pool_size, old_thread_pool_size); 1781 1782 if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) 1783 goto out; 1784 1785 if (*flags & SB_RDONLY) { 1786 /* 1787 * this also happens on 'umount -rf' or on shutdown, when 1788 * the filesystem is busy. 1789 */ 1790 cancel_work_sync(&fs_info->async_reclaim_work); 1791 1792 btrfs_discard_cleanup(fs_info); 1793 1794 /* wait for the uuid_scan task to finish */ 1795 down(&fs_info->uuid_tree_rescan_sem); 1796 /* avoid complains from lockdep et al. */ 1797 up(&fs_info->uuid_tree_rescan_sem); 1798 1799 sb->s_flags |= SB_RDONLY; 1800 1801 /* 1802 * Setting SB_RDONLY will put the cleaner thread to 1803 * sleep at the next loop if it's already active. 1804 * If it's already asleep, we'll leave unused block 1805 * groups on disk until we're mounted read-write again 1806 * unless we clean them up here. 1807 */ 1808 btrfs_delete_unused_bgs(fs_info); 1809 1810 btrfs_dev_replace_suspend_for_unmount(fs_info); 1811 btrfs_scrub_cancel(fs_info); 1812 btrfs_pause_balance(fs_info); 1813 1814 ret = btrfs_commit_super(fs_info); 1815 if (ret) 1816 goto restore; 1817 } else { 1818 if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { 1819 btrfs_err(fs_info, 1820 "Remounting read-write after error is not allowed"); 1821 ret = -EINVAL; 1822 goto restore; 1823 } 1824 if (fs_info->fs_devices->rw_devices == 0) { 1825 ret = -EACCES; 1826 goto restore; 1827 } 1828 1829 if (!btrfs_check_rw_degradable(fs_info, NULL)) { 1830 btrfs_warn(fs_info, 1831 "too many missing devices, writable remount is not allowed"); 1832 ret = -EACCES; 1833 goto restore; 1834 } 1835 1836 if (btrfs_super_log_root(fs_info->super_copy) != 0) {
1837 btrfs_warn(f_info,
1838 "mount required to replay tree-log, cannot remount read-write"); 1839 ret = -EINVAL; 1840 goto restore; 1841 } 1842 1843 ret = btrfs_cleanup_fs_roots(fs_info); 1844 if (ret) 1845 goto restore; 1846 1847 /* recover relocation */ 1848 mutex_lock(&fs_info->cleaner_mutex); 1849 ret = btrfs_recover_relocation(root); 1850 mutex_unlock(&fs_info->cleaner_mutex); 1851 if (ret) 1852 goto restore; 1853 1854 ret = btrfs_resume_balance_async(fs_info); 1855 if (ret) 1856 goto restore; 1857 1858 ret = btrfs_resume_dev_replace_async(fs_info); 1859 if (ret) { 1860 btrfs_warn(fs_info, "failed to resume dev_replace"); 1861 goto restore; 1862 } 1863 1864 btrfs_qgroup_rescan_resume(fs_info); 1865 1866 if (!fs_info->uuid_root) { 1867 btrfs_info(fs_info, "creating UUID tree"); 1868 ret = btrfs_create_uuid_tree(fs_info); 1869 if (ret) { 1870 btrfs_warn(fs_info, 1871 "failed to create the UUID tree %d", 1872 ret); 1873 goto restore; 1874 } 1875 } 1876 sb->s_flags &= ~SB_RDONLY; 1877 1878 set_bit(BTRFS_FS_OPEN, &fs_info->flags); 1879 } 1880 out: 1881 wake_up_process(fs_info->transaction_kthread); 1882 btrfs_remount_cleanup(fs_info, old_opts); 1883 return 0; 1884 1885 restore: 1886 /* We've hit an error - don't reset SB_RDONLY */ 1887 if (sb_rdonly(sb)) 1888 old_flags |= SB_RDONLY; 1889 sb->s_flags = old_flags; 1890 fs_info->mount_opt = old_opts; 1891 fs_info->compress_type = old_compress_type; 1892 fs_info->max_inline = old_max_inline; 1893 btrfs_resize_thread_pool(fs_info, 1894 old_thread_pool_size, fs_info->thread_pool_size); 1895 fs_info->metadata_ratio = old_metadata_ratio; 1896 btrfs_remount_cleanup(fs_info, old_opts); 1897 return ret; 1898 } 1899
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on kdave/for-next] [also build test ERROR on v5.5 next-20200206] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/David-Sterba/btrfs-log-message-when... base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next config: x86_64-randconfig-s2-20200206 (attached as .config) compiler: gcc-5 (Ubuntu 5.5.0-12ubuntu1) 5.5.0 20171010 reproduce: # save the attached .config to linux build tree make ARCH=x86_64
If you fix the issue, kindly add following tag Reported-by: kbuild test robot lkp@intel.com
All errors (new ones prefixed by >>):
In file included from fs/btrfs/delayed-inode.h:17:0, from fs/btrfs/super.c:30: fs/btrfs/super.c: In function 'btrfs_remount':
fs/btrfs/super.c:1837:15: error: 'f_info' undeclared (first use in this function)
btrfs_warn(f_info, ^ fs/btrfs/ctree.h:3035:15: note: in definition of macro 'btrfs_warn' btrfs_printk(fs_info, KERN_WARNING fmt, ##args) ^ fs/btrfs/super.c:1837:15: note: each undeclared identifier is reported only once for each function it appears in btrfs_warn(f_info, ^ fs/btrfs/ctree.h:3035:15: note: in definition of macro 'btrfs_warn' btrfs_printk(fs_info, KERN_WARNING fmt, ##args) ^
vim +/f_info +1837 fs/btrfs/super.c
1747 1748 static int btrfs_remount(struct super_block *sb, int *flags, char *data) 1749 { 1750 struct btrfs_fs_info *fs_info = btrfs_sb(sb); 1751 struct btrfs_root *root = fs_info->tree_root; 1752 unsigned old_flags = sb->s_flags; 1753 unsigned long old_opts = fs_info->mount_opt; 1754 unsigned long old_compress_type = fs_info->compress_type; 1755 u64 old_max_inline = fs_info->max_inline; 1756 u32 old_thread_pool_size = fs_info->thread_pool_size; 1757 u32 old_metadata_ratio = fs_info->metadata_ratio; 1758 int ret; 1759 1760 sync_filesystem(sb); 1761 btrfs_remount_prepare(fs_info); 1762 1763 if (data) { 1764 void *new_sec_opts = NULL; 1765 1766 ret = security_sb_eat_lsm_opts(data, &new_sec_opts); 1767 if (!ret) 1768 ret = security_sb_remount(sb, new_sec_opts); 1769 security_free_mnt_opts(&new_sec_opts); 1770 if (ret) 1771 goto restore; 1772 } 1773 1774 ret = btrfs_parse_options(fs_info, data, *flags); 1775 if (ret) 1776 goto restore; 1777 1778 btrfs_remount_begin(fs_info, old_opts, *flags); 1779 btrfs_resize_thread_pool(fs_info, 1780 fs_info->thread_pool_size, old_thread_pool_size); 1781 1782 if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) 1783 goto out; 1784 1785 if (*flags & SB_RDONLY) { 1786 /* 1787 * this also happens on 'umount -rf' or on shutdown, when 1788 * the filesystem is busy. 1789 */ 1790 cancel_work_sync(&fs_info->async_reclaim_work); 1791 1792 btrfs_discard_cleanup(fs_info); 1793 1794 /* wait for the uuid_scan task to finish */ 1795 down(&fs_info->uuid_tree_rescan_sem); 1796 /* avoid complains from lockdep et al. */ 1797 up(&fs_info->uuid_tree_rescan_sem); 1798 1799 sb->s_flags |= SB_RDONLY; 1800 1801 /* 1802 * Setting SB_RDONLY will put the cleaner thread to 1803 * sleep at the next loop if it's already active. 1804 * If it's already asleep, we'll leave unused block 1805 * groups on disk until we're mounted read-write again 1806 * unless we clean them up here. 1807 */ 1808 btrfs_delete_unused_bgs(fs_info); 1809 1810 btrfs_dev_replace_suspend_for_unmount(fs_info); 1811 btrfs_scrub_cancel(fs_info); 1812 btrfs_pause_balance(fs_info); 1813 1814 ret = btrfs_commit_super(fs_info); 1815 if (ret) 1816 goto restore; 1817 } else { 1818 if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { 1819 btrfs_err(fs_info, 1820 "Remounting read-write after error is not allowed"); 1821 ret = -EINVAL; 1822 goto restore; 1823 } 1824 if (fs_info->fs_devices->rw_devices == 0) { 1825 ret = -EACCES; 1826 goto restore; 1827 } 1828 1829 if (!btrfs_check_rw_degradable(fs_info, NULL)) { 1830 btrfs_warn(fs_info, 1831 "too many missing devices, writable remount is not allowed"); 1832 ret = -EACCES; 1833 goto restore; 1834 } 1835 1836 if (btrfs_super_log_root(fs_info->super_copy) != 0) {
1837 btrfs_warn(f_info,
1838 "mount required to replay tree-log, cannot remount read-write"); 1839 ret = -EINVAL; 1840 goto restore; 1841 } 1842 1843 ret = btrfs_cleanup_fs_roots(fs_info); 1844 if (ret) 1845 goto restore; 1846 1847 /* recover relocation */ 1848 mutex_lock(&fs_info->cleaner_mutex); 1849 ret = btrfs_recover_relocation(root); 1850 mutex_unlock(&fs_info->cleaner_mutex); 1851 if (ret) 1852 goto restore; 1853 1854 ret = btrfs_resume_balance_async(fs_info); 1855 if (ret) 1856 goto restore; 1857 1858 ret = btrfs_resume_dev_replace_async(fs_info); 1859 if (ret) { 1860 btrfs_warn(fs_info, "failed to resume dev_replace"); 1861 goto restore; 1862 } 1863 1864 btrfs_qgroup_rescan_resume(fs_info); 1865 1866 if (!fs_info->uuid_root) { 1867 btrfs_info(fs_info, "creating UUID tree"); 1868 ret = btrfs_create_uuid_tree(fs_info); 1869 if (ret) { 1870 btrfs_warn(fs_info, 1871 "failed to create the UUID tree %d", 1872 ret); 1873 goto restore; 1874 } 1875 } 1876 sb->s_flags &= ~SB_RDONLY; 1877 1878 set_bit(BTRFS_FS_OPEN, &fs_info->flags); 1879 } 1880 out: 1881 wake_up_process(fs_info->transaction_kthread); 1882 btrfs_remount_cleanup(fs_info, old_opts); 1883 return 0; 1884 1885 restore: 1886 /* We've hit an error - don't reset SB_RDONLY */ 1887 if (sb_rdonly(sb)) 1888 old_flags |= SB_RDONLY; 1889 sb->s_flags = old_flags; 1890 fs_info->mount_opt = old_opts; 1891 fs_info->compress_type = old_compress_type; 1892 fs_info->max_inline = old_max_inline; 1893 btrfs_resize_thread_pool(fs_info, 1894 old_thread_pool_size, fs_info->thread_pool_size); 1895 fs_info->metadata_ratio = old_metadata_ratio; 1896 btrfs_remount_cleanup(fs_info, old_opts); 1897 return ret; 1898 } 1899
--- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
linux-stable-mirror@lists.linaro.org