Skip to content

Commit 8103d10

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Always trim all unallocated space in btrfs_trim_free_extents
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. Fixes: c2d1b3a ("btrfs: Honour FITRIM range constraints during free space trim") Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Nikolay Borisov <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 06989c7 commit 8103d10

File tree

1 file changed

+3
-25
lines changed

1 file changed

+3
-25
lines changed

fs/btrfs/extent-tree.c

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11137,13 +11137,11 @@ int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
1113711137
* it while performing the free space search since we have already
1113811138
* held back allocations.
1113911139
*/
11140-
static int btrfs_trim_free_extents(struct btrfs_device *device,
11141-
struct fstrim_range *range, u64 *trimmed)
11140+
static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
1114211141
{
11143-
u64 start, len = 0, end = 0;
11142+
u64 start = SZ_1M, len = 0, end = 0;
1114411143
int ret;
1114511144

11146-
start = max_t(u64, range->start, SZ_1M);
1114711145
*trimmed = 0;
1114811146

1114911147
/* Discard not supported = nothing to do. */
@@ -11186,22 +11184,6 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
1118611184
break;
1118711185
}
1118811186

11189-
/* Keep going until we satisfy minlen or reach end of space */
11190-
if (len < range->minlen) {
11191-
mutex_unlock(&fs_info->chunk_mutex);
11192-
start += len;
11193-
continue;
11194-
}
11195-
11196-
/* If we are out of the passed range break */
11197-
if (start > range->start + range->len - 1) {
11198-
mutex_unlock(&fs_info->chunk_mutex);
11199-
break;
11200-
}
11201-
11202-
start = max(range->start, start);
11203-
len = min(range->len, len);
11204-
1120511187
ret = btrfs_issue_discard(device->bdev, start, len,
1120611188
&bytes);
1120711189
if (!ret)
@@ -11216,10 +11198,6 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
1121611198
start += len;
1121711199
*trimmed += bytes;
1121811200

11219-
/* We've trimmed enough */
11220-
if (*trimmed >= range->len)
11221-
break;
11222-
1122311201
if (fatal_signal_pending(current)) {
1122411202
ret = -ERESTARTSYS;
1122511203
break;
@@ -11303,7 +11281,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
1130311281
mutex_lock(&fs_info->fs_devices->device_list_mutex);
1130411282
devices = &fs_info->fs_devices->devices;
1130511283
list_for_each_entry(device, devices, dev_list) {
11306-
ret = btrfs_trim_free_extents(device, range, &group_trimmed);
11284+
ret = btrfs_trim_free_extents(device, &group_trimmed);
1130711285
if (ret) {
1130811286
dev_failed++;
1130911287
dev_ret = ret;

0 commit comments

Comments
 (0)