On 2019/6/3 下午6:06, Nikolay Borisov wrote:
> This patch removes support for range parameters of FITRIM ioctl when
> trimming unallocated space on devices. This is necessary since ranges
> passed from user space are generally interpreted as logical addresses,
> whereas btrfs_trim_free_extents used to interpret them as device
> physical extents. This could result in counter-intuitive behavior for
> users so it's best to remove that support altogether.
>
> Additionally, the existing range support had a bug where if an offset
> was passed to FITRIM which overflows u64 e.g. -1 (parsed as u64
> 18446744073709551615) then wrong data was fed into btrfs_issue_discard,
> which in turn leads to wrap-around when aligning the passed range and
> results in wrong regions being discarded which leads to data corruption.
>
> Signed-off-by: Nikolay Borisov <nbori...@suse.com>

Reveiwed-by: Qu Wenruo <w...@suse.com>

Thanks,
Qu

> ---
>  fs/btrfs/extent-tree.c | 28 +++-------------------------
>  1 file changed, 3 insertions(+), 25 deletions(-)
>
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index 96628eb4b389..d8c5febf7636 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -11145,13 +11145,11 @@ int btrfs_error_unpin_extent_range(struct 
> btrfs_fs_info *fs_info,
>   * it while performing the free space search since we have already
>   * held back allocations.
>   */
> -static int btrfs_trim_free_extents(struct btrfs_device *device,
> -                                struct fstrim_range *range, u64 *trimmed)
> +static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
>  {
> -     u64 start, len = 0, end = 0;
> +     u64 start = SZ_1M, len = 0, end = 0;
>       int ret;
>
> -     start = max_t(u64, range->start, SZ_1M);
>       *trimmed = 0;
>
>       /* Discard not supported = nothing to do. */
> @@ -11194,22 +11192,6 @@ static int btrfs_trim_free_extents(struct 
> btrfs_device *device,
>                       break;
>               }
>
> -             /* Keep going until we satisfy minlen or reach end of space */
> -             if (len < range->minlen) {
> -                     mutex_unlock(&fs_info->chunk_mutex);
> -                     start += len;
> -                     continue;
> -             }
> -
> -             /* If we are out of the passed range break */
> -             if (start > range->start + range->len - 1) {
> -                     mutex_unlock(&fs_info->chunk_mutex);
> -                     break;
> -             }
> -
> -             start = max(range->start, start);
> -             len = min(range->len, len);
> -
>               ret = btrfs_issue_discard(device->bdev, start, len,
>                                         &bytes);
>               if (!ret)
> @@ -11224,10 +11206,6 @@ static int btrfs_trim_free_extents(struct 
> btrfs_device *device,
>               start += len;
>               *trimmed += bytes;
>
> -             /* We've trimmed enough */
> -             if (*trimmed >= range->len)
> -                     break;
> -
>               if (fatal_signal_pending(current)) {
>                       ret = -ERESTARTSYS;
>                       break;
> @@ -11311,7 +11289,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, 
> struct fstrim_range *range)
>       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, &group_trimmed);
>               if (ret) {
>                       dev_failed++;
>                       dev_ret = ret;
>

Reply via email to