summaryrefslogtreecommitdiff
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c255
1 files changed, 126 insertions, 129 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d830c33be7c6..b4e901da9e8b 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -150,6 +150,18 @@ struct walk_control {
*/
int (*process_func)(struct extent_buffer *eb,
struct walk_control *wc, u64 gen, int level);
+
+ /*
+ * The following are used only when stage is >= LOG_WALK_REPLAY_INODES
+ * and by the replay_one_buffer() callback.
+ */
+
+ /* The current log leaf being processed. */
+ struct extent_buffer *log_leaf;
+ /* The key being processed of the current log leaf. */
+ struct btrfs_key log_key;
+ /* The slot being processed of the current log leaf. */
+ int log_slot;
};
static int btrfs_log_inode(struct btrfs_trans_handle *trans,
@@ -396,8 +408,9 @@ static int process_one_buffer(struct extent_buffer *eb,
}
/*
- * Item overwrite used by log replay. The given eb, slot and key all refer to
- * the source data we are copying out.
+ * Item overwrite used by log replay. The given log tree leaf, slot and key
+ * from the walk_control structure all refer to the source data we are copying
+ * out.
*
* The given root is for the tree we are copying into, and path is a scratch
* path for use in this function (it should be released on entry and will be
@@ -409,10 +422,7 @@ static int process_one_buffer(struct extent_buffer *eb,
*
* If the key isn't in the destination yet, a new item is inserted.
*/
-static int overwrite_item(struct walk_control *wc,
- struct btrfs_path *path,
- struct extent_buffer *eb, int slot,
- struct btrfs_key *key)
+static int overwrite_item(struct walk_control *wc, struct btrfs_path *path)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
@@ -424,7 +434,7 @@ static int overwrite_item(struct walk_control *wc,
unsigned long dst_ptr;
struct extent_buffer *dst_eb;
int dst_slot;
- const bool is_inode_item = (key->type == BTRFS_INODE_ITEM_KEY);
+ const bool is_inode_item = (wc->log_key.type == BTRFS_INODE_ITEM_KEY);
/*
* This is only used during log replay, so the root is always from a
@@ -435,11 +445,11 @@ static int overwrite_item(struct walk_control *wc,
*/
ASSERT(btrfs_root_id(root) != BTRFS_TREE_LOG_OBJECTID);
- item_size = btrfs_item_size(eb, slot);
- src_ptr = btrfs_item_ptr_offset(eb, slot);
+ item_size = btrfs_item_size(wc->log_leaf, wc->log_slot);
+ src_ptr = btrfs_item_ptr_offset(wc->log_leaf, wc->log_slot);
/* Look for the key in the destination tree. */
- ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+ ret = btrfs_search_slot(NULL, root, &wc->log_key, path, 0, 0);
if (ret < 0) {
btrfs_abort_transaction(trans, ret);
return ret;
@@ -466,7 +476,7 @@ static int overwrite_item(struct walk_control *wc,
return -ENOMEM;
}
- read_extent_buffer(eb, src_copy, src_ptr, item_size);
+ read_extent_buffer(wc->log_leaf, src_copy, src_ptr, item_size);
dst_ptr = btrfs_item_ptr_offset(dst_eb, dst_slot);
ret = memcmp_extent_buffer(dst_eb, src_copy, dst_ptr, item_size);
@@ -494,18 +504,18 @@ static int overwrite_item(struct walk_control *wc,
item = btrfs_item_ptr(dst_eb, dst_slot,
struct btrfs_inode_item);
nbytes = btrfs_inode_nbytes(dst_eb, item);
- item = btrfs_item_ptr(eb, slot,
+ item = btrfs_item_ptr(wc->log_leaf, wc->log_slot,
struct btrfs_inode_item);
- btrfs_set_inode_nbytes(eb, item, nbytes);
+ btrfs_set_inode_nbytes(wc->log_leaf, item, nbytes);
/*
* If this is a directory we need to reset the i_size to
* 0 so that we can set it up properly when replaying
* the rest of the items in this log.
*/
- mode = btrfs_inode_mode(eb, item);
+ mode = btrfs_inode_mode(wc->log_leaf, item);
if (S_ISDIR(mode))
- btrfs_set_inode_size(eb, item, 0);
+ btrfs_set_inode_size(wc->log_leaf, item, 0);
}
} else if (is_inode_item) {
struct btrfs_inode_item *item;
@@ -515,24 +525,23 @@ static int overwrite_item(struct walk_control *wc,
* New inode, set nbytes to 0 so that the nbytes comes out
* properly when we replay the extents.
*/
- item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
- btrfs_set_inode_nbytes(eb, item, 0);
+ item = btrfs_item_ptr(wc->log_leaf, wc->log_slot, struct btrfs_inode_item);
+ btrfs_set_inode_nbytes(wc->log_leaf, item, 0);
/*
* If this is a directory we need to reset the i_size to 0 so
* that we can set it up properly when replaying the rest of
* the items in this log.
*/
- mode = btrfs_inode_mode(eb, item);
+ mode = btrfs_inode_mode(wc->log_leaf, item);
if (S_ISDIR(mode))
- btrfs_set_inode_size(eb, item, 0);
+ btrfs_set_inode_size(wc->log_leaf, item, 0);
}
insert:
btrfs_release_path(path);
/* try to insert the key into the destination tree */
path->skip_release_on_error = 1;
- ret = btrfs_insert_empty_item(trans, root, path,
- key, item_size);
+ ret = btrfs_insert_empty_item(trans, root, path, &wc->log_key, item_size);
path->skip_release_on_error = 0;
dst_eb = path->nodes[0];
@@ -568,8 +577,8 @@ insert:
src_item = (struct btrfs_inode_item *)src_ptr;
dst_item = (struct btrfs_inode_item *)dst_ptr;
- if (btrfs_inode_generation(eb, src_item) == 0) {
- const u64 ino_size = btrfs_inode_size(eb, src_item);
+ if (btrfs_inode_generation(wc->log_leaf, src_item) == 0) {
+ const u64 ino_size = btrfs_inode_size(wc->log_leaf, src_item);
/*
* For regular files an ino_size == 0 is used only when
@@ -578,21 +587,21 @@ insert:
* case don't set the size of the inode in the fs/subvol
* tree, otherwise we would be throwing valid data away.
*/
- if (S_ISREG(btrfs_inode_mode(eb, src_item)) &&
+ if (S_ISREG(btrfs_inode_mode(wc->log_leaf, src_item)) &&
S_ISREG(btrfs_inode_mode(dst_eb, dst_item)) &&
ino_size != 0)
btrfs_set_inode_size(dst_eb, dst_item, ino_size);
goto no_copy;
}
- if (S_ISDIR(btrfs_inode_mode(eb, src_item)) &&
+ if (S_ISDIR(btrfs_inode_mode(wc->log_leaf, src_item)) &&
S_ISDIR(btrfs_inode_mode(dst_eb, dst_item))) {
save_old_i_size = 1;
saved_i_size = btrfs_inode_size(dst_eb, dst_item);
}
}
- copy_extent_buffer(dst_eb, eb, dst_ptr, src_ptr, item_size);
+ copy_extent_buffer(dst_eb, wc->log_leaf, dst_ptr, src_ptr, item_size);
if (save_old_i_size) {
struct btrfs_inode_item *dst_item;
@@ -641,10 +650,7 @@ static int read_alloc_one_name(struct extent_buffer *eb, void *start, int len,
* The extent is inserted into the file, dropping any existing extents
* from the file that overlap the new one.
*/
-static noinline int replay_one_extent(struct walk_control *wc,
- struct btrfs_path *path,
- struct extent_buffer *eb, int slot,
- struct btrfs_key *key)
+static noinline int replay_one_extent(struct walk_control *wc, struct btrfs_path *path)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
@@ -652,7 +658,7 @@ static noinline int replay_one_extent(struct walk_control *wc,
struct btrfs_fs_info *fs_info = root->fs_info;
int found_type;
u64 extent_end;
- u64 start = key->offset;
+ const u64 start = wc->log_key.offset;
u64 nbytes = 0;
u64 csum_start;
u64 csum_end;
@@ -665,34 +671,35 @@ static noinline int replay_one_extent(struct walk_control *wc,
unsigned long size;
int ret = 0;
- item = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
- found_type = btrfs_file_extent_type(eb, item);
+ item = btrfs_item_ptr(wc->log_leaf, wc->log_slot, struct btrfs_file_extent_item);
+ found_type = btrfs_file_extent_type(wc->log_leaf, item);
if (found_type == BTRFS_FILE_EXTENT_REG ||
found_type == BTRFS_FILE_EXTENT_PREALLOC) {
- nbytes = btrfs_file_extent_num_bytes(eb, item);
+ nbytes = btrfs_file_extent_num_bytes(wc->log_leaf, item);
extent_end = start + nbytes;
/*
* We don't add to the inodes nbytes if we are prealloc or a
* hole.
*/
- if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
+ if (btrfs_file_extent_disk_bytenr(wc->log_leaf, item) == 0)
nbytes = 0;
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
- size = btrfs_file_extent_ram_bytes(eb, item);
- nbytes = btrfs_file_extent_ram_bytes(eb, item);
+ size = btrfs_file_extent_ram_bytes(wc->log_leaf, item);
+ nbytes = btrfs_file_extent_ram_bytes(wc->log_leaf, item);
extent_end = ALIGN(start + size,
fs_info->sectorsize);
} else {
btrfs_abort_transaction(trans, -EUCLEAN);
btrfs_err(fs_info,
"unexpected extent type=%d root=%llu inode=%llu offset=%llu",
- found_type, btrfs_root_id(root), key->objectid, key->offset);
+ found_type, btrfs_root_id(root), wc->log_key.objectid,
+ wc->log_key.offset);
return -EUCLEAN;
}
- inode = btrfs_iget_logging(key->objectid, root);
+ inode = btrfs_iget_logging(wc->log_key.objectid, root);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
btrfs_abort_transaction(trans, ret);
@@ -719,7 +726,7 @@ static noinline int replay_one_extent(struct walk_control *wc,
* we already have a pointer to this exact extent,
* we don't have to do anything
*/
- if (memcmp_extent_buffer(eb, &existing, (unsigned long)item,
+ if (memcmp_extent_buffer(wc->log_leaf, &existing, (unsigned long)item,
sizeof(existing)) == 0) {
btrfs_release_path(path);
goto out;
@@ -739,7 +746,7 @@ static noinline int replay_one_extent(struct walk_control *wc,
if (found_type == BTRFS_FILE_EXTENT_INLINE) {
/* inline extents are easy, we just overwrite them */
- ret = overwrite_item(wc, path, eb, slot, key);
+ ret = overwrite_item(wc, path);
if (ret)
goto out;
goto update_inode;
@@ -751,18 +758,18 @@ static noinline int replay_one_extent(struct walk_control *wc,
*/
/* A hole and NO_HOLES feature enabled, nothing else to do. */
- if (btrfs_file_extent_disk_bytenr(eb, item) == 0 &&
+ if (btrfs_file_extent_disk_bytenr(wc->log_leaf, item) == 0 &&
btrfs_fs_incompat(fs_info, NO_HOLES))
goto update_inode;
- ret = btrfs_insert_empty_item(trans, root, path, key, sizeof(*item));
+ ret = btrfs_insert_empty_item(trans, root, path, &wc->log_key, sizeof(*item));
if (ret) {
btrfs_abort_transaction(trans, ret);
goto out;
}
dest_offset = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]);
- copy_extent_buffer(path->nodes[0], eb, dest_offset, (unsigned long)item,
- sizeof(*item));
+ copy_extent_buffer(path->nodes[0], wc->log_leaf, dest_offset,
+ (unsigned long)item, sizeof(*item));
/*
* We have an explicit hole and NO_HOLES is not enabled. We have added
@@ -770,15 +777,15 @@ static noinline int replay_one_extent(struct walk_control *wc,
* anything else to do other than update the file extent item range and
* update the inode item.
*/
- if (btrfs_file_extent_disk_bytenr(eb, item) == 0) {
+ if (btrfs_file_extent_disk_bytenr(wc->log_leaf, item) == 0) {
btrfs_release_path(path);
goto update_inode;
}
- ins.objectid = btrfs_file_extent_disk_bytenr(eb, item);
+ ins.objectid = btrfs_file_extent_disk_bytenr(wc->log_leaf, item);
ins.type = BTRFS_EXTENT_ITEM_KEY;
- ins.offset = btrfs_file_extent_disk_num_bytes(eb, item);
- offset = key->offset - btrfs_file_extent_offset(eb, item);
+ ins.offset = btrfs_file_extent_disk_num_bytes(wc->log_leaf, item);
+ offset = wc->log_key.offset - btrfs_file_extent_offset(wc->log_leaf, item);
/*
* Manually record dirty extent, as here we did a shallow file extent
@@ -810,7 +817,7 @@ static noinline int replay_one_extent(struct walk_control *wc,
.ref_root = btrfs_root_id(root),
};
- btrfs_init_data_ref(&ref, key->objectid, offset, 0, false);
+ btrfs_init_data_ref(&ref, wc->log_key.objectid, offset, 0, false);
ret = btrfs_inc_extent_ref(trans, &ref);
if (ret) {
btrfs_abort_transaction(trans, ret);
@@ -819,7 +826,7 @@ static noinline int replay_one_extent(struct walk_control *wc,
} else {
/* Insert the extent pointer in the extent tree. */
ret = btrfs_alloc_logged_file_extent(trans, btrfs_root_id(root),
- key->objectid, offset, &ins);
+ wc->log_key.objectid, offset, &ins);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto out;
@@ -828,12 +835,12 @@ static noinline int replay_one_extent(struct walk_control *wc,
btrfs_release_path(path);
- if (btrfs_file_extent_compression(eb, item)) {
+ if (btrfs_file_extent_compression(wc->log_leaf, item)) {
csum_start = ins.objectid;
csum_end = csum_start + ins.offset;
} else {
- csum_start = ins.objectid + btrfs_file_extent_offset(eb, item);
- csum_end = csum_start + btrfs_file_extent_num_bytes(eb, item);
+ csum_start = ins.objectid + btrfs_file_extent_offset(wc->log_leaf, item);
+ csum_end = csum_start + btrfs_file_extent_num_bytes(wc->log_leaf, item);
}
ret = btrfs_lookup_csums_list(root->log_root, csum_start, csum_end - 1,
@@ -1352,10 +1359,7 @@ static int ref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr,
*/
static int unlink_old_inode_refs(struct walk_control *wc,
struct btrfs_path *path,
- struct btrfs_inode *inode,
- struct extent_buffer *log_eb,
- int log_slot,
- struct btrfs_key *key)
+ struct btrfs_inode *inode)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
@@ -1366,7 +1370,7 @@ static int unlink_old_inode_refs(struct walk_control *wc,
again:
btrfs_release_path(path);
- ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+ ret = btrfs_search_slot(NULL, root, &wc->log_key, path, 0, 0);
if (ret > 0) {
ret = 0;
goto out;
@@ -1383,7 +1387,7 @@ again:
struct fscrypt_str name;
u64 parent_id;
- if (key->type == BTRFS_INODE_EXTREF_KEY) {
+ if (wc->log_key.type == BTRFS_INODE_EXTREF_KEY) {
ret = extref_get_fields(eb, ref_ptr, &name,
NULL, &parent_id);
if (ret) {
@@ -1391,7 +1395,7 @@ again:
goto out;
}
} else {
- parent_id = key->offset;
+ parent_id = wc->log_key.offset;
ret = ref_get_fields(eb, ref_ptr, &name, NULL);
if (ret) {
btrfs_abort_transaction(trans, ret);
@@ -1399,11 +1403,12 @@ again:
}
}
- if (key->type == BTRFS_INODE_EXTREF_KEY)
- ret = !!btrfs_find_name_in_ext_backref(log_eb, log_slot,
+ if (wc->log_key.type == BTRFS_INODE_EXTREF_KEY)
+ ret = !!btrfs_find_name_in_ext_backref(wc->log_leaf, wc->log_slot,
parent_id, &name);
else
- ret = !!btrfs_find_name_in_backref(log_eb, log_slot, &name);
+ ret = !!btrfs_find_name_in_backref(wc->log_leaf, wc->log_slot,
+ &name);
if (!ret) {
struct btrfs_inode *dir;
@@ -1426,7 +1431,7 @@ again:
kfree(name.name);
ref_ptr += name.len;
- if (key->type == BTRFS_INODE_EXTREF_KEY)
+ if (wc->log_key.type == BTRFS_INODE_EXTREF_KEY)
ref_ptr += sizeof(struct btrfs_inode_extref);
else
ref_ptr += sizeof(struct btrfs_inode_ref);
@@ -1438,15 +1443,10 @@ again:
}
/*
- * replay one inode back reference item found in the log tree.
- * eb, slot and key refer to the buffer and key found in the log tree.
- * root is the destination we are replaying into, and path is for temp
- * use by this function. (it should be released on return).
+ * Replay one inode back reference item found in the log tree.
+ * Path is for temporary use by this function (it should be released on return).
*/
-static noinline int add_inode_ref(struct walk_control *wc,
- struct btrfs_path *path,
- struct extent_buffer *eb, int slot,
- struct btrfs_key *key)
+static noinline int add_inode_ref(struct walk_control *wc, struct btrfs_path *path)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
@@ -1456,26 +1456,26 @@ static noinline int add_inode_ref(struct walk_control *wc,
unsigned long ref_end;
struct fscrypt_str name = { 0 };
int ret;
- const bool is_extref_item = (key->type == BTRFS_INODE_EXTREF_KEY);
+ const bool is_extref_item = (wc->log_key.type == BTRFS_INODE_EXTREF_KEY);
u64 parent_objectid;
u64 inode_objectid;
u64 ref_index = 0;
int ref_struct_size;
- ref_ptr = btrfs_item_ptr_offset(eb, slot);
- ref_end = ref_ptr + btrfs_item_size(eb, slot);
+ ref_ptr = btrfs_item_ptr_offset(wc->log_leaf, wc->log_slot);
+ ref_end = ref_ptr + btrfs_item_size(wc->log_leaf, wc->log_slot);
if (is_extref_item) {
struct btrfs_inode_extref *r;
ref_struct_size = sizeof(struct btrfs_inode_extref);
r = (struct btrfs_inode_extref *)ref_ptr;
- parent_objectid = btrfs_inode_extref_parent(eb, r);
+ parent_objectid = btrfs_inode_extref_parent(wc->log_leaf, r);
} else {
ref_struct_size = sizeof(struct btrfs_inode_ref);
- parent_objectid = key->offset;
+ parent_objectid = wc->log_key.offset;
}
- inode_objectid = key->objectid;
+ inode_objectid = wc->log_key.objectid;
/*
* it is possible that we didn't log all the parent directories
@@ -1504,7 +1504,7 @@ static noinline int add_inode_ref(struct walk_control *wc,
while (ref_ptr < ref_end) {
if (is_extref_item) {
- ret = extref_get_fields(eb, ref_ptr, &name,
+ ret = extref_get_fields(wc->log_leaf, ref_ptr, &name,
&ref_index, &parent_objectid);
if (ret) {
btrfs_abort_transaction(trans, ret);
@@ -1541,7 +1541,7 @@ static noinline int add_inode_ref(struct walk_control *wc,
}
}
} else {
- ret = ref_get_fields(eb, ref_ptr, &name, &ref_index);
+ ret = ref_get_fields(wc->log_leaf, ref_ptr, &name, &ref_index);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto out;
@@ -1602,12 +1602,12 @@ next:
* dir index entries exist for a name but there is no inode reference
* item with the same name.
*/
- ret = unlink_old_inode_refs(wc, path, inode, eb, slot, key);
+ ret = unlink_old_inode_refs(wc, path, inode);
if (ret)
goto out;
/* finally write the back reference in the inode */
- ret = overwrite_item(wc, path, eb, slot, key);
+ ret = overwrite_item(wc, path);
out:
btrfs_release_path(path);
kfree(name.name);
@@ -1965,9 +1965,7 @@ static int delete_conflicting_dir_entry(struct walk_control *wc,
*/
static noinline int replay_one_name(struct walk_control *wc,
struct btrfs_path *path,
- struct extent_buffer *eb,
- struct btrfs_dir_item *di,
- struct btrfs_key *key)
+ struct btrfs_dir_item *di)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
@@ -1985,21 +1983,22 @@ static noinline int replay_one_name(struct walk_control *wc,
bool update_size = true;
bool name_added = false;
- dir = btrfs_iget_logging(key->objectid, root);
+ dir = btrfs_iget_logging(wc->log_key.objectid, root);
if (IS_ERR(dir)) {
ret = PTR_ERR(dir);
btrfs_abort_transaction(trans, ret);
return ret;
}
- ret = read_alloc_one_name(eb, di + 1, btrfs_dir_name_len(eb, di), &name);
+ ret = read_alloc_one_name(wc->log_leaf, di + 1,
+ btrfs_dir_name_len(wc->log_leaf, di), &name);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto out;
}
- log_flags = btrfs_dir_flags(eb, di);
- btrfs_dir_item_key_to_cpu(eb, di, &log_key);
+ log_flags = btrfs_dir_flags(wc->log_leaf, di);
+ btrfs_dir_item_key_to_cpu(wc->log_leaf, di, &log_key);
ret = btrfs_lookup_inode(trans, root, path, &log_key, 0);
btrfs_release_path(path);
if (ret < 0) {
@@ -2009,7 +2008,7 @@ static noinline int replay_one_name(struct walk_control *wc,
exists = (ret == 0);
ret = 0;
- dir_dst_di = btrfs_lookup_dir_item(trans, root, path, key->objectid,
+ dir_dst_di = btrfs_lookup_dir_item(trans, root, path, wc->log_key.objectid,
&name, 1);
if (IS_ERR(dir_dst_di)) {
ret = PTR_ERR(dir_dst_di);
@@ -2028,8 +2027,8 @@ static noinline int replay_one_name(struct walk_control *wc,
btrfs_release_path(path);
index_dst_di = btrfs_lookup_dir_index_item(trans, root, path,
- key->objectid, key->offset,
- &name, 1);
+ wc->log_key.objectid,
+ wc->log_key.offset, &name, 1);
if (IS_ERR(index_dst_di)) {
ret = PTR_ERR(index_dst_di);
btrfs_abort_transaction(trans, ret);
@@ -2058,7 +2057,7 @@ static noinline int replay_one_name(struct walk_control *wc,
*/
search_key.objectid = log_key.objectid;
search_key.type = BTRFS_INODE_REF_KEY;
- search_key.offset = key->objectid;
+ search_key.offset = wc->log_key.objectid;
ret = backref_in_log(root->log_root, &search_key, 0, &name);
if (ret < 0) {
btrfs_abort_transaction(trans, ret);
@@ -2072,8 +2071,8 @@ static noinline int replay_one_name(struct walk_control *wc,
search_key.objectid = log_key.objectid;
search_key.type = BTRFS_INODE_EXTREF_KEY;
- search_key.offset = btrfs_extref_hash(key->objectid, name.name, name.len);
- ret = backref_in_log(root->log_root, &search_key, key->objectid, &name);
+ search_key.offset = btrfs_extref_hash(wc->log_key.objectid, name.name, name.len);
+ ret = backref_in_log(root->log_root, &search_key, wc->log_key.objectid, &name);
if (ret < 0) {
btrfs_abort_transaction(trans, ret);
goto out;
@@ -2084,7 +2083,7 @@ static noinline int replay_one_name(struct walk_control *wc,
goto out;
}
btrfs_release_path(path);
- ret = insert_one_name(trans, root, key->objectid, key->offset,
+ ret = insert_one_name(trans, root, wc->log_key.objectid, wc->log_key.offset,
&name, &log_key);
if (ret && ret != -ENOENT && ret != -EEXIST) {
btrfs_abort_transaction(trans, ret);
@@ -2111,18 +2110,16 @@ out:
/* Replay one dir item from a BTRFS_DIR_INDEX_KEY key. */
static noinline int replay_one_dir_item(struct walk_control *wc,
- struct btrfs_path *path,
- struct extent_buffer *eb, int slot,
- struct btrfs_key *key)
+ struct btrfs_path *path)
{
int ret;
struct btrfs_dir_item *di;
/* We only log dir index keys, which only contain a single dir item. */
- ASSERT(key->type == BTRFS_DIR_INDEX_KEY);
+ ASSERT(wc->log_key.type == BTRFS_DIR_INDEX_KEY);
- di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
- ret = replay_one_name(wc, path, eb, di, key);
+ di = btrfs_item_ptr(wc->log_leaf, wc->log_slot, struct btrfs_dir_item);
+ ret = replay_one_name(wc, path, di);
if (ret < 0)
return ret;
@@ -2152,7 +2149,7 @@ static noinline int replay_one_dir_item(struct walk_control *wc,
* to ever delete the parent directory has it would result in stale
* dentries that can never be deleted.
*/
- if (ret == 1 && btrfs_dir_ftype(eb, di) != BTRFS_FT_DIR) {
+ if (ret == 1 && btrfs_dir_ftype(wc->log_leaf, di) != BTRFS_FT_DIR) {
struct btrfs_path *fixup_path;
struct btrfs_key di_key;
@@ -2162,7 +2159,7 @@ static noinline int replay_one_dir_item(struct walk_control *wc,
return -ENOMEM;
}
- btrfs_dir_item_key_to_cpu(eb, di, &di_key);
+ btrfs_dir_item_key_to_cpu(wc->log_leaf, di, &di_key);
ret = link_to_fixup_dir(wc, fixup_path, di_key.objectid);
btrfs_free_path(fixup_path);
}
@@ -2339,15 +2336,14 @@ out:
return ret;
}
-static int replay_xattr_deletes(struct walk_control *wc,
- struct btrfs_path *path,
- const u64 ino)
+static int replay_xattr_deletes(struct walk_control *wc, struct btrfs_path *path)
{
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_root *root = wc->root;
struct btrfs_root *log = wc->log;
struct btrfs_key search_key;
struct btrfs_path *log_path;
+ const u64 ino = wc->log_key.objectid;
int i;
int nritems;
int ret;
@@ -2587,8 +2583,6 @@ static int replay_one_buffer(struct extent_buffer *eb,
struct btrfs_path *path;
struct btrfs_root *root = wc->root;
struct btrfs_trans_handle *trans = wc->trans;
- struct btrfs_key key;
- int i;
int ret;
if (level != 0)
@@ -2606,14 +2600,17 @@ static int replay_one_buffer(struct extent_buffer *eb,
return -ENOMEM;
}
+ wc->log_leaf = eb;
+
nritems = btrfs_header_nritems(eb);
- for (i = 0; i < nritems; i++) {
+ for (wc->log_slot = 0; wc->log_slot < nritems; wc->log_slot++) {
struct btrfs_inode_item *inode_item;
- btrfs_item_key_to_cpu(eb, &key, i);
+ btrfs_item_key_to_cpu(eb, &wc->log_key, wc->log_slot);
- if (key.type == BTRFS_INODE_ITEM_KEY) {
- inode_item = btrfs_item_ptr(eb, i, struct btrfs_inode_item);
+ if (wc->log_key.type == BTRFS_INODE_ITEM_KEY) {
+ inode_item = btrfs_item_ptr(eb, wc->log_slot,
+ struct btrfs_inode_item);
/*
* An inode with no links is either:
*
@@ -2642,20 +2639,20 @@ static int replay_one_buffer(struct extent_buffer *eb,
}
/* Inode keys are done during the first stage. */
- if (key.type == BTRFS_INODE_ITEM_KEY &&
+ if (wc->log_key.type == BTRFS_INODE_ITEM_KEY &&
wc->stage == LOG_WALK_REPLAY_INODES) {
u32 mode;
- ret = replay_xattr_deletes(wc, path, key.objectid);
+ ret = replay_xattr_deletes(wc, path);
if (ret)
break;
mode = btrfs_inode_mode(eb, inode_item);
if (S_ISDIR(mode)) {
- ret = replay_dir_deletes(wc, path, key.objectid, false);
+ ret = replay_dir_deletes(wc, path, wc->log_key.objectid, false);
if (ret)
break;
}
- ret = overwrite_item(wc, path, eb, i, &key);
+ ret = overwrite_item(wc, path);
if (ret)
break;
@@ -2672,7 +2669,7 @@ static int replay_one_buffer(struct extent_buffer *eb,
struct btrfs_inode *inode;
u64 from;
- inode = btrfs_iget_logging(key.objectid, root);
+ inode = btrfs_iget_logging(wc->log_key.objectid, root);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
btrfs_abort_transaction(trans, ret);
@@ -2699,7 +2696,7 @@ static int replay_one_buffer(struct extent_buffer *eb,
break;
}
- ret = link_to_fixup_dir(wc, path, key.objectid);
+ ret = link_to_fixup_dir(wc, path, wc->log_key.objectid);
if (ret)
break;
}
@@ -2707,9 +2704,9 @@ static int replay_one_buffer(struct extent_buffer *eb,
if (wc->ignore_cur_inode)
continue;
- if (key.type == BTRFS_DIR_INDEX_KEY &&
+ if (wc->log_key.type == BTRFS_DIR_INDEX_KEY &&
wc->stage == LOG_WALK_REPLAY_DIR_INDEX) {
- ret = replay_one_dir_item(wc, path, eb, i, &key);
+ ret = replay_one_dir_item(wc, path);
if (ret)
break;
}
@@ -2718,17 +2715,17 @@ static int replay_one_buffer(struct extent_buffer *eb,
continue;
/* these keys are simply copied */
- if (key.type == BTRFS_XATTR_ITEM_KEY) {
- ret = overwrite_item(wc, path, eb, i, &key);
+ if (wc->log_key.type == BTRFS_XATTR_ITEM_KEY) {
+ ret = overwrite_item(wc, path);
if (ret)
break;
- } else if (key.type == BTRFS_INODE_REF_KEY ||
- key.type == BTRFS_INODE_EXTREF_KEY) {
- ret = add_inode_ref(wc, path, eb, i, &key);
+ } else if (wc->log_key.type == BTRFS_INODE_REF_KEY ||
+ wc->log_key.type == BTRFS_INODE_EXTREF_KEY) {
+ ret = add_inode_ref(wc, path);
if (ret)
break;
- } else if (key.type == BTRFS_EXTENT_DATA_KEY) {
- ret = replay_one_extent(wc, path, eb, i, &key);
+ } else if (wc->log_key.type == BTRFS_EXTENT_DATA_KEY) {
+ ret = replay_one_extent(wc, path);
if (ret)
break;
}