func: static noinline long CVE_2010_2537_PATCHED_btrfs_ioctl_clone(struct file *file, unsigned long u64 off, u64 olen, u64 destoff) struct inode * inode = fdentry ( file ) -> d_inode ; struct btrfs_root * root = BTRFS_I ( inode ) -> root ; struct file * src_file ; struct inode * src ; struct btrfs_trans_handle * trans ; struct btrfs_path * path ; struct extent_buffer * leaf ; char * buf ; struct btrfs_key key ; u32 nritems ; int slot ; int ret ; u64 len = olen ; u64 bs = root -> fs_info -> sb -> s_blocksize ; if ( ! ( file -> f_mode & FMODE_WRITE ) || ( file -> f_flags & O_APPEND ) )  ret = mnt_want_write ( file -> f_path . mnt ); if ( ret )  src_file = fget ( srcfd ); if ( ! src_file )  src = src_file -> f_dentry -> d_inode; if ( src == inode )  if ( ! ( src_file -> f_mode & FMODE_READ ) )  if ( S_ISDIR ( src -> i_mode ) || S_ISDIR ( inode -> i_mode ) )  ret = - EXDEV; if ( src -> i_sb != inode -> i_sb || BTRFS_I ( src ) -> root != root )  ret = - ENOMEM; buf = vmalloc ( btrfs_level_size ( root , 0 ) ); if ( ! buf )  path = btrfs_alloc_path ( ); if ( ! path )  path -> reada = 2; ret = - EINVAL; if ( off + len > src -> i_size || off + len < off )  if ( len == 0 )  olen = len = src -> i_size - off; if ( off + len == src -> i_size )  len = ( ( src -> i_size + bs - 1 ) & ~ ( bs - 1 ) ) - off; if ( ( off & ( bs - 1 ) ) || ( ( off + len ) & ( bs - 1 ) ) )  trans = btrfs_start_transaction ( root , 1 ); key . objectid = src -> i_ino; key . type = BTRFS_EXTENT_DATA_KEY; key . offset = 0; while ( 1 )  ret = btrfs_search_slot ( trans , root , & key , path , 0 , 0 ); if ( ret < 0 )  nritems = btrfs_header_nritems ( path -> nodes [ 0 ] ); if ( path -> slots [ 0 ] >= nritems )  ret = btrfs_next_leaf ( root , path ); if ( ret < 0 )  if ( ret > 0 )  leaf = path -> nodes [ 0 ]; slot = path -> slots [ 0 ]; if ( btrfs_key_type ( & key ) > BTRFS_EXTENT_DATA_KEY || key . objectid != src -> i_ino )  if ( btrfs_key_type ( & key ) == BTRFS_EXTENT_DATA_KEY )  struct btrfs_file_extent_item * extent ; int type ; u32 size ; struct btrfs_key new_key ; u64 datao = 0 , datal = 0 ; u8 comp ; size = btrfs_item_size_nr ( leaf , slot ); extent = btrfs_item_ptr ( leaf , slot struct btrfs_file_extent_item ) comp = btrfs_file_extent_compression ( leaf , extent ); type = btrfs_file_extent_type ( leaf , extent ); if ( type == BTRFS_FILE_EXTENT_REG || type == BTRFS_FILE_EXTENT_PREALLOC )  datal = btrfs_file_extent_num_bytes ( leaf , extent ); if ( type == BTRFS_FILE_EXTENT_INLINE )  datal = btrfs_file_extent_ram_bytes ( leaf , extent ); if ( key . offset + datal < off || key . offset >= off + len )  memcpy ( & new_key , & key , sizeof ( new_key ) ); new_key . objectid = inode -> i_ino; new_key . offset = key . offset + destoff - off; if ( type == BTRFS_FILE_EXTENT_REG || type == BTRFS_FILE_EXTENT_PREALLOC )  ret = btrfs_insert_empty_item ( trans , root , path , & new_key , size ); if ( ret )  if ( type == BTRFS_FILE_EXTENT_INLINE )  u64 skip = 0 ; u64 trim = 0 ; if ( off > key . offset )  skip = off - key . offset; new_key . offset += skip; if ( key . offset + datal > off + len )  trim = key . offset + datal - ( off + len ); if ( comp && ( skip || trim ) )  size -= skip + trim; datal -= skip + trim; ret = btrfs_insert_empty_item ( trans , root , path , & new_key , size ); if ( ret )  if ( skip )  u32 start = btrfs_file_extent_calc_inline_size ( 0 ) ; memmove ( buf + start , buf + start + skip , datal ); write_extent_buffer ( leaf , buf , btrfs_item_ptr_offset ( leaf , slot ) , size ); key . offset ++; vfree ( buf ); 