* held back allocations.
  */
 static int btrfs_trim_free_extents(struct btrfs_device *device,
-                                  u64 minlen, u64 *trimmed)
+                                  struct fstrim_range *range, u64 *trimmed)
 {
-       u64 start = 0, len = 0;
+       u64 start = range->start, len = 0;
        int ret;
 
        *trimmed = 0;
                if (!trans)
                        up_read(&fs_info->commit_root_sem);
 
-               ret = find_free_dev_extent_start(trans, device, minlen, start,
-                                                &start, &len);
+               ret = find_free_dev_extent_start(trans, device, range->minlen,
+                                                start, &start, &len);
                if (trans) {
                        up_read(&fs_info->commit_root_sem);
                        btrfs_put_transaction(trans);
                        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);
 
                start += len;
                *trimmed += bytes;
 
+               /* We've trimmed enough */
+               if (*trimmed >= range->len)
+                       break;
+
                if (fatal_signal_pending(current)) {
                        ret = -ERESTARTSYS;
                        break;
        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->minlen,
-                                             &group_trimmed);
+               ret = btrfs_trim_free_extents(device, range, &group_trimmed);
                if (ret) {
                        dev_failed++;
                        dev_ret = ret;