diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-11-12 14:34:12 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-11-12 14:34:12 -0500 |
commit | c146afad2c7fea6a366d4945c1bab9b03880f526 (patch) | |
tree | dd217139525a521895125843ca31f61cfbb49dca /fs | |
parent | f3465ca44e2a51fd647c167045768a8ab5a96603 (diff) |
Btrfs: mount ro and remount support
This patch adds mount ro and remount support. The main
changes in patch are: adding btrfs_remount and related
helper function; splitting the transaction related code
out of close_ctree into btrfs_commit_super; updating
allocator to properly handle read only block group.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 83 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 61 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 15 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 22 | ||||
-rw-r--r-- | fs/btrfs/super.c | 37 |
7 files changed, 163 insertions, 58 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index f575939e0258..c4c6c127323b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -541,6 +541,7 @@ struct btrfs_space_info { | |||
541 | u64 bytes_used; | 541 | u64 bytes_used; |
542 | u64 bytes_pinned; | 542 | u64 bytes_pinned; |
543 | u64 bytes_reserved; | 543 | u64 bytes_reserved; |
544 | u64 bytes_readonly; | ||
544 | int full; | 545 | int full; |
545 | int force_alloc; | 546 | int force_alloc; |
546 | struct list_head list; | 547 | struct list_head list; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3b0e974a9e9c..c599f0ee997a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1075,10 +1075,12 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
1075 | kfree(root); | 1075 | kfree(root); |
1076 | return ERR_PTR(ret); | 1076 | return ERR_PTR(ret); |
1077 | } | 1077 | } |
1078 | ret = btrfs_find_dead_roots(fs_info->tree_root, | 1078 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { |
1079 | root->root_key.objectid, root); | 1079 | ret = btrfs_find_dead_roots(fs_info->tree_root, |
1080 | BUG_ON(ret); | 1080 | root->root_key.objectid, root); |
1081 | 1081 | BUG_ON(ret); | |
1082 | btrfs_orphan_cleanup(root); | ||
1083 | } | ||
1082 | return root; | 1084 | return root; |
1083 | } | 1085 | } |
1084 | 1086 | ||
@@ -1700,7 +1702,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1700 | 1702 | ||
1701 | btrfs_read_block_groups(extent_root); | 1703 | btrfs_read_block_groups(extent_root); |
1702 | 1704 | ||
1703 | fs_info->generation = btrfs_super_generation(disk_super) + 1; | 1705 | fs_info->generation = generation + 1; |
1706 | fs_info->last_trans_committed = generation; | ||
1704 | fs_info->data_alloc_profile = (u64)-1; | 1707 | fs_info->data_alloc_profile = (u64)-1; |
1705 | fs_info->metadata_alloc_profile = (u64)-1; | 1708 | fs_info->metadata_alloc_profile = (u64)-1; |
1706 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; | 1709 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; |
@@ -1715,6 +1718,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1715 | if (!fs_info->transaction_kthread) | 1718 | if (!fs_info->transaction_kthread) |
1716 | goto fail_cleaner; | 1719 | goto fail_cleaner; |
1717 | 1720 | ||
1721 | if (sb->s_flags & MS_RDONLY) | ||
1722 | return tree_root; | ||
1723 | |||
1718 | if (btrfs_super_log_root(disk_super) != 0) { | 1724 | if (btrfs_super_log_root(disk_super) != 0) { |
1719 | u32 blocksize; | 1725 | u32 blocksize; |
1720 | u64 bytenr = btrfs_super_log_root(disk_super); | 1726 | u64 bytenr = btrfs_super_log_root(disk_super); |
@@ -1735,7 +1741,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1735 | ret = btrfs_recover_log_trees(log_tree_root); | 1741 | ret = btrfs_recover_log_trees(log_tree_root); |
1736 | BUG_ON(ret); | 1742 | BUG_ON(ret); |
1737 | } | 1743 | } |
1738 | fs_info->last_trans_committed = btrfs_super_generation(disk_super); | ||
1739 | 1744 | ||
1740 | ret = btrfs_cleanup_reloc_trees(tree_root); | 1745 | ret = btrfs_cleanup_reloc_trees(tree_root); |
1741 | BUG_ON(ret); | 1746 | BUG_ON(ret); |
@@ -1955,28 +1960,69 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info) | |||
1955 | return 0; | 1960 | return 0; |
1956 | } | 1961 | } |
1957 | 1962 | ||
1958 | int close_ctree(struct btrfs_root *root) | 1963 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) |
1959 | { | 1964 | { |
1965 | u64 root_objectid = 0; | ||
1966 | struct btrfs_root *gang[8]; | ||
1967 | int i; | ||
1960 | int ret; | 1968 | int ret; |
1961 | struct btrfs_trans_handle *trans; | ||
1962 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
1963 | 1969 | ||
1964 | fs_info->closing = 1; | 1970 | while (1) { |
1965 | smp_mb(); | 1971 | ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, |
1972 | (void **)gang, root_objectid, | ||
1973 | ARRAY_SIZE(gang)); | ||
1974 | if (!ret) | ||
1975 | break; | ||
1976 | for (i = 0; i < ret; i++) { | ||
1977 | root_objectid = gang[i]->root_key.objectid; | ||
1978 | ret = btrfs_find_dead_roots(fs_info->tree_root, | ||
1979 | root_objectid, gang[i]); | ||
1980 | BUG_ON(ret); | ||
1981 | btrfs_orphan_cleanup(gang[i]); | ||
1982 | } | ||
1983 | root_objectid++; | ||
1984 | } | ||
1985 | return 0; | ||
1986 | } | ||
1966 | 1987 | ||
1967 | kthread_stop(root->fs_info->transaction_kthread); | 1988 | int btrfs_commit_super(struct btrfs_root *root) |
1968 | kthread_stop(root->fs_info->cleaner_kthread); | 1989 | { |
1990 | struct btrfs_trans_handle *trans; | ||
1991 | int ret; | ||
1969 | 1992 | ||
1993 | mutex_lock(&root->fs_info->cleaner_mutex); | ||
1970 | btrfs_clean_old_snapshots(root); | 1994 | btrfs_clean_old_snapshots(root); |
1995 | mutex_unlock(&root->fs_info->cleaner_mutex); | ||
1971 | trans = btrfs_start_transaction(root, 1); | 1996 | trans = btrfs_start_transaction(root, 1); |
1972 | ret = btrfs_commit_transaction(trans, root); | 1997 | ret = btrfs_commit_transaction(trans, root); |
1973 | /* run commit again to drop the original snapshot */ | 1998 | BUG_ON(ret); |
1999 | /* run commit again to drop the original snapshot */ | ||
1974 | trans = btrfs_start_transaction(root, 1); | 2000 | trans = btrfs_start_transaction(root, 1); |
1975 | btrfs_commit_transaction(trans, root); | 2001 | btrfs_commit_transaction(trans, root); |
1976 | ret = btrfs_write_and_wait_transaction(NULL, root); | 2002 | ret = btrfs_write_and_wait_transaction(NULL, root); |
1977 | BUG_ON(ret); | 2003 | BUG_ON(ret); |
1978 | 2004 | ||
1979 | write_ctree_super(NULL, root); | 2005 | ret = write_ctree_super(NULL, root); |
2006 | return ret; | ||
2007 | } | ||
2008 | |||
2009 | int close_ctree(struct btrfs_root *root) | ||
2010 | { | ||
2011 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
2012 | int ret; | ||
2013 | |||
2014 | fs_info->closing = 1; | ||
2015 | smp_mb(); | ||
2016 | |||
2017 | kthread_stop(root->fs_info->transaction_kthread); | ||
2018 | kthread_stop(root->fs_info->cleaner_kthread); | ||
2019 | |||
2020 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { | ||
2021 | ret = btrfs_commit_super(root); | ||
2022 | if (ret) { | ||
2023 | printk("btrfs: commit super returns %d\n", ret); | ||
2024 | } | ||
2025 | } | ||
1980 | 2026 | ||
1981 | if (fs_info->delalloc_bytes) { | 2027 | if (fs_info->delalloc_bytes) { |
1982 | printk("btrfs: at unmount delalloc count %Lu\n", | 2028 | printk("btrfs: at unmount delalloc count %Lu\n", |
@@ -2000,12 +2046,10 @@ int close_ctree(struct btrfs_root *root) | |||
2000 | free_extent_buffer(root->fs_info->dev_root->node); | 2046 | free_extent_buffer(root->fs_info->dev_root->node); |
2001 | 2047 | ||
2002 | btrfs_free_block_groups(root->fs_info); | 2048 | btrfs_free_block_groups(root->fs_info); |
2003 | fs_info->closing = 2; | ||
2004 | del_fs_roots(fs_info); | ||
2005 | 2049 | ||
2006 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); | 2050 | del_fs_roots(fs_info); |
2007 | 2051 | ||
2008 | truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); | 2052 | iput(fs_info->btree_inode); |
2009 | 2053 | ||
2010 | btrfs_stop_workers(&fs_info->fixup_workers); | 2054 | btrfs_stop_workers(&fs_info->fixup_workers); |
2011 | btrfs_stop_workers(&fs_info->delalloc_workers); | 2055 | btrfs_stop_workers(&fs_info->delalloc_workers); |
@@ -2014,7 +2058,6 @@ int close_ctree(struct btrfs_root *root) | |||
2014 | btrfs_stop_workers(&fs_info->endio_write_workers); | 2058 | btrfs_stop_workers(&fs_info->endio_write_workers); |
2015 | btrfs_stop_workers(&fs_info->submit_workers); | 2059 | btrfs_stop_workers(&fs_info->submit_workers); |
2016 | 2060 | ||
2017 | iput(fs_info->btree_inode); | ||
2018 | #if 0 | 2061 | #if 0 |
2019 | while(!list_empty(&fs_info->hashers)) { | 2062 | while(!list_empty(&fs_info->hashers)) { |
2020 | struct btrfs_hasher *hasher; | 2063 | struct btrfs_hasher *hasher; |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index b8d5948fa279..717e94811e4e 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -38,6 +38,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
38 | int close_ctree(struct btrfs_root *root); | 38 | int close_ctree(struct btrfs_root *root); |
39 | int write_ctree_super(struct btrfs_trans_handle *trans, | 39 | int write_ctree_super(struct btrfs_trans_handle *trans, |
40 | struct btrfs_root *root); | 40 | struct btrfs_root *root); |
41 | int btrfs_commit_super(struct btrfs_root *root); | ||
41 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | 42 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
42 | u64 bytenr, u32 blocksize); | 43 | u64 bytenr, u32 blocksize); |
43 | struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, | 44 | struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, |
@@ -49,6 +50,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |||
49 | struct btrfs_key *location); | 50 | struct btrfs_key *location); |
50 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | 51 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, |
51 | struct btrfs_key *location); | 52 | struct btrfs_key *location); |
53 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); | ||
52 | int btrfs_insert_dev_radix(struct btrfs_root *root, | 54 | int btrfs_insert_dev_radix(struct btrfs_root *root, |
53 | struct block_device *bdev, | 55 | struct block_device *bdev, |
54 | u64 device_id, | 56 | u64 device_id, |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e785f0a0632b..af2de30dbeac 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1794,7 +1794,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1794 | *space_info = found; | 1794 | *space_info = found; |
1795 | return 0; | 1795 | return 0; |
1796 | } | 1796 | } |
1797 | found = kmalloc(sizeof(*found), GFP_NOFS); | 1797 | found = kzalloc(sizeof(*found), GFP_NOFS); |
1798 | if (!found) | 1798 | if (!found) |
1799 | return -ENOMEM; | 1799 | return -ENOMEM; |
1800 | 1800 | ||
@@ -1807,6 +1807,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1807 | found->bytes_used = bytes_used; | 1807 | found->bytes_used = bytes_used; |
1808 | found->bytes_pinned = 0; | 1808 | found->bytes_pinned = 0; |
1809 | found->bytes_reserved = 0; | 1809 | found->bytes_reserved = 0; |
1810 | found->bytes_readonly = 0; | ||
1810 | found->full = 0; | 1811 | found->full = 0; |
1811 | found->force_alloc = 0; | 1812 | found->force_alloc = 0; |
1812 | *space_info = found; | 1813 | *space_info = found; |
@@ -1829,6 +1830,19 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
1829 | } | 1830 | } |
1830 | } | 1831 | } |
1831 | 1832 | ||
1833 | static void set_block_group_readonly(struct btrfs_block_group_cache *cache) | ||
1834 | { | ||
1835 | spin_lock(&cache->space_info->lock); | ||
1836 | spin_lock(&cache->lock); | ||
1837 | if (!cache->ro) { | ||
1838 | cache->space_info->bytes_readonly += cache->key.offset - | ||
1839 | btrfs_block_group_used(&cache->item); | ||
1840 | cache->ro = 1; | ||
1841 | } | ||
1842 | spin_unlock(&cache->lock); | ||
1843 | spin_unlock(&cache->space_info->lock); | ||
1844 | } | ||
1845 | |||
1832 | static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 1846 | static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
1833 | { | 1847 | { |
1834 | u64 num_devices = root->fs_info->fs_devices->num_devices; | 1848 | u64 num_devices = root->fs_info->fs_devices->num_devices; |
@@ -1865,7 +1879,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1865 | u64 thresh; | 1879 | u64 thresh; |
1866 | u64 start; | 1880 | u64 start; |
1867 | u64 num_bytes; | 1881 | u64 num_bytes; |
1868 | int ret = 0, waited = 0; | 1882 | int ret = 0; |
1883 | |||
1884 | mutex_lock(&extent_root->fs_info->chunk_mutex); | ||
1869 | 1885 | ||
1870 | flags = reduce_alloc_profile(extent_root, flags); | 1886 | flags = reduce_alloc_profile(extent_root, flags); |
1871 | 1887 | ||
@@ -1887,46 +1903,28 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1887 | goto out; | 1903 | goto out; |
1888 | } | 1904 | } |
1889 | 1905 | ||
1890 | thresh = div_factor(space_info->total_bytes, 6); | 1906 | thresh = space_info->total_bytes - space_info->bytes_readonly; |
1907 | thresh = div_factor(thresh, 6); | ||
1891 | if (!force && | 1908 | if (!force && |
1892 | (space_info->bytes_used + space_info->bytes_pinned + | 1909 | (space_info->bytes_used + space_info->bytes_pinned + |
1893 | space_info->bytes_reserved + alloc_bytes) < thresh) { | 1910 | space_info->bytes_reserved + alloc_bytes) < thresh) { |
1894 | spin_unlock(&space_info->lock); | 1911 | spin_unlock(&space_info->lock); |
1895 | goto out; | 1912 | goto out; |
1896 | } | 1913 | } |
1897 | |||
1898 | spin_unlock(&space_info->lock); | 1914 | spin_unlock(&space_info->lock); |
1899 | 1915 | ||
1900 | ret = mutex_trylock(&extent_root->fs_info->chunk_mutex); | ||
1901 | if (!ret && !force) { | ||
1902 | goto out; | ||
1903 | } else if (!ret) { | ||
1904 | mutex_lock(&extent_root->fs_info->chunk_mutex); | ||
1905 | waited = 1; | ||
1906 | } | ||
1907 | |||
1908 | if (waited) { | ||
1909 | spin_lock(&space_info->lock); | ||
1910 | if (space_info->full) { | ||
1911 | spin_unlock(&space_info->lock); | ||
1912 | goto out_unlock; | ||
1913 | } | ||
1914 | spin_unlock(&space_info->lock); | ||
1915 | } | ||
1916 | |||
1917 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); | 1916 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); |
1918 | if (ret) { | 1917 | if (ret) { |
1919 | printk("space info full %Lu\n", flags); | 1918 | printk("space info full %Lu\n", flags); |
1920 | space_info->full = 1; | 1919 | space_info->full = 1; |
1921 | goto out_unlock; | 1920 | goto out; |
1922 | } | 1921 | } |
1923 | 1922 | ||
1924 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, | 1923 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, |
1925 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); | 1924 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); |
1926 | BUG_ON(ret); | 1925 | BUG_ON(ret); |
1927 | out_unlock: | ||
1928 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | ||
1929 | out: | 1926 | out: |
1927 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | ||
1930 | return ret; | 1928 | return ret; |
1931 | } | 1929 | } |
1932 | 1930 | ||
@@ -1956,12 +1954,18 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1956 | if (alloc) { | 1954 | if (alloc) { |
1957 | old_val += num_bytes; | 1955 | old_val += num_bytes; |
1958 | cache->space_info->bytes_used += num_bytes; | 1956 | cache->space_info->bytes_used += num_bytes; |
1957 | if (cache->ro) { | ||
1958 | cache->space_info->bytes_readonly -= num_bytes; | ||
1959 | WARN_ON(1); | ||
1960 | } | ||
1959 | btrfs_set_block_group_used(&cache->item, old_val); | 1961 | btrfs_set_block_group_used(&cache->item, old_val); |
1960 | spin_unlock(&cache->lock); | 1962 | spin_unlock(&cache->lock); |
1961 | spin_unlock(&cache->space_info->lock); | 1963 | spin_unlock(&cache->space_info->lock); |
1962 | } else { | 1964 | } else { |
1963 | old_val -= num_bytes; | 1965 | old_val -= num_bytes; |
1964 | cache->space_info->bytes_used -= num_bytes; | 1966 | cache->space_info->bytes_used -= num_bytes; |
1967 | if (cache->ro) | ||
1968 | cache->space_info->bytes_readonly += num_bytes; | ||
1965 | btrfs_set_block_group_used(&cache->item, old_val); | 1969 | btrfs_set_block_group_used(&cache->item, old_val); |
1966 | spin_unlock(&cache->lock); | 1970 | spin_unlock(&cache->lock); |
1967 | spin_unlock(&cache->space_info->lock); | 1971 | spin_unlock(&cache->space_info->lock); |
@@ -5560,8 +5564,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) | |||
5560 | BUG_ON(IS_ERR(reloc_inode)); | 5564 | BUG_ON(IS_ERR(reloc_inode)); |
5561 | 5565 | ||
5562 | __alloc_chunk_for_shrink(root, block_group, 1); | 5566 | __alloc_chunk_for_shrink(root, block_group, 1); |
5563 | block_group->ro = 1; | 5567 | set_block_group_readonly(block_group); |
5564 | block_group->space_info->total_bytes -= block_group->key.offset; | ||
5565 | 5568 | ||
5566 | btrfs_start_delalloc_inodes(info->tree_root); | 5569 | btrfs_start_delalloc_inodes(info->tree_root); |
5567 | btrfs_wait_ordered_extents(info->tree_root, 0); | 5570 | btrfs_wait_ordered_extents(info->tree_root, 0); |
@@ -5868,6 +5871,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5868 | 5871 | ||
5869 | block_group = btrfs_lookup_block_group(root->fs_info, group_start); | 5872 | block_group = btrfs_lookup_block_group(root->fs_info, group_start); |
5870 | BUG_ON(!block_group); | 5873 | BUG_ON(!block_group); |
5874 | BUG_ON(!block_group->ro); | ||
5871 | 5875 | ||
5872 | memcpy(&key, &block_group->key, sizeof(key)); | 5876 | memcpy(&key, &block_group->key, sizeof(key)); |
5873 | 5877 | ||
@@ -5881,6 +5885,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5881 | list_del(&block_group->list); | 5885 | list_del(&block_group->list); |
5882 | up_write(&block_group->space_info->groups_sem); | 5886 | up_write(&block_group->space_info->groups_sem); |
5883 | 5887 | ||
5888 | spin_lock(&block_group->space_info->lock); | ||
5889 | block_group->space_info->total_bytes -= block_group->key.offset; | ||
5890 | block_group->space_info->bytes_readonly -= block_group->key.offset; | ||
5891 | spin_unlock(&block_group->space_info->lock); | ||
5892 | |||
5884 | /* | 5893 | /* |
5885 | memset(shrink_block_group, 0, sizeof(*shrink_block_group)); | 5894 | memset(shrink_block_group, 0, sizeof(*shrink_block_group)); |
5886 | kfree(shrink_block_group); | 5895 | kfree(shrink_block_group); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2ed2deacde90..3e3620e69bb9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1808,10 +1808,6 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
1808 | struct inode *inode; | 1808 | struct inode *inode; |
1809 | int ret = 0, nr_unlink = 0, nr_truncate = 0; | 1809 | int ret = 0, nr_unlink = 0, nr_truncate = 0; |
1810 | 1810 | ||
1811 | /* don't do orphan cleanup if the fs is readonly. */ | ||
1812 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
1813 | return; | ||
1814 | |||
1815 | path = btrfs_alloc_path(); | 1811 | path = btrfs_alloc_path(); |
1816 | if (!path) | 1812 | if (!path) |
1817 | return; | 1813 | return; |
@@ -3050,7 +3046,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
3050 | struct btrfs_root *root = bi->root; | 3046 | struct btrfs_root *root = bi->root; |
3051 | struct btrfs_root *sub_root = root; | 3047 | struct btrfs_root *sub_root = root; |
3052 | struct btrfs_key location; | 3048 | struct btrfs_key location; |
3053 | int ret, new, do_orphan = 0; | 3049 | int ret, new; |
3054 | 3050 | ||
3055 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 3051 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
3056 | return ERR_PTR(-ENAMETOOLONG); | 3052 | return ERR_PTR(-ENAMETOOLONG); |
@@ -3076,13 +3072,9 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
3076 | if (new && root != sub_root) { | 3072 | if (new && root != sub_root) { |
3077 | igrab(inode); | 3073 | igrab(inode); |
3078 | sub_root->inode = inode; | 3074 | sub_root->inode = inode; |
3079 | do_orphan = 1; | ||
3080 | } | 3075 | } |
3081 | } | 3076 | } |
3082 | 3077 | ||
3083 | if (unlikely(do_orphan)) | ||
3084 | btrfs_orphan_cleanup(sub_root); | ||
3085 | |||
3086 | return d_splice_alias(inode, dentry); | 3078 | return d_splice_alias(inode, dentry); |
3087 | } | 3079 | } |
3088 | 3080 | ||
@@ -3237,7 +3229,7 @@ int btrfs_write_inode(struct inode *inode, int wait) | |||
3237 | struct btrfs_trans_handle *trans; | 3229 | struct btrfs_trans_handle *trans; |
3238 | int ret = 0; | 3230 | int ret = 0; |
3239 | 3231 | ||
3240 | if (root->fs_info->closing > 1) | 3232 | if (root->fs_info->btree_inode == inode) |
3241 | return 0; | 3233 | return 0; |
3242 | 3234 | ||
3243 | if (wait) { | 3235 | if (wait) { |
@@ -4625,6 +4617,9 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root) | |||
4625 | struct inode *inode; | 4617 | struct inode *inode; |
4626 | unsigned long flags; | 4618 | unsigned long flags; |
4627 | 4619 | ||
4620 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
4621 | return -EROFS; | ||
4622 | |||
4628 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | 4623 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); |
4629 | while(!list_empty(head)) { | 4624 | while(!list_empty(head)) { |
4630 | binode = list_entry(head->next, struct btrfs_inode, | 4625 | binode = list_entry(head->next, struct btrfs_inode, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4d7cc7c504d0..52863cebd594 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -378,6 +378,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
378 | int namelen; | 378 | int namelen; |
379 | int mod = 0; | 379 | int mod = 0; |
380 | 380 | ||
381 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
382 | return -EROFS; | ||
383 | |||
381 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 384 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); |
382 | 385 | ||
383 | if (!vol_args) | 386 | if (!vol_args) |
@@ -478,6 +481,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
478 | int namelen; | 481 | int namelen; |
479 | int ret; | 482 | int ret; |
480 | 483 | ||
484 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
485 | return -EROFS; | ||
486 | |||
481 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 487 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); |
482 | 488 | ||
483 | if (!vol_args) | 489 | if (!vol_args) |
@@ -534,6 +540,11 @@ static int btrfs_ioctl_defrag(struct file *file) | |||
534 | { | 540 | { |
535 | struct inode *inode = fdentry(file)->d_inode; | 541 | struct inode *inode = fdentry(file)->d_inode; |
536 | struct btrfs_root *root = BTRFS_I(inode)->root; | 542 | struct btrfs_root *root = BTRFS_I(inode)->root; |
543 | int ret; | ||
544 | |||
545 | ret = mnt_want_write(file->f_path.mnt); | ||
546 | if (ret) | ||
547 | return ret; | ||
537 | 548 | ||
538 | switch (inode->i_mode & S_IFMT) { | 549 | switch (inode->i_mode & S_IFMT) { |
539 | case S_IFDIR: | 550 | case S_IFDIR: |
@@ -575,6 +586,9 @@ long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
575 | struct btrfs_ioctl_vol_args *vol_args; | 586 | struct btrfs_ioctl_vol_args *vol_args; |
576 | int ret; | 587 | int ret; |
577 | 588 | ||
589 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
590 | return -EROFS; | ||
591 | |||
578 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 592 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); |
579 | 593 | ||
580 | if (!vol_args) | 594 | if (!vol_args) |
@@ -621,6 +635,10 @@ long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, u64 off, | |||
621 | * they don't overlap)? | 635 | * they don't overlap)? |
622 | */ | 636 | */ |
623 | 637 | ||
638 | ret = mnt_want_write(file->f_path.mnt); | ||
639 | if (ret) | ||
640 | return ret; | ||
641 | |||
624 | src_file = fget(srcfd); | 642 | src_file = fget(srcfd); |
625 | if (!src_file) | 643 | if (!src_file) |
626 | return -EBADF; | 644 | return -EBADF; |
@@ -958,6 +976,10 @@ long btrfs_ioctl_trans_start(struct file *file) | |||
958 | goto out; | 976 | goto out; |
959 | } | 977 | } |
960 | 978 | ||
979 | ret = mnt_want_write(file->f_path.mnt); | ||
980 | if (ret) | ||
981 | goto out; | ||
982 | |||
961 | mutex_lock(&root->fs_info->trans_mutex); | 983 | mutex_lock(&root->fs_info->trans_mutex); |
962 | root->fs_info->open_ioctl_trans++; | 984 | root->fs_info->open_ioctl_trans++; |
963 | mutex_unlock(&root->fs_info->trans_mutex); | 985 | mutex_unlock(&root->fs_info->trans_mutex); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ab9d5e89ed13..04a3bf816509 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -370,6 +370,9 @@ int btrfs_sync_fs(struct super_block *sb, int wait) | |||
370 | int ret; | 370 | int ret; |
371 | root = btrfs_sb(sb); | 371 | root = btrfs_sb(sb); |
372 | 372 | ||
373 | if (sb->s_flags & MS_RDONLY) | ||
374 | return 0; | ||
375 | |||
373 | sb->s_dirt = 0; | 376 | sb->s_dirt = 0; |
374 | if (!wait) { | 377 | if (!wait) { |
375 | filemap_flush(root->fs_info->btree_inode->i_mapping); | 378 | filemap_flush(root->fs_info->btree_inode->i_mapping); |
@@ -438,7 +441,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
438 | up_write(&s->s_umount); | 441 | up_write(&s->s_umount); |
439 | deactivate_super(s); | 442 | deactivate_super(s); |
440 | error = -EBUSY; | 443 | error = -EBUSY; |
441 | goto error_bdev; | 444 | goto error_close_devices; |
442 | } | 445 | } |
443 | 446 | ||
444 | } else { | 447 | } else { |
@@ -487,7 +490,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
487 | 490 | ||
488 | error_s: | 491 | error_s: |
489 | error = PTR_ERR(s); | 492 | error = PTR_ERR(s); |
490 | error_bdev: | 493 | error_close_devices: |
491 | btrfs_close_devices(fs_devices); | 494 | btrfs_close_devices(fs_devices); |
492 | error_free_subvol_name: | 495 | error_free_subvol_name: |
493 | kfree(subvol_name); | 496 | kfree(subvol_name); |
@@ -495,6 +498,35 @@ error: | |||
495 | return error; | 498 | return error; |
496 | } | 499 | } |
497 | 500 | ||
501 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) | ||
502 | { | ||
503 | struct btrfs_root *root = btrfs_sb(sb); | ||
504 | int ret; | ||
505 | |||
506 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | ||
507 | return 0; | ||
508 | |||
509 | if (*flags & MS_RDONLY) { | ||
510 | sb->s_flags |= MS_RDONLY; | ||
511 | |||
512 | ret = btrfs_commit_super(root); | ||
513 | WARN_ON(ret); | ||
514 | } else { | ||
515 | if (btrfs_super_log_root(&root->fs_info->super_copy) != 0) | ||
516 | return -EINVAL; | ||
517 | |||
518 | ret = btrfs_cleanup_reloc_trees(root); | ||
519 | WARN_ON(ret); | ||
520 | |||
521 | ret = btrfs_cleanup_fs_roots(root->fs_info); | ||
522 | WARN_ON(ret); | ||
523 | |||
524 | sb->s_flags &= ~MS_RDONLY; | ||
525 | } | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
498 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 530 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
499 | { | 531 | { |
500 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); | 532 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); |
@@ -582,6 +614,7 @@ static struct super_operations btrfs_super_ops = { | |||
582 | .alloc_inode = btrfs_alloc_inode, | 614 | .alloc_inode = btrfs_alloc_inode, |
583 | .destroy_inode = btrfs_destroy_inode, | 615 | .destroy_inode = btrfs_destroy_inode, |
584 | .statfs = btrfs_statfs, | 616 | .statfs = btrfs_statfs, |
617 | .remount_fs = btrfs_remount, | ||
585 | .write_super_lockfs = btrfs_write_super_lockfs, | 618 | .write_super_lockfs = btrfs_write_super_lockfs, |
586 | .unlockfs = btrfs_unlockfs, | 619 | .unlockfs = btrfs_unlockfs, |
587 | }; | 620 | }; |