aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.h
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-04-11 06:30:16 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:46 -0400
commitceda08642459e31673d24d7968d864390d2ce5fa (patch)
tree57d1a9be32a9a2653011b5fedf6615731af48b7f /fs/btrfs/ctree.h
parentf42a34b2f10c411ef45f247f3000ed03ba4e80c0 (diff)
Btrfs: use a lock to protect incompat/compat flag of the super block
The following case will make the incompat/compat flag of the super block be recovered. Task1 |Task2 flags = btrfs_super_incompat_flags(); | |flags = btrfs_super_incompat_flags(); flags |= new_flag1; | |flags |= new_flag2; btrfs_set_super_incompat_flags(flags); | |btrfs_set_super_incompat_flags(flags); the new_flag1 is recovered. In order to avoid this problem, we introduce a lock named super_lock into the btrfs_fs_info structure. If we want to update incompat/compat flags of the super block, we must hold it. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/ctree.h')
-rw-r--r--fs/btrfs/ctree.h22
1 files changed, 20 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 1a850402937d..c3b15f8dca00 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1362,6 +1362,17 @@ struct btrfs_fs_info {
1362 wait_queue_head_t transaction_blocked_wait; 1362 wait_queue_head_t transaction_blocked_wait;
1363 wait_queue_head_t async_submit_wait; 1363 wait_queue_head_t async_submit_wait;
1364 1364
1365 /*
1366 * Used to protect the incompat_flags, compat_flags, compat_ro_flags
1367 * when they are updated.
1368 *
1369 * Because we do not clear the flags for ever, so we needn't use
1370 * the lock on the read side.
1371 *
1372 * We also needn't use the lock when we mount the fs, because
1373 * there is no other task which will update the flag.
1374 */
1375 spinlock_t super_lock;
1365 struct btrfs_super_block *super_copy; 1376 struct btrfs_super_block *super_copy;
1366 struct btrfs_super_block *super_for_commit; 1377 struct btrfs_super_block *super_for_commit;
1367 struct block_device *__bdev; 1378 struct block_device *__bdev;
@@ -3688,8 +3699,15 @@ static inline void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info,
3688 disk_super = fs_info->super_copy; 3699 disk_super = fs_info->super_copy;
3689 features = btrfs_super_incompat_flags(disk_super); 3700 features = btrfs_super_incompat_flags(disk_super);
3690 if (!(features & flag)) { 3701 if (!(features & flag)) {
3691 features |= flag; 3702 spin_lock(&fs_info->super_lock);
3692 btrfs_set_super_incompat_flags(disk_super, features); 3703 features = btrfs_super_incompat_flags(disk_super);
3704 if (!(features & flag)) {
3705 features |= flag;
3706 btrfs_set_super_incompat_flags(disk_super, features);
3707 printk(KERN_INFO "btrfs: setting %llu feature flag\n",
3708 flag);
3709 }
3710 spin_unlock(&fs_info->super_lock);
3693 } 3711 }
3694} 3712}
3695 3713