diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 128 |
1 files changed, 98 insertions, 30 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index feaa13b105d9..29ff749ff4ca 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/writeback.h> | 28 | #include <linux/writeback.h> |
29 | #include <linux/statfs.h> | 29 | #include <linux/statfs.h> |
30 | #include <linux/compat.h> | 30 | #include <linux/compat.h> |
31 | #include <linux/slab.h> | ||
31 | #include "ctree.h" | 32 | #include "ctree.h" |
32 | #include "disk-io.h" | 33 | #include "disk-io.h" |
33 | #include "transaction.h" | 34 | #include "transaction.h" |
@@ -123,7 +124,8 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
123 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | 124 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
124 | 125 | ||
125 | end_of_last_block = start_pos + num_bytes - 1; | 126 | end_of_last_block = start_pos + num_bytes - 1; |
126 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block); | 127 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
128 | NULL); | ||
127 | if (err) | 129 | if (err) |
128 | return err; | 130 | return err; |
129 | 131 | ||
@@ -506,7 +508,8 @@ next_slot: | |||
506 | } | 508 | } |
507 | 509 | ||
508 | static int extent_mergeable(struct extent_buffer *leaf, int slot, | 510 | static int extent_mergeable(struct extent_buffer *leaf, int slot, |
509 | u64 objectid, u64 bytenr, u64 *start, u64 *end) | 511 | u64 objectid, u64 bytenr, u64 orig_offset, |
512 | u64 *start, u64 *end) | ||
510 | { | 513 | { |
511 | struct btrfs_file_extent_item *fi; | 514 | struct btrfs_file_extent_item *fi; |
512 | struct btrfs_key key; | 515 | struct btrfs_key key; |
@@ -522,6 +525,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
522 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 525 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
523 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || | 526 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || |
524 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || | 527 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || |
528 | btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset || | ||
525 | btrfs_file_extent_compression(leaf, fi) || | 529 | btrfs_file_extent_compression(leaf, fi) || |
526 | btrfs_file_extent_encryption(leaf, fi) || | 530 | btrfs_file_extent_encryption(leaf, fi) || |
527 | btrfs_file_extent_other_encoding(leaf, fi)) | 531 | btrfs_file_extent_other_encoding(leaf, fi)) |
@@ -561,6 +565,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
561 | u64 split; | 565 | u64 split; |
562 | int del_nr = 0; | 566 | int del_nr = 0; |
563 | int del_slot = 0; | 567 | int del_slot = 0; |
568 | int recow; | ||
564 | int ret; | 569 | int ret; |
565 | 570 | ||
566 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 571 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
@@ -568,6 +573,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
568 | path = btrfs_alloc_path(); | 573 | path = btrfs_alloc_path(); |
569 | BUG_ON(!path); | 574 | BUG_ON(!path); |
570 | again: | 575 | again: |
576 | recow = 0; | ||
571 | split = start; | 577 | split = start; |
572 | key.objectid = inode->i_ino; | 578 | key.objectid = inode->i_ino; |
573 | key.type = BTRFS_EXTENT_DATA_KEY; | 579 | key.type = BTRFS_EXTENT_DATA_KEY; |
@@ -591,12 +597,60 @@ again: | |||
591 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 597 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
592 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | 598 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); |
593 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); | 599 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); |
600 | memcpy(&new_key, &key, sizeof(new_key)); | ||
601 | |||
602 | if (start == key.offset && end < extent_end) { | ||
603 | other_start = 0; | ||
604 | other_end = start; | ||
605 | if (extent_mergeable(leaf, path->slots[0] - 1, | ||
606 | inode->i_ino, bytenr, orig_offset, | ||
607 | &other_start, &other_end)) { | ||
608 | new_key.offset = end; | ||
609 | btrfs_set_item_key_safe(trans, root, path, &new_key); | ||
610 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
611 | struct btrfs_file_extent_item); | ||
612 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
613 | extent_end - end); | ||
614 | btrfs_set_file_extent_offset(leaf, fi, | ||
615 | end - orig_offset); | ||
616 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | ||
617 | struct btrfs_file_extent_item); | ||
618 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
619 | end - other_start); | ||
620 | btrfs_mark_buffer_dirty(leaf); | ||
621 | goto out; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | if (start > key.offset && end == extent_end) { | ||
626 | other_start = end; | ||
627 | other_end = 0; | ||
628 | if (extent_mergeable(leaf, path->slots[0] + 1, | ||
629 | inode->i_ino, bytenr, orig_offset, | ||
630 | &other_start, &other_end)) { | ||
631 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
632 | struct btrfs_file_extent_item); | ||
633 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
634 | start - key.offset); | ||
635 | path->slots[0]++; | ||
636 | new_key.offset = start; | ||
637 | btrfs_set_item_key_safe(trans, root, path, &new_key); | ||
638 | |||
639 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
640 | struct btrfs_file_extent_item); | ||
641 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
642 | other_end - start); | ||
643 | btrfs_set_file_extent_offset(leaf, fi, | ||
644 | start - orig_offset); | ||
645 | btrfs_mark_buffer_dirty(leaf); | ||
646 | goto out; | ||
647 | } | ||
648 | } | ||
594 | 649 | ||
595 | while (start > key.offset || end < extent_end) { | 650 | while (start > key.offset || end < extent_end) { |
596 | if (key.offset == start) | 651 | if (key.offset == start) |
597 | split = end; | 652 | split = end; |
598 | 653 | ||
599 | memcpy(&new_key, &key, sizeof(new_key)); | ||
600 | new_key.offset = split; | 654 | new_key.offset = split; |
601 | ret = btrfs_duplicate_item(trans, root, path, &new_key); | 655 | ret = btrfs_duplicate_item(trans, root, path, &new_key); |
602 | if (ret == -EAGAIN) { | 656 | if (ret == -EAGAIN) { |
@@ -631,15 +685,18 @@ again: | |||
631 | path->slots[0]--; | 685 | path->slots[0]--; |
632 | extent_end = end; | 686 | extent_end = end; |
633 | } | 687 | } |
688 | recow = 1; | ||
634 | } | 689 | } |
635 | 690 | ||
636 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
637 | struct btrfs_file_extent_item); | ||
638 | |||
639 | other_start = end; | 691 | other_start = end; |
640 | other_end = 0; | 692 | other_end = 0; |
641 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | 693 | if (extent_mergeable(leaf, path->slots[0] + 1, |
642 | bytenr, &other_start, &other_end)) { | 694 | inode->i_ino, bytenr, orig_offset, |
695 | &other_start, &other_end)) { | ||
696 | if (recow) { | ||
697 | btrfs_release_path(root, path); | ||
698 | goto again; | ||
699 | } | ||
643 | extent_end = other_end; | 700 | extent_end = other_end; |
644 | del_slot = path->slots[0] + 1; | 701 | del_slot = path->slots[0] + 1; |
645 | del_nr++; | 702 | del_nr++; |
@@ -650,8 +707,13 @@ again: | |||
650 | } | 707 | } |
651 | other_start = 0; | 708 | other_start = 0; |
652 | other_end = start; | 709 | other_end = start; |
653 | if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, | 710 | if (extent_mergeable(leaf, path->slots[0] - 1, |
654 | bytenr, &other_start, &other_end)) { | 711 | inode->i_ino, bytenr, orig_offset, |
712 | &other_start, &other_end)) { | ||
713 | if (recow) { | ||
714 | btrfs_release_path(root, path); | ||
715 | goto again; | ||
716 | } | ||
655 | key.offset = other_start; | 717 | key.offset = other_start; |
656 | del_slot = path->slots[0]; | 718 | del_slot = path->slots[0]; |
657 | del_nr++; | 719 | del_nr++; |
@@ -661,21 +723,23 @@ again: | |||
661 | BUG_ON(ret); | 723 | BUG_ON(ret); |
662 | } | 724 | } |
663 | if (del_nr == 0) { | 725 | if (del_nr == 0) { |
726 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
727 | struct btrfs_file_extent_item); | ||
664 | btrfs_set_file_extent_type(leaf, fi, | 728 | btrfs_set_file_extent_type(leaf, fi, |
665 | BTRFS_FILE_EXTENT_REG); | 729 | BTRFS_FILE_EXTENT_REG); |
666 | btrfs_mark_buffer_dirty(leaf); | 730 | btrfs_mark_buffer_dirty(leaf); |
667 | goto out; | 731 | } else { |
668 | } | 732 | fi = btrfs_item_ptr(leaf, del_slot - 1, |
669 | 733 | struct btrfs_file_extent_item); | |
670 | fi = btrfs_item_ptr(leaf, del_slot - 1, | 734 | btrfs_set_file_extent_type(leaf, fi, |
671 | struct btrfs_file_extent_item); | 735 | BTRFS_FILE_EXTENT_REG); |
672 | btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); | 736 | btrfs_set_file_extent_num_bytes(leaf, fi, |
673 | btrfs_set_file_extent_num_bytes(leaf, fi, | 737 | extent_end - key.offset); |
674 | extent_end - key.offset); | 738 | btrfs_mark_buffer_dirty(leaf); |
675 | btrfs_mark_buffer_dirty(leaf); | ||
676 | 739 | ||
677 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | 740 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); |
678 | BUG_ON(ret); | 741 | BUG_ON(ret); |
742 | } | ||
679 | out: | 743 | out: |
680 | btrfs_free_path(path); | 744 | btrfs_free_path(path); |
681 | return 0; | 745 | return 0; |
@@ -691,6 +755,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
691 | loff_t pos, unsigned long first_index, | 755 | loff_t pos, unsigned long first_index, |
692 | unsigned long last_index, size_t write_bytes) | 756 | unsigned long last_index, size_t write_bytes) |
693 | { | 757 | { |
758 | struct extent_state *cached_state = NULL; | ||
694 | int i; | 759 | int i; |
695 | unsigned long index = pos >> PAGE_CACHE_SHIFT; | 760 | unsigned long index = pos >> PAGE_CACHE_SHIFT; |
696 | struct inode *inode = fdentry(file)->d_inode; | 761 | struct inode *inode = fdentry(file)->d_inode; |
@@ -719,16 +784,18 @@ again: | |||
719 | } | 784 | } |
720 | if (start_pos < inode->i_size) { | 785 | if (start_pos < inode->i_size) { |
721 | struct btrfs_ordered_extent *ordered; | 786 | struct btrfs_ordered_extent *ordered; |
722 | lock_extent(&BTRFS_I(inode)->io_tree, | 787 | lock_extent_bits(&BTRFS_I(inode)->io_tree, |
723 | start_pos, last_pos - 1, GFP_NOFS); | 788 | start_pos, last_pos - 1, 0, &cached_state, |
789 | GFP_NOFS); | ||
724 | ordered = btrfs_lookup_first_ordered_extent(inode, | 790 | ordered = btrfs_lookup_first_ordered_extent(inode, |
725 | last_pos - 1); | 791 | last_pos - 1); |
726 | if (ordered && | 792 | if (ordered && |
727 | ordered->file_offset + ordered->len > start_pos && | 793 | ordered->file_offset + ordered->len > start_pos && |
728 | ordered->file_offset < last_pos) { | 794 | ordered->file_offset < last_pos) { |
729 | btrfs_put_ordered_extent(ordered); | 795 | btrfs_put_ordered_extent(ordered); |
730 | unlock_extent(&BTRFS_I(inode)->io_tree, | 796 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, |
731 | start_pos, last_pos - 1, GFP_NOFS); | 797 | start_pos, last_pos - 1, |
798 | &cached_state, GFP_NOFS); | ||
732 | for (i = 0; i < num_pages; i++) { | 799 | for (i = 0; i < num_pages; i++) { |
733 | unlock_page(pages[i]); | 800 | unlock_page(pages[i]); |
734 | page_cache_release(pages[i]); | 801 | page_cache_release(pages[i]); |
@@ -740,12 +807,13 @@ again: | |||
740 | if (ordered) | 807 | if (ordered) |
741 | btrfs_put_ordered_extent(ordered); | 808 | btrfs_put_ordered_extent(ordered); |
742 | 809 | ||
743 | clear_extent_bits(&BTRFS_I(inode)->io_tree, start_pos, | 810 | clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos, |
744 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC | | 811 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC | |
745 | EXTENT_DO_ACCOUNTING, | 812 | EXTENT_DO_ACCOUNTING, 0, 0, &cached_state, |
746 | GFP_NOFS); | 813 | GFP_NOFS); |
747 | unlock_extent(&BTRFS_I(inode)->io_tree, | 814 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, |
748 | start_pos, last_pos - 1, GFP_NOFS); | 815 | start_pos, last_pos - 1, &cached_state, |
816 | GFP_NOFS); | ||
749 | } | 817 | } |
750 | for (i = 0; i < num_pages; i++) { | 818 | for (i = 0; i < num_pages; i++) { |
751 | clear_page_dirty_for_io(pages[i]); | 819 | clear_page_dirty_for_io(pages[i]); |
@@ -1073,7 +1141,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1073 | } | 1141 | } |
1074 | mutex_lock(&dentry->d_inode->i_mutex); | 1142 | mutex_lock(&dentry->d_inode->i_mutex); |
1075 | out: | 1143 | out: |
1076 | return ret > 0 ? EIO : ret; | 1144 | return ret > 0 ? -EIO : ret; |
1077 | } | 1145 | } |
1078 | 1146 | ||
1079 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 1147 | static const struct vm_operations_struct btrfs_file_vm_ops = { |