Home Home > GIT Browse > SLE11-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.com>2019-01-14 13:17:47 +0100
committerMichal Hocko <mhocko@suse.com>2019-01-14 13:17:47 +0100
commitee215f00badaa146dfd776dd240d6f98100ab621 (patch)
tree47c1603945074877d817bdea0b9fbc6bf15f0a24
parentbd3070861b998ff74b126f6404772ff5e0383cb4 (diff)
parent281940a9c6a0fa6744a2acb57b300e3a692b5904 (diff)
Merge remote-tracking branch 'origin/users/wqu/SLE11-SP4/for-next' into users/mhocko/SLE11-SP4/for-next
-rw-r--r--patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch145
-rw-r--r--patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch97
-rw-r--r--series.conf2
3 files changed, 244 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/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch b/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
new file mode 100644
index 0000000000..643f8edcb6
--- /dev/null
+++ b/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
@@ -0,0 +1,97 @@
+From 6ba9fc8e628becf0e3ec94083450d089b0dec5f5 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 7 Sep 2018 14:16:24 +0800
+Patch-mainline: v4.20
+Git-commit: 6ba9fc8e628becf0e3ec94083450d089b0dec5f5
+References: bsc#1113667
+Subject: [PATCH 2/2] btrfs: Ensure btrfs_trim_fs can trim the whole filesystem
+
+[BUG]
+fstrim on some btrfs only trims the unallocated space, not trimming any
+space in existing block groups.
+
+[CAUSE]
+Before fstrim_range passed to btrfs_trim_fs(), it gets truncated to
+range [0, super->total_bytes). So later btrfs_trim_fs() will only be
+able to trim block groups in range [0, super->total_bytes).
+
+While for btrfs, any bytenr aligned to sectorsize is valid, since btrfs
+uses its logical address space, there is nothing limiting the location
+where we put block groups.
+
+For filesystem with frequent balance, it's quite easy to relocate all
+block groups and bytenr of block groups will start beyond
+super->total_bytes.
+
+In that case, btrfs will not trim existing block groups.
+
+[FIX]
+Just remove the truncation in btrfs_ioctl_fitrim(), so btrfs_trim_fs()
+can get the unmodified range, which is normally set to [0, U64_MAX].
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+Fixes: f4c697e6406d ("btrfs: return EINVAL if start > total_bytes in fitrim ioctl")
+CC: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 10 +---------
+ fs/btrfs/ioctl.c | 11 +++++++----
+ 2 files changed, 8 insertions(+), 13 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -9369,21 +9369,13 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ u64 start;
+ 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;
+
+- /*
+- * try to trim all FS space, our block group may start from non-zero.
+- */
+- if (range->len == total_bytes)
+- cache = btrfs_lookup_first_block_group(fs_info, range->start);
+- else
+- cache = btrfs_lookup_block_group(fs_info, range->start);
+-
++ cache = btrfs_lookup_first_block_group(fs_info, range->start);
+ for (; cache; cache = next_block_group(fs_info, cache)) {
+ if (cache->key.objectid >= (range->start + range->len)) {
+ btrfs_put_block_group(cache);
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -328,7 +328,6 @@ static noinline int btrfs_ioctl_fitrim(s
+ struct fstrim_range range;
+ u64 minlen = ULLONG_MAX;
+ u64 num_devices = 0;
+- u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
+ int ret;
+
+ if (!capable(CAP_SYS_ADMIN))
+@@ -352,11 +351,15 @@ static noinline int btrfs_ioctl_fitrim(s
+ return -EOPNOTSUPP;
+ if (copy_from_user(&range, arg, sizeof(range)))
+ return -EFAULT;
+- if (range.start > total_bytes ||
+- range.len < fs_info->sb->s_blocksize)
++
++ /*
++ * NOTE: Don't truncate the range using super->total_bytes. Bytenr of
++ * block group is in the logical address space, which can be any
++ * sectorsize aligned bytenr in the range [0, U64_MAX].
++ */
++ if (range.len < fs_info->sb->s_blocksize)
+ return -EINVAL;
+
+- range.len = min(range.len, total_bytes - range.start);
+ range.minlen = max(range.minlen, minlen);
+ ret = btrfs_trim_fs(fs_info->tree_root, &range);
+ if (ret < 0)
diff --git a/series.conf b/series.conf
index 5ff40b5682..2869c6c80f 100644
--- a/series.conf
+++ b/series.conf
@@ -5198,6 +5198,8 @@
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
+ patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
# Non-upstreamed btrfs patches
patches.suse/btrfs-1009-fixup-writeback_inodes_sb-wrappers-use.patch