@@ -1580,6 +1580,7 @@ out:
* 1 is returned if we find something, 0 if nothing was in the tree
*/
static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
+ struct page *locked_page,
u64 *start, u64 *end, u64 max_bytes,
struct extent_state **cached_state)
{
@@ -1588,6 +1589,9 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
u64 cur_start = *start;
u64 found = 0;
u64 total_bytes = 0;
+ u64 page_end;
+
+ page_end = page_offset(locked_page) + PAGE_SIZE - 1;
spin_lock(&tree->lock);
@@ -1608,7 +1612,8 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
(state->state & EXTENT_BOUNDARY))) {
goto out;
}
- if (!(state->state & EXTENT_DELALLOC)) {
+ if (!(state->state & EXTENT_DELALLOC)
+ || (page_end < state->start)) {
if (!found)
*end = state->end;
goto out;
@@ -1746,8 +1751,9 @@ again:
/* step one, find a bunch of delalloc bytes starting at start */
delalloc_start = *start;
delalloc_end = 0;
- found = find_delalloc_range(tree, &delalloc_start, &delalloc_end,
- max_bytes, &cached_state);
+ found = find_delalloc_range(tree, locked_page,
+ &delalloc_start, &delalloc_end,
+ max_bytes, &cached_state);
if (!found || delalloc_end <= *start) {
*start = delalloc_start;
*end = delalloc_end;
find_delalloc_range indirectly depends on EXTENT_UPTODDATE to make sure that the delalloc range returned intersects with the file range mapped by the page. Since we now track "uptodate" state in a per-page bitmap (i.e. in btrfs_page_private->bstate), this commit makes an explicit check to make sure that the delalloc range starts from within the file range mapped by the page. Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> --- fs/btrfs/extent_io.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)