diff options
author | Alexander Block <ablock84@googlemail.com> | 2012-07-28 04:42:24 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:18:45 -0400 |
commit | 1f4692da951af4179a6522c6b48a09a43d37e614 (patch) | |
tree | 4021e2c4c0c931ff30015b3ab630ce67df71772a | |
parent | 85a7b33b9653ade7b26b9f29765cb1f0719c1e84 (diff) |
Btrfs: fix cur_ino < parent_ino case for send/receive
When the current inodes inum is smaller then the inum of the
parent directory strange things were happending due to wrong
path resolution and other bugs. Fix this with a new approach
for the problem.
Reported-by: Alex Lyakas <alex.bolshoy.btrfs@gmail.com>
Signed-off-by: Alexander Block <ablock84@googlemail.com>
-rw-r--r-- | fs/btrfs/send.c | 390 |
1 files changed, 146 insertions, 244 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 5721401548e8..a5fae484d4e1 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -107,7 +107,6 @@ struct send_ctx { | |||
107 | int cur_inode_new; | 107 | int cur_inode_new; |
108 | int cur_inode_new_gen; | 108 | int cur_inode_new_gen; |
109 | int cur_inode_deleted; | 109 | int cur_inode_deleted; |
110 | int cur_inode_first_ref_orphan; | ||
111 | u64 cur_inode_size; | 110 | u64 cur_inode_size; |
112 | u64 cur_inode_mode; | 111 | u64 cur_inode_mode; |
113 | 112 | ||
@@ -2296,25 +2295,25 @@ out: | |||
2296 | * a valid path yet because we did not process the refs yet. So, the inode | 2295 | * a valid path yet because we did not process the refs yet. So, the inode |
2297 | * is created as orphan. | 2296 | * is created as orphan. |
2298 | */ | 2297 | */ |
2299 | static int send_create_inode(struct send_ctx *sctx, struct btrfs_path *path, | 2298 | static int send_create_inode(struct send_ctx *sctx, u64 ino) |
2300 | struct btrfs_key *key) | ||
2301 | { | 2299 | { |
2302 | int ret = 0; | 2300 | int ret = 0; |
2303 | struct extent_buffer *eb = path->nodes[0]; | ||
2304 | struct btrfs_inode_item *ii; | ||
2305 | struct fs_path *p; | 2301 | struct fs_path *p; |
2306 | int slot = path->slots[0]; | ||
2307 | int cmd; | 2302 | int cmd; |
2303 | u64 gen; | ||
2308 | u64 mode; | 2304 | u64 mode; |
2305 | u64 rdev; | ||
2309 | 2306 | ||
2310 | verbose_printk("btrfs: send_create_inode %llu\n", sctx->cur_ino); | 2307 | verbose_printk("btrfs: send_create_inode %llu\n", ino); |
2311 | 2308 | ||
2312 | p = fs_path_alloc(sctx); | 2309 | p = fs_path_alloc(sctx); |
2313 | if (!p) | 2310 | if (!p) |
2314 | return -ENOMEM; | 2311 | return -ENOMEM; |
2315 | 2312 | ||
2316 | ii = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); | 2313 | ret = get_inode_info(sctx->send_root, ino, NULL, &gen, &mode, NULL, |
2317 | mode = btrfs_inode_mode(eb, ii); | 2314 | NULL, &rdev); |
2315 | if (ret < 0) | ||
2316 | goto out; | ||
2318 | 2317 | ||
2319 | if (S_ISREG(mode)) | 2318 | if (S_ISREG(mode)) |
2320 | cmd = BTRFS_SEND_C_MKFILE; | 2319 | cmd = BTRFS_SEND_C_MKFILE; |
@@ -2339,22 +2338,22 @@ verbose_printk("btrfs: send_create_inode %llu\n", sctx->cur_ino); | |||
2339 | if (ret < 0) | 2338 | if (ret < 0) |
2340 | goto out; | 2339 | goto out; |
2341 | 2340 | ||
2342 | ret = gen_unique_name(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); | 2341 | ret = gen_unique_name(sctx, ino, gen, p); |
2343 | if (ret < 0) | 2342 | if (ret < 0) |
2344 | goto out; | 2343 | goto out; |
2345 | 2344 | ||
2346 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); | 2345 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); |
2347 | TLV_PUT_U64(sctx, BTRFS_SEND_A_INO, sctx->cur_ino); | 2346 | TLV_PUT_U64(sctx, BTRFS_SEND_A_INO, ino); |
2348 | 2347 | ||
2349 | if (S_ISLNK(mode)) { | 2348 | if (S_ISLNK(mode)) { |
2350 | fs_path_reset(p); | 2349 | fs_path_reset(p); |
2351 | ret = read_symlink(sctx, sctx->send_root, sctx->cur_ino, p); | 2350 | ret = read_symlink(sctx, sctx->send_root, ino, p); |
2352 | if (ret < 0) | 2351 | if (ret < 0) |
2353 | goto out; | 2352 | goto out; |
2354 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); | 2353 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); |
2355 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || | 2354 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || |
2356 | S_ISFIFO(mode) || S_ISSOCK(mode)) { | 2355 | S_ISFIFO(mode) || S_ISSOCK(mode)) { |
2357 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, btrfs_inode_rdev(eb, ii)); | 2356 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev); |
2358 | } | 2357 | } |
2359 | 2358 | ||
2360 | ret = send_cmd(sctx); | 2359 | ret = send_cmd(sctx); |
@@ -2368,6 +2367,92 @@ out: | |||
2368 | return ret; | 2367 | return ret; |
2369 | } | 2368 | } |
2370 | 2369 | ||
2370 | /* | ||
2371 | * We need some special handling for inodes that get processed before the parent | ||
2372 | * directory got created. See process_recorded_refs for details. | ||
2373 | * This function does the check if we already created the dir out of order. | ||
2374 | */ | ||
2375 | static int did_create_dir(struct send_ctx *sctx, u64 dir) | ||
2376 | { | ||
2377 | int ret = 0; | ||
2378 | struct btrfs_path *path = NULL; | ||
2379 | struct btrfs_key key; | ||
2380 | struct btrfs_key found_key; | ||
2381 | struct btrfs_key di_key; | ||
2382 | struct extent_buffer *eb; | ||
2383 | struct btrfs_dir_item *di; | ||
2384 | int slot; | ||
2385 | |||
2386 | path = alloc_path_for_send(); | ||
2387 | if (!path) { | ||
2388 | ret = -ENOMEM; | ||
2389 | goto out; | ||
2390 | } | ||
2391 | |||
2392 | key.objectid = dir; | ||
2393 | key.type = BTRFS_DIR_INDEX_KEY; | ||
2394 | key.offset = 0; | ||
2395 | while (1) { | ||
2396 | ret = btrfs_search_slot_for_read(sctx->send_root, &key, path, | ||
2397 | 1, 0); | ||
2398 | if (ret < 0) | ||
2399 | goto out; | ||
2400 | if (!ret) { | ||
2401 | eb = path->nodes[0]; | ||
2402 | slot = path->slots[0]; | ||
2403 | btrfs_item_key_to_cpu(eb, &found_key, slot); | ||
2404 | } | ||
2405 | if (ret || found_key.objectid != key.objectid || | ||
2406 | found_key.type != key.type) { | ||
2407 | ret = 0; | ||
2408 | goto out; | ||
2409 | } | ||
2410 | |||
2411 | di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item); | ||
2412 | btrfs_dir_item_key_to_cpu(eb, di, &di_key); | ||
2413 | |||
2414 | if (di_key.objectid < sctx->send_progress) { | ||
2415 | ret = 1; | ||
2416 | goto out; | ||
2417 | } | ||
2418 | |||
2419 | key.offset = found_key.offset + 1; | ||
2420 | btrfs_release_path(path); | ||
2421 | } | ||
2422 | |||
2423 | out: | ||
2424 | btrfs_free_path(path); | ||
2425 | return ret; | ||
2426 | } | ||
2427 | |||
2428 | /* | ||
2429 | * Only creates the inode if it is: | ||
2430 | * 1. Not a directory | ||
2431 | * 2. Or a directory which was not created already due to out of order | ||
2432 | * directories. See did_create_dir and process_recorded_refs for details. | ||
2433 | */ | ||
2434 | static int send_create_inode_if_needed(struct send_ctx *sctx) | ||
2435 | { | ||
2436 | int ret; | ||
2437 | |||
2438 | if (S_ISDIR(sctx->cur_inode_mode)) { | ||
2439 | ret = did_create_dir(sctx, sctx->cur_ino); | ||
2440 | if (ret < 0) | ||
2441 | goto out; | ||
2442 | if (ret) { | ||
2443 | ret = 0; | ||
2444 | goto out; | ||
2445 | } | ||
2446 | } | ||
2447 | |||
2448 | ret = send_create_inode(sctx, sctx->cur_ino); | ||
2449 | if (ret < 0) | ||
2450 | goto out; | ||
2451 | |||
2452 | out: | ||
2453 | return ret; | ||
2454 | } | ||
2455 | |||
2371 | struct recorded_ref { | 2456 | struct recorded_ref { |
2372 | struct list_head list; | 2457 | struct list_head list; |
2373 | char *dir_path; | 2458 | char *dir_path; |
@@ -2517,160 +2602,6 @@ out: | |||
2517 | return ret; | 2602 | return ret; |
2518 | } | 2603 | } |
2519 | 2604 | ||
2520 | struct finish_unordered_dir_ctx { | ||
2521 | struct send_ctx *sctx; | ||
2522 | struct fs_path *cur_path; | ||
2523 | struct fs_path *dir_path; | ||
2524 | u64 dir_ino; | ||
2525 | int need_delete; | ||
2526 | int delete_pass; | ||
2527 | }; | ||
2528 | |||
2529 | int __finish_unordered_dir(int num, struct btrfs_key *di_key, | ||
2530 | const char *name, int name_len, | ||
2531 | const char *data, int data_len, | ||
2532 | u8 type, void *ctx) | ||
2533 | { | ||
2534 | int ret = 0; | ||
2535 | struct finish_unordered_dir_ctx *fctx = ctx; | ||
2536 | struct send_ctx *sctx = fctx->sctx; | ||
2537 | u64 di_gen; | ||
2538 | u64 di_mode; | ||
2539 | int is_orphan = 0; | ||
2540 | |||
2541 | if (di_key->objectid >= fctx->dir_ino) | ||
2542 | goto out; | ||
2543 | |||
2544 | fs_path_reset(fctx->cur_path); | ||
2545 | |||
2546 | ret = get_inode_info(sctx->send_root, di_key->objectid, | ||
2547 | NULL, &di_gen, &di_mode, NULL, NULL, NULL); | ||
2548 | if (ret < 0) | ||
2549 | goto out; | ||
2550 | |||
2551 | ret = is_first_ref(sctx, sctx->send_root, di_key->objectid, | ||
2552 | fctx->dir_ino, name, name_len); | ||
2553 | if (ret < 0) | ||
2554 | goto out; | ||
2555 | if (ret) { | ||
2556 | is_orphan = 1; | ||
2557 | ret = gen_unique_name(sctx, di_key->objectid, di_gen, | ||
2558 | fctx->cur_path); | ||
2559 | } else { | ||
2560 | ret = get_cur_path(sctx, di_key->objectid, di_gen, | ||
2561 | fctx->cur_path); | ||
2562 | } | ||
2563 | if (ret < 0) | ||
2564 | goto out; | ||
2565 | |||
2566 | ret = fs_path_add(fctx->dir_path, name, name_len); | ||
2567 | if (ret < 0) | ||
2568 | goto out; | ||
2569 | |||
2570 | if (!fctx->delete_pass) { | ||
2571 | if (S_ISDIR(di_mode)) { | ||
2572 | ret = send_rename(sctx, fctx->cur_path, | ||
2573 | fctx->dir_path); | ||
2574 | } else { | ||
2575 | ret = send_link(sctx, fctx->dir_path, | ||
2576 | fctx->cur_path); | ||
2577 | if (is_orphan) | ||
2578 | fctx->need_delete = 1; | ||
2579 | } | ||
2580 | } else if (!S_ISDIR(di_mode)) { | ||
2581 | ret = send_unlink(sctx, fctx->cur_path); | ||
2582 | } else { | ||
2583 | ret = 0; | ||
2584 | } | ||
2585 | |||
2586 | fs_path_remove(fctx->dir_path); | ||
2587 | |||
2588 | out: | ||
2589 | return ret; | ||
2590 | } | ||
2591 | |||
2592 | /* | ||
2593 | * Go through all dir items and see if we find refs which could not be created | ||
2594 | * in the past because the dir did not exist at that time. | ||
2595 | */ | ||
2596 | static int finish_outoforder_dir(struct send_ctx *sctx, u64 dir, u64 dir_gen) | ||
2597 | { | ||
2598 | int ret = 0; | ||
2599 | struct btrfs_path *path = NULL; | ||
2600 | struct btrfs_key key; | ||
2601 | struct btrfs_key found_key; | ||
2602 | struct extent_buffer *eb; | ||
2603 | struct finish_unordered_dir_ctx fctx; | ||
2604 | int slot; | ||
2605 | |||
2606 | path = alloc_path_for_send(); | ||
2607 | if (!path) { | ||
2608 | ret = -ENOMEM; | ||
2609 | goto out; | ||
2610 | } | ||
2611 | |||
2612 | memset(&fctx, 0, sizeof(fctx)); | ||
2613 | fctx.sctx = sctx; | ||
2614 | fctx.cur_path = fs_path_alloc(sctx); | ||
2615 | fctx.dir_path = fs_path_alloc(sctx); | ||
2616 | if (!fctx.cur_path || !fctx.dir_path) { | ||
2617 | ret = -ENOMEM; | ||
2618 | goto out; | ||
2619 | } | ||
2620 | fctx.dir_ino = dir; | ||
2621 | |||
2622 | ret = get_cur_path(sctx, dir, dir_gen, fctx.dir_path); | ||
2623 | if (ret < 0) | ||
2624 | goto out; | ||
2625 | |||
2626 | /* | ||
2627 | * We do two passes. The first links in the new refs and the second | ||
2628 | * deletes orphans if required. Deletion of orphans is not required for | ||
2629 | * directory inodes, as we always have only one ref and use rename | ||
2630 | * instead of link for those. | ||
2631 | */ | ||
2632 | |||
2633 | again: | ||
2634 | key.objectid = dir; | ||
2635 | key.type = BTRFS_DIR_ITEM_KEY; | ||
2636 | key.offset = 0; | ||
2637 | while (1) { | ||
2638 | ret = btrfs_search_slot_for_read(sctx->send_root, &key, path, | ||
2639 | 1, 0); | ||
2640 | if (ret < 0) | ||
2641 | goto out; | ||
2642 | eb = path->nodes[0]; | ||
2643 | slot = path->slots[0]; | ||
2644 | btrfs_item_key_to_cpu(eb, &found_key, slot); | ||
2645 | |||
2646 | if (found_key.objectid != key.objectid || | ||
2647 | found_key.type != key.type) { | ||
2648 | btrfs_release_path(path); | ||
2649 | break; | ||
2650 | } | ||
2651 | |||
2652 | ret = iterate_dir_item(sctx, sctx->send_root, path, | ||
2653 | &found_key, __finish_unordered_dir, | ||
2654 | &fctx); | ||
2655 | if (ret < 0) | ||
2656 | goto out; | ||
2657 | |||
2658 | key.offset = found_key.offset + 1; | ||
2659 | btrfs_release_path(path); | ||
2660 | } | ||
2661 | |||
2662 | if (!fctx.delete_pass && fctx.need_delete) { | ||
2663 | fctx.delete_pass = 1; | ||
2664 | goto again; | ||
2665 | } | ||
2666 | |||
2667 | out: | ||
2668 | btrfs_free_path(path); | ||
2669 | fs_path_free(sctx, fctx.cur_path); | ||
2670 | fs_path_free(sctx, fctx.dir_path); | ||
2671 | return ret; | ||
2672 | } | ||
2673 | |||
2674 | /* | 2605 | /* |
2675 | * This does all the move/link/unlink/rmdir magic. | 2606 | * This does all the move/link/unlink/rmdir magic. |
2676 | */ | 2607 | */ |
@@ -2678,6 +2609,7 @@ static int process_recorded_refs(struct send_ctx *sctx) | |||
2678 | { | 2609 | { |
2679 | int ret = 0; | 2610 | int ret = 0; |
2680 | struct recorded_ref *cur; | 2611 | struct recorded_ref *cur; |
2612 | struct recorded_ref *cur2; | ||
2681 | struct ulist *check_dirs = NULL; | 2613 | struct ulist *check_dirs = NULL; |
2682 | struct ulist_iterator uit; | 2614 | struct ulist_iterator uit; |
2683 | struct ulist_node *un; | 2615 | struct ulist_node *un; |
@@ -2735,6 +2667,46 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2735 | 2667 | ||
2736 | list_for_each_entry(cur, &sctx->new_refs, list) { | 2668 | list_for_each_entry(cur, &sctx->new_refs, list) { |
2737 | /* | 2669 | /* |
2670 | * We may have refs where the parent directory does not exist | ||
2671 | * yet. This happens if the parent directories inum is higher | ||
2672 | * the the current inum. To handle this case, we create the | ||
2673 | * parent directory out of order. But we need to check if this | ||
2674 | * did already happen before due to other refs in the same dir. | ||
2675 | */ | ||
2676 | ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen); | ||
2677 | if (ret < 0) | ||
2678 | goto out; | ||
2679 | if (ret == inode_state_will_create) { | ||
2680 | ret = 0; | ||
2681 | /* | ||
2682 | * First check if any of the current inodes refs did | ||
2683 | * already create the dir. | ||
2684 | */ | ||
2685 | list_for_each_entry(cur2, &sctx->new_refs, list) { | ||
2686 | if (cur == cur2) | ||
2687 | break; | ||
2688 | if (cur2->dir == cur->dir) { | ||
2689 | ret = 1; | ||
2690 | break; | ||
2691 | } | ||
2692 | } | ||
2693 | |||
2694 | /* | ||
2695 | * If that did not happen, check if a previous inode | ||
2696 | * did already create the dir. | ||
2697 | */ | ||
2698 | if (!ret) | ||
2699 | ret = did_create_dir(sctx, cur->dir); | ||
2700 | if (ret < 0) | ||
2701 | goto out; | ||
2702 | if (!ret) { | ||
2703 | ret = send_create_inode(sctx, cur->dir); | ||
2704 | if (ret < 0) | ||
2705 | goto out; | ||
2706 | } | ||
2707 | } | ||
2708 | |||
2709 | /* | ||
2738 | * Check if this new ref would overwrite the first ref of | 2710 | * Check if this new ref would overwrite the first ref of |
2739 | * another unprocessed inode. If yes, orphanize the | 2711 | * another unprocessed inode. If yes, orphanize the |
2740 | * overwritten inode. If we find an overwritten ref that is | 2712 | * overwritten inode. If we find an overwritten ref that is |
@@ -2768,7 +2740,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2768 | * inode, move it and update valid_path. If not, link or move | 2740 | * inode, move it and update valid_path. If not, link or move |
2769 | * it depending on the inode mode. | 2741 | * it depending on the inode mode. |
2770 | */ | 2742 | */ |
2771 | if (is_orphan && !sctx->cur_inode_first_ref_orphan) { | 2743 | if (is_orphan) { |
2772 | ret = send_rename(sctx, valid_path, cur->full_path); | 2744 | ret = send_rename(sctx, valid_path, cur->full_path); |
2773 | if (ret < 0) | 2745 | if (ret < 0) |
2774 | goto out; | 2746 | goto out; |
@@ -2844,35 +2816,9 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2844 | if (ret < 0) | 2816 | if (ret < 0) |
2845 | goto out; | 2817 | goto out; |
2846 | if (!ret) { | 2818 | if (!ret) { |
2847 | /* | 2819 | ret = send_unlink(sctx, cur->full_path); |
2848 | * In case the inode was moved to a directory | 2820 | if (ret < 0) |
2849 | * that was not created yet (see | 2821 | goto out; |
2850 | * __record_new_ref), we can not unlink the ref | ||
2851 | * as it will be needed later when the parent | ||
2852 | * directory is created, so that we can move in | ||
2853 | * the inode to the new dir. | ||
2854 | */ | ||
2855 | if (!is_orphan && | ||
2856 | sctx->cur_inode_first_ref_orphan) { | ||
2857 | ret = orphanize_inode(sctx, | ||
2858 | sctx->cur_ino, | ||
2859 | sctx->cur_inode_gen, | ||
2860 | cur->full_path); | ||
2861 | if (ret < 0) | ||
2862 | goto out; | ||
2863 | ret = gen_unique_name(sctx, | ||
2864 | sctx->cur_ino, | ||
2865 | sctx->cur_inode_gen, | ||
2866 | valid_path); | ||
2867 | if (ret < 0) | ||
2868 | goto out; | ||
2869 | is_orphan = 1; | ||
2870 | |||
2871 | } else { | ||
2872 | ret = send_unlink(sctx, cur->full_path); | ||
2873 | if (ret < 0) | ||
2874 | goto out; | ||
2875 | } | ||
2876 | } | 2822 | } |
2877 | ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, | 2823 | ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, |
2878 | GFP_NOFS); | 2824 | GFP_NOFS); |
@@ -2885,11 +2831,8 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2885 | * happen when a previous inode did overwrite the first ref | 2831 | * happen when a previous inode did overwrite the first ref |
2886 | * of this inode and no new refs were added for the current | 2832 | * of this inode and no new refs were added for the current |
2887 | * inode. | 2833 | * inode. |
2888 | * We can however not delete the orphan in case the inode relies | ||
2889 | * in a directory that was not created yet (see | ||
2890 | * __record_new_ref) | ||
2891 | */ | 2834 | */ |
2892 | if (is_orphan && !sctx->cur_inode_first_ref_orphan) { | 2835 | if (is_orphan) { |
2893 | ret = send_unlink(sctx, valid_path); | 2836 | ret = send_unlink(sctx, valid_path); |
2894 | if (ret < 0) | 2837 | if (ret < 0) |
2895 | goto out; | 2838 | goto out; |
@@ -2939,19 +2882,6 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2939 | */ | 2882 | */ |
2940 | sctx->send_progress = sctx->cur_ino + 1; | 2883 | sctx->send_progress = sctx->cur_ino + 1; |
2941 | 2884 | ||
2942 | /* | ||
2943 | * We may have a directory here that has pending refs which could not | ||
2944 | * be created before (because the dir did not exist before, see | ||
2945 | * __record_new_ref). finish_outoforder_dir will link/move the pending | ||
2946 | * refs. | ||
2947 | */ | ||
2948 | if (S_ISDIR(sctx->cur_inode_mode) && sctx->cur_inode_new) { | ||
2949 | ret = finish_outoforder_dir(sctx, sctx->cur_ino, | ||
2950 | sctx->cur_inode_gen); | ||
2951 | if (ret < 0) | ||
2952 | goto out; | ||
2953 | } | ||
2954 | |||
2955 | ret = 0; | 2885 | ret = 0; |
2956 | 2886 | ||
2957 | out: | 2887 | out: |
@@ -2979,31 +2909,6 @@ static int __record_new_ref(int num, u64 dir, int index, | |||
2979 | if (ret < 0) | 2909 | if (ret < 0) |
2980 | goto out; | 2910 | goto out; |
2981 | 2911 | ||
2982 | /* | ||
2983 | * The parent may be non-existent at this point in time. This happens | ||
2984 | * if the ino of the parent dir is higher then the current ino. In this | ||
2985 | * case, we can not process this ref until the parent dir is finally | ||
2986 | * created. If we reach the parent dir later, process_recorded_refs | ||
2987 | * will go through all dir items and process the refs that could not be | ||
2988 | * processed before. In case this is the first ref, we set | ||
2989 | * cur_inode_first_ref_orphan to 1 to inform process_recorded_refs to | ||
2990 | * keep an orphan of the inode so that it later can be used for | ||
2991 | * link/move | ||
2992 | */ | ||
2993 | ret = is_inode_existent(sctx, dir, gen); | ||
2994 | if (ret < 0) | ||
2995 | goto out; | ||
2996 | if (!ret) { | ||
2997 | ret = is_first_ref(sctx, sctx->send_root, sctx->cur_ino, dir, | ||
2998 | name->start, fs_path_len(name)); | ||
2999 | if (ret < 0) | ||
3000 | goto out; | ||
3001 | if (ret) | ||
3002 | sctx->cur_inode_first_ref_orphan = 1; | ||
3003 | ret = 0; | ||
3004 | goto out; | ||
3005 | } | ||
3006 | |||
3007 | ret = get_cur_path(sctx, dir, gen, p); | 2912 | ret = get_cur_path(sctx, dir, gen, p); |
3008 | if (ret < 0) | 2913 | if (ret < 0) |
3009 | goto out; | 2914 | goto out; |
@@ -4078,7 +3983,6 @@ static int changed_inode(struct send_ctx *sctx, | |||
4078 | 3983 | ||
4079 | sctx->cur_ino = key->objectid; | 3984 | sctx->cur_ino = key->objectid; |
4080 | sctx->cur_inode_new_gen = 0; | 3985 | sctx->cur_inode_new_gen = 0; |
4081 | sctx->cur_inode_first_ref_orphan = 0; | ||
4082 | sctx->send_progress = sctx->cur_ino; | 3986 | sctx->send_progress = sctx->cur_ino; |
4083 | 3987 | ||
4084 | if (result == BTRFS_COMPARE_TREE_NEW || | 3988 | if (result == BTRFS_COMPARE_TREE_NEW || |
@@ -4115,8 +4019,7 @@ static int changed_inode(struct send_ctx *sctx, | |||
4115 | sctx->cur_inode_mode = btrfs_inode_mode( | 4019 | sctx->cur_inode_mode = btrfs_inode_mode( |
4116 | sctx->left_path->nodes[0], left_ii); | 4020 | sctx->left_path->nodes[0], left_ii); |
4117 | if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) | 4021 | if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) |
4118 | ret = send_create_inode(sctx, sctx->left_path, | 4022 | ret = send_create_inode_if_needed(sctx); |
4119 | sctx->cmp_key); | ||
4120 | } else if (result == BTRFS_COMPARE_TREE_DELETED) { | 4023 | } else if (result == BTRFS_COMPARE_TREE_DELETED) { |
4121 | sctx->cur_inode_gen = right_gen; | 4024 | sctx->cur_inode_gen = right_gen; |
4122 | sctx->cur_inode_new = 0; | 4025 | sctx->cur_inode_new = 0; |
@@ -4146,8 +4049,7 @@ static int changed_inode(struct send_ctx *sctx, | |||
4146 | sctx->left_path->nodes[0], left_ii); | 4049 | sctx->left_path->nodes[0], left_ii); |
4147 | sctx->cur_inode_mode = btrfs_inode_mode( | 4050 | sctx->cur_inode_mode = btrfs_inode_mode( |
4148 | sctx->left_path->nodes[0], left_ii); | 4051 | sctx->left_path->nodes[0], left_ii); |
4149 | ret = send_create_inode(sctx, sctx->left_path, | 4052 | ret = send_create_inode_if_needed(sctx); |
4150 | sctx->cmp_key); | ||
4151 | if (ret < 0) | 4053 | if (ret < 0) |
4152 | goto out; | 4054 | goto out; |
4153 | 4055 | ||