aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandan Rajendra <chandan@linux.vnet.ibm.com>2016-01-21 05:25:58 -0500
committerDavid Sterba <dsterba@suse.com>2016-02-01 13:24:29 -0500
commitdbfdb6d1b369b88253af1cd71723437d152b0b50 (patch)
tree1823ea5a0d8c276886b41478234b91d800058aaa
parentd0b7da88f6409c740435712b092a8e2c7d2a8f74 (diff)
Btrfs: Search for all ordered extents that could span across a page
In subpagesize-blocksize scenario it is not sufficient to search using the first byte of the page to make sure that there are no ordered extents present across the page. Fix this. Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/extent_io.c3
-rw-r--r--fs/btrfs/inode.c25
2 files changed, 20 insertions, 8 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 2e7c97a3f344..1b2073389dc2 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3186,7 +3186,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
3186 3186
3187 while (1) { 3187 while (1) {
3188 lock_extent(tree, start, end); 3188 lock_extent(tree, start, end);
3189 ordered = btrfs_lookup_ordered_extent(inode, start); 3189 ordered = btrfs_lookup_ordered_range(inode, start,
3190 PAGE_CACHE_SIZE);
3190 if (!ordered) 3191 if (!ordered)
3191 break; 3192 break;
3192 unlock_extent(tree, start, end); 3193 unlock_extent(tree, start, end);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ad27f5d1a4a1..917ab6b6c277 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2002,7 +2002,8 @@ again:
2002 if (PagePrivate2(page)) 2002 if (PagePrivate2(page))
2003 goto out; 2003 goto out;
2004 2004
2005 ordered = btrfs_lookup_ordered_extent(inode, page_start); 2005 ordered = btrfs_lookup_ordered_range(inode, page_start,
2006 PAGE_CACHE_SIZE);
2006 if (ordered) { 2007 if (ordered) {
2007 unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, 2008 unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start,
2008 page_end, &cached_state, GFP_NOFS); 2009 page_end, &cached_state, GFP_NOFS);
@@ -8683,6 +8684,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
8683 struct extent_state *cached_state = NULL; 8684 struct extent_state *cached_state = NULL;
8684 u64 page_start = page_offset(page); 8685 u64 page_start = page_offset(page);
8685 u64 page_end = page_start + PAGE_CACHE_SIZE - 1; 8686 u64 page_end = page_start + PAGE_CACHE_SIZE - 1;
8687 u64 start;
8688 u64 end;
8686 int inode_evicting = inode->i_state & I_FREEING; 8689 int inode_evicting = inode->i_state & I_FREEING;
8687 8690
8688 /* 8691 /*
@@ -8702,14 +8705,18 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
8702 8705
8703 if (!inode_evicting) 8706 if (!inode_evicting)
8704 lock_extent_bits(tree, page_start, page_end, &cached_state); 8707 lock_extent_bits(tree, page_start, page_end, &cached_state);
8705 ordered = btrfs_lookup_ordered_extent(inode, page_start); 8708again:
8709 start = page_start;
8710 ordered = btrfs_lookup_ordered_range(inode, start,
8711 page_end - start + 1);
8706 if (ordered) { 8712 if (ordered) {
8713 end = min(page_end, ordered->file_offset + ordered->len - 1);
8707 /* 8714 /*
8708 * IO on this page will never be started, so we need 8715 * IO on this page will never be started, so we need
8709 * to account for any ordered extents now 8716 * to account for any ordered extents now
8710 */ 8717 */
8711 if (!inode_evicting) 8718 if (!inode_evicting)
8712 clear_extent_bit(tree, page_start, page_end, 8719 clear_extent_bit(tree, start, end,
8713 EXTENT_DIRTY | EXTENT_DELALLOC | 8720 EXTENT_DIRTY | EXTENT_DELALLOC |
8714 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING | 8721 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
8715 EXTENT_DEFRAG, 1, 0, &cached_state, 8722 EXTENT_DEFRAG, 1, 0, &cached_state,
@@ -8726,22 +8733,26 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
8726 8733
8727 spin_lock_irq(&tree->lock); 8734 spin_lock_irq(&tree->lock);
8728 set_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags); 8735 set_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags);
8729 new_len = page_start - ordered->file_offset; 8736 new_len = start - ordered->file_offset;
8730 if (new_len < ordered->truncated_len) 8737 if (new_len < ordered->truncated_len)
8731 ordered->truncated_len = new_len; 8738 ordered->truncated_len = new_len;
8732 spin_unlock_irq(&tree->lock); 8739 spin_unlock_irq(&tree->lock);
8733 8740
8734 if (btrfs_dec_test_ordered_pending(inode, &ordered, 8741 if (btrfs_dec_test_ordered_pending(inode, &ordered,
8735 page_start, 8742 start,
8736 PAGE_CACHE_SIZE, 1)) 8743 end - start + 1, 1))
8737 btrfs_finish_ordered_io(ordered); 8744 btrfs_finish_ordered_io(ordered);
8738 } 8745 }
8739 btrfs_put_ordered_extent(ordered); 8746 btrfs_put_ordered_extent(ordered);
8740 if (!inode_evicting) { 8747 if (!inode_evicting) {
8741 cached_state = NULL; 8748 cached_state = NULL;
8742 lock_extent_bits(tree, page_start, page_end, 8749 lock_extent_bits(tree, start, end,
8743 &cached_state); 8750 &cached_state);
8744 } 8751 }
8752
8753 start = end + 1;
8754 if (start < page_end)
8755 goto again;
8745 } 8756 }
8746 8757
8747 /* 8758 /*