Skip to content

Commit c2d1b3a

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Honour FITRIM range constraints during free space trim
Up until now trimming the freespace was done irrespective of what the arguments of the FITRIM ioctl were. For example fstrim's -o/-l arguments will be entirely ignored. Fix it by correctly handling those paramter. This requires breaking if the found freespace extent is after the end of the passed range as well as completing trim after trimming fstrim_range::len bytes. Fixes: 499f377 ("btrfs: iterate over unused chunk space in FITRIM") CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 040ee61 commit c2d1b3a

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

fs/btrfs/extent-tree.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11309,9 +11309,9 @@ int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
1130911309
* held back allocations.
1131011310
*/
1131111311
static int btrfs_trim_free_extents(struct btrfs_device *device,
11312-
u64 minlen, u64 *trimmed)
11312+
struct fstrim_range *range, u64 *trimmed)
1131311313
{
11314-
u64 start = 0, len = 0;
11314+
u64 start = range->start, len = 0;
1131511315
int ret;
1131611316

1131711317
*trimmed = 0;
@@ -11354,8 +11354,8 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
1135411354
if (!trans)
1135511355
up_read(&fs_info->commit_root_sem);
1135611356

11357-
ret = find_free_dev_extent_start(trans, device, minlen, start,
11358-
&start, &len);
11357+
ret = find_free_dev_extent_start(trans, device, range->minlen,
11358+
start, &start, &len);
1135911359
if (trans) {
1136011360
up_read(&fs_info->commit_root_sem);
1136111361
btrfs_put_transaction(trans);
@@ -11368,6 +11368,16 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
1136811368
break;
1136911369
}
1137011370

11371+
/* If we are out of the passed range break */
11372+
if (start > range->start + range->len - 1) {
11373+
mutex_unlock(&fs_info->chunk_mutex);
11374+
ret = 0;
11375+
break;
11376+
}
11377+
11378+
start = max(range->start, start);
11379+
len = min(range->len, len);
11380+
1137111381
ret = btrfs_issue_discard(device->bdev, start, len, &bytes);
1137211382
mutex_unlock(&fs_info->chunk_mutex);
1137311383

@@ -11377,6 +11387,10 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
1137711387
start += len;
1137811388
*trimmed += bytes;
1137911389

11390+
/* We've trimmed enough */
11391+
if (*trimmed >= range->len)
11392+
break;
11393+
1138011394
if (fatal_signal_pending(current)) {
1138111395
ret = -ERESTARTSYS;
1138211396
break;
@@ -11460,8 +11474,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
1146011474
mutex_lock(&fs_info->fs_devices->device_list_mutex);
1146111475
devices = &fs_info->fs_devices->devices;
1146211476
list_for_each_entry(device, devices, dev_list) {
11463-
ret = btrfs_trim_free_extents(device, range->minlen,
11464-
&group_trimmed);
11477+
ret = btrfs_trim_free_extents(device, range, &group_trimmed);
1146511478
if (ret) {
1146611479
dev_failed++;
1146711480
dev_ret = ret;

0 commit comments

Comments
 (0)