@@ -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,
@@ -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 */