|
@@ -2470,6 +2470,26 @@ out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline void lock_extent_range(struct inode *inode, u64 off, u64 len)
|
|
|
|
+{
|
|
|
|
+ /* do any pending delalloc/csum calc on src, one way or
|
|
|
|
+ another, and lock file content */
|
|
|
|
+ while (1) {
|
|
|
|
+ struct btrfs_ordered_extent *ordered;
|
|
|
|
+ lock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
|
|
|
|
+ ordered = btrfs_lookup_first_ordered_extent(inode,
|
|
|
|
+ off + len - 1);
|
|
|
|
+ if (!ordered &&
|
|
|
|
+ !test_range_bit(&BTRFS_I(inode)->io_tree, off,
|
|
|
|
+ off + len - 1, EXTENT_DELALLOC, 0, NULL))
|
|
|
|
+ break;
|
|
|
|
+ unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
|
|
|
|
+ if (ordered)
|
|
|
|
+ btrfs_put_ordered_extent(ordered);
|
|
|
|
+ btrfs_wait_ordered_range(inode, off, len);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
|
static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
|
u64 off, u64 olen, u64 destoff)
|
|
u64 off, u64 olen, u64 destoff)
|
|
{
|
|
{
|
|
@@ -2598,21 +2618,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
|
truncate_inode_pages_range(&inode->i_data, destoff,
|
|
truncate_inode_pages_range(&inode->i_data, destoff,
|
|
PAGE_CACHE_ALIGN(destoff + len) - 1);
|
|
PAGE_CACHE_ALIGN(destoff + len) - 1);
|
|
|
|
|
|
- /* do any pending delalloc/csum calc on src, one way or
|
|
|
|
- another, and lock file content */
|
|
|
|
- while (1) {
|
|
|
|
- struct btrfs_ordered_extent *ordered;
|
|
|
|
- lock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
|
|
|
|
- ordered = btrfs_lookup_first_ordered_extent(src, off + len - 1);
|
|
|
|
- if (!ordered &&
|
|
|
|
- !test_range_bit(&BTRFS_I(src)->io_tree, off, off + len - 1,
|
|
|
|
- EXTENT_DELALLOC, 0, NULL))
|
|
|
|
- break;
|
|
|
|
- unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
|
|
|
|
- if (ordered)
|
|
|
|
- btrfs_put_ordered_extent(ordered);
|
|
|
|
- btrfs_wait_ordered_range(src, off, len);
|
|
|
|
- }
|
|
|
|
|
|
+ lock_extent_range(src, off, len);
|
|
|
|
|
|
/* clone data */
|
|
/* clone data */
|
|
key.objectid = btrfs_ino(src);
|
|
key.objectid = btrfs_ino(src);
|