2323#include "print-tree.h"
2424#include "delalloc-space.h"
2525#include "block-group.h"
26+ #include "backref.h"
2627
2728/*
2829 * Relocation overview
@@ -3620,31 +3621,6 @@ static int __add_tree_block(struct reloc_control *rc,
36203621 return ret ;
36213622}
36223623
3623- /*
3624- * helper to check if the block use full backrefs for pointers in it
3625- */
3626- static int block_use_full_backref (struct reloc_control * rc ,
3627- struct extent_buffer * eb )
3628- {
3629- u64 flags ;
3630- int ret ;
3631-
3632- if (btrfs_header_flag (eb , BTRFS_HEADER_FLAG_RELOC ) ||
3633- btrfs_header_backref_rev (eb ) < BTRFS_MIXED_BACKREF_REV )
3634- return 1 ;
3635-
3636- ret = btrfs_lookup_extent_info (NULL , rc -> extent_root -> fs_info ,
3637- eb -> start , btrfs_header_level (eb ), 1 ,
3638- NULL , & flags );
3639- BUG_ON (ret );
3640-
3641- if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF )
3642- ret = 1 ;
3643- else
3644- ret = 0 ;
3645- return ret ;
3646- }
3647-
36483624static int delete_block_group_cache (struct btrfs_fs_info * fs_info ,
36493625 struct btrfs_block_group * block_group ,
36503626 struct inode * inode ,
@@ -3688,174 +3664,40 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
36883664}
36893665
36903666/*
3691- * helper to add tree blocks for backref of type BTRFS_EXTENT_DATA_REF_KEY
3692- * this function scans fs tree to find blocks reference the data extent
3667+ * Locate the free space cache EXTENT_DATA in root tree leaf and delete the
3668+ * cache inode, to avoid free space cache data extent blocking data relocation.
36933669 */
3694- static int find_data_references (struct reloc_control * rc ,
3695- struct btrfs_key * extent_key ,
3696- struct extent_buffer * leaf ,
3697- struct btrfs_extent_data_ref * ref ,
3698- struct rb_root * blocks )
3670+ static int delete_v1_space_cache (struct extent_buffer * leaf ,
3671+ struct btrfs_block_group * block_group ,
3672+ u64 data_bytenr )
36993673{
3700- struct btrfs_fs_info * fs_info = rc -> extent_root -> fs_info ;
3701- struct btrfs_path * path ;
3702- struct tree_block * block ;
3703- struct btrfs_root * root ;
3704- struct btrfs_file_extent_item * fi ;
3705- struct rb_node * rb_node ;
3674+ u64 space_cache_ino ;
3675+ struct btrfs_file_extent_item * ei ;
37063676 struct btrfs_key key ;
3707- u64 ref_root ;
3708- u64 ref_objectid ;
3709- u64 ref_offset ;
3710- u32 ref_count ;
3711- u32 nritems ;
3712- int err = 0 ;
3713- int added = 0 ;
3714- int counted ;
3677+ bool found = false;
3678+ int i ;
37153679 int ret ;
37163680
3717- ref_root = btrfs_extent_data_ref_root (leaf , ref );
3718- ref_objectid = btrfs_extent_data_ref_objectid (leaf , ref );
3719- ref_offset = btrfs_extent_data_ref_offset (leaf , ref );
3720- ref_count = btrfs_extent_data_ref_count (leaf , ref );
3721-
3722- /*
3723- * This is an extent belonging to the free space cache, lets just delete
3724- * it and redo the search.
3725- */
3726- if (ref_root == BTRFS_ROOT_TREE_OBJECTID ) {
3727- ret = delete_block_group_cache (fs_info , rc -> block_group ,
3728- NULL , ref_objectid );
3729- if (ret != - ENOENT )
3730- return ret ;
3731- ret = 0 ;
3732- }
3733-
3734- path = btrfs_alloc_path ();
3735- if (!path )
3736- return - ENOMEM ;
3737- path -> reada = READA_FORWARD ;
3738-
3739- root = read_fs_root (fs_info , ref_root );
3740- if (IS_ERR (root )) {
3741- err = PTR_ERR (root );
3742- goto out_free ;
3743- }
3744-
3745- key .objectid = ref_objectid ;
3746- key .type = BTRFS_EXTENT_DATA_KEY ;
3747- if (ref_offset > ((u64 )- 1 << 32 ))
3748- key .offset = 0 ;
3749- else
3750- key .offset = ref_offset ;
3751-
3752- path -> search_commit_root = 1 ;
3753- path -> skip_locking = 1 ;
3754- ret = btrfs_search_slot (NULL , root , & key , path , 0 , 0 );
3755- if (ret < 0 ) {
3756- err = ret ;
3757- goto out ;
3758- }
3759-
3760- leaf = path -> nodes [0 ];
3761- nritems = btrfs_header_nritems (leaf );
3762- /*
3763- * the references in tree blocks that use full backrefs
3764- * are not counted in
3765- */
3766- if (block_use_full_backref (rc , leaf ))
3767- counted = 0 ;
3768- else
3769- counted = 1 ;
3770- rb_node = tree_search (blocks , leaf -> start );
3771- if (rb_node ) {
3772- if (counted )
3773- added = 1 ;
3774- else
3775- path -> slots [0 ] = nritems ;
3776- }
3777-
3778- while (ref_count > 0 ) {
3779- while (path -> slots [0 ] >= nritems ) {
3780- ret = btrfs_next_leaf (root , path );
3781- if (ret < 0 ) {
3782- err = ret ;
3783- goto out ;
3784- }
3785- if (WARN_ON (ret > 0 ))
3786- goto out ;
3787-
3788- leaf = path -> nodes [0 ];
3789- nritems = btrfs_header_nritems (leaf );
3790- added = 0 ;
3791-
3792- if (block_use_full_backref (rc , leaf ))
3793- counted = 0 ;
3794- else
3795- counted = 1 ;
3796- rb_node = tree_search (blocks , leaf -> start );
3797- if (rb_node ) {
3798- if (counted )
3799- added = 1 ;
3800- else
3801- path -> slots [0 ] = nritems ;
3802- }
3803- }
3681+ if (btrfs_header_owner (leaf ) != BTRFS_ROOT_TREE_OBJECTID )
3682+ return 0 ;
38043683
3805- btrfs_item_key_to_cpu (leaf , & key , path -> slots [0 ]);
3806- if (WARN_ON (key .objectid != ref_objectid ||
3807- key .type != BTRFS_EXTENT_DATA_KEY ))
3684+ for (i = 0 ; i < btrfs_header_nritems (leaf ); i ++ ) {
3685+ btrfs_item_key_to_cpu (leaf , & key , i );
3686+ if (key .type != BTRFS_EXTENT_DATA_KEY )
3687+ continue ;
3688+ ei = btrfs_item_ptr (leaf , i , struct btrfs_file_extent_item );
3689+ if (btrfs_file_extent_type (leaf , ei ) == BTRFS_FILE_EXTENT_REG &&
3690+ btrfs_file_extent_disk_bytenr (leaf , ei ) == data_bytenr ) {
3691+ found = true;
3692+ space_cache_ino = key .objectid ;
38083693 break ;
3809-
3810- fi = btrfs_item_ptr (leaf , path -> slots [0 ],
3811- struct btrfs_file_extent_item );
3812-
3813- if (btrfs_file_extent_type (leaf , fi ) ==
3814- BTRFS_FILE_EXTENT_INLINE )
3815- goto next ;
3816-
3817- if (btrfs_file_extent_disk_bytenr (leaf , fi ) !=
3818- extent_key -> objectid )
3819- goto next ;
3820-
3821- key .offset -= btrfs_file_extent_offset (leaf , fi );
3822- if (key .offset != ref_offset )
3823- goto next ;
3824-
3825- if (counted )
3826- ref_count -- ;
3827- if (added )
3828- goto next ;
3829-
3830- if (!tree_block_processed (leaf -> start , rc )) {
3831- block = kmalloc (sizeof (* block ), GFP_NOFS );
3832- if (!block ) {
3833- err = - ENOMEM ;
3834- break ;
3835- }
3836- block -> bytenr = leaf -> start ;
3837- btrfs_item_key_to_cpu (leaf , & block -> key , 0 );
3838- block -> level = 0 ;
3839- block -> key_ready = 1 ;
3840- rb_node = tree_insert (blocks , block -> bytenr ,
3841- & block -> rb_node );
3842- if (rb_node )
3843- backref_tree_panic (rb_node , - EEXIST ,
3844- block -> bytenr );
38453694 }
3846- if (counted )
3847- added = 1 ;
3848- else
3849- path -> slots [0 ] = nritems ;
3850- next :
3851- path -> slots [0 ]++ ;
3852-
38533695 }
3854- out :
3855- btrfs_put_root ( root ) ;
3856- out_free :
3857- btrfs_free_path ( path );
3858- return err ;
3696+ if (! found )
3697+ return - ENOENT ;
3698+ ret = delete_block_group_cache ( leaf -> fs_info , block_group , NULL ,
3699+ space_cache_ino );
3700+ return ret ;
38593701}
38603702
38613703/*
@@ -3867,91 +3709,41 @@ int add_data_references(struct reloc_control *rc,
38673709 struct btrfs_path * path ,
38683710 struct rb_root * blocks )
38693711{
3870- struct btrfs_key key ;
3871- struct extent_buffer * eb ;
3872- struct btrfs_extent_data_ref * dref ;
3873- struct btrfs_extent_inline_ref * iref ;
3874- unsigned long ptr ;
3875- unsigned long end ;
3876- u32 blocksize = rc -> extent_root -> fs_info -> nodesize ;
3712+ struct btrfs_fs_info * fs_info = rc -> extent_root -> fs_info ;
3713+ struct ulist * leaves = NULL ;
3714+ struct ulist_iterator leaf_uiter ;
3715+ struct ulist_node * ref_node = NULL ;
3716+ const u32 blocksize = fs_info -> nodesize ;
38773717 int ret = 0 ;
3878- int err = 0 ;
3879-
3880- eb = path -> nodes [0 ];
3881- ptr = btrfs_item_ptr_offset (eb , path -> slots [0 ]);
3882- end = ptr + btrfs_item_size_nr (eb , path -> slots [0 ]);
3883- ptr += sizeof (struct btrfs_extent_item );
38843718
3885- while (ptr < end ) {
3886- iref = (struct btrfs_extent_inline_ref * )ptr ;
3887- key .type = btrfs_get_extent_inline_ref_type (eb , iref ,
3888- BTRFS_REF_TYPE_DATA );
3889- if (key .type == BTRFS_SHARED_DATA_REF_KEY ) {
3890- key .offset = btrfs_extent_inline_ref_offset (eb , iref );
3891- ret = __add_tree_block (rc , key .offset , blocksize ,
3892- blocks );
3893- } else if (key .type == BTRFS_EXTENT_DATA_REF_KEY ) {
3894- dref = (struct btrfs_extent_data_ref * )(& iref -> offset );
3895- ret = find_data_references (rc , extent_key ,
3896- eb , dref , blocks );
3897- } else {
3898- ret = - EUCLEAN ;
3899- btrfs_err (rc -> extent_root -> fs_info ,
3900- "extent %llu slot %d has an invalid inline ref type" ,
3901- eb -> start , path -> slots [0 ]);
3902- }
3903- if (ret ) {
3904- err = ret ;
3905- goto out ;
3906- }
3907- ptr += btrfs_extent_inline_ref_size (key .type );
3908- }
3909- WARN_ON (ptr > end );
3719+ btrfs_release_path (path );
3720+ ret = btrfs_find_all_leafs (NULL , fs_info , extent_key -> objectid ,
3721+ 0 , & leaves , NULL , true);
3722+ if (ret < 0 )
3723+ return ret ;
39103724
3911- while (1 ) {
3912- cond_resched ();
3913- eb = path -> nodes [0 ];
3914- if (path -> slots [0 ] >= btrfs_header_nritems (eb )) {
3915- ret = btrfs_next_leaf (rc -> extent_root , path );
3916- if (ret < 0 ) {
3917- err = ret ;
3918- break ;
3919- }
3920- if (ret > 0 )
3921- break ;
3922- eb = path -> nodes [0 ];
3923- }
3725+ ULIST_ITER_INIT (& leaf_uiter );
3726+ while ((ref_node = ulist_next (leaves , & leaf_uiter ))) {
3727+ struct extent_buffer * eb ;
39243728
3925- btrfs_item_key_to_cpu (eb , & key , path -> slots [0 ]);
3926- if (key .objectid != extent_key -> objectid )
3729+ eb = read_tree_block (fs_info , ref_node -> val , 0 , 0 , NULL );
3730+ if (IS_ERR (eb )) {
3731+ ret = PTR_ERR (eb );
39273732 break ;
3928-
3929- if (key .type == BTRFS_SHARED_DATA_REF_KEY ) {
3930- ret = __add_tree_block (rc , key .offset , blocksize ,
3931- blocks );
3932- } else if (key .type == BTRFS_EXTENT_DATA_REF_KEY ) {
3933- dref = btrfs_item_ptr (eb , path -> slots [0 ],
3934- struct btrfs_extent_data_ref );
3935- ret = find_data_references (rc , extent_key ,
3936- eb , dref , blocks );
3937- } else if (unlikely (key .type == BTRFS_EXTENT_REF_V0_KEY )) {
3938- btrfs_print_v0_err (eb -> fs_info );
3939- btrfs_handle_fs_error (eb -> fs_info , - EINVAL , NULL );
3940- ret = - EINVAL ;
3941- } else {
3942- ret = 0 ;
39433733 }
3944- if (ret ) {
3945- err = ret ;
3734+ ret = delete_v1_space_cache (eb , rc -> block_group ,
3735+ extent_key -> objectid );
3736+ free_extent_buffer (eb );
3737+ if (ret < 0 )
3738+ break ;
3739+ ret = __add_tree_block (rc , ref_node -> val , blocksize , blocks );
3740+ if (ret < 0 )
39463741 break ;
3947- }
3948- path -> slots [0 ]++ ;
39493742 }
3950- out :
3951- btrfs_release_path (path );
3952- if (err )
3743+ if (ret < 0 )
39533744 free_block_list (blocks );
3954- return err ;
3745+ ulist_free (leaves );
3746+ return ret ;
39553747}
39563748
39573749/*
0 commit comments