| From dsterba@suse.com Wed May 29 11:32:36 2019 |
| From: David Sterba <dsterba@suse.com> |
| Date: Wed, 29 May 2019 19:25:47 +0200 |
| Subject: Revert "btrfs: Honour FITRIM range constraints during free space trim" |
| To: stable@vger.kernel.org |
| Cc: David Sterba <dsterba@suse.com> |
| Message-ID: <20190529172547.30563-5-dsterba@suse.com> |
| |
| From: David Sterba <dsterba@suse.com> |
| |
| This reverts commit eb432217d775a90c061681c0dfa3c7abfba75123. |
| |
| There is currently no corresponding patch in master due to additional |
| changes that would be significantly different from plain revert in the |
| respective stable branch. |
| |
| The range argument was not handled correctly and could cause trim to |
| overlap allocated areas or reach beyond the end of the device. The |
| address space that fitrim normally operates on is in logical |
| coordinates, while the discards are done on the physical device extents. |
| This distinction cannot be made with the current ioctl interface and |
| caused the confusion. |
| |
| The bug depends on the layout of block groups and does not always |
| happen. The whole-fs trim (run by default by the fstrim tool) is not |
| affected. |
| |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/btrfs/extent-tree.c | 25 ++++++------------------- |
| 1 file changed, 6 insertions(+), 19 deletions(-) |
| |
| --- a/fs/btrfs/extent-tree.c |
| +++ b/fs/btrfs/extent-tree.c |
| @@ -11314,9 +11314,9 @@ int btrfs_error_unpin_extent_range(struc |
| * held back allocations. |
| */ |
| static int btrfs_trim_free_extents(struct btrfs_device *device, |
| - struct fstrim_range *range, u64 *trimmed) |
| + u64 minlen, u64 *trimmed) |
| { |
| - u64 start = range->start, len = 0; |
| + u64 start = 0, len = 0; |
| int ret; |
| |
| *trimmed = 0; |
| @@ -11359,8 +11359,8 @@ static int btrfs_trim_free_extents(struc |
| if (!trans) |
| up_read(&fs_info->commit_root_sem); |
| |
| - ret = find_free_dev_extent_start(trans, device, range->minlen, |
| - start, &start, &len); |
| + ret = find_free_dev_extent_start(trans, device, minlen, start, |
| + &start, &len); |
| if (trans) { |
| up_read(&fs_info->commit_root_sem); |
| btrfs_put_transaction(trans); |
| @@ -11373,16 +11373,6 @@ static int btrfs_trim_free_extents(struc |
| break; |
| } |
| |
| - /* If we are out of the passed range break */ |
| - if (start > range->start + range->len - 1) { |
| - mutex_unlock(&fs_info->chunk_mutex); |
| - ret = 0; |
| - break; |
| - } |
| - |
| - start = max(range->start, start); |
| - len = min(range->len, len); |
| - |
| ret = btrfs_issue_discard(device->bdev, start, len, &bytes); |
| mutex_unlock(&fs_info->chunk_mutex); |
| |
| @@ -11392,10 +11382,6 @@ static int btrfs_trim_free_extents(struc |
| start += len; |
| *trimmed += bytes; |
| |
| - /* We've trimmed enough */ |
| - if (*trimmed >= range->len) |
| - break; |
| - |
| if (fatal_signal_pending(current)) { |
| ret = -ERESTARTSYS; |
| break; |
| @@ -11479,7 +11465,8 @@ int btrfs_trim_fs(struct btrfs_fs_info * |
| mutex_lock(&fs_info->fs_devices->device_list_mutex); |
| devices = &fs_info->fs_devices->devices; |
| list_for_each_entry(device, devices, dev_list) { |
| - ret = btrfs_trim_free_extents(device, range, &group_trimmed); |
| + ret = btrfs_trim_free_extents(device, range->minlen, |
| + &group_trimmed); |
| if (ret) { |
| dev_failed++; |
| dev_ret = ret; |