Commit b945a463 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: make page Ordered bit to be subpage compatible

This involves the following modification:

- Ordered extent creation
  This is done in process_one_page(), now PAGE_SET_ORDERED will call
  subpage helper to do the work.

- endio functions
  This is done in btrfs_mark_ordered_io_finished().

- btrfs_invalidatepage()

- btrfs_cleanup_ordered_extents()
  Use the subpage page helper, and add an extra branch to exit if the
  locked page have covered the full range.

Now the usage of page Ordered flag for ordered extent accounting is fully
subpage compatible.

Tested-by: Ritesh Harjani <riteshh@linux.ibm.com> # [ppc64]
Tested-by: Anand Jain <anand.jain@oracle.com> # [aarch64]
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 6f17400b
...@@ -1827,7 +1827,7 @@ static int process_one_page(struct btrfs_fs_info *fs_info, ...@@ -1827,7 +1827,7 @@ static int process_one_page(struct btrfs_fs_info *fs_info,
len = end + 1 - start; len = end + 1 - start;
if (page_ops & PAGE_SET_ORDERED) if (page_ops & PAGE_SET_ORDERED)
SetPageOrdered(page); btrfs_page_clamp_set_ordered(fs_info, page, start, len);
if (page == locked_page) if (page == locked_page)
return 1; return 1;
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "block-group.h" #include "block-group.h"
#include "space-info.h" #include "space-info.h"
#include "zoned.h" #include "zoned.h"
#include "subpage.h"
struct btrfs_iget_args { struct btrfs_iget_args {
u64 ino; u64 ino;
...@@ -191,18 +192,22 @@ static inline void btrfs_cleanup_ordered_extents(struct btrfs_inode *inode, ...@@ -191,18 +192,22 @@ static inline void btrfs_cleanup_ordered_extents(struct btrfs_inode *inode,
* range, then __endio_write_update_ordered() will handle * range, then __endio_write_update_ordered() will handle
* the ordered extent accounting for the range. * the ordered extent accounting for the range.
*/ */
ClearPageOrdered(page); btrfs_page_clamp_clear_ordered(inode->root->fs_info, page,
offset, bytes);
put_page(page); put_page(page);
} }
/* The locked page covers the full range, nothing needs to be done */
if (bytes + offset <= page_offset(locked_page) + PAGE_SIZE)
return;
/* /*
* In case this page belongs to the delalloc range being instantiated * 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 * then skip it, since the first page of a range is going to be
* properly cleaned up by the caller of run_delalloc_range * properly cleaned up by the caller of run_delalloc_range
*/ */
if (page_start >= offset && page_end <= (offset + bytes - 1)) { if (page_start >= offset && page_end <= (offset + bytes - 1)) {
offset += PAGE_SIZE; bytes = offset + bytes - page_offset(locked_page) - PAGE_SIZE;
bytes -= PAGE_SIZE; offset = page_offset(locked_page) + PAGE_SIZE;
} }
return __endio_write_update_ordered(inode, offset, bytes, false); return __endio_write_update_ordered(inode, offset, bytes, false);
...@@ -8339,6 +8344,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8339,6 +8344,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
unsigned int length) unsigned int length)
{ {
struct btrfs_inode *inode = BTRFS_I(page->mapping->host); struct btrfs_inode *inode = BTRFS_I(page->mapping->host);
struct btrfs_fs_info *fs_info = inode->root->fs_info;
struct extent_io_tree *tree = &inode->io_tree; struct extent_io_tree *tree = &inode->io_tree;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
u64 page_start = page_offset(page); u64 page_start = page_offset(page);
...@@ -8374,6 +8380,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8374,6 +8380,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
bool delete_states; bool delete_states;
u64 range_end; u64 range_end;
u32 range_len;
ordered = btrfs_lookup_first_ordered_range(inode, cur, ordered = btrfs_lookup_first_ordered_range(inode, cur,
page_end + 1 - cur); page_end + 1 - cur);
...@@ -8400,7 +8407,9 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8400,7 +8407,9 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
range_end = min(ordered->file_offset + ordered->num_bytes - 1, range_end = min(ordered->file_offset + ordered->num_bytes - 1,
page_end); page_end);
if (!PageOrdered(page)) { ASSERT(range_end + 1 - cur < U32_MAX);
range_len = range_end + 1 - cur;
if (!btrfs_page_test_ordered(fs_info, page, cur, range_len)) {
/* /*
* If Ordered (Private2) is cleared, it means endio has * If Ordered (Private2) is cleared, it means endio has
* already been executed for the range. * already been executed for the range.
...@@ -8410,7 +8419,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8410,7 +8419,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
delete_states = false; delete_states = false;
goto next; goto next;
} }
ClearPageOrdered(page); btrfs_page_clear_ordered(fs_info, page, cur, range_len);
/* /*
* IO on this page will never be started, so we need to account * IO on this page will never be started, so we need to account
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "compression.h" #include "compression.h"
#include "delalloc-space.h" #include "delalloc-space.h"
#include "qgroup.h" #include "qgroup.h"
#include "subpage.h"
static struct kmem_cache *btrfs_ordered_extent_cache; static struct kmem_cache *btrfs_ordered_extent_cache;
...@@ -395,11 +396,11 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode, ...@@ -395,11 +396,11 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
* *
* If there's no such bit, we need to skip to next range. * If there's no such bit, we need to skip to next range.
*/ */
if (!PageOrdered(page)) { if (!btrfs_page_test_ordered(fs_info, page, cur, len)) {
cur += len; cur += len;
continue; continue;
} }
ClearPageOrdered(page); btrfs_page_clear_ordered(fs_info, page, cur, len);
} }
/* Now we're fine to update the accounting */ /* Now we're fine to update the accounting */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment