aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c117
1 files changed, 42 insertions, 75 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 9b6da9d55f9a..1ac3ca98c429 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -493,6 +493,7 @@ static struct btrfs_path *alloc_path_for_send(void)
493 return NULL; 493 return NULL;
494 path->search_commit_root = 1; 494 path->search_commit_root = 1;
495 path->skip_locking = 1; 495 path->skip_locking = 1;
496 path->need_commit_sem = 1;
496 return path; 497 return path;
497} 498}
498 499
@@ -771,29 +772,22 @@ out:
771/* 772/*
772 * Helper function to retrieve some fields from an inode item. 773 * Helper function to retrieve some fields from an inode item.
773 */ 774 */
774static int get_inode_info(struct btrfs_root *root, 775static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path,
775 u64 ino, u64 *size, u64 *gen, 776 u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid,
776 u64 *mode, u64 *uid, u64 *gid, 777 u64 *gid, u64 *rdev)
777 u64 *rdev)
778{ 778{
779 int ret; 779 int ret;
780 struct btrfs_inode_item *ii; 780 struct btrfs_inode_item *ii;
781 struct btrfs_key key; 781 struct btrfs_key key;
782 struct btrfs_path *path;
783
784 path = alloc_path_for_send();
785 if (!path)
786 return -ENOMEM;
787 782
788 key.objectid = ino; 783 key.objectid = ino;
789 key.type = BTRFS_INODE_ITEM_KEY; 784 key.type = BTRFS_INODE_ITEM_KEY;
790 key.offset = 0; 785 key.offset = 0;
791 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 786 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
792 if (ret < 0)
793 goto out;
794 if (ret) { 787 if (ret) {
795 ret = -ENOENT; 788 if (ret > 0)
796 goto out; 789 ret = -ENOENT;
790 return ret;
797 } 791 }
798 792
799 ii = btrfs_item_ptr(path->nodes[0], path->slots[0], 793 ii = btrfs_item_ptr(path->nodes[0], path->slots[0],
@@ -811,7 +805,22 @@ static int get_inode_info(struct btrfs_root *root,
811 if (rdev) 805 if (rdev)
812 *rdev = btrfs_inode_rdev(path->nodes[0], ii); 806 *rdev = btrfs_inode_rdev(path->nodes[0], ii);
813 807
814out: 808 return ret;
809}
810
811static int get_inode_info(struct btrfs_root *root,
812 u64 ino, u64 *size, u64 *gen,
813 u64 *mode, u64 *uid, u64 *gid,
814 u64 *rdev)
815{
816 struct btrfs_path *path;
817 int ret;
818
819 path = alloc_path_for_send();
820 if (!path)
821 return -ENOMEM;
822 ret = __get_inode_info(root, path, ino, size, gen, mode, uid, gid,
823 rdev);
815 btrfs_free_path(path); 824 btrfs_free_path(path);
816 return ret; 825 return ret;
817} 826}
@@ -1085,6 +1094,7 @@ out:
1085struct backref_ctx { 1094struct backref_ctx {
1086 struct send_ctx *sctx; 1095 struct send_ctx *sctx;
1087 1096
1097 struct btrfs_path *path;
1088 /* number of total found references */ 1098 /* number of total found references */
1089 u64 found; 1099 u64 found;
1090 1100
@@ -1155,8 +1165,9 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
1155 * There are inodes that have extents that lie behind its i_size. Don't 1165 * There are inodes that have extents that lie behind its i_size. Don't
1156 * accept clones from these extents. 1166 * accept clones from these extents.
1157 */ 1167 */
1158 ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL, 1168 ret = __get_inode_info(found->root, bctx->path, ino, &i_size, NULL, NULL,
1159 NULL); 1169 NULL, NULL, NULL);
1170 btrfs_release_path(bctx->path);
1160 if (ret < 0) 1171 if (ret < 0)
1161 return ret; 1172 return ret;
1162 1173
@@ -1235,12 +1246,17 @@ static int find_extent_clone(struct send_ctx *sctx,
1235 if (!tmp_path) 1246 if (!tmp_path)
1236 return -ENOMEM; 1247 return -ENOMEM;
1237 1248
1249 /* We only use this path under the commit sem */
1250 tmp_path->need_commit_sem = 0;
1251
1238 backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS); 1252 backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS);
1239 if (!backref_ctx) { 1253 if (!backref_ctx) {
1240 ret = -ENOMEM; 1254 ret = -ENOMEM;
1241 goto out; 1255 goto out;
1242 } 1256 }
1243 1257
1258 backref_ctx->path = tmp_path;
1259
1244 if (data_offset >= ino_size) { 1260 if (data_offset >= ino_size) {
1245 /* 1261 /*
1246 * There may be extents that lie behind the file's size. 1262 * There may be extents that lie behind the file's size.
@@ -1268,8 +1284,10 @@ static int find_extent_clone(struct send_ctx *sctx,
1268 } 1284 }
1269 logical = disk_byte + btrfs_file_extent_offset(eb, fi); 1285 logical = disk_byte + btrfs_file_extent_offset(eb, fi);
1270 1286
1287 down_read(&sctx->send_root->fs_info->commit_root_sem);
1271 ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, 1288 ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path,
1272 &found_key, &flags); 1289 &found_key, &flags);
1290 up_read(&sctx->send_root->fs_info->commit_root_sem);
1273 btrfs_release_path(tmp_path); 1291 btrfs_release_path(tmp_path);
1274 1292
1275 if (ret < 0) 1293 if (ret < 0)
@@ -4418,6 +4436,9 @@ static int send_hole(struct send_ctx *sctx, u64 end)
4418 p = fs_path_alloc(); 4436 p = fs_path_alloc();
4419 if (!p) 4437 if (!p)
4420 return -ENOMEM; 4438 return -ENOMEM;
4439 ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p);
4440 if (ret < 0)
4441 goto tlv_put_failure;
4421 memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE); 4442 memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE);
4422 while (offset < end) { 4443 while (offset < end) {
4423 len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE); 4444 len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE);
@@ -4425,9 +4446,6 @@ static int send_hole(struct send_ctx *sctx, u64 end)
4425 ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); 4446 ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE);
4426 if (ret < 0) 4447 if (ret < 0)
4427 break; 4448 break;
4428 ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p);
4429 if (ret < 0)
4430 break;
4431 TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 4449 TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
4432 TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 4450 TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset);
4433 TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len); 4451 TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len);
@@ -4968,7 +4986,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
4968 4986
4969 if (S_ISREG(sctx->cur_inode_mode)) { 4987 if (S_ISREG(sctx->cur_inode_mode)) {
4970 if (need_send_hole(sctx)) { 4988 if (need_send_hole(sctx)) {
4971 if (sctx->cur_inode_last_extent == (u64)-1) { 4989 if (sctx->cur_inode_last_extent == (u64)-1 ||
4990 sctx->cur_inode_last_extent <
4991 sctx->cur_inode_size) {
4972 ret = get_last_extent(sctx, (u64)-1); 4992 ret = get_last_extent(sctx, (u64)-1);
4973 if (ret) 4993 if (ret)
4974 goto out; 4994 goto out;
@@ -5367,57 +5387,21 @@ out:
5367static int full_send_tree(struct send_ctx *sctx) 5387static int full_send_tree(struct send_ctx *sctx)
5368{ 5388{
5369 int ret; 5389 int ret;
5370 struct btrfs_trans_handle *trans = NULL;
5371 struct btrfs_root *send_root = sctx->send_root; 5390 struct btrfs_root *send_root = sctx->send_root;
5372 struct btrfs_key key; 5391 struct btrfs_key key;
5373 struct btrfs_key found_key; 5392 struct btrfs_key found_key;
5374 struct btrfs_path *path; 5393 struct btrfs_path *path;
5375 struct extent_buffer *eb; 5394 struct extent_buffer *eb;
5376 int slot; 5395 int slot;
5377 u64 start_ctransid;
5378 u64 ctransid;
5379 5396
5380 path = alloc_path_for_send(); 5397 path = alloc_path_for_send();
5381 if (!path) 5398 if (!path)
5382 return -ENOMEM; 5399 return -ENOMEM;
5383 5400
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; 5401 key.objectid = BTRFS_FIRST_FREE_OBJECTID;
5389 key.type = BTRFS_INODE_ITEM_KEY; 5402 key.type = BTRFS_INODE_ITEM_KEY;
5390 key.offset = 0; 5403 key.offset = 0;
5391 5404
5392join_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); 5405 ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0);
5422 if (ret < 0) 5406 if (ret < 0)
5423 goto out; 5407 goto out;
@@ -5425,19 +5409,6 @@ join_trans:
5425 goto out_finish; 5409 goto out_finish;
5426 5410
5427 while (1) { 5411 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]; 5412 eb = path->nodes[0];
5442 slot = path->slots[0]; 5413 slot = path->slots[0];
5443 btrfs_item_key_to_cpu(eb, &found_key, slot); 5414 btrfs_item_key_to_cpu(eb, &found_key, slot);
@@ -5465,12 +5436,6 @@ out_finish:
5465 5436
5466out: 5437out:
5467 btrfs_free_path(path); 5438 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; 5439 return ret;
5475} 5440}
5476 5441
@@ -5718,7 +5683,9 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5718 NULL); 5683 NULL);
5719 sort_clone_roots = 1; 5684 sort_clone_roots = 1;
5720 5685
5686 current->journal_info = (void *)BTRFS_SEND_TRANS_STUB;
5721 ret = send_subvol(sctx); 5687 ret = send_subvol(sctx);
5688 current->journal_info = NULL;
5722 if (ret < 0) 5689 if (ret < 0)
5723 goto out; 5690 goto out;
5724 5691