Re: [PATCH] btrfs: change the set_page_extent_mapped() call into an ASSERT()
From: David Sterba <hidden>
Date: 2021-07-27 14:26:25
On Tue, Jul 27, 2021 at 06:29:08PM +0800, Qu Wenruo wrote:
On 2021/7/27 上午9:39, Qu Wenruo wrote:quoted
Btrfs uses set_page_extent_mapped() to properly setup a page. That function would set PagePrivate, and populate needed structure for subpage. The timing of calling set_page_extent_mapped() happens before reading a page or dirtying a page. Thus when we got a page to write back, if it doesn't have PagePrivate, it is a big problem in code logic. Calling set_page_extent_mapped() for such page would just mask the problem. Furthermore, for subpage case, we call subpage error helper to clear the page error bit before calling set_page_extent_mapped(). If we really got a page without Private bit, it can call kernel NULL pointer dereference. So change the set_page_extent_mapped() call to an ASSERT(), and move the check before any page status update call. Signed-off-by: Qu Wenruo <redacted>Please discard the patch. Although I haven't hit any problem testing the patch, it's still possible that we have a special page that would need cow fixup. Such page will be: - Dirty - Not Private Thus no page->private, this could still cause problem for subpage case though - No EXTENT_DELALLOC flags set for any range inside the page Thus writepage_delalloc() will not find a delalloc range inside the page. Such page will be caught by btrfs_writepage_cow_fixup(), but it will trigger the ASSERT() added by this patch.
Hm yeah the mismatch between dirty/private/delalloc sounds exactly like work for the cow fixup.