aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
authorWang Shilong <wangsl.fnst@cn.fujitsu.com>2014-02-08 10:46:36 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:16:35 -0400
commitdcfd5ad2fc3337a959873e9d20ca33ad9809aa90 (patch)
tree9081f9b4d8e21eddf05c7d1bd5f1c121bb99a509 /fs/btrfs/send.c
parentbcbba5e6593281adc234938b42d3c3d3570335db (diff)
Revert "Btrfs: remove transaction from btrfs send"
This reverts commit 41ce9970a8a6a362ae8df145f7a03d789e9ef9d2. Previously i was thinking we can use readonly root's commit root safely while it is not true, readonly root may be cowed with the following cases. 1.snapshot send root will cow source root. 2.balance,device operations will also cow readonly send root to relocate. So i have two ideas to make us safe to use commit root. -->approach 1: make it protected by transaction and end transaction properly and we research next item from root node(see btrfs_search_slot_for_read()). -->approach 2: add another counter to local root structure to sync snapshot with send. and add a global counter to sync send with exclusive device operations. So with approach 2, send can use commit root safely, because we make sure send root can not be cowed during send. Unfortunately, it make codes *ugly* and more complex to maintain. To make snapshot and send exclusively, device operations and send operation exclusively with each other is a little confusing for common users. So why not drop into previous way. Cc: Josef Bacik <jbacik@fb.com> Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index a5da82f49120..3ddd2bb75083 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -5104,6 +5104,7 @@ out:
5104static int full_send_tree(struct send_ctx *sctx) 5104static int full_send_tree(struct send_ctx *sctx)
5105{ 5105{
5106 int ret; 5106 int ret;
5107 struct btrfs_trans_handle *trans = NULL;
5107 struct btrfs_root *send_root = sctx->send_root; 5108 struct btrfs_root *send_root = sctx->send_root;
5108 struct btrfs_key key; 5109 struct btrfs_key key;
5109 struct btrfs_key found_key; 5110 struct btrfs_key found_key;
@@ -5125,6 +5126,19 @@ static int full_send_tree(struct send_ctx *sctx)
5125 key.type = BTRFS_INODE_ITEM_KEY; 5126 key.type = BTRFS_INODE_ITEM_KEY;
5126 key.offset = 0; 5127 key.offset = 0;
5127 5128
5129join_trans:
5130 /*
5131 * We need to make sure the transaction does not get committed
5132 * while we do anything on commit roots. Join a transaction to prevent
5133 * this.
5134 */
5135 trans = btrfs_join_transaction(send_root);
5136 if (IS_ERR(trans)) {
5137 ret = PTR_ERR(trans);
5138 trans = NULL;
5139 goto out;
5140 }
5141
5128 /* 5142 /*
5129 * Make sure the tree has not changed after re-joining. We detect this 5143 * Make sure the tree has not changed after re-joining. We detect this
5130 * by comparing start_ctransid and ctransid. They should always match. 5144 * by comparing start_ctransid and ctransid. They should always match.
@@ -5148,6 +5162,19 @@ static int full_send_tree(struct send_ctx *sctx)
5148 goto out_finish; 5162 goto out_finish;
5149 5163
5150 while (1) { 5164 while (1) {
5165 /*
5166 * When someone want to commit while we iterate, end the
5167 * joined transaction and rejoin.
5168 */
5169 if (btrfs_should_end_transaction(trans, send_root)) {
5170 ret = btrfs_end_transaction(trans, send_root);
5171 trans = NULL;
5172 if (ret < 0)
5173 goto out;
5174 btrfs_release_path(path);
5175 goto join_trans;
5176 }
5177
5151 eb = path->nodes[0]; 5178 eb = path->nodes[0];
5152 slot = path->slots[0]; 5179 slot = path->slots[0];
5153 btrfs_item_key_to_cpu(eb, &found_key, slot); 5180 btrfs_item_key_to_cpu(eb, &found_key, slot);
@@ -5175,6 +5202,12 @@ out_finish:
5175 5202
5176out: 5203out:
5177 btrfs_free_path(path); 5204 btrfs_free_path(path);
5205 if (trans) {
5206 if (!ret)
5207 ret = btrfs_end_transaction(trans, send_root);
5208 else
5209 btrfs_end_transaction(trans, send_root);
5210 }
5178 return ret; 5211 return ret;
5179} 5212}
5180 5213