diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 571 |
1 files changed, 340 insertions, 231 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 9027bb1e7466..c276ac9a0ec3 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -277,18 +277,19 @@ static int process_one_buffer(struct btrfs_root *log, | |||
277 | struct extent_buffer *eb, | 277 | struct extent_buffer *eb, |
278 | struct walk_control *wc, u64 gen) | 278 | struct walk_control *wc, u64 gen) |
279 | { | 279 | { |
280 | int ret = 0; | ||
281 | |||
280 | if (wc->pin) | 282 | if (wc->pin) |
281 | btrfs_pin_extent_for_log_replay(wc->trans, | 283 | ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root, |
282 | log->fs_info->extent_root, | 284 | eb->start, eb->len); |
283 | eb->start, eb->len); | ||
284 | 285 | ||
285 | if (btrfs_buffer_uptodate(eb, gen, 0)) { | 286 | if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { |
286 | if (wc->write) | 287 | if (wc->write) |
287 | btrfs_write_tree_block(eb); | 288 | btrfs_write_tree_block(eb); |
288 | if (wc->wait) | 289 | if (wc->wait) |
289 | btrfs_wait_tree_block_writeback(eb); | 290 | btrfs_wait_tree_block_writeback(eb); |
290 | } | 291 | } |
291 | return 0; | 292 | return ret; |
292 | } | 293 | } |
293 | 294 | ||
294 | /* | 295 | /* |
@@ -318,6 +319,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
318 | unsigned long src_ptr; | 319 | unsigned long src_ptr; |
319 | unsigned long dst_ptr; | 320 | unsigned long dst_ptr; |
320 | int overwrite_root = 0; | 321 | int overwrite_root = 0; |
322 | bool inode_item = key->type == BTRFS_INODE_ITEM_KEY; | ||
321 | 323 | ||
322 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 324 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
323 | overwrite_root = 1; | 325 | overwrite_root = 1; |
@@ -327,6 +329,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
327 | 329 | ||
328 | /* look for the key in the destination tree */ | 330 | /* look for the key in the destination tree */ |
329 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 331 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | |||
330 | if (ret == 0) { | 335 | if (ret == 0) { |
331 | char *src_copy; | 336 | char *src_copy; |
332 | char *dst_copy; | 337 | char *dst_copy; |
@@ -368,6 +373,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
368 | return 0; | 373 | return 0; |
369 | } | 374 | } |
370 | 375 | ||
376 | /* | ||
377 | * We need to load the old nbytes into the inode so when we | ||
378 | * replay the extents we've logged we get the right nbytes. | ||
379 | */ | ||
380 | if (inode_item) { | ||
381 | struct btrfs_inode_item *item; | ||
382 | u64 nbytes; | ||
383 | |||
384 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
385 | struct btrfs_inode_item); | ||
386 | nbytes = btrfs_inode_nbytes(path->nodes[0], item); | ||
387 | item = btrfs_item_ptr(eb, slot, | ||
388 | struct btrfs_inode_item); | ||
389 | btrfs_set_inode_nbytes(eb, item, nbytes); | ||
390 | } | ||
391 | } else if (inode_item) { | ||
392 | struct btrfs_inode_item *item; | ||
393 | |||
394 | /* | ||
395 | * New inode, set nbytes to 0 so that the nbytes comes out | ||
396 | * properly when we replay the extents. | ||
397 | */ | ||
398 | item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); | ||
399 | btrfs_set_inode_nbytes(eb, item, 0); | ||
371 | } | 400 | } |
372 | insert: | 401 | insert: |
373 | btrfs_release_path(path); | 402 | btrfs_release_path(path); |
@@ -381,9 +410,9 @@ insert: | |||
381 | found_size = btrfs_item_size_nr(path->nodes[0], | 410 | found_size = btrfs_item_size_nr(path->nodes[0], |
382 | path->slots[0]); | 411 | path->slots[0]); |
383 | if (found_size > item_size) | 412 | if (found_size > item_size) |
384 | btrfs_truncate_item(trans, root, path, item_size, 1); | 413 | btrfs_truncate_item(root, path, item_size, 1); |
385 | else if (found_size < item_size) | 414 | else if (found_size < item_size) |
386 | btrfs_extend_item(trans, root, path, | 415 | btrfs_extend_item(root, path, |
387 | item_size - found_size); | 416 | item_size - found_size); |
388 | } else if (ret) { | 417 | } else if (ret) { |
389 | return ret; | 418 | return ret; |
@@ -485,10 +514,9 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
485 | struct btrfs_key *key) | 514 | struct btrfs_key *key) |
486 | { | 515 | { |
487 | int found_type; | 516 | int found_type; |
488 | u64 mask = root->sectorsize - 1; | ||
489 | u64 extent_end; | 517 | u64 extent_end; |
490 | u64 start = key->offset; | 518 | u64 start = key->offset; |
491 | u64 saved_nbytes; | 519 | u64 nbytes = 0; |
492 | struct btrfs_file_extent_item *item; | 520 | struct btrfs_file_extent_item *item; |
493 | struct inode *inode = NULL; | 521 | struct inode *inode = NULL; |
494 | unsigned long size; | 522 | unsigned long size; |
@@ -498,11 +526,20 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
498 | found_type = btrfs_file_extent_type(eb, item); | 526 | found_type = btrfs_file_extent_type(eb, item); |
499 | 527 | ||
500 | if (found_type == BTRFS_FILE_EXTENT_REG || | 528 | if (found_type == BTRFS_FILE_EXTENT_REG || |
501 | found_type == BTRFS_FILE_EXTENT_PREALLOC) | 529 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
502 | extent_end = start + btrfs_file_extent_num_bytes(eb, item); | 530 | nbytes = btrfs_file_extent_num_bytes(eb, item); |
503 | else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 531 | extent_end = start + nbytes; |
532 | |||
533 | /* | ||
534 | * We don't add to the inodes nbytes if we are prealloc or a | ||
535 | * hole. | ||
536 | */ | ||
537 | if (btrfs_file_extent_disk_bytenr(eb, item) == 0) | ||
538 | nbytes = 0; | ||
539 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | ||
504 | size = btrfs_file_extent_inline_len(eb, item); | 540 | size = btrfs_file_extent_inline_len(eb, item); |
505 | extent_end = (start + size + mask) & ~mask; | 541 | nbytes = btrfs_file_extent_ram_bytes(eb, item); |
542 | extent_end = ALIGN(start + size, root->sectorsize); | ||
506 | } else { | 543 | } else { |
507 | ret = 0; | 544 | ret = 0; |
508 | goto out; | 545 | goto out; |
@@ -550,10 +587,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
550 | } | 587 | } |
551 | btrfs_release_path(path); | 588 | btrfs_release_path(path); |
552 | 589 | ||
553 | saved_nbytes = inode_get_bytes(inode); | ||
554 | /* drop any overlapping extents */ | 590 | /* drop any overlapping extents */ |
555 | ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1); | 591 | ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1); |
556 | BUG_ON(ret); | 592 | if (ret) |
593 | goto out; | ||
557 | 594 | ||
558 | if (found_type == BTRFS_FILE_EXTENT_REG || | 595 | if (found_type == BTRFS_FILE_EXTENT_REG || |
559 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | 596 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
@@ -563,7 +600,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
563 | 600 | ||
564 | ret = btrfs_insert_empty_item(trans, root, path, key, | 601 | ret = btrfs_insert_empty_item(trans, root, path, key, |
565 | sizeof(*item)); | 602 | sizeof(*item)); |
566 | BUG_ON(ret); | 603 | if (ret) |
604 | goto out; | ||
567 | dest_offset = btrfs_item_ptr_offset(path->nodes[0], | 605 | dest_offset = btrfs_item_ptr_offset(path->nodes[0], |
568 | path->slots[0]); | 606 | path->slots[0]); |
569 | copy_extent_buffer(path->nodes[0], eb, dest_offset, | 607 | copy_extent_buffer(path->nodes[0], eb, dest_offset, |
@@ -589,7 +627,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
589 | ins.objectid, ins.offset, | 627 | ins.objectid, ins.offset, |
590 | 0, root->root_key.objectid, | 628 | 0, root->root_key.objectid, |
591 | key->objectid, offset, 0); | 629 | key->objectid, offset, 0); |
592 | BUG_ON(ret); | 630 | if (ret) |
631 | goto out; | ||
593 | } else { | 632 | } else { |
594 | /* | 633 | /* |
595 | * insert the extent pointer in the extent | 634 | * insert the extent pointer in the extent |
@@ -598,7 +637,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
598 | ret = btrfs_alloc_logged_file_extent(trans, | 637 | ret = btrfs_alloc_logged_file_extent(trans, |
599 | root, root->root_key.objectid, | 638 | root, root->root_key.objectid, |
600 | key->objectid, offset, &ins); | 639 | key->objectid, offset, &ins); |
601 | BUG_ON(ret); | 640 | if (ret) |
641 | goto out; | ||
602 | } | 642 | } |
603 | btrfs_release_path(path); | 643 | btrfs_release_path(path); |
604 | 644 | ||
@@ -615,29 +655,33 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
615 | ret = btrfs_lookup_csums_range(root->log_root, | 655 | ret = btrfs_lookup_csums_range(root->log_root, |
616 | csum_start, csum_end - 1, | 656 | csum_start, csum_end - 1, |
617 | &ordered_sums, 0); | 657 | &ordered_sums, 0); |
618 | BUG_ON(ret); | 658 | if (ret) |
659 | goto out; | ||
619 | while (!list_empty(&ordered_sums)) { | 660 | while (!list_empty(&ordered_sums)) { |
620 | struct btrfs_ordered_sum *sums; | 661 | struct btrfs_ordered_sum *sums; |
621 | sums = list_entry(ordered_sums.next, | 662 | sums = list_entry(ordered_sums.next, |
622 | struct btrfs_ordered_sum, | 663 | struct btrfs_ordered_sum, |
623 | list); | 664 | list); |
624 | ret = btrfs_csum_file_blocks(trans, | 665 | if (!ret) |
666 | ret = btrfs_csum_file_blocks(trans, | ||
625 | root->fs_info->csum_root, | 667 | root->fs_info->csum_root, |
626 | sums); | 668 | sums); |
627 | BUG_ON(ret); | ||
628 | list_del(&sums->list); | 669 | list_del(&sums->list); |
629 | kfree(sums); | 670 | kfree(sums); |
630 | } | 671 | } |
672 | if (ret) | ||
673 | goto out; | ||
631 | } else { | 674 | } else { |
632 | btrfs_release_path(path); | 675 | btrfs_release_path(path); |
633 | } | 676 | } |
634 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 677 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
635 | /* inline extents are easy, we just overwrite them */ | 678 | /* inline extents are easy, we just overwrite them */ |
636 | ret = overwrite_item(trans, root, path, eb, slot, key); | 679 | ret = overwrite_item(trans, root, path, eb, slot, key); |
637 | BUG_ON(ret); | 680 | if (ret) |
681 | goto out; | ||
638 | } | 682 | } |
639 | 683 | ||
640 | inode_set_bytes(inode, saved_nbytes); | 684 | inode_add_bytes(inode, nbytes); |
641 | ret = btrfs_update_inode(trans, root, inode); | 685 | ret = btrfs_update_inode(trans, root, inode); |
642 | out: | 686 | out: |
643 | if (inode) | 687 | if (inode) |
@@ -679,20 +723,21 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, | |||
679 | 723 | ||
680 | inode = read_one_inode(root, location.objectid); | 724 | inode = read_one_inode(root, location.objectid); |
681 | if (!inode) { | 725 | if (!inode) { |
682 | kfree(name); | 726 | ret = -EIO; |
683 | return -EIO; | 727 | goto out; |
684 | } | 728 | } |
685 | 729 | ||
686 | ret = link_to_fixup_dir(trans, root, path, location.objectid); | 730 | ret = link_to_fixup_dir(trans, root, path, location.objectid); |
687 | BUG_ON(ret); | 731 | if (ret) |
732 | goto out; | ||
688 | 733 | ||
689 | ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); | 734 | ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); |
690 | BUG_ON(ret); | 735 | if (ret) |
736 | goto out; | ||
737 | btrfs_run_delayed_items(trans, root); | ||
738 | out: | ||
691 | kfree(name); | 739 | kfree(name); |
692 | |||
693 | iput(inode); | 740 | iput(inode); |
694 | |||
695 | btrfs_run_delayed_items(trans, root); | ||
696 | return ret; | 741 | return ret; |
697 | } | 742 | } |
698 | 743 | ||
@@ -845,7 +890,8 @@ again: | |||
845 | victim_name_len = btrfs_inode_ref_name_len(leaf, | 890 | victim_name_len = btrfs_inode_ref_name_len(leaf, |
846 | victim_ref); | 891 | victim_ref); |
847 | victim_name = kmalloc(victim_name_len, GFP_NOFS); | 892 | victim_name = kmalloc(victim_name_len, GFP_NOFS); |
848 | BUG_ON(!victim_name); | 893 | if (!victim_name) |
894 | return -ENOMEM; | ||
849 | 895 | ||
850 | read_extent_buffer(leaf, victim_name, | 896 | read_extent_buffer(leaf, victim_name, |
851 | (unsigned long)(victim_ref + 1), | 897 | (unsigned long)(victim_ref + 1), |
@@ -861,9 +907,10 @@ again: | |||
861 | ret = btrfs_unlink_inode(trans, root, dir, | 907 | ret = btrfs_unlink_inode(trans, root, dir, |
862 | inode, victim_name, | 908 | inode, victim_name, |
863 | victim_name_len); | 909 | victim_name_len); |
864 | BUG_ON(ret); | ||
865 | btrfs_run_delayed_items(trans, root); | ||
866 | kfree(victim_name); | 910 | kfree(victim_name); |
911 | if (ret) | ||
912 | return ret; | ||
913 | btrfs_run_delayed_items(trans, root); | ||
867 | *search_done = 1; | 914 | *search_done = 1; |
868 | goto again; | 915 | goto again; |
869 | } | 916 | } |
@@ -871,7 +918,6 @@ again: | |||
871 | 918 | ||
872 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; | 919 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; |
873 | } | 920 | } |
874 | BUG_ON(ret); | ||
875 | 921 | ||
876 | /* | 922 | /* |
877 | * NOTE: we have searched root tree and checked the | 923 | * NOTE: we have searched root tree and checked the |
@@ -905,6 +951,8 @@ again: | |||
905 | goto next; | 951 | goto next; |
906 | 952 | ||
907 | victim_name = kmalloc(victim_name_len, GFP_NOFS); | 953 | victim_name = kmalloc(victim_name_len, GFP_NOFS); |
954 | if (!victim_name) | ||
955 | return -ENOMEM; | ||
908 | read_extent_buffer(leaf, victim_name, (unsigned long)&extref->name, | 956 | read_extent_buffer(leaf, victim_name, (unsigned long)&extref->name, |
909 | victim_name_len); | 957 | victim_name_len); |
910 | 958 | ||
@@ -931,14 +979,16 @@ again: | |||
931 | victim_name_len); | 979 | victim_name_len); |
932 | btrfs_run_delayed_items(trans, root); | 980 | btrfs_run_delayed_items(trans, root); |
933 | } | 981 | } |
934 | BUG_ON(ret); | ||
935 | iput(victim_parent); | 982 | iput(victim_parent); |
936 | kfree(victim_name); | 983 | kfree(victim_name); |
984 | if (ret) | ||
985 | return ret; | ||
937 | *search_done = 1; | 986 | *search_done = 1; |
938 | goto again; | 987 | goto again; |
939 | } | 988 | } |
940 | kfree(victim_name); | 989 | kfree(victim_name); |
941 | BUG_ON(ret); | 990 | if (ret) |
991 | return ret; | ||
942 | next: | 992 | next: |
943 | cur_offset += victim_name_len + sizeof(*extref); | 993 | cur_offset += victim_name_len + sizeof(*extref); |
944 | } | 994 | } |
@@ -951,7 +1001,8 @@ next: | |||
951 | ref_index, name, namelen, 0); | 1001 | ref_index, name, namelen, 0); |
952 | if (di && !IS_ERR(di)) { | 1002 | if (di && !IS_ERR(di)) { |
953 | ret = drop_one_dir_item(trans, root, path, dir, di); | 1003 | ret = drop_one_dir_item(trans, root, path, dir, di); |
954 | BUG_ON(ret); | 1004 | if (ret) |
1005 | return ret; | ||
955 | } | 1006 | } |
956 | btrfs_release_path(path); | 1007 | btrfs_release_path(path); |
957 | 1008 | ||
@@ -960,7 +1011,8 @@ next: | |||
960 | name, namelen, 0); | 1011 | name, namelen, 0); |
961 | if (di && !IS_ERR(di)) { | 1012 | if (di && !IS_ERR(di)) { |
962 | ret = drop_one_dir_item(trans, root, path, dir, di); | 1013 | ret = drop_one_dir_item(trans, root, path, dir, di); |
963 | BUG_ON(ret); | 1014 | if (ret) |
1015 | return ret; | ||
964 | } | 1016 | } |
965 | btrfs_release_path(path); | 1017 | btrfs_release_path(path); |
966 | 1018 | ||
@@ -1105,15 +1157,19 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
1105 | parent_objectid, | 1157 | parent_objectid, |
1106 | ref_index, name, namelen, | 1158 | ref_index, name, namelen, |
1107 | &search_done); | 1159 | &search_done); |
1108 | if (ret == 1) | 1160 | if (ret == 1) { |
1161 | ret = 0; | ||
1162 | goto out; | ||
1163 | } | ||
1164 | if (ret) | ||
1109 | goto out; | 1165 | goto out; |
1110 | BUG_ON(ret); | ||
1111 | } | 1166 | } |
1112 | 1167 | ||
1113 | /* insert our name */ | 1168 | /* insert our name */ |
1114 | ret = btrfs_add_link(trans, dir, inode, name, namelen, | 1169 | ret = btrfs_add_link(trans, dir, inode, name, namelen, |
1115 | 0, ref_index); | 1170 | 0, ref_index); |
1116 | BUG_ON(ret); | 1171 | if (ret) |
1172 | goto out; | ||
1117 | 1173 | ||
1118 | btrfs_update_inode(trans, root, inode); | 1174 | btrfs_update_inode(trans, root, inode); |
1119 | } | 1175 | } |
@@ -1128,13 +1184,11 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
1128 | 1184 | ||
1129 | /* finally write the back reference in the inode */ | 1185 | /* finally write the back reference in the inode */ |
1130 | ret = overwrite_item(trans, root, path, eb, slot, key); | 1186 | ret = overwrite_item(trans, root, path, eb, slot, key); |
1131 | BUG_ON(ret); | ||
1132 | |||
1133 | out: | 1187 | out: |
1134 | btrfs_release_path(path); | 1188 | btrfs_release_path(path); |
1135 | iput(dir); | 1189 | iput(dir); |
1136 | iput(inode); | 1190 | iput(inode); |
1137 | return 0; | 1191 | return ret; |
1138 | } | 1192 | } |
1139 | 1193 | ||
1140 | static int insert_orphan_item(struct btrfs_trans_handle *trans, | 1194 | static int insert_orphan_item(struct btrfs_trans_handle *trans, |
@@ -1292,10 +1346,10 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
1292 | if (S_ISDIR(inode->i_mode)) { | 1346 | if (S_ISDIR(inode->i_mode)) { |
1293 | ret = replay_dir_deletes(trans, root, NULL, path, | 1347 | ret = replay_dir_deletes(trans, root, NULL, path, |
1294 | ino, 1); | 1348 | ino, 1); |
1295 | BUG_ON(ret); | 1349 | if (ret) |
1350 | goto out; | ||
1296 | } | 1351 | } |
1297 | ret = insert_orphan_item(trans, root, ino); | 1352 | ret = insert_orphan_item(trans, root, ino); |
1298 | BUG_ON(ret); | ||
1299 | } | 1353 | } |
1300 | 1354 | ||
1301 | out: | 1355 | out: |
@@ -1340,9 +1394,9 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, | |||
1340 | return -EIO; | 1394 | return -EIO; |
1341 | 1395 | ||
1342 | ret = fixup_inode_link_count(trans, root, inode); | 1396 | ret = fixup_inode_link_count(trans, root, inode); |
1343 | BUG_ON(ret); | ||
1344 | |||
1345 | iput(inode); | 1397 | iput(inode); |
1398 | if (ret) | ||
1399 | goto out; | ||
1346 | 1400 | ||
1347 | /* | 1401 | /* |
1348 | * fixup on a directory may create new entries, | 1402 | * fixup on a directory may create new entries, |
@@ -1384,12 +1438,15 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans, | |||
1384 | 1438 | ||
1385 | btrfs_release_path(path); | 1439 | btrfs_release_path(path); |
1386 | if (ret == 0) { | 1440 | if (ret == 0) { |
1387 | btrfs_inc_nlink(inode); | 1441 | if (!inode->i_nlink) |
1442 | set_nlink(inode, 1); | ||
1443 | else | ||
1444 | btrfs_inc_nlink(inode); | ||
1388 | ret = btrfs_update_inode(trans, root, inode); | 1445 | ret = btrfs_update_inode(trans, root, inode); |
1389 | } else if (ret == -EEXIST) { | 1446 | } else if (ret == -EEXIST) { |
1390 | ret = 0; | 1447 | ret = 0; |
1391 | } else { | 1448 | } else { |
1392 | BUG(); | 1449 | BUG(); /* Logic Error */ |
1393 | } | 1450 | } |
1394 | iput(inode); | 1451 | iput(inode); |
1395 | 1452 | ||
@@ -1458,7 +1515,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, | |||
1458 | struct inode *dir; | 1515 | struct inode *dir; |
1459 | u8 log_type; | 1516 | u8 log_type; |
1460 | int exists; | 1517 | int exists; |
1461 | int ret; | 1518 | int ret = 0; |
1462 | 1519 | ||
1463 | dir = read_one_inode(root, key->objectid); | 1520 | dir = read_one_inode(root, key->objectid); |
1464 | if (!dir) | 1521 | if (!dir) |
@@ -1490,7 +1547,9 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, | |||
1490 | key->offset, name, | 1547 | key->offset, name, |
1491 | name_len, 1); | 1548 | name_len, 1); |
1492 | } else { | 1549 | } else { |
1493 | BUG(); | 1550 | /* Corruption */ |
1551 | ret = -EINVAL; | ||
1552 | goto out; | ||
1494 | } | 1553 | } |
1495 | if (IS_ERR_OR_NULL(dst_di)) { | 1554 | if (IS_ERR_OR_NULL(dst_di)) { |
1496 | /* we need a sequence number to insert, so we only | 1555 | /* we need a sequence number to insert, so we only |
@@ -1518,7 +1577,8 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, | |||
1518 | goto out; | 1577 | goto out; |
1519 | 1578 | ||
1520 | ret = drop_one_dir_item(trans, root, path, dir, dst_di); | 1579 | ret = drop_one_dir_item(trans, root, path, dir, dst_di); |
1521 | BUG_ON(ret); | 1580 | if (ret) |
1581 | goto out; | ||
1522 | 1582 | ||
1523 | if (key->type == BTRFS_DIR_INDEX_KEY) | 1583 | if (key->type == BTRFS_DIR_INDEX_KEY) |
1524 | goto insert; | 1584 | goto insert; |
@@ -1526,14 +1586,15 @@ out: | |||
1526 | btrfs_release_path(path); | 1586 | btrfs_release_path(path); |
1527 | kfree(name); | 1587 | kfree(name); |
1528 | iput(dir); | 1588 | iput(dir); |
1529 | return 0; | 1589 | return ret; |
1530 | 1590 | ||
1531 | insert: | 1591 | insert: |
1532 | btrfs_release_path(path); | 1592 | btrfs_release_path(path); |
1533 | ret = insert_one_name(trans, root, path, key->objectid, key->offset, | 1593 | ret = insert_one_name(trans, root, path, key->objectid, key->offset, |
1534 | name, name_len, log_type, &log_key); | 1594 | name, name_len, log_type, &log_key); |
1535 | 1595 | if (ret && ret != -ENOENT) | |
1536 | BUG_ON(ret && ret != -ENOENT); | 1596 | goto out; |
1597 | ret = 0; | ||
1537 | goto out; | 1598 | goto out; |
1538 | } | 1599 | } |
1539 | 1600 | ||
@@ -1564,7 +1625,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, | |||
1564 | return -EIO; | 1625 | return -EIO; |
1565 | name_len = btrfs_dir_name_len(eb, di); | 1626 | name_len = btrfs_dir_name_len(eb, di); |
1566 | ret = replay_one_name(trans, root, path, eb, di, key); | 1627 | ret = replay_one_name(trans, root, path, eb, di, key); |
1567 | BUG_ON(ret); | 1628 | if (ret) |
1629 | return ret; | ||
1568 | ptr = (unsigned long)(di + 1); | 1630 | ptr = (unsigned long)(di + 1); |
1569 | ptr += name_len; | 1631 | ptr += name_len; |
1570 | } | 1632 | } |
@@ -1725,16 +1787,21 @@ again: | |||
1725 | 1787 | ||
1726 | ret = link_to_fixup_dir(trans, root, | 1788 | ret = link_to_fixup_dir(trans, root, |
1727 | path, location.objectid); | 1789 | path, location.objectid); |
1728 | BUG_ON(ret); | 1790 | if (ret) { |
1791 | kfree(name); | ||
1792 | iput(inode); | ||
1793 | goto out; | ||
1794 | } | ||
1795 | |||
1729 | btrfs_inc_nlink(inode); | 1796 | btrfs_inc_nlink(inode); |
1730 | ret = btrfs_unlink_inode(trans, root, dir, inode, | 1797 | ret = btrfs_unlink_inode(trans, root, dir, inode, |
1731 | name, name_len); | 1798 | name, name_len); |
1732 | BUG_ON(ret); | 1799 | if (!ret) |
1733 | 1800 | btrfs_run_delayed_items(trans, root); | |
1734 | btrfs_run_delayed_items(trans, root); | ||
1735 | |||
1736 | kfree(name); | 1801 | kfree(name); |
1737 | iput(inode); | 1802 | iput(inode); |
1803 | if (ret) | ||
1804 | goto out; | ||
1738 | 1805 | ||
1739 | /* there might still be more names under this key | 1806 | /* there might still be more names under this key |
1740 | * check and repeat if required | 1807 | * check and repeat if required |
@@ -1838,7 +1905,8 @@ again: | |||
1838 | ret = check_item_in_log(trans, root, log, path, | 1905 | ret = check_item_in_log(trans, root, log, path, |
1839 | log_path, dir, | 1906 | log_path, dir, |
1840 | &found_key); | 1907 | &found_key); |
1841 | BUG_ON(ret); | 1908 | if (ret) |
1909 | goto out; | ||
1842 | if (found_key.offset == (u64)-1) | 1910 | if (found_key.offset == (u64)-1) |
1843 | break; | 1911 | break; |
1844 | dir_key.offset = found_key.offset + 1; | 1912 | dir_key.offset = found_key.offset + 1; |
@@ -1915,11 +1983,13 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1915 | if (S_ISDIR(mode)) { | 1983 | if (S_ISDIR(mode)) { |
1916 | ret = replay_dir_deletes(wc->trans, | 1984 | ret = replay_dir_deletes(wc->trans, |
1917 | root, log, path, key.objectid, 0); | 1985 | root, log, path, key.objectid, 0); |
1918 | BUG_ON(ret); | 1986 | if (ret) |
1987 | break; | ||
1919 | } | 1988 | } |
1920 | ret = overwrite_item(wc->trans, root, path, | 1989 | ret = overwrite_item(wc->trans, root, path, |
1921 | eb, i, &key); | 1990 | eb, i, &key); |
1922 | BUG_ON(ret); | 1991 | if (ret) |
1992 | break; | ||
1923 | 1993 | ||
1924 | /* for regular files, make sure corresponding | 1994 | /* for regular files, make sure corresponding |
1925 | * orhpan item exist. extents past the new EOF | 1995 | * orhpan item exist. extents past the new EOF |
@@ -1928,12 +1998,14 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1928 | if (S_ISREG(mode)) { | 1998 | if (S_ISREG(mode)) { |
1929 | ret = insert_orphan_item(wc->trans, root, | 1999 | ret = insert_orphan_item(wc->trans, root, |
1930 | key.objectid); | 2000 | key.objectid); |
1931 | BUG_ON(ret); | 2001 | if (ret) |
2002 | break; | ||
1932 | } | 2003 | } |
1933 | 2004 | ||
1934 | ret = link_to_fixup_dir(wc->trans, root, | 2005 | ret = link_to_fixup_dir(wc->trans, root, |
1935 | path, key.objectid); | 2006 | path, key.objectid); |
1936 | BUG_ON(ret); | 2007 | if (ret) |
2008 | break; | ||
1937 | } | 2009 | } |
1938 | if (wc->stage < LOG_WALK_REPLAY_ALL) | 2010 | if (wc->stage < LOG_WALK_REPLAY_ALL) |
1939 | continue; | 2011 | continue; |
@@ -1942,28 +2014,35 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1942 | if (key.type == BTRFS_XATTR_ITEM_KEY) { | 2014 | if (key.type == BTRFS_XATTR_ITEM_KEY) { |
1943 | ret = overwrite_item(wc->trans, root, path, | 2015 | ret = overwrite_item(wc->trans, root, path, |
1944 | eb, i, &key); | 2016 | eb, i, &key); |
1945 | BUG_ON(ret); | 2017 | if (ret) |
2018 | break; | ||
1946 | } else if (key.type == BTRFS_INODE_REF_KEY) { | 2019 | } else if (key.type == BTRFS_INODE_REF_KEY) { |
1947 | ret = add_inode_ref(wc->trans, root, log, path, | 2020 | ret = add_inode_ref(wc->trans, root, log, path, |
1948 | eb, i, &key); | 2021 | eb, i, &key); |
1949 | BUG_ON(ret && ret != -ENOENT); | 2022 | if (ret && ret != -ENOENT) |
2023 | break; | ||
2024 | ret = 0; | ||
1950 | } else if (key.type == BTRFS_INODE_EXTREF_KEY) { | 2025 | } else if (key.type == BTRFS_INODE_EXTREF_KEY) { |
1951 | ret = add_inode_ref(wc->trans, root, log, path, | 2026 | ret = add_inode_ref(wc->trans, root, log, path, |
1952 | eb, i, &key); | 2027 | eb, i, &key); |
1953 | BUG_ON(ret && ret != -ENOENT); | 2028 | if (ret && ret != -ENOENT) |
2029 | break; | ||
2030 | ret = 0; | ||
1954 | } else if (key.type == BTRFS_EXTENT_DATA_KEY) { | 2031 | } else if (key.type == BTRFS_EXTENT_DATA_KEY) { |
1955 | ret = replay_one_extent(wc->trans, root, path, | 2032 | ret = replay_one_extent(wc->trans, root, path, |
1956 | eb, i, &key); | 2033 | eb, i, &key); |
1957 | BUG_ON(ret); | 2034 | if (ret) |
2035 | break; | ||
1958 | } else if (key.type == BTRFS_DIR_ITEM_KEY || | 2036 | } else if (key.type == BTRFS_DIR_ITEM_KEY || |
1959 | key.type == BTRFS_DIR_INDEX_KEY) { | 2037 | key.type == BTRFS_DIR_INDEX_KEY) { |
1960 | ret = replay_one_dir_item(wc->trans, root, path, | 2038 | ret = replay_one_dir_item(wc->trans, root, path, |
1961 | eb, i, &key); | 2039 | eb, i, &key); |
1962 | BUG_ON(ret); | 2040 | if (ret) |
2041 | break; | ||
1963 | } | 2042 | } |
1964 | } | 2043 | } |
1965 | btrfs_free_path(path); | 2044 | btrfs_free_path(path); |
1966 | return 0; | 2045 | return ret; |
1967 | } | 2046 | } |
1968 | 2047 | ||
1969 | static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | 2048 | static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, |
@@ -2008,8 +2087,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
2008 | 2087 | ||
2009 | if (*level == 1) { | 2088 | if (*level == 1) { |
2010 | ret = wc->process_func(root, next, wc, ptr_gen); | 2089 | ret = wc->process_func(root, next, wc, ptr_gen); |
2011 | if (ret) | 2090 | if (ret) { |
2091 | free_extent_buffer(next); | ||
2012 | return ret; | 2092 | return ret; |
2093 | } | ||
2013 | 2094 | ||
2014 | path->slots[*level]++; | 2095 | path->slots[*level]++; |
2015 | if (wc->free) { | 2096 | if (wc->free) { |
@@ -2029,7 +2110,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
2029 | BTRFS_TREE_LOG_OBJECTID); | 2110 | BTRFS_TREE_LOG_OBJECTID); |
2030 | ret = btrfs_free_and_pin_reserved_extent(root, | 2111 | ret = btrfs_free_and_pin_reserved_extent(root, |
2031 | bytenr, blocksize); | 2112 | bytenr, blocksize); |
2032 | BUG_ON(ret); /* -ENOMEM or logic errors */ | 2113 | if (ret) { |
2114 | free_extent_buffer(next); | ||
2115 | return ret; | ||
2116 | } | ||
2033 | } | 2117 | } |
2034 | free_extent_buffer(next); | 2118 | free_extent_buffer(next); |
2035 | continue; | 2119 | continue; |
@@ -2102,7 +2186,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
2102 | ret = btrfs_free_and_pin_reserved_extent(root, | 2186 | ret = btrfs_free_and_pin_reserved_extent(root, |
2103 | path->nodes[*level]->start, | 2187 | path->nodes[*level]->start, |
2104 | path->nodes[*level]->len); | 2188 | path->nodes[*level]->len); |
2105 | BUG_ON(ret); | 2189 | if (ret) |
2190 | return ret; | ||
2106 | } | 2191 | } |
2107 | free_extent_buffer(path->nodes[*level]); | 2192 | free_extent_buffer(path->nodes[*level]); |
2108 | path->nodes[*level] = NULL; | 2193 | path->nodes[*level] = NULL; |
@@ -2124,7 +2209,6 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
2124 | int wret; | 2209 | int wret; |
2125 | int level; | 2210 | int level; |
2126 | struct btrfs_path *path; | 2211 | struct btrfs_path *path; |
2127 | int i; | ||
2128 | int orig_level; | 2212 | int orig_level; |
2129 | 2213 | ||
2130 | path = btrfs_alloc_path(); | 2214 | path = btrfs_alloc_path(); |
@@ -2176,17 +2260,12 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
2176 | BTRFS_TREE_LOG_OBJECTID); | 2260 | BTRFS_TREE_LOG_OBJECTID); |
2177 | ret = btrfs_free_and_pin_reserved_extent(log, next->start, | 2261 | ret = btrfs_free_and_pin_reserved_extent(log, next->start, |
2178 | next->len); | 2262 | next->len); |
2179 | BUG_ON(ret); /* -ENOMEM or logic errors */ | 2263 | if (ret) |
2264 | goto out; | ||
2180 | } | 2265 | } |
2181 | } | 2266 | } |
2182 | 2267 | ||
2183 | out: | 2268 | out: |
2184 | for (i = 0; i <= orig_level; i++) { | ||
2185 | if (path->nodes[i]) { | ||
2186 | free_extent_buffer(path->nodes[i]); | ||
2187 | path->nodes[i] = NULL; | ||
2188 | } | ||
2189 | } | ||
2190 | btrfs_free_path(path); | 2269 | btrfs_free_path(path); |
2191 | return ret; | 2270 | return ret; |
2192 | } | 2271 | } |
@@ -2281,6 +2360,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2281 | unsigned long log_transid = 0; | 2360 | unsigned long log_transid = 0; |
2282 | 2361 | ||
2283 | mutex_lock(&root->log_mutex); | 2362 | mutex_lock(&root->log_mutex); |
2363 | log_transid = root->log_transid; | ||
2284 | index1 = root->log_transid % 2; | 2364 | index1 = root->log_transid % 2; |
2285 | if (atomic_read(&root->log_commit[index1])) { | 2365 | if (atomic_read(&root->log_commit[index1])) { |
2286 | wait_log_commit(trans, root, root->log_transid); | 2366 | wait_log_commit(trans, root, root->log_transid); |
@@ -2308,11 +2388,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2308 | /* bail out if we need to do a full commit */ | 2388 | /* bail out if we need to do a full commit */ |
2309 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2389 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
2310 | ret = -EAGAIN; | 2390 | ret = -EAGAIN; |
2391 | btrfs_free_logged_extents(log, log_transid); | ||
2311 | mutex_unlock(&root->log_mutex); | 2392 | mutex_unlock(&root->log_mutex); |
2312 | goto out; | 2393 | goto out; |
2313 | } | 2394 | } |
2314 | 2395 | ||
2315 | log_transid = root->log_transid; | ||
2316 | if (log_transid % 2 == 0) | 2396 | if (log_transid % 2 == 0) |
2317 | mark = EXTENT_DIRTY; | 2397 | mark = EXTENT_DIRTY; |
2318 | else | 2398 | else |
@@ -2324,6 +2404,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2324 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); | 2404 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); |
2325 | if (ret) { | 2405 | if (ret) { |
2326 | btrfs_abort_transaction(trans, root, ret); | 2406 | btrfs_abort_transaction(trans, root, ret); |
2407 | btrfs_free_logged_extents(log, log_transid); | ||
2327 | mutex_unlock(&root->log_mutex); | 2408 | mutex_unlock(&root->log_mutex); |
2328 | goto out; | 2409 | goto out; |
2329 | } | 2410 | } |
@@ -2363,6 +2444,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2363 | } | 2444 | } |
2364 | root->fs_info->last_trans_log_full_commit = trans->transid; | 2445 | root->fs_info->last_trans_log_full_commit = trans->transid; |
2365 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2446 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2447 | btrfs_free_logged_extents(log, log_transid); | ||
2366 | mutex_unlock(&log_root_tree->log_mutex); | 2448 | mutex_unlock(&log_root_tree->log_mutex); |
2367 | ret = -EAGAIN; | 2449 | ret = -EAGAIN; |
2368 | goto out; | 2450 | goto out; |
@@ -2373,6 +2455,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2373 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2455 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2374 | wait_log_commit(trans, log_root_tree, | 2456 | wait_log_commit(trans, log_root_tree, |
2375 | log_root_tree->log_transid); | 2457 | log_root_tree->log_transid); |
2458 | btrfs_free_logged_extents(log, log_transid); | ||
2376 | mutex_unlock(&log_root_tree->log_mutex); | 2459 | mutex_unlock(&log_root_tree->log_mutex); |
2377 | ret = 0; | 2460 | ret = 0; |
2378 | goto out; | 2461 | goto out; |
@@ -2392,6 +2475,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2392 | */ | 2475 | */ |
2393 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2476 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
2394 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2477 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2478 | btrfs_free_logged_extents(log, log_transid); | ||
2395 | mutex_unlock(&log_root_tree->log_mutex); | 2479 | mutex_unlock(&log_root_tree->log_mutex); |
2396 | ret = -EAGAIN; | 2480 | ret = -EAGAIN; |
2397 | goto out_wake_log_root; | 2481 | goto out_wake_log_root; |
@@ -2402,10 +2486,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2402 | EXTENT_DIRTY | EXTENT_NEW); | 2486 | EXTENT_DIRTY | EXTENT_NEW); |
2403 | if (ret) { | 2487 | if (ret) { |
2404 | btrfs_abort_transaction(trans, root, ret); | 2488 | btrfs_abort_transaction(trans, root, ret); |
2489 | btrfs_free_logged_extents(log, log_transid); | ||
2405 | mutex_unlock(&log_root_tree->log_mutex); | 2490 | mutex_unlock(&log_root_tree->log_mutex); |
2406 | goto out_wake_log_root; | 2491 | goto out_wake_log_root; |
2407 | } | 2492 | } |
2408 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2493 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2494 | btrfs_wait_logged_extents(log, log_transid); | ||
2409 | 2495 | ||
2410 | btrfs_set_super_log_root(root->fs_info->super_for_commit, | 2496 | btrfs_set_super_log_root(root->fs_info->super_for_commit, |
2411 | log_root_tree->node->start); | 2497 | log_root_tree->node->start); |
@@ -2461,8 +2547,13 @@ static void free_log_tree(struct btrfs_trans_handle *trans, | |||
2461 | .process_func = process_one_buffer | 2547 | .process_func = process_one_buffer |
2462 | }; | 2548 | }; |
2463 | 2549 | ||
2464 | ret = walk_log_tree(trans, log, &wc); | 2550 | if (trans) { |
2465 | BUG_ON(ret); | 2551 | ret = walk_log_tree(trans, log, &wc); |
2552 | |||
2553 | /* I don't think this can happen but just in case */ | ||
2554 | if (ret) | ||
2555 | btrfs_abort_transaction(trans, log, ret); | ||
2556 | } | ||
2466 | 2557 | ||
2467 | while (1) { | 2558 | while (1) { |
2468 | ret = find_first_extent_bit(&log->dirty_log_pages, | 2559 | ret = find_first_extent_bit(&log->dirty_log_pages, |
@@ -2475,6 +2566,14 @@ static void free_log_tree(struct btrfs_trans_handle *trans, | |||
2475 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); | 2566 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); |
2476 | } | 2567 | } |
2477 | 2568 | ||
2569 | /* | ||
2570 | * We may have short-circuited the log tree with the full commit logic | ||
2571 | * and left ordered extents on our list, so clear these out to keep us | ||
2572 | * from leaking inodes and memory. | ||
2573 | */ | ||
2574 | btrfs_free_logged_extents(log, 0); | ||
2575 | btrfs_free_logged_extents(log, 1); | ||
2576 | |||
2478 | free_extent_buffer(log->node); | 2577 | free_extent_buffer(log->node); |
2479 | kfree(log); | 2578 | kfree(log); |
2480 | } | 2579 | } |
@@ -2561,7 +2660,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2561 | if (di) { | 2660 | if (di) { |
2562 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2661 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
2563 | bytes_del += name_len; | 2662 | bytes_del += name_len; |
2564 | BUG_ON(ret); | 2663 | if (ret) { |
2664 | err = ret; | ||
2665 | goto fail; | ||
2666 | } | ||
2565 | } | 2667 | } |
2566 | btrfs_release_path(path); | 2668 | btrfs_release_path(path); |
2567 | di = btrfs_lookup_dir_index_item(trans, log, path, dir_ino, | 2669 | di = btrfs_lookup_dir_index_item(trans, log, path, dir_ino, |
@@ -2573,7 +2675,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2573 | if (di) { | 2675 | if (di) { |
2574 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2676 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
2575 | bytes_del += name_len; | 2677 | bytes_del += name_len; |
2576 | BUG_ON(ret); | 2678 | if (ret) { |
2679 | err = ret; | ||
2680 | goto fail; | ||
2681 | } | ||
2577 | } | 2682 | } |
2578 | 2683 | ||
2579 | /* update the directory size in the log to reflect the names | 2684 | /* update the directory size in the log to reflect the names |
@@ -2724,7 +2829,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2724 | path->keep_locks = 1; | 2829 | path->keep_locks = 1; |
2725 | 2830 | ||
2726 | ret = btrfs_search_forward(root, &min_key, &max_key, | 2831 | ret = btrfs_search_forward(root, &min_key, &max_key, |
2727 | path, 0, trans->transid); | 2832 | path, trans->transid); |
2728 | 2833 | ||
2729 | /* | 2834 | /* |
2730 | * we didn't find anything from this transaction, see if there | 2835 | * we didn't find anything from this transaction, see if there |
@@ -2912,7 +3017,7 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
2912 | 3017 | ||
2913 | while (1) { | 3018 | while (1) { |
2914 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); | 3019 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); |
2915 | BUG_ON(ret == 0); | 3020 | BUG_ON(ret == 0); /* Logic error */ |
2916 | if (ret < 0) | 3021 | if (ret < 0) |
2917 | break; | 3022 | break; |
2918 | 3023 | ||
@@ -3115,7 +3220,11 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
3115 | log->fs_info->csum_root, | 3220 | log->fs_info->csum_root, |
3116 | ds + cs, ds + cs + cl - 1, | 3221 | ds + cs, ds + cs + cl - 1, |
3117 | &ordered_sums, 0); | 3222 | &ordered_sums, 0); |
3118 | BUG_ON(ret); | 3223 | if (ret) { |
3224 | btrfs_release_path(dst_path); | ||
3225 | kfree(ins_data); | ||
3226 | return ret; | ||
3227 | } | ||
3119 | } | 3228 | } |
3120 | } | 3229 | } |
3121 | } | 3230 | } |
@@ -3155,115 +3264,6 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
3155 | return 0; | 3264 | return 0; |
3156 | } | 3265 | } |
3157 | 3266 | ||
3158 | static int drop_adjacent_extents(struct btrfs_trans_handle *trans, | ||
3159 | struct btrfs_root *root, struct inode *inode, | ||
3160 | struct extent_map *em, | ||
3161 | struct btrfs_path *path) | ||
3162 | { | ||
3163 | struct btrfs_file_extent_item *fi; | ||
3164 | struct extent_buffer *leaf; | ||
3165 | struct btrfs_key key, new_key; | ||
3166 | struct btrfs_map_token token; | ||
3167 | u64 extent_end; | ||
3168 | u64 extent_offset = 0; | ||
3169 | int extent_type; | ||
3170 | int del_slot = 0; | ||
3171 | int del_nr = 0; | ||
3172 | int ret = 0; | ||
3173 | |||
3174 | while (1) { | ||
3175 | btrfs_init_map_token(&token); | ||
3176 | leaf = path->nodes[0]; | ||
3177 | path->slots[0]++; | ||
3178 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | ||
3179 | if (del_nr) { | ||
3180 | ret = btrfs_del_items(trans, root, path, | ||
3181 | del_slot, del_nr); | ||
3182 | if (ret) | ||
3183 | return ret; | ||
3184 | del_nr = 0; | ||
3185 | } | ||
3186 | |||
3187 | ret = btrfs_next_leaf_write(trans, root, path, 1); | ||
3188 | if (ret < 0) | ||
3189 | return ret; | ||
3190 | if (ret > 0) | ||
3191 | return 0; | ||
3192 | leaf = path->nodes[0]; | ||
3193 | } | ||
3194 | |||
3195 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
3196 | if (key.objectid != btrfs_ino(inode) || | ||
3197 | key.type != BTRFS_EXTENT_DATA_KEY || | ||
3198 | key.offset >= em->start + em->len) | ||
3199 | break; | ||
3200 | |||
3201 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
3202 | struct btrfs_file_extent_item); | ||
3203 | extent_type = btrfs_token_file_extent_type(leaf, fi, &token); | ||
3204 | if (extent_type == BTRFS_FILE_EXTENT_REG || | ||
3205 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
3206 | extent_offset = btrfs_token_file_extent_offset(leaf, | ||
3207 | fi, &token); | ||
3208 | extent_end = key.offset + | ||
3209 | btrfs_token_file_extent_num_bytes(leaf, fi, | ||
3210 | &token); | ||
3211 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | ||
3212 | extent_end = key.offset + | ||
3213 | btrfs_file_extent_inline_len(leaf, fi); | ||
3214 | } else { | ||
3215 | BUG(); | ||
3216 | } | ||
3217 | |||
3218 | if (extent_end <= em->len + em->start) { | ||
3219 | if (!del_nr) { | ||
3220 | del_slot = path->slots[0]; | ||
3221 | } | ||
3222 | del_nr++; | ||
3223 | continue; | ||
3224 | } | ||
3225 | |||
3226 | /* | ||
3227 | * Ok so we'll ignore previous items if we log a new extent, | ||
3228 | * which can lead to overlapping extents, so if we have an | ||
3229 | * existing extent we want to adjust we _have_ to check the next | ||
3230 | * guy to make sure we even need this extent anymore, this keeps | ||
3231 | * us from panicing in set_item_key_safe. | ||
3232 | */ | ||
3233 | if (path->slots[0] < btrfs_header_nritems(leaf) - 1) { | ||
3234 | struct btrfs_key tmp_key; | ||
3235 | |||
3236 | btrfs_item_key_to_cpu(leaf, &tmp_key, | ||
3237 | path->slots[0] + 1); | ||
3238 | if (tmp_key.objectid == btrfs_ino(inode) && | ||
3239 | tmp_key.type == BTRFS_EXTENT_DATA_KEY && | ||
3240 | tmp_key.offset <= em->start + em->len) { | ||
3241 | if (!del_nr) | ||
3242 | del_slot = path->slots[0]; | ||
3243 | del_nr++; | ||
3244 | continue; | ||
3245 | } | ||
3246 | } | ||
3247 | |||
3248 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); | ||
3249 | memcpy(&new_key, &key, sizeof(new_key)); | ||
3250 | new_key.offset = em->start + em->len; | ||
3251 | btrfs_set_item_key_safe(trans, root, path, &new_key); | ||
3252 | extent_offset += em->start + em->len - key.offset; | ||
3253 | btrfs_set_token_file_extent_offset(leaf, fi, extent_offset, | ||
3254 | &token); | ||
3255 | btrfs_set_token_file_extent_num_bytes(leaf, fi, extent_end - | ||
3256 | (em->start + em->len), | ||
3257 | &token); | ||
3258 | btrfs_mark_buffer_dirty(leaf); | ||
3259 | } | ||
3260 | |||
3261 | if (del_nr) | ||
3262 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | ||
3263 | |||
3264 | return ret; | ||
3265 | } | ||
3266 | |||
3267 | static int log_one_extent(struct btrfs_trans_handle *trans, | 3267 | static int log_one_extent(struct btrfs_trans_handle *trans, |
3268 | struct inode *inode, struct btrfs_root *root, | 3268 | struct inode *inode, struct btrfs_root *root, |
3269 | struct extent_map *em, struct btrfs_path *path) | 3269 | struct extent_map *em, struct btrfs_path *path) |
@@ -3271,31 +3271,38 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3271 | struct btrfs_root *log = root->log_root; | 3271 | struct btrfs_root *log = root->log_root; |
3272 | struct btrfs_file_extent_item *fi; | 3272 | struct btrfs_file_extent_item *fi; |
3273 | struct extent_buffer *leaf; | 3273 | struct extent_buffer *leaf; |
3274 | struct btrfs_ordered_extent *ordered; | ||
3274 | struct list_head ordered_sums; | 3275 | struct list_head ordered_sums; |
3275 | struct btrfs_map_token token; | 3276 | struct btrfs_map_token token; |
3276 | struct btrfs_key key; | 3277 | struct btrfs_key key; |
3277 | u64 csum_offset = em->mod_start - em->start; | 3278 | u64 mod_start = em->mod_start; |
3278 | u64 csum_len = em->mod_len; | 3279 | u64 mod_len = em->mod_len; |
3280 | u64 csum_offset; | ||
3281 | u64 csum_len; | ||
3279 | u64 extent_offset = em->start - em->orig_start; | 3282 | u64 extent_offset = em->start - em->orig_start; |
3280 | u64 block_len; | 3283 | u64 block_len; |
3281 | int ret; | 3284 | int ret; |
3285 | int index = log->log_transid % 2; | ||
3282 | bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; | 3286 | bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
3283 | 3287 | ||
3288 | ret = __btrfs_drop_extents(trans, log, inode, path, em->start, | ||
3289 | em->start + em->len, NULL, 0); | ||
3290 | if (ret) | ||
3291 | return ret; | ||
3292 | |||
3284 | INIT_LIST_HEAD(&ordered_sums); | 3293 | INIT_LIST_HEAD(&ordered_sums); |
3285 | btrfs_init_map_token(&token); | 3294 | btrfs_init_map_token(&token); |
3286 | key.objectid = btrfs_ino(inode); | 3295 | key.objectid = btrfs_ino(inode); |
3287 | key.type = BTRFS_EXTENT_DATA_KEY; | 3296 | key.type = BTRFS_EXTENT_DATA_KEY; |
3288 | key.offset = em->start; | 3297 | key.offset = em->start; |
3289 | path->really_keep_locks = 1; | ||
3290 | 3298 | ||
3291 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi)); | 3299 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi)); |
3292 | if (ret && ret != -EEXIST) { | 3300 | if (ret) |
3293 | path->really_keep_locks = 0; | ||
3294 | return ret; | 3301 | return ret; |
3295 | } | ||
3296 | leaf = path->nodes[0]; | 3302 | leaf = path->nodes[0]; |
3297 | fi = btrfs_item_ptr(leaf, path->slots[0], | 3303 | fi = btrfs_item_ptr(leaf, path->slots[0], |
3298 | struct btrfs_file_extent_item); | 3304 | struct btrfs_file_extent_item); |
3305 | |||
3299 | btrfs_set_token_file_extent_generation(leaf, fi, em->generation, | 3306 | btrfs_set_token_file_extent_generation(leaf, fi, em->generation, |
3300 | &token); | 3307 | &token); |
3301 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { | 3308 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { |
@@ -3334,22 +3341,14 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3334 | em->start - em->orig_start, | 3341 | em->start - em->orig_start, |
3335 | &token); | 3342 | &token); |
3336 | btrfs_set_token_file_extent_num_bytes(leaf, fi, em->len, &token); | 3343 | btrfs_set_token_file_extent_num_bytes(leaf, fi, em->len, &token); |
3337 | btrfs_set_token_file_extent_ram_bytes(leaf, fi, em->len, &token); | 3344 | btrfs_set_token_file_extent_ram_bytes(leaf, fi, em->ram_bytes, &token); |
3338 | btrfs_set_token_file_extent_compression(leaf, fi, em->compress_type, | 3345 | btrfs_set_token_file_extent_compression(leaf, fi, em->compress_type, |
3339 | &token); | 3346 | &token); |
3340 | btrfs_set_token_file_extent_encryption(leaf, fi, 0, &token); | 3347 | btrfs_set_token_file_extent_encryption(leaf, fi, 0, &token); |
3341 | btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token); | 3348 | btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token); |
3342 | btrfs_mark_buffer_dirty(leaf); | 3349 | btrfs_mark_buffer_dirty(leaf); |
3343 | 3350 | ||
3344 | /* | ||
3345 | * Have to check the extent to the right of us to make sure it doesn't | ||
3346 | * fall in our current range. We're ok if the previous extent is in our | ||
3347 | * range since the recovery stuff will run us in key order and thus just | ||
3348 | * drop the part we overwrote. | ||
3349 | */ | ||
3350 | ret = drop_adjacent_extents(trans, log, inode, em, path); | ||
3351 | btrfs_release_path(path); | 3351 | btrfs_release_path(path); |
3352 | path->really_keep_locks = 0; | ||
3353 | if (ret) { | 3352 | if (ret) { |
3354 | return ret; | 3353 | return ret; |
3355 | } | 3354 | } |
@@ -3362,6 +3361,92 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3362 | csum_len = block_len; | 3361 | csum_len = block_len; |
3363 | } | 3362 | } |
3364 | 3363 | ||
3364 | /* | ||
3365 | * First check and see if our csums are on our outstanding ordered | ||
3366 | * extents. | ||
3367 | */ | ||
3368 | again: | ||
3369 | spin_lock_irq(&log->log_extents_lock[index]); | ||
3370 | list_for_each_entry(ordered, &log->logged_list[index], log_list) { | ||
3371 | struct btrfs_ordered_sum *sum; | ||
3372 | |||
3373 | if (!mod_len) | ||
3374 | break; | ||
3375 | |||
3376 | if (ordered->inode != inode) | ||
3377 | continue; | ||
3378 | |||
3379 | if (ordered->file_offset + ordered->len <= mod_start || | ||
3380 | mod_start + mod_len <= ordered->file_offset) | ||
3381 | continue; | ||
3382 | |||
3383 | /* | ||
3384 | * We are going to copy all the csums on this ordered extent, so | ||
3385 | * go ahead and adjust mod_start and mod_len in case this | ||
3386 | * ordered extent has already been logged. | ||
3387 | */ | ||
3388 | if (ordered->file_offset > mod_start) { | ||
3389 | if (ordered->file_offset + ordered->len >= | ||
3390 | mod_start + mod_len) | ||
3391 | mod_len = ordered->file_offset - mod_start; | ||
3392 | /* | ||
3393 | * If we have this case | ||
3394 | * | ||
3395 | * |--------- logged extent ---------| | ||
3396 | * |----- ordered extent ----| | ||
3397 | * | ||
3398 | * Just don't mess with mod_start and mod_len, we'll | ||
3399 | * just end up logging more csums than we need and it | ||
3400 | * will be ok. | ||
3401 | */ | ||
3402 | } else { | ||
3403 | if (ordered->file_offset + ordered->len < | ||
3404 | mod_start + mod_len) { | ||
3405 | mod_len = (mod_start + mod_len) - | ||
3406 | (ordered->file_offset + ordered->len); | ||
3407 | mod_start = ordered->file_offset + | ||
3408 | ordered->len; | ||
3409 | } else { | ||
3410 | mod_len = 0; | ||
3411 | } | ||
3412 | } | ||
3413 | |||
3414 | /* | ||
3415 | * To keep us from looping for the above case of an ordered | ||
3416 | * extent that falls inside of the logged extent. | ||
3417 | */ | ||
3418 | if (test_and_set_bit(BTRFS_ORDERED_LOGGED_CSUM, | ||
3419 | &ordered->flags)) | ||
3420 | continue; | ||
3421 | atomic_inc(&ordered->refs); | ||
3422 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
3423 | /* | ||
3424 | * we've dropped the lock, we must either break or | ||
3425 | * start over after this. | ||
3426 | */ | ||
3427 | |||
3428 | wait_event(ordered->wait, ordered->csum_bytes_left == 0); | ||
3429 | |||
3430 | list_for_each_entry(sum, &ordered->list, list) { | ||
3431 | ret = btrfs_csum_file_blocks(trans, log, sum); | ||
3432 | if (ret) { | ||
3433 | btrfs_put_ordered_extent(ordered); | ||
3434 | goto unlocked; | ||
3435 | } | ||
3436 | } | ||
3437 | btrfs_put_ordered_extent(ordered); | ||
3438 | goto again; | ||
3439 | |||
3440 | } | ||
3441 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
3442 | unlocked: | ||
3443 | |||
3444 | if (!mod_len || ret) | ||
3445 | return ret; | ||
3446 | |||
3447 | csum_offset = mod_start - em->start; | ||
3448 | csum_len = mod_len; | ||
3449 | |||
3365 | /* block start is already adjusted for the file extent offset. */ | 3450 | /* block start is already adjusted for the file extent offset. */ |
3366 | ret = btrfs_lookup_csums_range(log->fs_info->csum_root, | 3451 | ret = btrfs_lookup_csums_range(log->fs_info->csum_root, |
3367 | em->block_start + csum_offset, | 3452 | em->block_start + csum_offset, |
@@ -3393,6 +3478,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
3393 | struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree; | 3478 | struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree; |
3394 | u64 test_gen; | 3479 | u64 test_gen; |
3395 | int ret = 0; | 3480 | int ret = 0; |
3481 | int num = 0; | ||
3396 | 3482 | ||
3397 | INIT_LIST_HEAD(&extents); | 3483 | INIT_LIST_HEAD(&extents); |
3398 | 3484 | ||
@@ -3401,16 +3487,31 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
3401 | 3487 | ||
3402 | list_for_each_entry_safe(em, n, &tree->modified_extents, list) { | 3488 | list_for_each_entry_safe(em, n, &tree->modified_extents, list) { |
3403 | list_del_init(&em->list); | 3489 | list_del_init(&em->list); |
3490 | |||
3491 | /* | ||
3492 | * Just an arbitrary number, this can be really CPU intensive | ||
3493 | * once we start getting a lot of extents, and really once we | ||
3494 | * have a bunch of extents we just want to commit since it will | ||
3495 | * be faster. | ||
3496 | */ | ||
3497 | if (++num > 32768) { | ||
3498 | list_del_init(&tree->modified_extents); | ||
3499 | ret = -EFBIG; | ||
3500 | goto process; | ||
3501 | } | ||
3502 | |||
3404 | if (em->generation <= test_gen) | 3503 | if (em->generation <= test_gen) |
3405 | continue; | 3504 | continue; |
3406 | /* Need a ref to keep it from getting evicted from cache */ | 3505 | /* Need a ref to keep it from getting evicted from cache */ |
3407 | atomic_inc(&em->refs); | 3506 | atomic_inc(&em->refs); |
3408 | set_bit(EXTENT_FLAG_LOGGING, &em->flags); | 3507 | set_bit(EXTENT_FLAG_LOGGING, &em->flags); |
3409 | list_add_tail(&em->list, &extents); | 3508 | list_add_tail(&em->list, &extents); |
3509 | num++; | ||
3410 | } | 3510 | } |
3411 | 3511 | ||
3412 | list_sort(NULL, &extents, extent_cmp); | 3512 | list_sort(NULL, &extents, extent_cmp); |
3413 | 3513 | ||
3514 | process: | ||
3414 | while (!list_empty(&extents)) { | 3515 | while (!list_empty(&extents)) { |
3415 | em = list_entry(extents.next, struct extent_map, list); | 3516 | em = list_entry(extents.next, struct extent_map, list); |
3416 | 3517 | ||
@@ -3472,8 +3573,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3472 | bool fast_search = false; | 3573 | bool fast_search = false; |
3473 | u64 ino = btrfs_ino(inode); | 3574 | u64 ino = btrfs_ino(inode); |
3474 | 3575 | ||
3475 | log = root->log_root; | ||
3476 | |||
3477 | path = btrfs_alloc_path(); | 3576 | path = btrfs_alloc_path(); |
3478 | if (!path) | 3577 | if (!path) |
3479 | return -ENOMEM; | 3578 | return -ENOMEM; |
@@ -3513,6 +3612,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3513 | 3612 | ||
3514 | mutex_lock(&BTRFS_I(inode)->log_mutex); | 3613 | mutex_lock(&BTRFS_I(inode)->log_mutex); |
3515 | 3614 | ||
3615 | btrfs_get_logged_extents(log, inode); | ||
3616 | |||
3516 | /* | 3617 | /* |
3517 | * a brute force approach to making sure we get the most uptodate | 3618 | * a brute force approach to making sure we get the most uptodate |
3518 | * copies of everything. | 3619 | * copies of everything. |
@@ -3558,7 +3659,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3558 | while (1) { | 3659 | while (1) { |
3559 | ins_nr = 0; | 3660 | ins_nr = 0; |
3560 | ret = btrfs_search_forward(root, &min_key, &max_key, | 3661 | ret = btrfs_search_forward(root, &min_key, &max_key, |
3561 | path, 0, trans->transid); | 3662 | path, trans->transid); |
3562 | if (ret != 0) | 3663 | if (ret != 0) |
3563 | break; | 3664 | break; |
3564 | again: | 3665 | again: |
@@ -3656,6 +3757,8 @@ log_extents: | |||
3656 | BTRFS_I(inode)->logged_trans = trans->transid; | 3757 | BTRFS_I(inode)->logged_trans = trans->transid; |
3657 | BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans; | 3758 | BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans; |
3658 | out_unlock: | 3759 | out_unlock: |
3760 | if (err) | ||
3761 | btrfs_free_logged_extents(log, log->log_transid); | ||
3659 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 3762 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
3660 | 3763 | ||
3661 | btrfs_free_path(path); | 3764 | btrfs_free_path(path); |
@@ -3736,9 +3839,9 @@ out: | |||
3736 | * only logging is done of any parent directories that are older than | 3839 | * only logging is done of any parent directories that are older than |
3737 | * the last committed transaction | 3840 | * the last committed transaction |
3738 | */ | 3841 | */ |
3739 | int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | 3842 | static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, |
3740 | struct btrfs_root *root, struct inode *inode, | 3843 | struct btrfs_root *root, struct inode *inode, |
3741 | struct dentry *parent, int exists_only) | 3844 | struct dentry *parent, int exists_only) |
3742 | { | 3845 | { |
3743 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; | 3846 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; |
3744 | struct super_block *sb; | 3847 | struct super_block *sb; |
@@ -3822,7 +3925,6 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
3822 | end_trans: | 3925 | end_trans: |
3823 | dput(old_parent); | 3926 | dput(old_parent); |
3824 | if (ret < 0) { | 3927 | if (ret < 0) { |
3825 | WARN_ON(ret != -ENOSPC); | ||
3826 | root->fs_info->last_trans_log_full_commit = trans->transid; | 3928 | root->fs_info->last_trans_log_full_commit = trans->transid; |
3827 | ret = 1; | 3929 | ret = 1; |
3828 | } | 3930 | } |
@@ -3930,6 +4032,9 @@ again: | |||
3930 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); | 4032 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); |
3931 | if (IS_ERR(wc.replay_dest)) { | 4033 | if (IS_ERR(wc.replay_dest)) { |
3932 | ret = PTR_ERR(wc.replay_dest); | 4034 | ret = PTR_ERR(wc.replay_dest); |
4035 | free_extent_buffer(log->node); | ||
4036 | free_extent_buffer(log->commit_root); | ||
4037 | kfree(log); | ||
3933 | btrfs_error(fs_info, ret, "Couldn't read target root " | 4038 | btrfs_error(fs_info, ret, "Couldn't read target root " |
3934 | "for tree log recovery."); | 4039 | "for tree log recovery."); |
3935 | goto error; | 4040 | goto error; |
@@ -3938,12 +4043,10 @@ again: | |||
3938 | wc.replay_dest->log_root = log; | 4043 | wc.replay_dest->log_root = log; |
3939 | btrfs_record_root_in_trans(trans, wc.replay_dest); | 4044 | btrfs_record_root_in_trans(trans, wc.replay_dest); |
3940 | ret = walk_log_tree(trans, log, &wc); | 4045 | ret = walk_log_tree(trans, log, &wc); |
3941 | BUG_ON(ret); | ||
3942 | 4046 | ||
3943 | if (wc.stage == LOG_WALK_REPLAY_ALL) { | 4047 | if (!ret && wc.stage == LOG_WALK_REPLAY_ALL) { |
3944 | ret = fixup_inode_link_counts(trans, wc.replay_dest, | 4048 | ret = fixup_inode_link_counts(trans, wc.replay_dest, |
3945 | path); | 4049 | path); |
3946 | BUG_ON(ret); | ||
3947 | } | 4050 | } |
3948 | 4051 | ||
3949 | key.offset = found_key.offset - 1; | 4052 | key.offset = found_key.offset - 1; |
@@ -3952,6 +4055,9 @@ again: | |||
3952 | free_extent_buffer(log->commit_root); | 4055 | free_extent_buffer(log->commit_root); |
3953 | kfree(log); | 4056 | kfree(log); |
3954 | 4057 | ||
4058 | if (ret) | ||
4059 | goto error; | ||
4060 | |||
3955 | if (found_key.offset == 0) | 4061 | if (found_key.offset == 0) |
3956 | break; | 4062 | break; |
3957 | } | 4063 | } |
@@ -3972,17 +4078,20 @@ again: | |||
3972 | 4078 | ||
3973 | btrfs_free_path(path); | 4079 | btrfs_free_path(path); |
3974 | 4080 | ||
4081 | /* step 4: commit the transaction, which also unpins the blocks */ | ||
4082 | ret = btrfs_commit_transaction(trans, fs_info->tree_root); | ||
4083 | if (ret) | ||
4084 | return ret; | ||
4085 | |||
3975 | free_extent_buffer(log_root_tree->node); | 4086 | free_extent_buffer(log_root_tree->node); |
3976 | log_root_tree->log_root = NULL; | 4087 | log_root_tree->log_root = NULL; |
3977 | fs_info->log_root_recovering = 0; | 4088 | fs_info->log_root_recovering = 0; |
3978 | |||
3979 | /* step 4: commit the transaction, which also unpins the blocks */ | ||
3980 | btrfs_commit_transaction(trans, fs_info->tree_root); | ||
3981 | |||
3982 | kfree(log_root_tree); | 4089 | kfree(log_root_tree); |
3983 | return 0; | ||
3984 | 4090 | ||
4091 | return 0; | ||
3985 | error: | 4092 | error: |
4093 | if (wc.trans) | ||
4094 | btrfs_end_transaction(wc.trans, fs_info->tree_root); | ||
3986 | btrfs_free_path(path); | 4095 | btrfs_free_path(path); |
3987 | return ret; | 4096 | return ret; |
3988 | } | 4097 | } |