aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Block <ablock84@googlemail.com>2012-07-28 04:42:24 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-01 15:18:45 -0400
commit1f4692da951af4179a6522c6b48a09a43d37e614 (patch)
tree4021e2c4c0c931ff30015b3ab630ce67df71772a
parent85a7b33b9653ade7b26b9f29765cb1f0719c1e84 (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.c390
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 */
2299static int send_create_inode(struct send_ctx *sctx, struct btrfs_path *path, 2298static 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
2310verbose_printk("btrfs: send_create_inode %llu\n", sctx->cur_ino); 2307verbose_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 */
2375static 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
2423out:
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 */
2434static 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
2452out:
2453 return ret;
2454}
2455
2371struct recorded_ref { 2456struct 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
2520struct 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
2529int __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
2588out:
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 */
2596static 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
2633again:
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
2667out:
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
2957out: 2887out:
@@ -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