Miao Xie
2010-Nov-25 09:56 UTC
[RFC PATCH 4/4] Btrfs: deal with filesystem state at mount, umount and remount
From: Liu Bo <liubo2009@cn.fujitsu.com> Since there is a filesystem state, we should deal with it carefully at mount, umount and remount. - At mount, the FS state should be checked if there is error on these FS. If it does have, btrfsck is recommended. - At umount, the FS state should be saved into disk for consistency. - At remount, the FS state in super block may be updated. Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> --- fs/btrfs/disk-io.c | 23 +++++++++++++++++++++++ fs/btrfs/super.c | 12 +++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fb827d0..15ff468 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -43,6 +43,8 @@ static struct extent_io_ops btree_extent_io_ops; static void end_workqueue_fn(struct btrfs_work *work); static void free_fs_root(struct btrfs_root *root); +static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, + int read_only); /* * end_io_wq structs are used to do processing in task context when an IO is @@ -1700,6 +1702,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, if (!btrfs_super_root(disk_super)) goto fail_iput; + /* check filesystem state */ + fs_info->fs_state |= btrfs_super_flags(disk_super); + + btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); + ret = btrfs_parse_options(tree_root, options); if (ret) { err = ret; @@ -2409,6 +2416,7 @@ int btrfs_commit_super(struct btrfs_root *root) int close_ctree(struct btrfs_root *root) { struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_super_block *sb = &fs_info->super_for_commit; int ret; fs_info->closing = 1; @@ -2416,6 +2424,7 @@ int close_ctree(struct btrfs_root *root) btrfs_put_block_group_cache(fs_info); if (!(fs_info->sb->s_flags & MS_RDONLY)) { + sb->flags |= cpu_to_le64(fs_info->fs_state); ret = btrfs_commit_super(root); if (ret) printk(KERN_ERR "btrfs: commit super ret %d\n", ret); @@ -2592,6 +2601,20 @@ out: return 0; } +static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, + int read_only) +{ + if (read_only) + return; + + if (!(fs_info->fs_state & BTRFS_SUPER_FLAG_VALID)) + printk(KERN_WARNING "warning: mount unchecked fs, " + "running btfsck is recommended\n"); + else if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) + printk(KERN_WARNING "warning: mount fs with errors, " + "running btfsck is recommended\n"); +} + static struct extent_io_ops btree_extent_io_ops = { .write_cache_pages_lock_hook = btree_lock_page_hook, .readpage_end_io_hook = btree_readpage_end_io_hook, diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 48fac6e..40130e8 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -771,6 +771,8 @@ error_free_subvol_name: static int btrfs_remount(struct super_block *sb, int *flags, char *data) { struct btrfs_root *root = btrfs_sb(sb); + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_super_block *disk_super = &fs_info->super_copy; int ret; ret = btrfs_parse_options(root, data); @@ -782,17 +784,21 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) if (*flags & MS_RDONLY) { sb->s_flags |= MS_RDONLY; + if (!(disk_super->flags & + cpu_to_le64(BTRFS_SUPER_FLAG_VALID)) && + (fs_info->fs_state & BTRFS_SUPER_FLAG_VALID)) + disk_super->flags |= cpu_to_le64(fs_info->fs_state); ret = btrfs_commit_super(root); WARN_ON(ret); } else { - if (root->fs_info->fs_devices->rw_devices == 0) + if (fs_info->fs_devices->rw_devices == 0) return -EACCES; - if (btrfs_super_log_root(&root->fs_info->super_copy) != 0) + if (btrfs_super_log_root(disk_super) != 0) return -EINVAL; - ret = btrfs_cleanup_fs_roots(root->fs_info); + ret = btrfs_cleanup_fs_roots(fs_info); WARN_ON(ret); /* recover relocation */ -- 1.7.0.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html