aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.h
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-06-13 20:00:16 -0400
committerChris Mason <chris.mason@oracle.com>2011-06-17 13:36:58 -0400
commit7585717f304f5ed005cc4ad933a69aab3efbd136 (patch)
tree2bbef7f61c61b125778d3631237094594b408e0a /fs/btrfs/ctree.h
parentf4c44016218a6fce357715b9bbabbbbe1f69853c (diff)
downloadkernel_samsung_smdk4412-7585717f304f5ed005cc4ad933a69aab3efbd136.zip
kernel_samsung_smdk4412-7585717f304f5ed005cc4ad933a69aab3efbd136.tar.gz
kernel_samsung_smdk4412-7585717f304f5ed005cc4ad933a69aab3efbd136.tar.bz2
Btrfs: fix relocation races
The recent commit to get rid of our trans_mutex introduced some races with block group relocation. The problem is that relocation needs to do some record keeping about each root, and it was relying on the transaction mutex to coordinate things in subtle ways. This fix adds a mutex just for the relocation code and makes sure it doesn't have a big impact on normal operations. The race is really fixed in btrfs_record_root_in_trans, which is where we step back and wait for the relocation code to finish accounting setup. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.h')
-rw-r--r--fs/btrfs/ctree.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 8490ee0..a2c91a1 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -967,6 +967,12 @@ struct btrfs_fs_info {
struct srcu_struct subvol_srcu;
spinlock_t trans_lock;
+ /*
+ * the reloc mutex goes with the trans lock, it is taken
+ * during commit to protect us from the relocation code
+ */
+ struct mutex reloc_mutex;
+
struct list_head trans_list;
struct list_head hashers;
struct list_head dead_roots;
@@ -1172,6 +1178,14 @@ struct btrfs_root {
u32 type;
u64 highest_objectid;
+
+ /* btrfs_record_root_in_trans is a multi-step process,
+ * and it can race with the balancing code. But the
+ * race is very small, and only the first time the root
+ * is added to each transaction. So in_trans_setup
+ * is used to tell us when more checks are required
+ */
+ unsigned long in_trans_setup;
int ref_cows;
int track_dirty;
int in_radix;