aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorZheng Yan <zheng.yan@oracle.com>2008-09-23 13:14:14 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:07 -0400
commit31840ae1a6b433ca0e6a8d341756ff478bbf959e (patch)
tree9343db596aec175e9640aa2800b80f01496d7047 /fs/btrfs/file.c
parent1c2308f8e7d8491467e0095af2b01500f1b70819 (diff)
Btrfs: Full back reference support
This patch makes the back reference system to explicit record the location of parent node for all types of extents. The location of parent node is placed into the offset field of backref key. Every time a tree block is balanced, the back references for the affected lower level extents are updated. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c121
1 files changed, 56 insertions, 65 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 58b329ddb426..48a702d41c8c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -524,6 +524,9 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans,
524{ 524{
525 u64 extent_end = 0; 525 u64 extent_end = 0;
526 u64 search_start = start; 526 u64 search_start = start;
527 u64 leaf_start;
528 u64 root_gen;
529 u64 root_owner;
527 struct extent_buffer *leaf; 530 struct extent_buffer *leaf;
528 struct btrfs_file_extent_item *extent; 531 struct btrfs_file_extent_item *extent;
529 struct btrfs_path *path; 532 struct btrfs_path *path;
@@ -562,6 +565,9 @@ next_slot:
562 bookend = 0; 565 bookend = 0;
563 found_extent = 0; 566 found_extent = 0;
564 found_inline = 0; 567 found_inline = 0;
568 leaf_start = 0;
569 root_gen = 0;
570 root_owner = 0;
565 extent = NULL; 571 extent = NULL;
566 leaf = path->nodes[0]; 572 leaf = path->nodes[0];
567 slot = path->slots[0]; 573 slot = path->slots[0];
@@ -628,27 +634,18 @@ next_slot:
628 search_start = extent_end; 634 search_start = extent_end;
629 if (end <= extent_end && start >= key.offset && found_inline) { 635 if (end <= extent_end && start >= key.offset && found_inline) {
630 *hint_byte = EXTENT_MAP_INLINE; 636 *hint_byte = EXTENT_MAP_INLINE;
631 continue; 637 goto out;
638 }
639
640 if (found_extent) {
641 read_extent_buffer(leaf, &old, (unsigned long)extent,
642 sizeof(old));
643 root_gen = btrfs_header_generation(leaf);
644 root_owner = btrfs_header_owner(leaf);
645 leaf_start = leaf->start;
632 } 646 }
647
633 if (end < extent_end && end >= key.offset) { 648 if (end < extent_end && end >= key.offset) {
634 if (found_extent) {
635 u64 disk_bytenr =
636 btrfs_file_extent_disk_bytenr(leaf, extent);
637 u64 disk_num_bytes =
638 btrfs_file_extent_disk_num_bytes(leaf,
639 extent);
640 read_extent_buffer(leaf, &old,
641 (unsigned long)extent,
642 sizeof(old));
643 if (disk_bytenr != 0) {
644 ret = btrfs_inc_extent_ref(trans, root,
645 disk_bytenr, disk_num_bytes,
646 root->root_key.objectid,
647 trans->transid,
648 key.objectid, end);
649 BUG_ON(ret);
650 }
651 }
652 bookend = 1; 649 bookend = 1;
653 if (found_inline && start <= key.offset) 650 if (found_inline && start <= key.offset)
654 keep = 1; 651 keep = 1;
@@ -687,49 +684,12 @@ next_slot:
687 } 684 }
688 /* delete the entire extent */ 685 /* delete the entire extent */
689 if (!keep) { 686 if (!keep) {
690 u64 disk_bytenr = 0;
691 u64 disk_num_bytes = 0;
692 u64 extent_num_bytes = 0;
693 u64 root_gen;
694 u64 root_owner;
695
696 root_gen = btrfs_header_generation(leaf);
697 root_owner = btrfs_header_owner(leaf);
698 if (found_extent) {
699 disk_bytenr =
700 btrfs_file_extent_disk_bytenr(leaf,
701 extent);
702 disk_num_bytes =
703 btrfs_file_extent_disk_num_bytes(leaf,
704 extent);
705 extent_num_bytes =
706 btrfs_file_extent_num_bytes(leaf, extent);
707 *hint_byte =
708 btrfs_file_extent_disk_bytenr(leaf,
709 extent);
710 }
711 ret = btrfs_del_item(trans, root, path); 687 ret = btrfs_del_item(trans, root, path);
712 /* TODO update progress marker and return */ 688 /* TODO update progress marker and return */
713 BUG_ON(ret); 689 BUG_ON(ret);
714 btrfs_release_path(root, path);
715 extent = NULL; 690 extent = NULL;
716 if (found_extent && disk_bytenr != 0) { 691 btrfs_release_path(root, path);
717 dec_i_blocks(inode, extent_num_bytes); 692 /* the extent will be freed later */
718 ret = btrfs_free_extent(trans, root,
719 disk_bytenr,
720 disk_num_bytes,
721 root_owner,
722 root_gen, inode->i_ino,
723 key.offset, 0);
724 }
725
726 BUG_ON(ret);
727 if (!bookend && search_start >= end) {
728 ret = 0;
729 goto out;
730 }
731 if (!bookend)
732 continue;
733 } 693 }
734 if (bookend && found_inline && start <= key.offset) { 694 if (bookend && found_inline && start <= key.offset) {
735 u32 new_size; 695 u32 new_size;
@@ -737,10 +697,13 @@ next_slot:
737 extent_end - end); 697 extent_end - end);
738 dec_i_blocks(inode, (extent_end - key.offset) - 698 dec_i_blocks(inode, (extent_end - key.offset) -
739 (extent_end - end)); 699 (extent_end - end));
740 btrfs_truncate_item(trans, root, path, new_size, 0); 700 ret = btrfs_truncate_item(trans, root, path,
701 new_size, 0);
702 BUG_ON(ret);
741 } 703 }
742 /* create bookend, splitting the extent in two */ 704 /* create bookend, splitting the extent in two */
743 if (bookend && found_extent) { 705 if (bookend && found_extent) {
706 u64 disk_bytenr;
744 struct btrfs_key ins; 707 struct btrfs_key ins;
745 ins.objectid = inode->i_ino; 708 ins.objectid = inode->i_ino;
746 ins.offset = end; 709 ins.offset = end;
@@ -748,13 +711,9 @@ next_slot:
748 btrfs_release_path(root, path); 711 btrfs_release_path(root, path);
749 ret = btrfs_insert_empty_item(trans, root, path, &ins, 712 ret = btrfs_insert_empty_item(trans, root, path, &ins,
750 sizeof(*extent)); 713 sizeof(*extent));
714 BUG_ON(ret);
751 715
752 leaf = path->nodes[0]; 716 leaf = path->nodes[0];
753 if (ret) {
754 btrfs_print_leaf(root, leaf);
755 printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.type, ins.offset, start, end, key.offset, extent_end, keep);
756 }
757 BUG_ON(ret);
758 extent = btrfs_item_ptr(leaf, path->slots[0], 717 extent = btrfs_item_ptr(leaf, path->slots[0],
759 struct btrfs_file_extent_item); 718 struct btrfs_file_extent_item);
760 write_extent_buffer(leaf, &old, 719 write_extent_buffer(leaf, &old,
@@ -770,11 +729,43 @@ next_slot:
770 BTRFS_FILE_EXTENT_REG); 729 BTRFS_FILE_EXTENT_REG);
771 730
772 btrfs_mark_buffer_dirty(path->nodes[0]); 731 btrfs_mark_buffer_dirty(path->nodes[0]);
773 if (le64_to_cpu(old.disk_bytenr) != 0) { 732
733 disk_bytenr = le64_to_cpu(old.disk_bytenr);
734 if (disk_bytenr != 0) {
735 ret = btrfs_inc_extent_ref(trans, root,
736 disk_bytenr,
737 le64_to_cpu(old.disk_num_bytes),
738 leaf->start,
739 root->root_key.objectid,
740 trans->transid,
741 ins.objectid, ins.offset);
742 BUG_ON(ret);
743 }
744 btrfs_release_path(root, path);
745 if (disk_bytenr != 0) {
774 inode->i_blocks += 746 inode->i_blocks +=
775 btrfs_file_extent_num_bytes(leaf, 747 btrfs_file_extent_num_bytes(leaf,
776 extent) >> 9; 748 extent) >> 9;
777 } 749 }
750 }
751
752 if (found_extent && !keep) {
753 u64 disk_bytenr = le64_to_cpu(old.disk_bytenr);
754
755 if (disk_bytenr != 0) {
756 dec_i_blocks(inode, le64_to_cpu(old.num_bytes));
757 ret = btrfs_free_extent(trans, root,
758 disk_bytenr,
759 le64_to_cpu(old.disk_num_bytes),
760 leaf_start, root_owner,
761 root_gen, key.objectid,
762 key.offset, 0);
763 BUG_ON(ret);
764 *hint_byte = disk_bytenr;
765 }
766 }
767
768 if (search_start >= end) {
778 ret = 0; 769 ret = 0;
779 goto out; 770 goto out;
780 } 771 }