@@ -3576,17 +3576,19 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans,
3576
3576
}
3577
3577
3578
3578
static int flush_dir_items_batch (struct btrfs_trans_handle * trans ,
3579
- struct btrfs_root * log ,
3579
+ struct btrfs_inode * inode ,
3580
3580
struct extent_buffer * src ,
3581
3581
struct btrfs_path * dst_path ,
3582
3582
int start_slot ,
3583
3583
int count )
3584
3584
{
3585
+ struct btrfs_root * log = inode -> root -> log_root ;
3585
3586
char * ins_data = NULL ;
3586
3587
struct btrfs_item_batch batch ;
3587
3588
struct extent_buffer * dst ;
3588
3589
unsigned long src_offset ;
3589
3590
unsigned long dst_offset ;
3591
+ u64 last_index ;
3590
3592
struct btrfs_key key ;
3591
3593
u32 item_size ;
3592
3594
int ret ;
@@ -3644,6 +3646,19 @@ static int flush_dir_items_batch(struct btrfs_trans_handle *trans,
3644
3646
src_offset = btrfs_item_ptr_offset (src , start_slot + count - 1 );
3645
3647
copy_extent_buffer (dst , src , dst_offset , src_offset , batch .total_data_size );
3646
3648
btrfs_release_path (dst_path );
3649
+
3650
+ last_index = batch .keys [count - 1 ].offset ;
3651
+ ASSERT (last_index > inode -> last_dir_index_offset );
3652
+
3653
+ /*
3654
+ * If for some unexpected reason the last item's index is not greater
3655
+ * than the last index we logged, warn and return an error to fallback
3656
+ * to a transaction commit.
3657
+ */
3658
+ if (WARN_ON (last_index <= inode -> last_dir_index_offset ))
3659
+ ret = - EUCLEAN ;
3660
+ else
3661
+ inode -> last_dir_index_offset = last_index ;
3647
3662
out :
3648
3663
kfree (ins_data );
3649
3664
@@ -3693,7 +3708,6 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans,
3693
3708
}
3694
3709
3695
3710
di = btrfs_item_ptr (src , i , struct btrfs_dir_item );
3696
- ctx -> last_dir_item_offset = key .offset ;
3697
3711
3698
3712
/*
3699
3713
* Skip ranges of items that consist only of dir item keys created
@@ -3756,7 +3770,7 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans,
3756
3770
if (batch_size > 0 ) {
3757
3771
int ret ;
3758
3772
3759
- ret = flush_dir_items_batch (trans , log , src , dst_path ,
3773
+ ret = flush_dir_items_batch (trans , inode , src , dst_path ,
3760
3774
batch_start , batch_size );
3761
3775
if (ret < 0 )
3762
3776
return ret ;
@@ -4044,7 +4058,6 @@ static noinline int log_directory_changes(struct btrfs_trans_handle *trans,
4044
4058
4045
4059
min_key = BTRFS_DIR_START_INDEX ;
4046
4060
max_key = 0 ;
4047
- ctx -> last_dir_item_offset = inode -> last_dir_index_offset ;
4048
4061
4049
4062
while (1 ) {
4050
4063
ret = log_dir_items (trans , inode , path , dst_path ,
@@ -4056,8 +4069,6 @@ static noinline int log_directory_changes(struct btrfs_trans_handle *trans,
4056
4069
min_key = max_key + 1 ;
4057
4070
}
4058
4071
4059
- inode -> last_dir_index_offset = ctx -> last_dir_item_offset ;
4060
-
4061
4072
return 0 ;
4062
4073
}
4063
4074
0 commit comments