|
|
@@ -110,17 +110,17 @@ static void __endio_write_update_ordered(struct inode *inode,
|
|
|
* extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING
|
|
|
* and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata
|
|
|
* to be released, which we want to happen only when finishing the ordered
|
|
|
- * extent (btrfs_finish_ordered_io()). Also note that the caller of
|
|
|
- * btrfs_run_delalloc_range already does proper cleanup for the first page of
|
|
|
- * the range, that is, it invokes the callback writepage_end_io_hook() for the
|
|
|
- * range of the first page.
|
|
|
+ * extent (btrfs_finish_ordered_io()).
|
|
|
*/
|
|
|
static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
|
|
|
- const u64 offset,
|
|
|
- const u64 bytes)
|
|
|
+ struct page *locked_page,
|
|
|
+ u64 offset, u64 bytes)
|
|
|
{
|
|
|
unsigned long index = offset >> PAGE_SHIFT;
|
|
|
unsigned long end_index = (offset + bytes - 1) >> PAGE_SHIFT;
|
|
|
+ u64 page_start = page_offset(locked_page);
|
|
|
+ u64 page_end = page_start + PAGE_SIZE - 1;
|
|
|
+
|
|
|
struct page *page;
|
|
|
|
|
|
while (index <= end_index) {
|
|
|
@@ -131,8 +131,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
|
|
|
ClearPagePrivate2(page);
|
|
|
put_page(page);
|
|
|
}
|
|
|
- return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
|
|
|
- bytes - PAGE_SIZE, false);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In case this page belongs to the delalloc range being instantiated
|
|
|
+ * then skip it, since the first page of a range is going to be
|
|
|
+ * properly cleaned up by the caller of run_delalloc_range
|
|
|
+ */
|
|
|
+ if (page_start >= offset && page_end <= (offset + bytes - 1)) {
|
|
|
+ offset += PAGE_SIZE;
|
|
|
+ bytes -= PAGE_SIZE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return __endio_write_update_ordered(inode, offset, bytes, false);
|
|
|
}
|
|
|
|
|
|
static int btrfs_dirty_inode(struct inode *inode);
|
|
|
@@ -1629,7 +1639,8 @@ int btrfs_run_delalloc_range(void *private_data, struct page *locked_page,
|
|
|
write_flags);
|
|
|
}
|
|
|
if (ret)
|
|
|
- btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
|
|
|
+ btrfs_cleanup_ordered_extents(inode, locked_page, start,
|
|
|
+ end - start + 1);
|
|
|
return ret;
|
|
|
}
|
|
|
|