summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-11-12 20:34:12 +0100
committerChris Mason <chris.mason@oracle.com>2008-11-12 20:34:12 +0100
commitc146afad2c7fea6a366d4945c1bab9b03880f526 (patch)
treedd217139525a521895125843ca31f61cfbb49dca /fs/btrfs/super.c
parentBtrfs: batch extent inserts/updates/deletions on the extent root (diff)
downloadlinux-c146afad2c7fea6a366d4945c1bab9b03880f526.tar.xz
linux-c146afad2c7fea6a366d4945c1bab9b03880f526.zip
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/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c37
1 files changed, 35 insertions, 2 deletions
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)
int ret;
root = btrfs_sb(sb);
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
+
sb->s_dirt = 0;
if (!wait) {
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,
up_write(&s->s_umount);
deactivate_super(s);
error = -EBUSY;
- goto error_bdev;
+ goto error_close_devices;
}
} else {
@@ -487,7 +490,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
error_s:
error = PTR_ERR(s);
-error_bdev:
+error_close_devices:
btrfs_close_devices(fs_devices);
error_free_subvol_name:
kfree(subvol_name);
@@ -495,6 +498,35 @@ error:
return error;
}
+static int btrfs_remount(struct super_block *sb, int *flags, char *data)
+{
+ struct btrfs_root *root = btrfs_sb(sb);
+ int ret;
+
+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ return 0;
+
+ if (*flags & MS_RDONLY) {
+ sb->s_flags |= MS_RDONLY;
+
+ ret = btrfs_commit_super(root);
+ WARN_ON(ret);
+ } else {
+ if (btrfs_super_log_root(&root->fs_info->super_copy) != 0)
+ return -EINVAL;
+
+ ret = btrfs_cleanup_reloc_trees(root);
+ WARN_ON(ret);
+
+ ret = btrfs_cleanup_fs_roots(root->fs_info);
+ WARN_ON(ret);
+
+ sb->s_flags &= ~MS_RDONLY;
+ }
+
+ return 0;
+}
+
static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct btrfs_root *root = btrfs_sb(dentry->d_sb);
@@ -582,6 +614,7 @@ static struct super_operations btrfs_super_ops = {
.alloc_inode = btrfs_alloc_inode,
.destroy_inode = btrfs_destroy_inode,
.statfs = btrfs_statfs,
+ .remount_fs = btrfs_remount,
.write_super_lockfs = btrfs_write_super_lockfs,
.unlockfs = btrfs_unlockfs,
};