Home Home > GIT Browse > SLE11-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2019-01-07 14:30:27 +0800
committerQu Wenruo <wqu@suse.com>2019-01-07 14:30:27 +0800
commit41dbfa66e4f060b3d6cf98497367db74ef22c7aa (patch)
treef6e0387116bf2027d3f068123bc40c6131cdbce4
parent1ff345db7f5e8e893562343c79bd971606c00f67 (diff)
btrfs: Enhance btrfs_trim_fs function to handle error better
(Dependency for bsc#1113667).
-rw-r--r--patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch145
-rw-r--r--series.conf1
2 files changed, 146 insertions, 0 deletions
diff --git a/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch b/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
new file mode 100644
index 0000000000..5e121120bd
--- /dev/null
+++ b/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
@@ -0,0 +1,145 @@
+From 93bba24d4b5ad1e5cd8b43f64e66ff9d6355dd20 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 7 Sep 2018 14:16:23 +0800
+Patch-mainline: v4.20
+Git-commit: 93bba24d4b5ad1e5cd8b43f64e66ff9d6355dd20
+References: Dependency for bsc#1113667
+Subject: [PATCH 1/2] btrfs: Enhance btrfs_trim_fs function to handle error
+ better
+
+Function btrfs_trim_fs() doesn't handle errors in a consistent way. If
+error happens when trimming existing block groups, it will skip the
+remaining blocks and continue to trim unallocated space for each device.
+
+The return value will only reflect the final error from device trimming.
+
+This patch will fix such behavior by:
+
+1) Recording the last error from block group or device trimming
+ The return value will also reflect the last error during trimming.
+ Make developer more aware of the problem.
+
+2) Continuing trimming if possible
+ If we failed to trim one block group or device, we could still try
+ the next block group or device.
+
+3) Report number of failures during block group and device trimming
+ It would be less noisy, but still gives user a brief summary of
+ what's going wrong.
+
+Such behavior can avoid confusion for cases like failure to trim the
+first block group and then only unallocated space is trimmed.
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ add bg_ret and dev_ret to the messages ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 49 ++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 38 insertions(+), 11 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -9350,6 +9350,15 @@ static int btrfs_trim_free_extents(struc
+ return ret;
+ }
+
++/*
++ * Trim the whole filesystem by:
++ * 1) trimming the free space in each block group
++ * 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
++ * happens.
++ */
+ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
+ {
+ struct btrfs_fs_info *fs_info = root->fs_info;
+@@ -9361,6 +9370,10 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ u64 end;
+ u64 trimmed = 0;
+ u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
++ u64 bg_failed = 0;
++ u64 dev_failed = 0;
++ int bg_ret = 0;
++ int dev_ret = 0;
+ int ret = 0;
+
+ /*
+@@ -9371,7 +9384,7 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ else
+ cache = btrfs_lookup_block_group(fs_info, range->start);
+
+- while (cache) {
++ for (; cache; cache = next_block_group(fs_info, cache)) {
+ if (cache->key.objectid >= (range->start + range->len)) {
+ btrfs_put_block_group(cache);
+ break;
+@@ -9385,13 +9398,15 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ if (!block_group_cache_done(cache)) {
+ ret = cache_block_group(cache, 0);
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ ret = wait_block_group_cache_done(cache);
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ }
+ ret = btrfs_trim_block_group(cache,
+@@ -9402,26 +9417,38 @@ int btrfs_trim_fs(struct btrfs_root *roo
+
+ trimmed += group_trimmed;
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ }
+-
+- cache = next_block_group(fs_info->tree_root, cache);
+ }
+
++ if (bg_failed)
++ btrfs_warn(fs_info,
++ "failed to trim %llu block group(s), last error %d",
++ bg_failed, bg_ret);
+ mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
+ devices = &root->fs_info->fs_devices->alloc_list;
+ list_for_each_entry(device, devices, dev_alloc_list) {
+ ret = btrfs_trim_free_extents(device, range->minlen,
+ &group_trimmed);
+- if (ret)
++ if (ret) {
++ dev_failed++;
++ dev_ret = ret;
+ break;
++ }
+
+ trimmed += group_trimmed;
+ }
+ mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+
++ if (dev_failed)
++ btrfs_warn(fs_info,
++ "failed to trim %llu device(s), last error %d",
++ dev_failed, dev_ret);
+ range->len = trimmed;
+- return ret;
++ if (bg_ret)
++ return bg_ret;
++ return dev_ret;
+ }
diff --git a/series.conf b/series.conf
index 5f25b35fbd..19240b5539 100644
--- a/series.conf
+++ b/series.conf
@@ -5198,6 +5198,7 @@
patches.suse/0001-btrfs-scrub-Don-t-use-inode-page-cache-in-scrub_hand.patch
patches.suse/btrfs-fix-quick-exhaustion-of-the-system-array-in-th.patch
patches.suse/btrfs-fix-deadlock-when-finalizing-block-group-creation.patch
+ patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
# Non-upstreamed btrfs patches
patches.suse/btrfs-1009-fixup-writeback_inodes_sb-wrappers-use.patch