diff options
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 57 |
1 files changed, 2 insertions, 55 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index d00534b78382..6b5f13659317 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1268,8 +1268,10 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
1268 | } | 1268 | } |
1269 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); | 1269 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); |
1270 | 1270 | ||
1271 | down_read(&sctx->send_root->fs_info->commit_root_sem); | ||
1271 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, | 1272 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, |
1272 | &found_key, &flags); | 1273 | &found_key, &flags); |
1274 | up_read(&sctx->send_root->fs_info->commit_root_sem); | ||
1273 | btrfs_release_path(tmp_path); | 1275 | btrfs_release_path(tmp_path); |
1274 | 1276 | ||
1275 | if (ret < 0) | 1277 | if (ret < 0) |
@@ -5367,57 +5369,21 @@ out: | |||
5367 | static int full_send_tree(struct send_ctx *sctx) | 5369 | static int full_send_tree(struct send_ctx *sctx) |
5368 | { | 5370 | { |
5369 | int ret; | 5371 | int ret; |
5370 | struct btrfs_trans_handle *trans = NULL; | ||
5371 | struct btrfs_root *send_root = sctx->send_root; | 5372 | struct btrfs_root *send_root = sctx->send_root; |
5372 | struct btrfs_key key; | 5373 | struct btrfs_key key; |
5373 | struct btrfs_key found_key; | 5374 | struct btrfs_key found_key; |
5374 | struct btrfs_path *path; | 5375 | struct btrfs_path *path; |
5375 | struct extent_buffer *eb; | 5376 | struct extent_buffer *eb; |
5376 | int slot; | 5377 | int slot; |
5377 | u64 start_ctransid; | ||
5378 | u64 ctransid; | ||
5379 | 5378 | ||
5380 | path = alloc_path_for_send(); | 5379 | path = alloc_path_for_send(); |
5381 | if (!path) | 5380 | if (!path) |
5382 | return -ENOMEM; | 5381 | return -ENOMEM; |
5383 | 5382 | ||
5384 | spin_lock(&send_root->root_item_lock); | ||
5385 | start_ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
5386 | spin_unlock(&send_root->root_item_lock); | ||
5387 | |||
5388 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | 5383 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
5389 | key.type = BTRFS_INODE_ITEM_KEY; | 5384 | key.type = BTRFS_INODE_ITEM_KEY; |
5390 | key.offset = 0; | 5385 | key.offset = 0; |
5391 | 5386 | ||
5392 | join_trans: | ||
5393 | /* | ||
5394 | * We need to make sure the transaction does not get committed | ||
5395 | * while we do anything on commit roots. Join a transaction to prevent | ||
5396 | * this. | ||
5397 | */ | ||
5398 | trans = btrfs_join_transaction(send_root); | ||
5399 | if (IS_ERR(trans)) { | ||
5400 | ret = PTR_ERR(trans); | ||
5401 | trans = NULL; | ||
5402 | goto out; | ||
5403 | } | ||
5404 | |||
5405 | /* | ||
5406 | * Make sure the tree has not changed after re-joining. We detect this | ||
5407 | * by comparing start_ctransid and ctransid. They should always match. | ||
5408 | */ | ||
5409 | spin_lock(&send_root->root_item_lock); | ||
5410 | ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
5411 | spin_unlock(&send_root->root_item_lock); | ||
5412 | |||
5413 | if (ctransid != start_ctransid) { | ||
5414 | WARN(1, KERN_WARNING "BTRFS: the root that you're trying to " | ||
5415 | "send was modified in between. This is " | ||
5416 | "probably a bug.\n"); | ||
5417 | ret = -EIO; | ||
5418 | goto out; | ||
5419 | } | ||
5420 | |||
5421 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); | 5387 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); |
5422 | if (ret < 0) | 5388 | if (ret < 0) |
5423 | goto out; | 5389 | goto out; |
@@ -5425,19 +5391,6 @@ join_trans: | |||
5425 | goto out_finish; | 5391 | goto out_finish; |
5426 | 5392 | ||
5427 | while (1) { | 5393 | while (1) { |
5428 | /* | ||
5429 | * When someone want to commit while we iterate, end the | ||
5430 | * joined transaction and rejoin. | ||
5431 | */ | ||
5432 | if (btrfs_should_end_transaction(trans, send_root)) { | ||
5433 | ret = btrfs_end_transaction(trans, send_root); | ||
5434 | trans = NULL; | ||
5435 | if (ret < 0) | ||
5436 | goto out; | ||
5437 | btrfs_release_path(path); | ||
5438 | goto join_trans; | ||
5439 | } | ||
5440 | |||
5441 | eb = path->nodes[0]; | 5394 | eb = path->nodes[0]; |
5442 | slot = path->slots[0]; | 5395 | slot = path->slots[0]; |
5443 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 5396 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
@@ -5465,12 +5418,6 @@ out_finish: | |||
5465 | 5418 | ||
5466 | out: | 5419 | out: |
5467 | btrfs_free_path(path); | 5420 | btrfs_free_path(path); |
5468 | if (trans) { | ||
5469 | if (!ret) | ||
5470 | ret = btrfs_end_transaction(trans, send_root); | ||
5471 | else | ||
5472 | btrfs_end_transaction(trans, send_root); | ||
5473 | } | ||
5474 | return ret; | 5421 | return ret; |
5475 | } | 5422 | } |
5476 | 5423 | ||