btrfs: preserve first error in btrfs_trim_fs()

When multiple block groups or devices fail during trim, preserve the
first error encountered rather than the last one. The first error is
typically more useful for debugging as it represents the original
failure, while subsequent errors may be cascading effects.

Signed-off-by: Robbie Ko <robbieko@synology.com>
Signed-off-by: jinbaohong <jinbaohong@synology.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
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:
jinbaohong 2026-01-28 07:06:39 +00:00 committed by David Sterba
parent 912d1c6680
commit 1cc4ada418

View File

@ -6608,7 +6608,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
* 2) trimming the unallocated space on each device
*
* This will also continue trimming even if a block group or device encounters
* an error. The return value will be the last error, or 0 if nothing bad
* an error. The return value will be the first error, or 0 if nothing bad
* happens.
*/
int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
@ -6653,7 +6653,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
ret = btrfs_cache_block_group(cache, true);
if (ret) {
bg_failed++;
bg_ret = ret;
if (!bg_ret)
bg_ret = ret;
continue;
}
}
@ -6666,7 +6667,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
trimmed += group_trimmed;
if (ret) {
bg_failed++;
bg_ret = ret;
if (!bg_ret)
bg_ret = ret;
continue;
}
}
@ -6674,7 +6676,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
if (bg_failed)
btrfs_warn(fs_info,
"failed to trim %llu block group(s), last error %d",
"failed to trim %llu block group(s), first error %d",
bg_failed, bg_ret);
mutex_lock(&fs_devices->device_list_mutex);
@ -6687,7 +6689,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
trimmed += group_trimmed;
if (ret) {
dev_failed++;
dev_ret = ret;
if (!dev_ret)
dev_ret = ret;
continue;
}
}
@ -6695,7 +6698,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
if (dev_failed)
btrfs_warn(fs_info,
"failed to trim %llu device(s), last error %d",
"failed to trim %llu device(s), first error %d",
dev_failed, dev_ret);
range->len = trimmed;
if (bg_ret)