diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3f8e93de2989..739a245e25d6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -426,7 +426,7 @@ again: | |||
426 | extent_clear_unlock_delalloc(inode, | 426 | extent_clear_unlock_delalloc(inode, |
427 | &BTRFS_I(inode)->io_tree, | 427 | &BTRFS_I(inode)->io_tree, |
428 | start, end, NULL, 1, 0, | 428 | start, end, NULL, 1, 0, |
429 | 0, 1, 1, 1); | 429 | 0, 1, 1, 1, 0); |
430 | ret = 0; | 430 | ret = 0; |
431 | goto free_pages_out; | 431 | goto free_pages_out; |
432 | } | 432 | } |
@@ -641,7 +641,7 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
641 | async_extent->start, | 641 | async_extent->start, |
642 | async_extent->start + | 642 | async_extent->start + |
643 | async_extent->ram_size - 1, | 643 | async_extent->ram_size - 1, |
644 | NULL, 1, 1, 0, 1, 1, 0); | 644 | NULL, 1, 1, 0, 1, 1, 0, 0); |
645 | 645 | ||
646 | ret = btrfs_submit_compressed_write(inode, | 646 | ret = btrfs_submit_compressed_write(inode, |
647 | async_extent->start, | 647 | async_extent->start, |
@@ -714,7 +714,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
714 | extent_clear_unlock_delalloc(inode, | 714 | extent_clear_unlock_delalloc(inode, |
715 | &BTRFS_I(inode)->io_tree, | 715 | &BTRFS_I(inode)->io_tree, |
716 | start, end, NULL, 1, 1, | 716 | start, end, NULL, 1, 1, |
717 | 1, 1, 1, 1); | 717 | 1, 1, 1, 1, 0); |
718 | *nr_written = *nr_written + | 718 | *nr_written = *nr_written + |
719 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; | 719 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; |
720 | *page_started = 1; | 720 | *page_started = 1; |
@@ -777,11 +777,14 @@ static noinline int cow_file_range(struct inode *inode, | |||
777 | /* we're not doing compressed IO, don't unlock the first | 777 | /* we're not doing compressed IO, don't unlock the first |
778 | * page (which the caller expects to stay locked), don't | 778 | * page (which the caller expects to stay locked), don't |
779 | * clear any dirty bits and don't set any writeback bits | 779 | * clear any dirty bits and don't set any writeback bits |
780 | * | ||
781 | * Do set the Private2 bit so we know this page was properly | ||
782 | * setup for writepage | ||
780 | */ | 783 | */ |
781 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | 784 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, |
782 | start, start + ram_size - 1, | 785 | start, start + ram_size - 1, |
783 | locked_page, unlock, 1, | 786 | locked_page, unlock, 1, |
784 | 1, 0, 0, 0); | 787 | 1, 0, 0, 0, 1); |
785 | disk_num_bytes -= cur_alloc_size; | 788 | disk_num_bytes -= cur_alloc_size; |
786 | num_bytes -= cur_alloc_size; | 789 | num_bytes -= cur_alloc_size; |
787 | alloc_hint = ins.objectid + ins.offset; | 790 | alloc_hint = ins.objectid + ins.offset; |
@@ -1102,7 +1105,7 @@ out_check: | |||
1102 | 1105 | ||
1103 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | 1106 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, |
1104 | cur_offset, cur_offset + num_bytes - 1, | 1107 | cur_offset, cur_offset + num_bytes - 1, |
1105 | locked_page, 1, 1, 1, 0, 0, 0); | 1108 | locked_page, 1, 1, 1, 0, 0, 0, 1); |
1106 | cur_offset = extent_end; | 1109 | cur_offset = extent_end; |
1107 | if (cur_offset > end) | 1110 | if (cur_offset > end) |
1108 | break; | 1111 | break; |
@@ -1375,10 +1378,8 @@ again: | |||
1375 | lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end, GFP_NOFS); | 1378 | lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end, GFP_NOFS); |
1376 | 1379 | ||
1377 | /* already ordered? We're done */ | 1380 | /* already ordered? We're done */ |
1378 | if (test_range_bit(&BTRFS_I(inode)->io_tree, page_start, page_end, | 1381 | if (PagePrivate2(page)) |
1379 | EXTENT_ORDERED, 0, NULL)) { | ||
1380 | goto out; | 1382 | goto out; |
1381 | } | ||
1382 | 1383 | ||
1383 | ordered = btrfs_lookup_ordered_extent(inode, page_start); | 1384 | ordered = btrfs_lookup_ordered_extent(inode, page_start); |
1384 | if (ordered) { | 1385 | if (ordered) { |
@@ -1414,11 +1415,9 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end) | |||
1414 | struct inode *inode = page->mapping->host; | 1415 | struct inode *inode = page->mapping->host; |
1415 | struct btrfs_writepage_fixup *fixup; | 1416 | struct btrfs_writepage_fixup *fixup; |
1416 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1417 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1417 | int ret; | ||
1418 | 1418 | ||
1419 | ret = test_range_bit(&BTRFS_I(inode)->io_tree, start, end, | 1419 | /* this page is properly in the ordered list */ |
1420 | EXTENT_ORDERED, 0, NULL); | 1420 | if (TestClearPagePrivate2(page)) |
1421 | if (ret) | ||
1422 | return 0; | 1421 | return 0; |
1423 | 1422 | ||
1424 | if (PageChecked(page)) | 1423 | if (PageChecked(page)) |
@@ -1624,6 +1623,7 @@ nocow: | |||
1624 | static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, | 1623 | static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, |
1625 | struct extent_state *state, int uptodate) | 1624 | struct extent_state *state, int uptodate) |
1626 | { | 1625 | { |
1626 | ClearPagePrivate2(page); | ||
1627 | return btrfs_finish_ordered_io(page->mapping->host, start, end); | 1627 | return btrfs_finish_ordered_io(page->mapping->host, start, end); |
1628 | } | 1628 | } |
1629 | 1629 | ||
@@ -4403,13 +4403,21 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4403 | u64 page_start = page_offset(page); | 4403 | u64 page_start = page_offset(page); |
4404 | u64 page_end = page_start + PAGE_CACHE_SIZE - 1; | 4404 | u64 page_end = page_start + PAGE_CACHE_SIZE - 1; |
4405 | 4405 | ||
4406 | |||
4407 | /* | ||
4408 | * we have the page locked, so new writeback can't start, | ||
4409 | * and the dirty bit won't be cleared while we are here. | ||
4410 | * | ||
4411 | * Wait for IO on this page so that we can safely clear | ||
4412 | * the PagePrivate2 bit and do ordered accounting | ||
4413 | */ | ||
4406 | wait_on_page_writeback(page); | 4414 | wait_on_page_writeback(page); |
4415 | |||
4407 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 4416 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
4408 | if (offset) { | 4417 | if (offset) { |
4409 | btrfs_releasepage(page, GFP_NOFS); | 4418 | btrfs_releasepage(page, GFP_NOFS); |
4410 | return; | 4419 | return; |
4411 | } | 4420 | } |
4412 | |||
4413 | lock_extent(tree, page_start, page_end, GFP_NOFS); | 4421 | lock_extent(tree, page_start, page_end, GFP_NOFS); |
4414 | ordered = btrfs_lookup_ordered_extent(page->mapping->host, | 4422 | ordered = btrfs_lookup_ordered_extent(page->mapping->host, |
4415 | page_offset(page)); | 4423 | page_offset(page)); |
@@ -4421,14 +4429,19 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4421 | clear_extent_bit(tree, page_start, page_end, | 4429 | clear_extent_bit(tree, page_start, page_end, |
4422 | EXTENT_DIRTY | EXTENT_DELALLOC | | 4430 | EXTENT_DIRTY | EXTENT_DELALLOC | |
4423 | EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS); | 4431 | EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS); |
4424 | btrfs_finish_ordered_io(page->mapping->host, | 4432 | /* |
4425 | page_start, page_end); | 4433 | * whoever cleared the private bit is responsible |
4434 | * for the finish_ordered_io | ||
4435 | */ | ||
4436 | if (TestClearPagePrivate2(page)) { | ||
4437 | btrfs_finish_ordered_io(page->mapping->host, | ||
4438 | page_start, page_end); | ||
4439 | } | ||
4426 | btrfs_put_ordered_extent(ordered); | 4440 | btrfs_put_ordered_extent(ordered); |
4427 | lock_extent(tree, page_start, page_end, GFP_NOFS); | 4441 | lock_extent(tree, page_start, page_end, GFP_NOFS); |
4428 | } | 4442 | } |
4429 | clear_extent_bit(tree, page_start, page_end, | 4443 | clear_extent_bit(tree, page_start, page_end, |
4430 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | | 4444 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC, |
4431 | EXTENT_ORDERED, | ||
4432 | 1, 1, NULL, GFP_NOFS); | 4445 | 1, 1, NULL, GFP_NOFS); |
4433 | __btrfs_releasepage(page, GFP_NOFS); | 4446 | __btrfs_releasepage(page, GFP_NOFS); |
4434 | 4447 | ||