btrfs: simplify update of last_dir_index_offset when logging a directory
[platform/kernel/linux-starfive.git] / fs / btrfs / tree-log.c
index 7535857..e71464c 100644 (file)
@@ -3607,17 +3607,19 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans,
 }
 
 static int flush_dir_items_batch(struct btrfs_trans_handle *trans,
-                                struct btrfs_root *log,
+                                struct btrfs_inode *inode,
                                 struct extent_buffer *src,
                                 struct btrfs_path *dst_path,
                                 int start_slot,
                                 int count)
 {
+       struct btrfs_root *log = inode->root->log_root;
        char *ins_data = NULL;
        struct btrfs_item_batch batch;
        struct extent_buffer *dst;
        unsigned long src_offset;
        unsigned long dst_offset;
+       u64 last_index;
        struct btrfs_key key;
        u32 item_size;
        int ret;
@@ -3675,6 +3677,19 @@ static int flush_dir_items_batch(struct btrfs_trans_handle *trans,
        src_offset = btrfs_item_ptr_offset(src, start_slot + count - 1);
        copy_extent_buffer(dst, src, dst_offset, src_offset, batch.total_data_size);
        btrfs_release_path(dst_path);
+
+       last_index = batch.keys[count - 1].offset;
+       ASSERT(last_index > inode->last_dir_index_offset);
+
+       /*
+        * If for some unexpected reason the last item's index is not greater
+        * than the last index we logged, warn and return an error to fallback
+        * to a transaction commit.
+        */
+       if (WARN_ON(last_index <= inode->last_dir_index_offset))
+               ret = -EUCLEAN;
+       else
+               inode->last_dir_index_offset = last_index;
 out:
        kfree(ins_data);
 
@@ -3724,7 +3739,6 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans,
                }
 
                di = btrfs_item_ptr(src, i, struct btrfs_dir_item);
-               ctx->last_dir_item_offset = key.offset;
 
                /*
                 * Skip ranges of items that consist only of dir item keys created
@@ -3787,7 +3801,7 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans,
        if (batch_size > 0) {
                int ret;
 
-               ret = flush_dir_items_batch(trans, log, src, dst_path,
+               ret = flush_dir_items_batch(trans, inode, src, dst_path,
                                            batch_start, batch_size);
                if (ret < 0)
                        return ret;
@@ -4075,7 +4089,6 @@ static noinline int log_directory_changes(struct btrfs_trans_handle *trans,
 
        min_key = BTRFS_DIR_START_INDEX;
        max_key = 0;
-       ctx->last_dir_item_offset = inode->last_dir_index_offset;
 
        while (1) {
                ret = log_dir_items(trans, inode, path, dst_path,
@@ -4087,8 +4100,6 @@ static noinline int log_directory_changes(struct btrfs_trans_handle *trans,
                min_key = max_key + 1;
        }
 
-       inode->last_dir_index_offset = ctx->last_dir_item_offset;
-
        return 0;
 }