aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
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 }