Skip to content

Commit

Permalink
btrfs: subpage: dump extra subpage bitmaps for debug
Browse files Browse the repository at this point in the history
There is a bug report that assert_eb_page_uptodate() gets triggered for
free space tree metadata.

Without proper dump for the subpage bitmaps it's much harder to debug.

Thus this patch would dump all the subpage bitmaps (split them into
their own bitmaps) for a easier debugging.

The output would look like this:
(Dumped after a tree block got read from disk)

  page:000000006e34bf49 refcount:4 mapcount:0 mapping:0000000067661ac4 index:0x1d1 pfn:0x110e9
  memcg:ffff0000d7d62000
  aops:btree_aops [btrfs] ino:1
  flags: 0x8000000000002002(referenced|private|zone=2)
  page_type: 0xffffffff()
  raw: 8000000000002002 0000000000000000 dead000000000122 ffff00000188bed0
  raw: 00000000000001d1 ffff0000c7992700 00000004ffffffff ffff0000d7d62000
  page dumped because: btrfs subpage dump
  BTRFS warning (device dm-1): start=30490624 len=16384 page=30474240 bitmaps: uptodate=4-7 error= dirty= writeback= ordered= checked=

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
adam900710 authored and kdave committed Jun 5, 2023
1 parent d840d1c commit 1d3777e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
5 changes: 3 additions & 2 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -4262,8 +4262,9 @@ static void assert_eb_page_uptodate(const struct extent_buffer *eb,
return;

if (fs_info->nodesize < PAGE_SIZE) {
WARN_ON(!btrfs_subpage_test_uptodate(fs_info, page,
eb->start, eb->len));
if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, page,
eb->start, eb->len)))
btrfs_subpage_dump_bitmap(fs_info, page, eb->start, eb->len);
} else {
WARN_ON(!PageUptodate(page));
}
Expand Down
42 changes: 42 additions & 0 deletions fs/btrfs/subpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,3 +745,45 @@ void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
/* Have writers, use proper subpage helper to end it */
btrfs_page_end_writer_lock(fs_info, page, start, len);
}

#define GET_SUBPAGE_BITMAP(subpage, subpage_info, name, dst) \
bitmap_cut(dst, subpage->bitmaps, 0, \
subpage_info->name##_offset, subpage_info->bitmap_nr_bits)

void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
struct btrfs_subpage_info *subpage_info = fs_info->subpage_info;
struct btrfs_subpage *subpage;
unsigned long uptodate_bitmap;
unsigned long error_bitmap;
unsigned long dirty_bitmap;
unsigned long writeback_bitmap;
unsigned long ordered_bitmap;
unsigned long checked_bitmap;
unsigned long flags;

ASSERT(PagePrivate(page) && page->private);
ASSERT(subpage_info);
subpage = (struct btrfs_subpage *)page->private;

spin_lock_irqsave(&subpage->lock, flags);
GET_SUBPAGE_BITMAP(subpage, subpage_info, uptodate, &uptodate_bitmap);
GET_SUBPAGE_BITMAP(subpage, subpage_info, error, &error_bitmap);
GET_SUBPAGE_BITMAP(subpage, subpage_info, dirty, &dirty_bitmap);
GET_SUBPAGE_BITMAP(subpage, subpage_info, writeback, &writeback_bitmap);
GET_SUBPAGE_BITMAP(subpage, subpage_info, ordered, &ordered_bitmap);
GET_SUBPAGE_BITMAP(subpage, subpage_info, checked, &checked_bitmap);
spin_unlock_irqrestore(&subpage->lock, flags);

dump_page(page, "btrfs subpage dump");
btrfs_warn(fs_info,
"start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl error=%*pbl dirty=%*pbl writeback=%*pbl ordered=%*pbl checked=%*pbl",
start, len, page_offset(page),
subpage_info->bitmap_nr_bits, &uptodate_bitmap,
subpage_info->bitmap_nr_bits, &error_bitmap,
subpage_info->bitmap_nr_bits, &dirty_bitmap,
subpage_info->bitmap_nr_bits, &writeback_bitmap,
subpage_info->bitmap_nr_bits, &ordered_bitmap,
subpage_info->bitmap_nr_bits, &checked_bitmap);
}
2 changes: 2 additions & 0 deletions fs/btrfs/subpage.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,7 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
struct page *page);
void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
u64 start, u32 len);
void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len);

#endif

0 comments on commit 1d3777e

Please sign in to comment.