* [PATCH 0/3] Error handling in unpin_extent_cache()
@ 2024-01-16 17:42 David Sterba
2024-01-16 17:42 ` [PATCH 1/3] brtfs: handle errors returned from unpin_extent_cache() David Sterba
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: David Sterba @ 2024-01-16 17:42 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
Do the erorr handling in unpin_extent_cache so we don't se any "change
the return value to void" patches again. The errors are pushed up one
level in each patch.
There's case in btrfs_finish_extent_commit() that still needs to be
changed from BUG_ON to proper handling but it does not look easy.
David Sterba (3):
brtfs: handle errors returned from unpin_extent_cache()
btrfs: return errors from unpin_extent_range()
btrfs: make btrfs_error_unpin_extent_range() return void
fs/btrfs/block-group.c | 2 +-
fs/btrfs/ctree.h | 3 +--
fs/btrfs/extent-tree.c | 22 ++++++++++++++++------
fs/btrfs/extent_map.c | 10 +++++++++-
fs/btrfs/inode.c | 9 +++++++--
5 files changed, 34 insertions(+), 12 deletions(-)
--
2.42.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] brtfs: handle errors returned from unpin_extent_cache()
2024-01-16 17:42 [PATCH 0/3] Error handling in unpin_extent_cache() David Sterba
@ 2024-01-16 17:42 ` David Sterba
2024-01-16 17:42 ` [PATCH 2/3] btrfs: return errors from unpin_extent_range() David Sterba
2024-01-16 17:42 ` [PATCH 3/3] btrfs: make btrfs_error_unpin_extent_range() return void David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2024-01-16 17:42 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
We've had numerous attempts to let function unpin_extent_cache() return
void as it only returns 0. There are still error cases to handle so do
that, in addition to the verbose messages. The only caller
btrfs_finish_one_ordered() will now abort the transaction, previously it
let it continue which could lead to further problems.
Signed-off-by: David Sterba <dsterba@suse.com>
---
fs/btrfs/extent_map.c | 10 +++++++++-
fs/btrfs/inode.c | 9 +++++++--
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index b61099bf97a8..f170e7122e74 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -291,6 +291,10 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
* Called after an extent has been written to disk properly. Set the generation
* 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().
+ *
+ * Returns: 0 on success
+ * -ENOENT when the extent is not found in the tree
+ * -EUCLEAN if the found extent does not match the expected start
*/
int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
{
@@ -308,14 +312,18 @@ int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
"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);
+ ret = -ENOENT;
goto out;
}
- if (WARN_ON(em->start != start))
+ 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);
+ ret = -EUCLEAN;
+ goto out;
+ }
em->generation = gen;
em->flags &= ~EXTENT_FLAG_PINNED;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7199670599d9..39eb005cd88d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3127,8 +3127,13 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
ordered_extent->disk_num_bytes);
}
}
- unpin_extent_cache(inode, ordered_extent->file_offset,
- ordered_extent->num_bytes, trans->transid);
+ if (ret < 0) {
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
+
+ ret = unpin_extent_cache(inode, ordered_extent->file_offset,
+ ordered_extent->num_bytes, trans->transid);
if (ret < 0) {
btrfs_abort_transaction(trans, ret);
goto out;
--
2.42.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] btrfs: return errors from unpin_extent_range()
2024-01-16 17:42 [PATCH 0/3] Error handling in unpin_extent_cache() David Sterba
2024-01-16 17:42 ` [PATCH 1/3] brtfs: handle errors returned from unpin_extent_cache() David Sterba
@ 2024-01-16 17:42 ` David Sterba
2024-01-16 17:42 ` [PATCH 3/3] btrfs: make btrfs_error_unpin_extent_range() return void David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2024-01-16 17:42 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
Handle the lookup failure of the block group to unpin, this is a logic
error as the block group must exist at this point. If not, something else
must have freed it, like clean_pinned_extents() would do without locking
the unused_bg_unpin_mutex.
Push the errors to the callers, proper handling will be done in followup
patches.
Signed-off-by: David Sterba <dsterba@suse.com>
---
fs/btrfs/block-group.c | 2 +-
fs/btrfs/extent-tree.c | 19 +++++++++++++++----
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index a9be9ac99222..1905d76772a9 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1429,7 +1429,7 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans,
* group in pinned_extents before we were able to clear the whole block
* group range from pinned_extents. This means that task can lookup for
* the block group after we unpinned it from pinned_extents and removed
- * it, leading to a BUG_ON() at unpin_extent_range().
+ * it, leading to an error at unpin_extent_range().
*/
mutex_lock(&fs_info->unused_bg_unpin_mutex);
if (prev_trans) {
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8e8cc1111277..42293f617f42 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2780,6 +2780,7 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
u64 total_unpinned = 0;
u64 empty_cluster = 0;
bool readonly;
+ int ret = 0;
while (start <= end) {
readonly = false;
@@ -2789,7 +2790,11 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
btrfs_put_block_group(cache);
total_unpinned = 0;
cache = btrfs_lookup_block_group(fs_info, start);
- BUG_ON(!cache); /* Logic error */
+ if (cache == NULL) {
+ /* Logic error, something removed the block group. */
+ ret = -EUCLEAN;
+ goto out;
+ }
cluster = fetch_cluster_info(fs_info,
cache->space_info,
@@ -2858,7 +2863,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
if (cache)
btrfs_put_block_group(cache);
- return 0;
+out:
+ return ret;
}
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
@@ -2888,7 +2894,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
end + 1 - start, NULL);
clear_extent_dirty(unpin, start, end, &cached_state);
- unpin_extent_range(fs_info, start, end, true);
+ ret = unpin_extent_range(fs_info, start, end, true);
+ BUG_ON(ret);
mutex_unlock(&fs_info->unused_bg_unpin_mutex);
free_extent_state(cached_state);
cond_resched();
@@ -6170,7 +6177,11 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
u64 start, u64 end)
{
- return unpin_extent_range(fs_info, start, end, false);
+ int ret;
+
+ ret = unpin_extent_range(fs_info, start, end, false);
+ BUG_ON(ret);
+ return ret;
}
/*
--
2.42.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] btrfs: make btrfs_error_unpin_extent_range() return void
2024-01-16 17:42 [PATCH 0/3] Error handling in unpin_extent_cache() David Sterba
2024-01-16 17:42 ` [PATCH 1/3] brtfs: handle errors returned from unpin_extent_cache() David Sterba
2024-01-16 17:42 ` [PATCH 2/3] btrfs: return errors from unpin_extent_range() David Sterba
@ 2024-01-16 17:42 ` David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2024-01-16 17:42 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
This helper is used in transaction abort or cleanup context and the
callers cannot handle all errors, only do best effort.
btrfs_cleanup_one_transaction
btrfs_destroy_delayed_refs
btrfs_error_unpin_extent_range
btrfs_destroy_pinned_extent
btrfs_error_unpin_extent_range
Signed-off-by: David Sterba <dsterba@suse.com>
---
fs/btrfs/ctree.h | 3 +--
fs/btrfs/extent-tree.c | 13 ++++++-------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 70e828d33177..eede81288196 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -478,8 +478,7 @@ static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping)
return mapping_gfp_constraint(mapping, ~__GFP_FS);
}
-int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
- u64 start, u64 end);
+void btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, u64 start, u64 end);
int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 num_bytes, u64 *actual_bytes);
int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 42293f617f42..4283e3025ab0 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6174,14 +6174,13 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
return ret;
}
-int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
- u64 start, u64 end)
+/*
+ * Unpin the extent range in an error context and don't add the space back.
+ * Errors are not propagated further.
+ */
+void btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, u64 start, u64 end)
{
- int ret;
-
- ret = unpin_extent_range(fs_info, start, end, false);
- BUG_ON(ret);
- return ret;
+ unpin_extent_range(fs_info, start, end, false);
}
/*
--
2.42.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-01-16 17:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-16 17:42 [PATCH 0/3] Error handling in unpin_extent_cache() David Sterba
2024-01-16 17:42 ` [PATCH 1/3] brtfs: handle errors returned from unpin_extent_cache() David Sterba
2024-01-16 17:42 ` [PATCH 2/3] btrfs: return errors from unpin_extent_range() David Sterba
2024-01-16 17:42 ` [PATCH 3/3] btrfs: make btrfs_error_unpin_extent_range() return void David Sterba
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.