btrfs: remove no longer needed logic for replaying directory deletes
[ Upstream commit ccae4a19c9140a34a0c5f0658812496dd8bbdeaf ] Now that we log only dir index keys when logging a directory, we no longer need to deal with dir item keys in the log replay code for replaying directory deletes. This is also true for the case when we replay a log tree created by a kernel that still logs dir items. So remove the remaining code of the replay of directory deletes algorithm that deals with dir item keys. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
7697ca60db
commit
9688152112
@ -2197,7 +2197,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
|
||||
*/
|
||||
static noinline int find_dir_range(struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
u64 dirid, int key_type,
|
||||
u64 dirid,
|
||||
u64 *start_ret, u64 *end_ret)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
@ -2210,7 +2210,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
|
||||
return 1;
|
||||
|
||||
key.objectid = dirid;
|
||||
key.type = key_type;
|
||||
key.type = BTRFS_DIR_LOG_INDEX_KEY;
|
||||
key.offset = *start_ret;
|
||||
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
@ -2224,7 +2224,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
|
||||
if (ret != 0)
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
|
||||
|
||||
if (key.type != key_type || key.objectid != dirid) {
|
||||
if (key.type != BTRFS_DIR_LOG_INDEX_KEY || key.objectid != dirid) {
|
||||
ret = 1;
|
||||
goto next;
|
||||
}
|
||||
@ -2251,7 +2251,7 @@ next:
|
||||
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
|
||||
|
||||
if (key.type != key_type || key.objectid != dirid) {
|
||||
if (key.type != BTRFS_DIR_LOG_INDEX_KEY || key.objectid != dirid) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
@ -2282,95 +2282,82 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
|
||||
int ret;
|
||||
struct extent_buffer *eb;
|
||||
int slot;
|
||||
u32 item_size;
|
||||
struct btrfs_dir_item *di;
|
||||
struct btrfs_dir_item *log_di;
|
||||
int name_len;
|
||||
unsigned long ptr;
|
||||
unsigned long ptr_end;
|
||||
char *name;
|
||||
struct inode *inode;
|
||||
struct inode *inode = NULL;
|
||||
struct btrfs_key location;
|
||||
|
||||
again:
|
||||
/*
|
||||
* Currenly we only log dir index keys. Even if we replay a log created
|
||||
* by an older kernel that logged both dir index and dir item keys, all
|
||||
* we need to do is process the dir index keys, we (and our caller) can
|
||||
* safely ignore dir item keys (key type BTRFS_DIR_ITEM_KEY).
|
||||
*/
|
||||
ASSERT(dir_key->type == BTRFS_DIR_INDEX_KEY);
|
||||
|
||||
eb = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
item_size = btrfs_item_size_nr(eb, slot);
|
||||
ptr = btrfs_item_ptr_offset(eb, slot);
|
||||
ptr_end = ptr + item_size;
|
||||
while (ptr < ptr_end) {
|
||||
di = (struct btrfs_dir_item *)ptr;
|
||||
name_len = btrfs_dir_name_len(eb, di);
|
||||
name = kmalloc(name_len, GFP_NOFS);
|
||||
if (!name) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
read_extent_buffer(eb, name, (unsigned long)(di + 1),
|
||||
name_len);
|
||||
log_di = NULL;
|
||||
if (log && dir_key->type == BTRFS_DIR_ITEM_KEY) {
|
||||
log_di = btrfs_lookup_dir_item(trans, log, log_path,
|
||||
dir_key->objectid,
|
||||
name, name_len, 0);
|
||||
} else if (log && dir_key->type == BTRFS_DIR_INDEX_KEY) {
|
||||
log_di = btrfs_lookup_dir_index_item(trans, log,
|
||||
log_path,
|
||||
di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
|
||||
name_len = btrfs_dir_name_len(eb, di);
|
||||
name = kmalloc(name_len, GFP_NOFS);
|
||||
if (!name) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len);
|
||||
|
||||
if (log) {
|
||||
struct btrfs_dir_item *log_di;
|
||||
|
||||
log_di = btrfs_lookup_dir_index_item(trans, log, log_path,
|
||||
dir_key->objectid,
|
||||
dir_key->offset,
|
||||
name, name_len, 0);
|
||||
}
|
||||
if (!log_di) {
|
||||
btrfs_dir_item_key_to_cpu(eb, di, &location);
|
||||
btrfs_release_path(path);
|
||||
btrfs_release_path(log_path);
|
||||
inode = read_one_inode(root, location.objectid);
|
||||
if (!inode) {
|
||||
kfree(name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = link_to_fixup_dir(trans, root,
|
||||
path, location.objectid);
|
||||
if (ret) {
|
||||
kfree(name);
|
||||
iput(inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
inc_nlink(inode);
|
||||
ret = btrfs_unlink_inode(trans, BTRFS_I(dir),
|
||||
BTRFS_I(inode), name, name_len);
|
||||
if (!ret)
|
||||
ret = btrfs_run_delayed_items(trans);
|
||||
kfree(name);
|
||||
iput(inode);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* there might still be more names under this key
|
||||
* check and repeat if required
|
||||
*/
|
||||
ret = btrfs_search_slot(NULL, root, dir_key, path,
|
||||
0, 0);
|
||||
if (ret == 0)
|
||||
goto again;
|
||||
if (IS_ERR(log_di)) {
|
||||
ret = PTR_ERR(log_di);
|
||||
goto out;
|
||||
} else if (log_di) {
|
||||
/* The dentry exists in the log, we have nothing to do. */
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (IS_ERR(log_di)) {
|
||||
kfree(name);
|
||||
return PTR_ERR(log_di);
|
||||
}
|
||||
btrfs_release_path(log_path);
|
||||
kfree(name);
|
||||
|
||||
ptr = (unsigned long)(di + 1);
|
||||
ptr += name_len;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
btrfs_dir_item_key_to_cpu(eb, di, &location);
|
||||
btrfs_release_path(path);
|
||||
btrfs_release_path(log_path);
|
||||
inode = read_one_inode(root, location.objectid);
|
||||
if (!inode) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = link_to_fixup_dir(trans, root, path, location.objectid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
inc_nlink(inode);
|
||||
ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(inode), name,
|
||||
name_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = btrfs_run_delayed_items(trans);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Unlike dir item keys, dir index keys can only have one name (entry) in
|
||||
* them, as there are no key collisions since each key has a unique offset
|
||||
* (an index number), so we're done.
|
||||
*/
|
||||
out:
|
||||
btrfs_release_path(path);
|
||||
btrfs_release_path(log_path);
|
||||
kfree(name);
|
||||
iput(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2490,7 +2477,6 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
u64 range_start;
|
||||
u64 range_end;
|
||||
int key_type = BTRFS_DIR_LOG_ITEM_KEY;
|
||||
int ret = 0;
|
||||
struct btrfs_key dir_key;
|
||||
struct btrfs_key found_key;
|
||||
@ -2498,7 +2484,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
|
||||
struct inode *dir;
|
||||
|
||||
dir_key.objectid = dirid;
|
||||
dir_key.type = BTRFS_DIR_ITEM_KEY;
|
||||
dir_key.type = BTRFS_DIR_INDEX_KEY;
|
||||
log_path = btrfs_alloc_path();
|
||||
if (!log_path)
|
||||
return -ENOMEM;
|
||||
@ -2512,14 +2498,14 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
|
||||
btrfs_free_path(log_path);
|
||||
return 0;
|
||||
}
|
||||
again:
|
||||
|
||||
range_start = 0;
|
||||
range_end = 0;
|
||||
while (1) {
|
||||
if (del_all)
|
||||
range_end = (u64)-1;
|
||||
else {
|
||||
ret = find_dir_range(log, path, dirid, key_type,
|
||||
ret = find_dir_range(log, path, dirid,
|
||||
&range_start, &range_end);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -2546,8 +2532,10 @@ again:
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &found_key,
|
||||
path->slots[0]);
|
||||
if (found_key.objectid != dirid ||
|
||||
found_key.type != dir_key.type)
|
||||
goto next_type;
|
||||
found_key.type != dir_key.type) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (found_key.offset > range_end)
|
||||
break;
|
||||
@ -2566,15 +2554,7 @@ again:
|
||||
break;
|
||||
range_start = range_end + 1;
|
||||
}
|
||||
|
||||
next_type:
|
||||
ret = 0;
|
||||
if (key_type == BTRFS_DIR_LOG_ITEM_KEY) {
|
||||
key_type = BTRFS_DIR_LOG_INDEX_KEY;
|
||||
dir_key.type = BTRFS_DIR_INDEX_KEY;
|
||||
btrfs_release_path(path);
|
||||
goto again;
|
||||
}
|
||||
out:
|
||||
btrfs_release_path(path);
|
||||
btrfs_free_path(log_path);
|
||||
|
@ -146,7 +146,9 @@
|
||||
|
||||
/*
|
||||
* dir items are the name -> inode pointers in a directory. There is one
|
||||
* for every name in a directory.
|
||||
* for every name in a directory. BTRFS_DIR_LOG_ITEM_KEY is no longer used
|
||||
* but it's still defined here for documentation purposes and to help avoid
|
||||
* having its numerical value reused in the future.
|
||||
*/
|
||||
#define BTRFS_DIR_LOG_ITEM_KEY 60
|
||||
#define BTRFS_DIR_LOG_INDEX_KEY 72
|
||||
|
Loading…
x
Reference in New Issue
Block a user