]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-5.1/btrfs-honour-fitrim-range-constraints-during-free-space-trim.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.1 / btrfs-honour-fitrim-range-constraints-during-free-space-trim.patch
CommitLineData
f5edbeaf
GKH
1From c2d1b3aae33605a61cbab445d8ae1c708ccd2698 Mon Sep 17 00:00:00 2001
2From: Nikolay Borisov <nborisov@suse.com>
3Date: Mon, 25 Mar 2019 14:31:21 +0200
4Subject: btrfs: Honour FITRIM range constraints during free space trim
5
6From: Nikolay Borisov <nborisov@suse.com>
7
8commit c2d1b3aae33605a61cbab445d8ae1c708ccd2698 upstream.
9
10Up until now trimming the freespace was done irrespective of what the
11arguments of the FITRIM ioctl were. For example fstrim's -o/-l arguments
12will be entirely ignored. Fix it by correctly handling those paramter.
13This requires breaking if the found freespace extent is after the end of
14the passed range as well as completing trim after trimming
15fstrim_range::len bytes.
16
17Fixes: 499f377f49f0 ("btrfs: iterate over unused chunk space in FITRIM")
18CC: stable@vger.kernel.org # 4.4+
19Signed-off-by: Nikolay Borisov <nborisov@suse.com>
20Reviewed-by: David Sterba <dsterba@suse.com>
21Signed-off-by: David Sterba <dsterba@suse.com>
22Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24---
25 fs/btrfs/extent-tree.c | 25 +++++++++++++++++++------
26 1 file changed, 19 insertions(+), 6 deletions(-)
27
28--- a/fs/btrfs/extent-tree.c
29+++ b/fs/btrfs/extent-tree.c
30@@ -11315,9 +11315,9 @@ int btrfs_error_unpin_extent_range(struc
31 * held back allocations.
32 */
33 static int btrfs_trim_free_extents(struct btrfs_device *device,
34- u64 minlen, u64 *trimmed)
35+ struct fstrim_range *range, u64 *trimmed)
36 {
37- u64 start = 0, len = 0;
38+ u64 start = range->start, len = 0;
39 int ret;
40
41 *trimmed = 0;
42@@ -11360,8 +11360,8 @@ static int btrfs_trim_free_extents(struc
43 if (!trans)
44 up_read(&fs_info->commit_root_sem);
45
46- ret = find_free_dev_extent_start(trans, device, minlen, start,
47- &start, &len);
48+ ret = find_free_dev_extent_start(trans, device, range->minlen,
49+ start, &start, &len);
50 if (trans) {
51 up_read(&fs_info->commit_root_sem);
52 btrfs_put_transaction(trans);
53@@ -11374,6 +11374,16 @@ static int btrfs_trim_free_extents(struc
54 break;
55 }
56
57+ /* If we are out of the passed range break */
58+ if (start > range->start + range->len - 1) {
59+ mutex_unlock(&fs_info->chunk_mutex);
60+ ret = 0;
61+ break;
62+ }
63+
64+ start = max(range->start, start);
65+ len = min(range->len, len);
66+
67 ret = btrfs_issue_discard(device->bdev, start, len, &bytes);
68 mutex_unlock(&fs_info->chunk_mutex);
69
70@@ -11383,6 +11393,10 @@ static int btrfs_trim_free_extents(struc
71 start += len;
72 *trimmed += bytes;
73
74+ /* We've trimmed enough */
75+ if (*trimmed >= range->len)
76+ break;
77+
78 if (fatal_signal_pending(current)) {
79 ret = -ERESTARTSYS;
80 break;
81@@ -11466,8 +11480,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *
82 mutex_lock(&fs_info->fs_devices->device_list_mutex);
83 devices = &fs_info->fs_devices->devices;
84 list_for_each_entry(device, devices, dev_list) {
85- ret = btrfs_trim_free_extents(device, range->minlen,
86- &group_trimmed);
87+ ret = btrfs_trim_free_extents(device, range, &group_trimmed);
88 if (ret) {
89 dev_failed++;
90 dev_ret = ret;