Skip to content

Commit

Permalink
btrfs: simplify update of last_dir_index_offset when logging a directory
Browse files Browse the repository at this point in the history
When logging a directory, we always set the inode's last_dir_index_offset
to the offset of the last dir index item we found. This is using an extra
field in the log context structure, and it makes more sense to update it
only after we insert dir index items, and we could directly update the
inode's last_dir_index_offset field instead.

So make this simpler by updating the inode's last_dir_index_offset only
when we actually insert dir index keys in the log tree, and getting rid
of the last_dir_item_offset field in the log context structure.

Reported-by: David Arendt <admin@prnet.org>
Link: https://lore.kernel.org/linux-btrfs/ae169fc6-f504-28f0-a098-6fa6a4dfb612@leemhuis.info/
Reported-by: Maxim Mikityanskiy <maxtram95@gmail.com>
Link: https://lore.kernel.org/linux-btrfs/Y8voyTXdnPDz8xwY@mail.gmail.com/
Reported-by: Hunter Wardlaw <wardlawhunter@gmail.com>
Link: https://bugzilla.suse.com/show_bug.cgi?id=1207231
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=216851
CC: stable@vger.kernel.org # 6.1+
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Filipe Manana authored and David Sterba committed Feb 6, 2023
1 parent a9ad4d8 commit 6afaed5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
23 changes: 17 additions & 6 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3576,17 +3576,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;
Expand Down Expand Up @@ -3644,6 +3646,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);

Expand Down Expand Up @@ -3693,7 +3708,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
Expand Down Expand Up @@ -3756,7 +3770,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;
Expand Down Expand Up @@ -4044,7 +4058,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,
Expand All @@ -4056,8 +4069,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;
}

Expand Down
2 changes: 0 additions & 2 deletions fs/btrfs/tree-log.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ struct btrfs_log_ctx {
bool logging_new_delayed_dentries;
/* Indicate if the inode being logged was logged before. */
bool logged_before;
/* Tracks the last logged dir item/index key offset. */
u64 last_dir_item_offset;
struct inode *inode;
struct list_head list;
/* Only used for fast fsyncs. */
Expand Down

0 comments on commit 6afaed5

Please sign in to comment.