diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 117 |
1 files changed, 78 insertions, 39 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c800d58f3013..f447b783bb84 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -70,6 +70,19 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
70 | 70 | ||
71 | /* Flush processor's dcache for this page */ | 71 | /* Flush processor's dcache for this page */ |
72 | flush_dcache_page(page); | 72 | flush_dcache_page(page); |
73 | |||
74 | /* | ||
75 | * if we get a partial write, we can end up with | ||
76 | * partially up to date pages. These add | ||
77 | * a lot of complexity, so make sure they don't | ||
78 | * happen by forcing this copy to be retried. | ||
79 | * | ||
80 | * The rest of the btrfs_file_write code will fall | ||
81 | * back to page at a time copies after we return 0. | ||
82 | */ | ||
83 | if (!PageUptodate(page) && copied < count) | ||
84 | copied = 0; | ||
85 | |||
73 | iov_iter_advance(i, copied); | 86 | iov_iter_advance(i, copied); |
74 | write_bytes -= copied; | 87 | write_bytes -= copied; |
75 | total_copied += copied; | 88 | total_copied += copied; |
@@ -186,6 +199,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
186 | split = alloc_extent_map(GFP_NOFS); | 199 | split = alloc_extent_map(GFP_NOFS); |
187 | if (!split2) | 200 | if (!split2) |
188 | split2 = alloc_extent_map(GFP_NOFS); | 201 | split2 = alloc_extent_map(GFP_NOFS); |
202 | BUG_ON(!split || !split2); | ||
189 | 203 | ||
190 | write_lock(&em_tree->lock); | 204 | write_lock(&em_tree->lock); |
191 | em = lookup_extent_mapping(em_tree, start, len); | 205 | em = lookup_extent_mapping(em_tree, start, len); |
@@ -762,6 +776,27 @@ out: | |||
762 | } | 776 | } |
763 | 777 | ||
764 | /* | 778 | /* |
779 | * on error we return an unlocked page and the error value | ||
780 | * on success we return a locked page and 0 | ||
781 | */ | ||
782 | static int prepare_uptodate_page(struct page *page, u64 pos) | ||
783 | { | ||
784 | int ret = 0; | ||
785 | |||
786 | if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { | ||
787 | ret = btrfs_readpage(NULL, page); | ||
788 | if (ret) | ||
789 | return ret; | ||
790 | lock_page(page); | ||
791 | if (!PageUptodate(page)) { | ||
792 | unlock_page(page); | ||
793 | return -EIO; | ||
794 | } | ||
795 | } | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /* | ||
765 | * this gets pages into the page cache and locks them down, it also properly | 800 | * this gets pages into the page cache and locks them down, it also properly |
766 | * waits for data=ordered extents to finish before allowing the pages to be | 801 | * waits for data=ordered extents to finish before allowing the pages to be |
767 | * modified. | 802 | * modified. |
@@ -776,6 +811,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
776 | unsigned long index = pos >> PAGE_CACHE_SHIFT; | 811 | unsigned long index = pos >> PAGE_CACHE_SHIFT; |
777 | struct inode *inode = fdentry(file)->d_inode; | 812 | struct inode *inode = fdentry(file)->d_inode; |
778 | int err = 0; | 813 | int err = 0; |
814 | int faili = 0; | ||
779 | u64 start_pos; | 815 | u64 start_pos; |
780 | u64 last_pos; | 816 | u64 last_pos; |
781 | 817 | ||
@@ -793,11 +829,24 @@ again: | |||
793 | for (i = 0; i < num_pages; i++) { | 829 | for (i = 0; i < num_pages; i++) { |
794 | pages[i] = grab_cache_page(inode->i_mapping, index + i); | 830 | pages[i] = grab_cache_page(inode->i_mapping, index + i); |
795 | if (!pages[i]) { | 831 | if (!pages[i]) { |
832 | faili = i - 1; | ||
796 | err = -ENOMEM; | 833 | err = -ENOMEM; |
797 | BUG_ON(1); | 834 | goto fail; |
835 | } | ||
836 | |||
837 | if (i == 0) | ||
838 | err = prepare_uptodate_page(pages[i], pos); | ||
839 | if (i == num_pages - 1) | ||
840 | err = prepare_uptodate_page(pages[i], | ||
841 | pos + write_bytes); | ||
842 | if (err) { | ||
843 | page_cache_release(pages[i]); | ||
844 | faili = i - 1; | ||
845 | goto fail; | ||
798 | } | 846 | } |
799 | wait_on_page_writeback(pages[i]); | 847 | wait_on_page_writeback(pages[i]); |
800 | } | 848 | } |
849 | err = 0; | ||
801 | if (start_pos < inode->i_size) { | 850 | if (start_pos < inode->i_size) { |
802 | struct btrfs_ordered_extent *ordered; | 851 | struct btrfs_ordered_extent *ordered; |
803 | lock_extent_bits(&BTRFS_I(inode)->io_tree, | 852 | lock_extent_bits(&BTRFS_I(inode)->io_tree, |
@@ -837,6 +886,14 @@ again: | |||
837 | WARN_ON(!PageLocked(pages[i])); | 886 | WARN_ON(!PageLocked(pages[i])); |
838 | } | 887 | } |
839 | return 0; | 888 | return 0; |
889 | fail: | ||
890 | while (faili >= 0) { | ||
891 | unlock_page(pages[faili]); | ||
892 | page_cache_release(pages[faili]); | ||
893 | faili--; | ||
894 | } | ||
895 | return err; | ||
896 | |||
840 | } | 897 | } |
841 | 898 | ||
842 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | 899 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, |
@@ -846,7 +903,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
846 | struct file *file = iocb->ki_filp; | 903 | struct file *file = iocb->ki_filp; |
847 | struct inode *inode = fdentry(file)->d_inode; | 904 | struct inode *inode = fdentry(file)->d_inode; |
848 | struct btrfs_root *root = BTRFS_I(inode)->root; | 905 | struct btrfs_root *root = BTRFS_I(inode)->root; |
849 | struct page *pinned[2]; | ||
850 | struct page **pages = NULL; | 906 | struct page **pages = NULL; |
851 | struct iov_iter i; | 907 | struct iov_iter i; |
852 | loff_t *ppos = &iocb->ki_pos; | 908 | loff_t *ppos = &iocb->ki_pos; |
@@ -867,9 +923,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
867 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || | 923 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || |
868 | (file->f_flags & O_DIRECT)); | 924 | (file->f_flags & O_DIRECT)); |
869 | 925 | ||
870 | pinned[0] = NULL; | ||
871 | pinned[1] = NULL; | ||
872 | |||
873 | start_pos = pos; | 926 | start_pos = pos; |
874 | 927 | ||
875 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 928 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
@@ -946,6 +999,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
946 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / | 999 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / |
947 | (sizeof(struct page *))); | 1000 | (sizeof(struct page *))); |
948 | pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); | 1001 | pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); |
1002 | if (!pages) { | ||
1003 | ret = -ENOMEM; | ||
1004 | goto out; | ||
1005 | } | ||
949 | 1006 | ||
950 | /* generic_write_checks can change our pos */ | 1007 | /* generic_write_checks can change our pos */ |
951 | start_pos = pos; | 1008 | start_pos = pos; |
@@ -953,39 +1010,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
953 | first_index = pos >> PAGE_CACHE_SHIFT; | 1010 | first_index = pos >> PAGE_CACHE_SHIFT; |
954 | last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; | 1011 | last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; |
955 | 1012 | ||
956 | /* | ||
957 | * there are lots of better ways to do this, but this code | ||
958 | * makes sure the first and last page in the file range are | ||
959 | * up to date and ready for cow | ||
960 | */ | ||
961 | if ((pos & (PAGE_CACHE_SIZE - 1))) { | ||
962 | pinned[0] = grab_cache_page(inode->i_mapping, first_index); | ||
963 | if (!PageUptodate(pinned[0])) { | ||
964 | ret = btrfs_readpage(NULL, pinned[0]); | ||
965 | BUG_ON(ret); | ||
966 | wait_on_page_locked(pinned[0]); | ||
967 | } else { | ||
968 | unlock_page(pinned[0]); | ||
969 | } | ||
970 | } | ||
971 | if ((pos + iov_iter_count(&i)) & (PAGE_CACHE_SIZE - 1)) { | ||
972 | pinned[1] = grab_cache_page(inode->i_mapping, last_index); | ||
973 | if (!PageUptodate(pinned[1])) { | ||
974 | ret = btrfs_readpage(NULL, pinned[1]); | ||
975 | BUG_ON(ret); | ||
976 | wait_on_page_locked(pinned[1]); | ||
977 | } else { | ||
978 | unlock_page(pinned[1]); | ||
979 | } | ||
980 | } | ||
981 | |||
982 | while (iov_iter_count(&i) > 0) { | 1013 | while (iov_iter_count(&i) > 0) { |
983 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); | 1014 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); |
984 | size_t write_bytes = min(iov_iter_count(&i), | 1015 | size_t write_bytes = min(iov_iter_count(&i), |
985 | nrptrs * (size_t)PAGE_CACHE_SIZE - | 1016 | nrptrs * (size_t)PAGE_CACHE_SIZE - |
986 | offset); | 1017 | offset); |
987 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> | 1018 | size_t num_pages = (write_bytes + offset + |
988 | PAGE_CACHE_SHIFT; | 1019 | PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
989 | 1020 | ||
990 | WARN_ON(num_pages > nrptrs); | 1021 | WARN_ON(num_pages > nrptrs); |
991 | memset(pages, 0, sizeof(struct page *) * nrptrs); | 1022 | memset(pages, 0, sizeof(struct page *) * nrptrs); |
@@ -1015,8 +1046,20 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1015 | 1046 | ||
1016 | copied = btrfs_copy_from_user(pos, num_pages, | 1047 | copied = btrfs_copy_from_user(pos, num_pages, |
1017 | write_bytes, pages, &i); | 1048 | write_bytes, pages, &i); |
1018 | dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >> | 1049 | |
1019 | PAGE_CACHE_SHIFT; | 1050 | /* |
1051 | * if we have trouble faulting in the pages, fall | ||
1052 | * back to one page at a time | ||
1053 | */ | ||
1054 | if (copied < write_bytes) | ||
1055 | nrptrs = 1; | ||
1056 | |||
1057 | if (copied == 0) | ||
1058 | dirty_pages = 0; | ||
1059 | else | ||
1060 | dirty_pages = (copied + offset + | ||
1061 | PAGE_CACHE_SIZE - 1) >> | ||
1062 | PAGE_CACHE_SHIFT; | ||
1020 | 1063 | ||
1021 | if (num_pages > dirty_pages) { | 1064 | if (num_pages > dirty_pages) { |
1022 | if (copied > 0) | 1065 | if (copied > 0) |
@@ -1060,10 +1103,6 @@ out: | |||
1060 | err = ret; | 1103 | err = ret; |
1061 | 1104 | ||
1062 | kfree(pages); | 1105 | kfree(pages); |
1063 | if (pinned[0]) | ||
1064 | page_cache_release(pinned[0]); | ||
1065 | if (pinned[1]) | ||
1066 | page_cache_release(pinned[1]); | ||
1067 | *ppos = pos; | 1106 | *ppos = pos; |
1068 | 1107 | ||
1069 | /* | 1108 | /* |