@ -2470,6 +2470,26 @@ out:
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 ,
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 ,
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 */
key . objectid = btrfs_ino ( src ) ;