aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-11-12 14:34:12 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-12 14:34:12 -0500
commitc146afad2c7fea6a366d4945c1bab9b03880f526 (patch)
treedd217139525a521895125843ca31f61cfbb49dca /fs
parentf3465ca44e2a51fd647c167045768a8ab5a96603 (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.h1
-rw-r--r--fs/btrfs/disk-io.c83
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c61
-rw-r--r--fs/btrfs/inode.c15
-rw-r--r--fs/btrfs/ioctl.c22
-rw-r--r--fs/btrfs/super.c37
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
1958int close_ctree(struct btrfs_root *root) 1963int 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); 1988int 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
2009int 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,
38int close_ctree(struct btrfs_root *root); 38int close_ctree(struct btrfs_root *root);
39int write_ctree_super(struct btrfs_trans_handle *trans, 39int write_ctree_super(struct btrfs_trans_handle *trans,
40 struct btrfs_root *root); 40 struct btrfs_root *root);
41int btrfs_commit_super(struct btrfs_root *root);
41struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 42struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
42 u64 bytenr, u32 blocksize); 43 u64 bytenr, u32 blocksize);
43struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, 44struct 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);
50struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, 51struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
51 struct btrfs_key *location); 52 struct btrfs_key *location);
53int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
52int btrfs_insert_dev_radix(struct btrfs_root *root, 54int 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
1833static 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
1832static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) 1846static 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) {
1919printk("space info full %Lu\n", flags); 1918printk("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);
1927out_unlock:
1928 mutex_unlock(&extent_root->fs_info->chunk_mutex);
1929out: 1926out:
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
488error_s: 491error_s:
489 error = PTR_ERR(s); 492 error = PTR_ERR(s);
490error_bdev: 493error_close_devices:
491 btrfs_close_devices(fs_devices); 494 btrfs_close_devices(fs_devices);
492error_free_subvol_name: 495error_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
501static 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
498static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) 530static 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};