Home Home > GIT Browse > SLE11-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2019-01-07 14:34:36 +0800
committerQu Wenruo <wqu@suse.com>2019-01-07 14:34:36 +0800
commit281940a9c6a0fa6744a2acb57b300e3a692b5904 (patch)
tree1fd2fbd93e872bbb7e2400bd6a4e61346c571a9d
parent41dbfa66e4f060b3d6cf98497367db74ef22c7aa (diff)
btrfs: Ensure btrfs_trim_fs can trim the whole filesystem
(bsc#1113667).
-rw-r--r--patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch97
-rw-r--r--series.conf1
2 files changed, 98 insertions, 0 deletions
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 19240b5539..0fa4e15237 100644
--- a/series.conf
+++ b/series.conf
@@ -5199,6 +5199,7 @@
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