aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-07-30 09:26:11 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commitf321e4910398cf7922265d269fb17fd26f312571 (patch)
tree8430f004991351e48a4b3f9441fe0cbbcf70eddb /fs/btrfs/transaction.c
parent3bf10418675cb424724b5cb9d7725b234defe1fd (diff)
Btrfs: Update and fix mount -o nodatacow
To check whether a given file extent is referenced by multiple snapshots, the checker walks down the fs tree through dead root and checks all tree blocks in the path. We can easily detect whether a given tree block is directly referenced by other snapshot. We can also detect any indirect reference from other snapshot by checking reference's generation. The checker can always detect multiple references, but can't reliably detect cases of single reference. So btrfs may do file data cow even there is only one reference. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b8be6703189a..216f31571620 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -32,12 +32,6 @@ extern struct kmem_cache *btrfs_transaction_cachep;
32 32
33#define BTRFS_ROOT_TRANS_TAG 0 33#define BTRFS_ROOT_TRANS_TAG 0
34 34
35struct dirty_root {
36 struct list_head list;
37 struct btrfs_root *root;
38 struct btrfs_root *latest_root;
39};
40
41static noinline void put_transaction(struct btrfs_transaction *transaction) 35static noinline void put_transaction(struct btrfs_transaction *transaction)
42{ 36{
43 WARN_ON(transaction->use_count == 0); 37 WARN_ON(transaction->use_count == 0);
@@ -91,7 +85,7 @@ static noinline int join_transaction(struct btrfs_root *root)
91 85
92static noinline int record_root_in_trans(struct btrfs_root *root) 86static noinline int record_root_in_trans(struct btrfs_root *root)
93{ 87{
94 struct dirty_root *dirty; 88 struct btrfs_dirty_root *dirty;
95 u64 running_trans_id = root->fs_info->running_transaction->transid; 89 u64 running_trans_id = root->fs_info->running_transaction->transid;
96 if (root->ref_cows && root->last_trans < running_trans_id) { 90 if (root->ref_cows && root->last_trans < running_trans_id) {
97 WARN_ON(root == root->fs_info->extent_root); 91 WARN_ON(root == root->fs_info->extent_root);
@@ -372,7 +366,7 @@ int btrfs_add_dead_root(struct btrfs_root *root,
372 struct btrfs_root *latest, 366 struct btrfs_root *latest,
373 struct list_head *dead_list) 367 struct list_head *dead_list)
374{ 368{
375 struct dirty_root *dirty; 369 struct btrfs_dirty_root *dirty;
376 370
377 dirty = kmalloc(sizeof(*dirty), GFP_NOFS); 371 dirty = kmalloc(sizeof(*dirty), GFP_NOFS);
378 if (!dirty) 372 if (!dirty)
@@ -387,7 +381,7 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
387 struct radix_tree_root *radix, 381 struct radix_tree_root *radix,
388 struct list_head *list) 382 struct list_head *list)
389{ 383{
390 struct dirty_root *dirty; 384 struct btrfs_dirty_root *dirty;
391 struct btrfs_root *gang[8]; 385 struct btrfs_root *gang[8];
392 struct btrfs_root *root; 386 struct btrfs_root *root;
393 int i; 387 int i;
@@ -498,7 +492,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
498static noinline int drop_dirty_roots(struct btrfs_root *tree_root, 492static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
499 struct list_head *list) 493 struct list_head *list)
500{ 494{
501 struct dirty_root *dirty; 495 struct btrfs_dirty_root *dirty;
502 struct btrfs_trans_handle *trans; 496 struct btrfs_trans_handle *trans;
503 unsigned long nr; 497 unsigned long nr;
504 u64 num_bytes; 498 u64 num_bytes;
@@ -509,7 +503,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
509 while(!list_empty(list)) { 503 while(!list_empty(list)) {
510 struct btrfs_root *root; 504 struct btrfs_root *root;
511 505
512 dirty = list_entry(list->prev, struct dirty_root, list); 506 dirty = list_entry(list->prev, struct btrfs_dirty_root, list);
513 list_del_init(&dirty->list); 507 list_del_init(&dirty->list);
514 508
515 num_bytes = btrfs_root_used(&dirty->root->root_item); 509 num_bytes = btrfs_root_used(&dirty->root->root_item);