mirror of https://gitee.com/openkylin/linux.git
btrfs: subpage: do more sanity checks on metadata page dirtying
For btree_set_page_dirty(), we should also check the extent buffer sanity for subpage support. Unlike the regular sector size case, since one page can contain multiple extent buffers, we need to make sure there is at least one dirty extent buffer in the page. So this patch will iterate through the btrfs_subpage::dirty_bitmap to get the extent buffers, and check if any dirty extent buffer in the page range has EXTENT_BUFFER_DIRTY and proper refs. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
3470da3b7d
commit
139e8cd325
|
@ -42,6 +42,7 @@
|
|||
#include "discard.h"
|
||||
#include "space-info.h"
|
||||
#include "zoned.h"
|
||||
#include "subpage.h"
|
||||
|
||||
#define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\
|
||||
BTRFS_HEADER_FLAG_RELOC |\
|
||||
|
@ -992,14 +993,48 @@ static void btree_invalidatepage(struct page *page, unsigned int offset,
|
|||
static int btree_set_page_dirty(struct page *page)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
|
||||
struct btrfs_subpage *subpage;
|
||||
struct extent_buffer *eb;
|
||||
int cur_bit = 0;
|
||||
u64 page_start = page_offset(page);
|
||||
|
||||
BUG_ON(!PagePrivate(page));
|
||||
eb = (struct extent_buffer *)page->private;
|
||||
BUG_ON(!eb);
|
||||
BUG_ON(!test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
|
||||
BUG_ON(!atomic_read(&eb->refs));
|
||||
btrfs_assert_tree_locked(eb);
|
||||
if (fs_info->sectorsize == PAGE_SIZE) {
|
||||
BUG_ON(!PagePrivate(page));
|
||||
eb = (struct extent_buffer *)page->private;
|
||||
BUG_ON(!eb);
|
||||
BUG_ON(!test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
|
||||
BUG_ON(!atomic_read(&eb->refs));
|
||||
btrfs_assert_tree_locked(eb);
|
||||
return __set_page_dirty_nobuffers(page);
|
||||
}
|
||||
ASSERT(PagePrivate(page) && page->private);
|
||||
subpage = (struct btrfs_subpage *)page->private;
|
||||
|
||||
ASSERT(subpage->dirty_bitmap);
|
||||
while (cur_bit < BTRFS_SUBPAGE_BITMAP_SIZE) {
|
||||
unsigned long flags;
|
||||
u64 cur;
|
||||
u16 tmp = (1 << cur_bit);
|
||||
|
||||
spin_lock_irqsave(&subpage->lock, flags);
|
||||
if (!(tmp & subpage->dirty_bitmap)) {
|
||||
spin_unlock_irqrestore(&subpage->lock, flags);
|
||||
cur_bit++;
|
||||
continue;
|
||||
}
|
||||
spin_unlock_irqrestore(&subpage->lock, flags);
|
||||
cur = page_start + cur_bit * fs_info->sectorsize;
|
||||
|
||||
eb = find_extent_buffer(fs_info, cur);
|
||||
ASSERT(eb);
|
||||
ASSERT(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
|
||||
ASSERT(atomic_read(&eb->refs));
|
||||
btrfs_assert_tree_locked(eb);
|
||||
free_extent_buffer(eb);
|
||||
|
||||
cur_bit += (fs_info->nodesize >> fs_info->sectorsize_bits);
|
||||
}
|
||||
#endif
|
||||
return __set_page_dirty_nobuffers(page);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue