diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d247fc0eea19..2f83448d34fe 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -3200,14 +3200,10 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, | |||
3200 | return ret; | 3200 | return ret; |
3201 | } | 3201 | } |
3202 | 3202 | ||
3203 | static noinline void update_nr_written(struct page *page, | 3203 | static void update_nr_written(struct page *page, struct writeback_control *wbc, |
3204 | struct writeback_control *wbc, | 3204 | unsigned long nr_written) |
3205 | unsigned long nr_written) | ||
3206 | { | 3205 | { |
3207 | wbc->nr_to_write -= nr_written; | 3206 | wbc->nr_to_write -= nr_written; |
3208 | if (wbc->range_cyclic || (wbc->nr_to_write > 0 && | ||
3209 | wbc->range_start == 0 && wbc->range_end == LLONG_MAX)) | ||
3210 | page->mapping->writeback_index = page->index + nr_written; | ||
3211 | } | 3207 | } |
3212 | 3208 | ||
3213 | /* | 3209 | /* |
@@ -3368,6 +3364,8 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, | |||
3368 | 3364 | ||
3369 | while (cur <= end) { | 3365 | while (cur <= end) { |
3370 | u64 em_end; | 3366 | u64 em_end; |
3367 | unsigned long max_nr; | ||
3368 | |||
3371 | if (cur >= i_size) { | 3369 | if (cur >= i_size) { |
3372 | if (tree->ops && tree->ops->writepage_end_io_hook) | 3370 | if (tree->ops && tree->ops->writepage_end_io_hook) |
3373 | tree->ops->writepage_end_io_hook(page, cur, | 3371 | tree->ops->writepage_end_io_hook(page, cur, |
@@ -3423,32 +3421,23 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, | |||
3423 | continue; | 3421 | continue; |
3424 | } | 3422 | } |
3425 | 3423 | ||
3426 | if (tree->ops && tree->ops->writepage_io_hook) { | 3424 | max_nr = (i_size >> PAGE_SHIFT) + 1; |
3427 | ret = tree->ops->writepage_io_hook(page, cur, | 3425 | |
3428 | cur + iosize - 1); | 3426 | set_range_writeback(tree, cur, cur + iosize - 1); |
3429 | } else { | 3427 | if (!PageWriteback(page)) { |
3430 | ret = 0; | 3428 | btrfs_err(BTRFS_I(inode)->root->fs_info, |
3429 | "page %lu not writeback, cur %llu end %llu", | ||
3430 | page->index, cur, end); | ||
3431 | } | 3431 | } |
3432 | if (ret) { | ||
3433 | SetPageError(page); | ||
3434 | } else { | ||
3435 | unsigned long max_nr = (i_size >> PAGE_SHIFT) + 1; | ||
3436 | 3432 | ||
3437 | set_range_writeback(tree, cur, cur + iosize - 1); | 3433 | ret = submit_extent_page(write_flags, tree, wbc, page, |
3438 | if (!PageWriteback(page)) { | 3434 | sector, iosize, pg_offset, |
3439 | btrfs_err(BTRFS_I(inode)->root->fs_info, | 3435 | bdev, &epd->bio, max_nr, |
3440 | "page %lu not writeback, cur %llu end %llu", | 3436 | end_bio_extent_writepage, |
3441 | page->index, cur, end); | 3437 | 0, 0, 0, false); |
3442 | } | 3438 | if (ret) |
3439 | SetPageError(page); | ||
3443 | 3440 | ||
3444 | ret = submit_extent_page(write_flags, tree, wbc, page, | ||
3445 | sector, iosize, pg_offset, | ||
3446 | bdev, &epd->bio, max_nr, | ||
3447 | end_bio_extent_writepage, | ||
3448 | 0, 0, 0, false); | ||
3449 | if (ret) | ||
3450 | SetPageError(page); | ||
3451 | } | ||
3452 | cur = cur + iosize; | 3441 | cur = cur + iosize; |
3453 | pg_offset += iosize; | 3442 | pg_offset += iosize; |
3454 | nr++; | 3443 | nr++; |
@@ -3920,12 +3909,13 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
3920 | struct inode *inode = mapping->host; | 3909 | struct inode *inode = mapping->host; |
3921 | int ret = 0; | 3910 | int ret = 0; |
3922 | int done = 0; | 3911 | int done = 0; |
3923 | int err = 0; | ||
3924 | int nr_to_write_done = 0; | 3912 | int nr_to_write_done = 0; |
3925 | struct pagevec pvec; | 3913 | struct pagevec pvec; |
3926 | int nr_pages; | 3914 | int nr_pages; |
3927 | pgoff_t index; | 3915 | pgoff_t index; |
3928 | pgoff_t end; /* Inclusive */ | 3916 | pgoff_t end; /* Inclusive */ |
3917 | pgoff_t done_index; | ||
3918 | int range_whole = 0; | ||
3929 | int scanned = 0; | 3919 | int scanned = 0; |
3930 | int tag; | 3920 | int tag; |
3931 | 3921 | ||
@@ -3948,6 +3938,8 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
3948 | } else { | 3938 | } else { |
3949 | index = wbc->range_start >> PAGE_SHIFT; | 3939 | index = wbc->range_start >> PAGE_SHIFT; |
3950 | end = wbc->range_end >> PAGE_SHIFT; | 3940 | end = wbc->range_end >> PAGE_SHIFT; |
3941 | if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) | ||
3942 | range_whole = 1; | ||
3951 | scanned = 1; | 3943 | scanned = 1; |
3952 | } | 3944 | } |
3953 | if (wbc->sync_mode == WB_SYNC_ALL) | 3945 | if (wbc->sync_mode == WB_SYNC_ALL) |
@@ -3957,6 +3949,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
3957 | retry: | 3949 | retry: |
3958 | if (wbc->sync_mode == WB_SYNC_ALL) | 3950 | if (wbc->sync_mode == WB_SYNC_ALL) |
3959 | tag_pages_for_writeback(mapping, index, end); | 3951 | tag_pages_for_writeback(mapping, index, end); |
3952 | done_index = index; | ||
3960 | while (!done && !nr_to_write_done && (index <= end) && | 3953 | while (!done && !nr_to_write_done && (index <= end) && |
3961 | (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, | 3954 | (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, |
3962 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { | 3955 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { |
@@ -3966,6 +3959,7 @@ retry: | |||
3966 | for (i = 0; i < nr_pages; i++) { | 3959 | for (i = 0; i < nr_pages; i++) { |
3967 | struct page *page = pvec.pages[i]; | 3960 | struct page *page = pvec.pages[i]; |
3968 | 3961 | ||
3962 | done_index = page->index; | ||
3969 | /* | 3963 | /* |
3970 | * At this point we hold neither mapping->tree_lock nor | 3964 | * At this point we hold neither mapping->tree_lock nor |
3971 | * lock on the page itself: the page may be truncated or | 3965 | * lock on the page itself: the page may be truncated or |
@@ -4007,8 +4001,20 @@ retry: | |||
4007 | unlock_page(page); | 4001 | unlock_page(page); |
4008 | ret = 0; | 4002 | ret = 0; |
4009 | } | 4003 | } |
4010 | if (!err && ret < 0) | 4004 | if (ret < 0) { |
4011 | err = ret; | 4005 | /* |
4006 | * done_index is set past this page, | ||
4007 | * so media errors will not choke | ||
4008 | * background writeout for the entire | ||
4009 | * file. This has consequences for | ||
4010 | * range_cyclic semantics (ie. it may | ||
4011 | * not be suitable for data integrity | ||
4012 | * writeout). | ||
4013 | */ | ||
4014 | done_index = page->index + 1; | ||
4015 | done = 1; | ||
4016 | break; | ||
4017 | } | ||
4012 | 4018 | ||
4013 | /* | 4019 | /* |
4014 | * the filesystem may choose to bump up nr_to_write. | 4020 | * the filesystem may choose to bump up nr_to_write. |
@@ -4020,7 +4026,7 @@ retry: | |||
4020 | pagevec_release(&pvec); | 4026 | pagevec_release(&pvec); |
4021 | cond_resched(); | 4027 | cond_resched(); |
4022 | } | 4028 | } |
4023 | if (!scanned && !done && !err) { | 4029 | if (!scanned && !done) { |
4024 | /* | 4030 | /* |
4025 | * We hit the last page and there is more work to be done: wrap | 4031 | * We hit the last page and there is more work to be done: wrap |
4026 | * back to the start of the file | 4032 | * back to the start of the file |
@@ -4029,8 +4035,12 @@ retry: | |||
4029 | index = 0; | 4035 | index = 0; |
4030 | goto retry; | 4036 | goto retry; |
4031 | } | 4037 | } |
4038 | |||
4039 | if (wbc->range_cyclic || (wbc->nr_to_write > 0 && range_whole)) | ||
4040 | mapping->writeback_index = done_index; | ||
4041 | |||
4032 | btrfs_add_delayed_iput(inode); | 4042 | btrfs_add_delayed_iput(inode); |
4033 | return err; | 4043 | return ret; |
4034 | } | 4044 | } |
4035 | 4045 | ||
4036 | static void flush_epd_write_bio(struct extent_page_data *epd) | 4046 | static void flush_epd_write_bio(struct extent_page_data *epd) |
@@ -4822,7 +4832,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4822 | return NULL; | 4832 | return NULL; |
4823 | eb->fs_info = fs_info; | 4833 | eb->fs_info = fs_info; |
4824 | again: | 4834 | again: |
4825 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | 4835 | ret = radix_tree_preload(GFP_NOFS); |
4826 | if (ret) | 4836 | if (ret) |
4827 | goto free_eb; | 4837 | goto free_eb; |
4828 | spin_lock(&fs_info->buffer_lock); | 4838 | spin_lock(&fs_info->buffer_lock); |
@@ -4923,7 +4933,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4923 | if (uptodate) | 4933 | if (uptodate) |
4924 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 4934 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
4925 | again: | 4935 | again: |
4926 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | 4936 | ret = radix_tree_preload(GFP_NOFS); |
4927 | if (ret) | 4937 | if (ret) |
4928 | goto free_eb; | 4938 | goto free_eb; |
4929 | 4939 | ||