From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 1/2] btrfs: fix the never finishing ordered extent when it get cleaned up
Date: Tue, 18 May 2021 09:41:51 +0800 [thread overview]
Message-ID: <20210518014152.77203-2-wqu@suse.com> (raw)
In-Reply-To: <20210518014152.77203-1-wqu@suse.com>
[BUG]
When running subpage preparation patches on x86, btrfs/125 will hang
forever with one ordered extent never finished:
[CAUSE]
The test case btrfs/125 itself will always fail as the fix is never merged.
When the test fails at balance, btrfs needs to cleanup the ordered
extent in btrfs_cleanup_ordered_extents().
The problem is in the sequence how we cleanup the page Order bit.
Currently it works like:
btrfs_cleanup_ordered_extents()
|- find_get_page();
|- btrfs_page_clear_ordered(page);
| Now the page doesn't have Ordered bit anymore.
| !!! This also includes the first (locked) page !!!
|
|- offset += PAGE_SIZE
| This is to skip the first page
|- __endio_write_update_ordered()
|- btrfs_mark_ordered_io_finished(NULL)
Except the first page, all ordered extent is finished.
Then the first page is cleaned up in __extent_writepage():
__extent_writepage()
|- If (PageError(page))
|- end_extent_writepage()
|- btrfs_mark_ordered_io_finished(page)
|- if (btrfs_test_page_ordered(page))
|- !!! The page get skipped !!!
The ordered extent is not decreased as the page doesn't
have ordered bit anymore.
This leaving the ordered extent with bytes_left == sectorsize, thus never
finish.
[FIX]
The proper fix is to ensure the one cleaning up the locked page to clear
page Ordered and finish ordered io range at the same time.
This patch choose to do it in btrfs_cleanup_ordered_extents().
Also since we're here, fix a problem in
btrfs_cleanup_ordered_extents() where it always cleanup all sectors
inside the page, which is not subpage friendly.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/inode.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 48bcb351aad6..c974a2827da7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -144,6 +144,8 @@ void btrfs_inode_unlock(struct inode *inode, unsigned int ilock_flags)
inode_unlock(inode);
}
+static void finish_ordered_fn(struct btrfs_work *work);
+
/*
* Cleanup all submitted ordered extents in specified range to handle errors
* from the btrfs_run_delalloc_range() callback.
@@ -166,10 +168,28 @@ static inline void btrfs_cleanup_ordered_extents(struct btrfs_inode *inode,
struct page *page;
while (index <= end_index) {
+ u64 range_start;
+ u64 range_len;
+
page = find_get_page(inode->vfs_inode.i_mapping, index);
index++;
if (!page)
continue;
+
+ range_start = max_t(u64, page_offset(page), offset);
+ range_len = min(offset + bytes, page_offset(page) + PAGE_SIZE) -
+ range_start;
+ /*
+ * Clear page Ordered and its ordered range manually.
+ *
+ * We used to clear page Ordered first, but since Ordered bit
+ * indicates whether we have ordered extent, if it get cleared
+ * without finishing the ordered io range, the ordered extent
+ * will hang forever, as later btrfs_mark_ordered_io_finished()
+ * will just skip the range.
+ */
+ btrfs_mark_ordered_io_finished(inode, page, range_start,
+ range_len, finish_ordered_fn, false);
ClearPageOrdered(page);
put_page(page);
}
--
2.31.1
next prev parent reply other threads:[~2021-05-18 1:42 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-18 1:41 [PATCH 0/2] btrfs: fixes for the 13 subpage preparation patches Qu Wenruo
2021-05-18 1:41 ` Qu Wenruo [this message]
2021-05-18 1:41 ` [PATCH 2/2] btrfs: fix the unsafe access in btrfs_lookup_first_ordered_range() Qu Wenruo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210518014152.77203-2-wqu@suse.com \
--to=wqu@suse.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox