aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-01-29 05:14:48 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:09 -0500
commit87533c475187c1420794a2e164bc67a7974f1327 (patch)
tree699709da85c0a6c284cf37fe7026fbaf4768e6ab /fs
parentde98ced9e743656d108de41841797def0f5cb951 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/btrfs/scrub.c2
-rw-r--r--fs/btrfs/super.c4
-rw-r--r--fs/btrfs/transaction.c9
6 files changed, 14 insertions, 12 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 5f5c30aaef36..78fba44ad3d9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -338,7 +338,9 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
338/* 338/*
339 * File system states 339 * File system states
340 */ 340 */
341#define BTRFS_FS_STATE_ERROR 0
341 342
343/* Super block flags */
342/* Errors detected */ 344/* Errors detected */
343#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2) 345#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2)
344 346
@@ -1549,7 +1551,7 @@ struct btrfs_fs_info {
1549 u64 qgroup_seq; 1551 u64 qgroup_seq;
1550 1552
1551 /* filesystem state */ 1553 /* filesystem state */
1552 u64 fs_state; 1554 unsigned long fs_state;
1553 1555
1554 struct btrfs_delayed_root *delayed_root; 1556 struct btrfs_delayed_root *delayed_root;
1555 1557
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 00b6742fdde7..8e58a1f90546 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2201,7 +2201,8 @@ int open_ctree(struct super_block *sb,
2201 goto fail_alloc; 2201 goto fail_alloc;
2202 2202
2203 /* check FS state, whether FS is broken. */ 2203 /* check FS state, whether FS is broken. */
2204 fs_info->fs_state |= btrfs_super_flags(disk_super); 2204 if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
2205 set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
2205 2206
2206 ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); 2207 ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY);
2207 if (ret) { 2208 if (ret) {
@@ -3359,7 +3360,7 @@ int close_ctree(struct btrfs_root *root)
3359 printk(KERN_ERR "btrfs: commit super ret %d\n", ret); 3360 printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
3360 } 3361 }
3361 3362
3362 if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) 3363 if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
3363 btrfs_error_commit_super(root); 3364 btrfs_error_commit_super(root);
3364 3365
3365 btrfs_put_block_group_cache(fs_info); 3366 btrfs_put_block_group_cache(fs_info);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 13c78ea3ebce..75d0fe134be3 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1545,7 +1545,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1545 * although we have opened a file as writable, we have 1545 * although we have opened a file as writable, we have
1546 * to stop this write operation to ensure FS consistency. 1546 * to stop this write operation to ensure FS consistency.
1547 */ 1547 */
1548 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 1548 if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) {
1549 mutex_unlock(&inode->i_mutex); 1549 mutex_unlock(&inode->i_mutex);
1550 err = -EROFS; 1550 err = -EROFS;
1551 goto out; 1551 goto out;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 67783e03d121..c78b2a3fc335 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2708,7 +2708,7 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
2708 int ret; 2708 int ret;
2709 struct btrfs_root *root = sctx->dev_root; 2709 struct btrfs_root *root = sctx->dev_root;
2710 2710
2711 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) 2711 if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
2712 return -EIO; 2712 return -EIO;
2713 2713
2714 gen = root->fs_info->last_trans_committed; 2714 gen = root->fs_info->last_trans_committed;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index eda330df45a4..4152f9ea34f5 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -98,7 +98,7 @@ static void __save_error_info(struct btrfs_fs_info *fs_info)
98 * today we only save the error info into ram. Long term we'll 98 * today we only save the error info into ram. Long term we'll
99 * also send it down to the disk 99 * also send it down to the disk
100 */ 100 */
101 fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR; 101 set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
102} 102}
103 103
104static void save_error_info(struct btrfs_fs_info *fs_info) 104static 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)
114 if (sb->s_flags & MS_RDONLY) 114 if (sb->s_flags & MS_RDONLY)
115 return; 115 return;
116 116
117 if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 117 if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
118 sb->s_flags |= MS_RDONLY; 118 sb->s_flags |= MS_RDONLY;
119 printk(KERN_INFO "btrfs is forced readonly\n"); 119 printk(KERN_INFO "btrfs is forced readonly\n");
120 /* 120 /*
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 34610dc6d140..baf6d74fd0f2 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -61,7 +61,7 @@ static noinline int join_transaction(struct btrfs_root *root, int type)
61 spin_lock(&fs_info->trans_lock); 61 spin_lock(&fs_info->trans_lock);
62loop: 62loop:
63 /* The file system has been taken offline. No new transactions. */ 63 /* The file system has been taken offline. No new transactions. */
64 if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 64 if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
65 spin_unlock(&fs_info->trans_lock); 65 spin_unlock(&fs_info->trans_lock);
66 return -EROFS; 66 return -EROFS;
67 } 67 }
@@ -113,7 +113,7 @@ loop:
113 kmem_cache_free(btrfs_transaction_cachep, cur_trans); 113 kmem_cache_free(btrfs_transaction_cachep, cur_trans);
114 cur_trans = fs_info->running_transaction; 114 cur_trans = fs_info->running_transaction;
115 goto loop; 115 goto loop;
116 } else if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 116 } else if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
117 spin_unlock(&fs_info->trans_lock); 117 spin_unlock(&fs_info->trans_lock);
118 kmem_cache_free(btrfs_transaction_cachep, cur_trans); 118 kmem_cache_free(btrfs_transaction_cachep, cur_trans);
119 return -EROFS; 119 return -EROFS;
@@ -301,7 +301,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
301 int ret; 301 int ret;
302 u64 qgroup_reserved = 0; 302 u64 qgroup_reserved = 0;
303 303
304 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) 304 if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
305 return ERR_PTR(-EROFS); 305 return ERR_PTR(-EROFS);
306 306
307 if (current->journal_info) { 307 if (current->journal_info) {
@@ -645,9 +645,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
645 btrfs_run_delayed_iputs(root); 645 btrfs_run_delayed_iputs(root);
646 646
647 if (trans->aborted || 647 if (trans->aborted ||
648 root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 648 test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
649 err = -EIO; 649 err = -EIO;
650 }
651 assert_qgroups_uptodate(trans); 650 assert_qgroups_uptodate(trans);
652 651
653 kmem_cache_free(btrfs_trans_handle_cachep, trans); 652 kmem_cache_free(btrfs_trans_handle_cachep, trans);