@@ -1139,7 +1139,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1139
1139
if (btrfs_header_nritems (right ) == 0 ) {
1140
1140
btrfs_clear_buffer_dirty (trans , right );
1141
1141
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
+ }
1143
1148
root_sub_used (root , right -> len );
1144
1149
btrfs_free_tree_block (trans , btrfs_root_id (root ), right ,
1145
1150
0 , 1 );
@@ -1192,7 +1197,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1192
1197
if (btrfs_header_nritems (mid ) == 0 ) {
1193
1198
btrfs_clear_buffer_dirty (trans , mid );
1194
1199
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
+ }
1196
1206
root_sub_used (root , mid -> len );
1197
1207
btrfs_free_tree_block (trans , btrfs_root_id (root ), mid , 0 , 1 );
1198
1208
free_extent_buffer_stale (mid );
@@ -4440,8 +4450,8 @@ int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
4440
4450
*
4441
4451
* This is exported for use inside btrfs-progs, don't un-export it.
4442
4452
*/
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 )
4445
4455
{
4446
4456
struct extent_buffer * parent = path -> nodes [level ];
4447
4457
u32 nritems ;
@@ -4452,7 +4462,10 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
4452
4462
if (level ) {
4453
4463
ret = btrfs_tree_mod_log_insert_move (parent , slot ,
4454
4464
slot + 1 , nritems - slot - 1 );
4455
- BUG_ON (ret < 0 );
4465
+ if (ret < 0 ) {
4466
+ btrfs_abort_transaction (trans , ret );
4467
+ return ret ;
4468
+ }
4456
4469
}
4457
4470
memmove_extent_buffer (parent ,
4458
4471
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,
4462
4475
} else if (level ) {
4463
4476
ret = btrfs_tree_mod_log_insert_key (parent , slot ,
4464
4477
BTRFS_MOD_LOG_KEY_REMOVE );
4465
- BUG_ON (ret < 0 );
4478
+ if (ret < 0 ) {
4479
+ btrfs_abort_transaction (trans , ret );
4480
+ return ret ;
4481
+ }
4466
4482
}
4467
4483
4468
4484
nritems -- ;
@@ -4478,6 +4494,7 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
4478
4494
fixup_low_keys (path , & disk_key , level + 1 );
4479
4495
}
4480
4496
btrfs_mark_buffer_dirty (parent );
4497
+ return 0 ;
4481
4498
}
4482
4499
4483
4500
/*
@@ -4490,13 +4507,17 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
4490
4507
* The path must have already been setup for deleting the leaf, including
4491
4508
* all the proper balancing. path->nodes[1] must be locked.
4492
4509
*/
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 )
4497
4514
{
4515
+ int ret ;
4516
+
4498
4517
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 ;
4500
4521
4501
4522
/*
4502
4523
* 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,
4509
4530
atomic_inc (& leaf -> refs );
4510
4531
btrfs_free_tree_block (trans , btrfs_root_id (root ), leaf , 0 , 1 );
4511
4532
free_extent_buffer_stale (leaf );
4533
+ return 0 ;
4512
4534
}
4513
4535
/*
4514
4536
* 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,
4558
4580
btrfs_set_header_level (leaf , 0 );
4559
4581
} else {
4560
4582
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 ;
4562
4586
}
4563
4587
} else {
4564
4588
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,
4619
4643
4620
4644
if (btrfs_header_nritems (leaf ) == 0 ) {
4621
4645
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 ;
4623
4649
free_extent_buffer (leaf );
4624
4650
ret = 0 ;
4625
4651
} else {
0 commit comments