Btrfs: use bit operation for ->fs_state
There is no lock to protect fs_info->fs_state, it will introduce some problems, such as the value may be covered by the other task when several tasks modify it. For example: Task0 - CPU0 Task1 - CPU1 mov %fs_state rax or $0x1 rax mov %fs_state rax or $0x2 rax mov rax %fs_state mov rax %fs_state The expected value is 3, but in fact, it is 2. Though this problem doesn't happen now (because there is only one flag currently), the code is error prone, if we add other flags, the above problem will happen to a certainty. Now we use bit operation for it to fix the above problem. In this way, we can make the code more robust and be easy to add new flags. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
parent
de98ced9e7
commit
87533c4751
|
@ -338,7 +338,9 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
|
||||||
/*
|
/*
|
||||||
* File system states
|
* File system states
|
||||||
*/
|
*/
|
||||||
|
#define BTRFS_FS_STATE_ERROR 0
|
||||||
|
|
||||||
|
/* Super block flags */
|
||||||
/* Errors detected */
|
/* Errors detected */
|
||||||
#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2)
|
#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2)
|
||||||
|
|
||||||
|
@ -1549,7 +1551,7 @@ struct btrfs_fs_info {
|
||||||
u64 qgroup_seq;
|
u64 qgroup_seq;
|
||||||
|
|
||||||
/* filesystem state */
|
/* filesystem state */
|
||||||
u64 fs_state;
|
unsigned long fs_state;
|
||||||
|
|
||||||
struct btrfs_delayed_root *delayed_root;
|
struct btrfs_delayed_root *delayed_root;
|
||||||
|
|
||||||
|
|
|
@ -2201,7 +2201,8 @@ int open_ctree(struct super_block *sb,
|
||||||
goto fail_alloc;
|
goto fail_alloc;
|
||||||
|
|
||||||
/* check FS state, whether FS is broken. */
|
/* check FS state, whether FS is broken. */
|
||||||
fs_info->fs_state |= btrfs_super_flags(disk_super);
|
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
|
||||||
|
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
|
||||||
|
|
||||||
ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY);
|
ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -3359,7 +3360,7 @@ int close_ctree(struct btrfs_root *root)
|
||||||
printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
|
printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
|
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
|
||||||
btrfs_error_commit_super(root);
|
btrfs_error_commit_super(root);
|
||||||
|
|
||||||
btrfs_put_block_group_cache(fs_info);
|
btrfs_put_block_group_cache(fs_info);
|
||||||
|
|
|
@ -1545,7 +1545,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||||
* although we have opened a file as writable, we have
|
* although we have opened a file as writable, we have
|
||||||
* to stop this write operation to ensure FS consistency.
|
* to stop this write operation to ensure FS consistency.
|
||||||
*/
|
*/
|
||||||
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) {
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -2708,7 +2708,7 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_root *root = sctx->dev_root;
|
struct btrfs_root *root = sctx->dev_root;
|
||||||
|
|
||||||
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
|
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
gen = root->fs_info->last_trans_committed;
|
gen = root->fs_info->last_trans_committed;
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void __save_error_info(struct btrfs_fs_info *fs_info)
|
||||||
* today we only save the error info into ram. Long term we'll
|
* today we only save the error info into ram. Long term we'll
|
||||||
* also send it down to the disk
|
* also send it down to the disk
|
||||||
*/
|
*/
|
||||||
fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR;
|
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_error_info(struct btrfs_fs_info *fs_info)
|
static void save_error_info(struct btrfs_fs_info *fs_info)
|
||||||
|
@ -114,7 +114,7 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
|
||||||
if (sb->s_flags & MS_RDONLY)
|
if (sb->s_flags & MS_RDONLY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
|
||||||
sb->s_flags |= MS_RDONLY;
|
sb->s_flags |= MS_RDONLY;
|
||||||
printk(KERN_INFO "btrfs is forced readonly\n");
|
printk(KERN_INFO "btrfs is forced readonly\n");
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -61,7 +61,7 @@ static noinline int join_transaction(struct btrfs_root *root, int type)
|
||||||
spin_lock(&fs_info->trans_lock);
|
spin_lock(&fs_info->trans_lock);
|
||||||
loop:
|
loop:
|
||||||
/* The file system has been taken offline. No new transactions. */
|
/* The file system has been taken offline. No new transactions. */
|
||||||
if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
|
||||||
spin_unlock(&fs_info->trans_lock);
|
spin_unlock(&fs_info->trans_lock);
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ loop:
|
||||||
kmem_cache_free(btrfs_transaction_cachep, cur_trans);
|
kmem_cache_free(btrfs_transaction_cachep, cur_trans);
|
||||||
cur_trans = fs_info->running_transaction;
|
cur_trans = fs_info->running_transaction;
|
||||||
goto loop;
|
goto loop;
|
||||||
} else if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
} else if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
|
||||||
spin_unlock(&fs_info->trans_lock);
|
spin_unlock(&fs_info->trans_lock);
|
||||||
kmem_cache_free(btrfs_transaction_cachep, cur_trans);
|
kmem_cache_free(btrfs_transaction_cachep, cur_trans);
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
@ -301,7 +301,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
|
||||||
int ret;
|
int ret;
|
||||||
u64 qgroup_reserved = 0;
|
u64 qgroup_reserved = 0;
|
||||||
|
|
||||||
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
|
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
|
||||||
return ERR_PTR(-EROFS);
|
return ERR_PTR(-EROFS);
|
||||||
|
|
||||||
if (current->journal_info) {
|
if (current->journal_info) {
|
||||||
|
@ -645,9 +645,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||||
btrfs_run_delayed_iputs(root);
|
btrfs_run_delayed_iputs(root);
|
||||||
|
|
||||||
if (trans->aborted ||
|
if (trans->aborted ||
|
||||||
root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
}
|
|
||||||
assert_qgroups_uptodate(trans);
|
assert_qgroups_uptodate(trans);
|
||||||
|
|
||||||
kmem_cache_free(btrfs_trans_handle_cachep, trans);
|
kmem_cache_free(btrfs_trans_handle_cachep, trans);
|
||||||
|
|
Loading…
Reference in New Issue