1

btrfs: log messages at unpin_extent_range() during unexpected cases

At unpin_extent_range() we trigger a WARN_ON() when we don't find an
extent map or we find one with a start offset not matching the start
offset of the target range. This however isn't very useful for debugging
because:

1) We don't know which condition was triggered, as they are both in the
   same WARN_ON() call;

2) We don't know which inode was affected, from which root, for which
   range, what's the start offset of the extent map, and so on.

So trigger a separate warning for each case and log a message for each
case providing information about the inode, its root, the target range,
the generation and the start offset of the extent map we found.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Filipe Manana 2023-12-04 16:20:29 +00:00 committed by David Sterba
parent d224d2ef95
commit 00deaf04df
3 changed files with 18 additions and 8 deletions

View File

@ -280,7 +280,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
/* /*
* Unpin an extent from the cache. * Unpin an extent from the cache.
* *
* @tree: tree to unpin the extent in * @inode: the inode from which we are unpinning an extent range
* @start: logical offset in the file * @start: logical offset in the file
* @len: length of the extent * @len: length of the extent
* @gen: generation that this extent has been modified in * @gen: generation that this extent has been modified in
@ -289,9 +289,10 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
* to the generation that actually added the file item to the inode so we know * to the generation that actually added the file item to the inode so we know
* we need to sync this extent when we call fsync(). * we need to sync this extent when we call fsync().
*/ */
int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
u64 gen)
{ {
struct btrfs_fs_info *fs_info = inode->root->fs_info;
struct extent_map_tree *tree = &inode->extent_tree;
int ret = 0; int ret = 0;
struct extent_map *em; struct extent_map *em;
bool prealloc = false; bool prealloc = false;
@ -299,10 +300,19 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len,
write_lock(&tree->lock); write_lock(&tree->lock);
em = lookup_extent_mapping(tree, start, len); em = lookup_extent_mapping(tree, start, len);
WARN_ON(!em || em->start != start); if (WARN_ON(!em)) {
btrfs_warn(fs_info,
if (!em) "no extent map found for inode %llu (root %lld) when unpinning extent range [%llu, %llu), generation %llu",
btrfs_ino(inode), btrfs_root_id(inode->root),
start, len, gen);
goto out; goto out;
}
if (WARN_ON(em->start != start))
btrfs_warn(fs_info,
"found extent map for inode %llu (root %lld) with unexpected start offset %llu when unpinning extent range [%llu, %llu), generation %llu",
btrfs_ino(inode), btrfs_root_id(inode->root),
em->start, start, len, gen);
em->generation = gen; em->generation = gen;
clear_bit(EXTENT_FLAG_PINNED, &em->flags); clear_bit(EXTENT_FLAG_PINNED, &em->flags);

View File

@ -82,7 +82,7 @@ struct extent_map *alloc_extent_map(void);
void free_extent_map(struct extent_map *em); void free_extent_map(struct extent_map *em);
int __init extent_map_init(void); int __init extent_map_init(void);
void __cold extent_map_exit(void); void __cold extent_map_exit(void);
int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen); int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen);
void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em); void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
struct extent_map *search_extent_mapping(struct extent_map_tree *tree, struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
u64 start, u64 len); u64 start, u64 len);

View File

@ -3127,7 +3127,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
ordered_extent->disk_num_bytes); ordered_extent->disk_num_bytes);
} }
} }
unpin_extent_cache(&inode->extent_tree, ordered_extent->file_offset, unpin_extent_cache(inode, ordered_extent->file_offset,
ordered_extent->num_bytes, trans->transid); ordered_extent->num_bytes, trans->transid);
if (ret < 0) { if (ret < 0) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);