@@ -1139,7 +1139,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
11391139 if (btrfs_header_nritems (right ) == 0 ) {
11401140 btrfs_clear_buffer_dirty (trans , right );
11411141 btrfs_tree_unlock (right );
1142- btrfs_del_ptr (root , path , level + 1 , pslot + 1 );
1142+ ret = btrfs_del_ptr (trans , root , path , level + 1 , pslot + 1 );
1143+ if (ret < 0 ) {
1144+ free_extent_buffer_stale (right );
1145+ right = NULL ;
1146+ goto out ;
1147+ }
11431148 root_sub_used (root , right -> len );
11441149 btrfs_free_tree_block (trans , btrfs_root_id (root ), right ,
11451150 0 , 1 );
@@ -1192,7 +1197,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
11921197 if (btrfs_header_nritems (mid ) == 0 ) {
11931198 btrfs_clear_buffer_dirty (trans , mid );
11941199 btrfs_tree_unlock (mid );
1195- btrfs_del_ptr (root , path , level + 1 , pslot );
1200+ ret = btrfs_del_ptr (trans , root , path , level + 1 , pslot );
1201+ if (ret < 0 ) {
1202+ free_extent_buffer_stale (mid );
1203+ mid = NULL ;
1204+ goto out ;
1205+ }
11961206 root_sub_used (root , mid -> len );
11971207 btrfs_free_tree_block (trans , btrfs_root_id (root ), mid , 0 , 1 );
11981208 free_extent_buffer_stale (mid );
@@ -4440,8 +4450,8 @@ int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
44404450 *
44414451 * This is exported for use inside btrfs-progs, don't un-export it.
44424452 */
4443- void btrfs_del_ptr (struct btrfs_root * root , struct btrfs_path * path , int level ,
4444- int slot )
4453+ int btrfs_del_ptr (struct btrfs_trans_handle * trans , struct btrfs_root * root ,
4454+ struct btrfs_path * path , int level , int slot )
44454455{
44464456 struct extent_buffer * parent = path -> nodes [level ];
44474457 u32 nritems ;
@@ -4452,7 +4462,10 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
44524462 if (level ) {
44534463 ret = btrfs_tree_mod_log_insert_move (parent , slot ,
44544464 slot + 1 , nritems - slot - 1 );
4455- BUG_ON (ret < 0 );
4465+ if (ret < 0 ) {
4466+ btrfs_abort_transaction (trans , ret );
4467+ return ret ;
4468+ }
44564469 }
44574470 memmove_extent_buffer (parent ,
44584471 btrfs_node_key_ptr_offset (parent , slot ),
@@ -4462,7 +4475,10 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
44624475 } else if (level ) {
44634476 ret = btrfs_tree_mod_log_insert_key (parent , slot ,
44644477 BTRFS_MOD_LOG_KEY_REMOVE );
4465- BUG_ON (ret < 0 );
4478+ if (ret < 0 ) {
4479+ btrfs_abort_transaction (trans , ret );
4480+ return ret ;
4481+ }
44664482 }
44674483
44684484 nritems -- ;
@@ -4478,6 +4494,7 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
44784494 fixup_low_keys (path , & disk_key , level + 1 );
44794495 }
44804496 btrfs_mark_buffer_dirty (parent );
4497+ return 0 ;
44814498}
44824499
44834500/*
@@ -4490,13 +4507,17 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
44904507 * The path must have already been setup for deleting the leaf, including
44914508 * all the proper balancing. path->nodes[1] must be locked.
44924509 */
4493- static noinline void btrfs_del_leaf (struct btrfs_trans_handle * trans ,
4494- struct btrfs_root * root ,
4495- struct btrfs_path * path ,
4496- struct extent_buffer * leaf )
4510+ static noinline int btrfs_del_leaf (struct btrfs_trans_handle * trans ,
4511+ struct btrfs_root * root ,
4512+ struct btrfs_path * path ,
4513+ struct extent_buffer * leaf )
44974514{
4515+ int ret ;
4516+
44984517 WARN_ON (btrfs_header_generation (leaf ) != trans -> transid );
4499- btrfs_del_ptr (root , path , 1 , path -> slots [1 ]);
4518+ ret = btrfs_del_ptr (trans , root , path , 1 , path -> slots [1 ]);
4519+ if (ret < 0 )
4520+ return ret ;
45004521
45014522 /*
45024523 * btrfs_free_extent is expensive, we want to make sure we
@@ -4509,6 +4530,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans,
45094530 atomic_inc (& leaf -> refs );
45104531 btrfs_free_tree_block (trans , btrfs_root_id (root ), leaf , 0 , 1 );
45114532 free_extent_buffer_stale (leaf );
4533+ return 0 ;
45124534}
45134535/*
45144536 * delete the item at the leaf level in path. If that empties
@@ -4558,7 +4580,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
45584580 btrfs_set_header_level (leaf , 0 );
45594581 } else {
45604582 btrfs_clear_buffer_dirty (trans , leaf );
4561- btrfs_del_leaf (trans , root , path , leaf );
4583+ ret = btrfs_del_leaf (trans , root , path , leaf );
4584+ if (ret < 0 )
4585+ return ret ;
45624586 }
45634587 } else {
45644588 int used = leaf_space_used (leaf , 0 , nritems );
@@ -4619,7 +4643,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
46194643
46204644 if (btrfs_header_nritems (leaf ) == 0 ) {
46214645 path -> slots [1 ] = slot ;
4622- btrfs_del_leaf (trans , root , path , leaf );
4646+ ret = btrfs_del_leaf (trans , root , path , leaf );
4647+ if (ret < 0 )
4648+ return ret ;
46234649 free_extent_buffer (leaf );
46244650 ret = 0 ;
46254651 } else {
0 commit comments