diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 255 |
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; } |
