@@ -4163,6 +4163,21 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
4163
4163
return err ;
4164
4164
}
4165
4165
4166
+ static int truncate_space_check (struct btrfs_trans_handle * trans ,
4167
+ struct btrfs_root * root ,
4168
+ u64 bytes_deleted )
4169
+ {
4170
+ int ret ;
4171
+
4172
+ bytes_deleted = btrfs_csum_bytes_to_leaves (root , bytes_deleted );
4173
+ ret = btrfs_block_rsv_add (root , & root -> fs_info -> trans_block_rsv ,
4174
+ bytes_deleted , BTRFS_RESERVE_NO_FLUSH );
4175
+ if (!ret )
4176
+ trans -> bytes_reserved += bytes_deleted ;
4177
+ return ret ;
4178
+
4179
+ }
4180
+
4166
4181
/*
4167
4182
* this can truncate away extent items, csum items and directory items.
4168
4183
* It starts at a high offset and removes keys until it can't find
@@ -4201,6 +4216,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4201
4216
u64 bytes_deleted = 0 ;
4202
4217
bool be_nice = 0 ;
4203
4218
bool should_throttle = 0 ;
4219
+ bool should_end = 0 ;
4204
4220
4205
4221
BUG_ON (new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY );
4206
4222
@@ -4396,6 +4412,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4396
4412
} else {
4397
4413
break ;
4398
4414
}
4415
+ should_throttle = 0 ;
4416
+
4399
4417
if (found_extent &&
4400
4418
(test_bit (BTRFS_ROOT_REF_COWS , & root -> state ) ||
4401
4419
root == root -> fs_info -> tree_root )) {
@@ -4409,17 +4427,24 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4409
4427
if (btrfs_should_throttle_delayed_refs (trans , root ))
4410
4428
btrfs_async_run_delayed_refs (root ,
4411
4429
trans -> delayed_ref_updates * 2 , 0 );
4430
+ if (be_nice ) {
4431
+ if (truncate_space_check (trans , root ,
4432
+ extent_num_bytes )) {
4433
+ should_end = 1 ;
4434
+ }
4435
+ if (btrfs_should_throttle_delayed_refs (trans ,
4436
+ root )) {
4437
+ should_throttle = 1 ;
4438
+ }
4439
+ }
4412
4440
}
4413
4441
4414
4442
if (found_type == BTRFS_INODE_ITEM_KEY )
4415
4443
break ;
4416
4444
4417
- should_throttle =
4418
- btrfs_should_throttle_delayed_refs (trans , root );
4419
-
4420
4445
if (path -> slots [0 ] == 0 ||
4421
4446
path -> slots [0 ] != pending_del_slot ||
4422
- ( be_nice && should_throttle ) ) {
4447
+ should_throttle || should_end ) {
4423
4448
if (pending_del_nr ) {
4424
4449
ret = btrfs_del_items (trans , root , path ,
4425
4450
pending_del_slot ,
@@ -4432,7 +4457,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4432
4457
pending_del_nr = 0 ;
4433
4458
}
4434
4459
btrfs_release_path (path );
4435
- if (be_nice && should_throttle ) {
4460
+ if (should_throttle ) {
4436
4461
unsigned long updates = trans -> delayed_ref_updates ;
4437
4462
if (updates ) {
4438
4463
trans -> delayed_ref_updates = 0 ;
@@ -4441,6 +4466,14 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4441
4466
err = ret ;
4442
4467
}
4443
4468
}
4469
+ /*
4470
+ * if we failed to refill our space rsv, bail out
4471
+ * and let the transaction restart
4472
+ */
4473
+ if (should_end ) {
4474
+ err = - EAGAIN ;
4475
+ goto error ;
4476
+ }
4444
4477
goto search_again ;
4445
4478
} else {
4446
4479
path -> slots [0 ]-- ;
@@ -4460,7 +4493,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
4460
4493
4461
4494
btrfs_free_path (path );
4462
4495
4463
- if (be_nice && btrfs_should_throttle_delayed_refs ( trans , root ) ) {
4496
+ if (be_nice && bytes_deleted > 32 * 1024 * 1024 ) {
4464
4497
unsigned long updates = trans -> delayed_ref_updates ;
4465
4498
if (updates ) {
4466
4499
trans -> delayed_ref_updates = 0 ;
0 commit comments