Commit ccae4a19 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: remove no longer needed logic for replaying directory deletes

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: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 339d0354
...@@ -2203,7 +2203,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, ...@@ -2203,7 +2203,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
*/ */
static noinline int find_dir_range(struct btrfs_root *root, static noinline int find_dir_range(struct btrfs_root *root,
struct btrfs_path *path, struct btrfs_path *path,
u64 dirid, int key_type, u64 dirid,
u64 *start_ret, u64 *end_ret) u64 *start_ret, u64 *end_ret)
{ {
struct btrfs_key key; struct btrfs_key key;
...@@ -2216,7 +2216,7 @@ static noinline int find_dir_range(struct btrfs_root *root, ...@@ -2216,7 +2216,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
return 1; return 1;
key.objectid = dirid; key.objectid = dirid;
key.type = key_type; key.type = BTRFS_DIR_LOG_INDEX_KEY;
key.offset = *start_ret; key.offset = *start_ret;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
...@@ -2230,7 +2230,7 @@ static noinline int find_dir_range(struct btrfs_root *root, ...@@ -2230,7 +2230,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
if (ret != 0) if (ret != 0)
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[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; ret = 1;
goto next; goto next;
} }
...@@ -2257,7 +2257,7 @@ static noinline int find_dir_range(struct btrfs_root *root, ...@@ -2257,7 +2257,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[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; ret = 1;
goto out; goto out;
} }
...@@ -2288,95 +2288,82 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans, ...@@ -2288,95 +2288,82 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
int ret; int ret;
struct extent_buffer *eb; struct extent_buffer *eb;
int slot; int slot;
u32 item_size;
struct btrfs_dir_item *di; struct btrfs_dir_item *di;
struct btrfs_dir_item *log_di;
int name_len; int name_len;
unsigned long ptr;
unsigned long ptr_end;
char *name; char *name;
struct inode *inode; struct inode *inode = NULL;
struct btrfs_key location; 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]; eb = path->nodes[0];
slot = path->slots[0]; slot = path->slots[0];
item_size = btrfs_item_size_nr(eb, slot); di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
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_len = btrfs_dir_name_len(eb, di);
name = kmalloc(name_len, GFP_NOFS); name = kmalloc(name_len, GFP_NOFS);
if (!name) { if (!name) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
read_extent_buffer(eb, name, (unsigned long)(di + 1),
name_len); read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len);
log_di = NULL;
if (log && dir_key->type == BTRFS_DIR_ITEM_KEY) { if (log) {
log_di = btrfs_lookup_dir_item(trans, log, log_path, struct btrfs_dir_item *log_di;
dir_key->objectid,
name, name_len, 0); log_di = btrfs_lookup_dir_index_item(trans, log, log_path,
} else if (log && dir_key->type == BTRFS_DIR_INDEX_KEY) {
log_di = btrfs_lookup_dir_index_item(trans, log,
log_path,
dir_key->objectid, dir_key->objectid,
dir_key->offset, dir_key->offset,
name, name_len, 0); name, name_len, 0);
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;
} }
if (!log_di) { }
btrfs_dir_item_key_to_cpu(eb, di, &location); btrfs_dir_item_key_to_cpu(eb, di, &location);
btrfs_release_path(path); btrfs_release_path(path);
btrfs_release_path(log_path); btrfs_release_path(log_path);
inode = read_one_inode(root, location.objectid); inode = read_one_inode(root, location.objectid);
if (!inode) { if (!inode) {
kfree(name); ret = -EIO;
return -EIO; goto out;
} }
ret = link_to_fixup_dir(trans, root, ret = link_to_fixup_dir(trans, root, path, location.objectid);
path, location.objectid); if (ret)
if (ret) {
kfree(name);
iput(inode);
goto out; goto out;
}
inc_nlink(inode); inc_nlink(inode);
ret = btrfs_unlink_inode(trans, BTRFS_I(dir), ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(inode), name,
BTRFS_I(inode), name, name_len); name_len);
if (!ret)
ret = btrfs_run_delayed_items(trans);
kfree(name);
iput(inode);
if (ret) if (ret)
goto out; goto out;
/* there might still be more names under this key ret = btrfs_run_delayed_items(trans);
* check and repeat if required if (ret)
*/
ret = btrfs_search_slot(NULL, root, dir_key, path,
0, 0);
if (ret == 0)
goto again;
ret = 0;
goto out; 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; * 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
ret = 0; * (an index number), so we're done.
*/
out: out:
btrfs_release_path(path); btrfs_release_path(path);
btrfs_release_path(log_path); btrfs_release_path(log_path);
kfree(name);
iput(inode);
return ret; return ret;
} }
...@@ -2496,7 +2483,6 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans, ...@@ -2496,7 +2483,6 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
{ {
u64 range_start; u64 range_start;
u64 range_end; u64 range_end;
int key_type = BTRFS_DIR_LOG_ITEM_KEY;
int ret = 0; int ret = 0;
struct btrfs_key dir_key; struct btrfs_key dir_key;
struct btrfs_key found_key; struct btrfs_key found_key;
...@@ -2504,7 +2490,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans, ...@@ -2504,7 +2490,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
struct inode *dir; struct inode *dir;
dir_key.objectid = dirid; dir_key.objectid = dirid;
dir_key.type = BTRFS_DIR_ITEM_KEY; dir_key.type = BTRFS_DIR_INDEX_KEY;
log_path = btrfs_alloc_path(); log_path = btrfs_alloc_path();
if (!log_path) if (!log_path)
return -ENOMEM; return -ENOMEM;
...@@ -2518,14 +2504,14 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans, ...@@ -2518,14 +2504,14 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
btrfs_free_path(log_path); btrfs_free_path(log_path);
return 0; return 0;
} }
again:
range_start = 0; range_start = 0;
range_end = 0; range_end = 0;
while (1) { while (1) {
if (del_all) if (del_all)
range_end = (u64)-1; range_end = (u64)-1;
else { else {
ret = find_dir_range(log, path, dirid, key_type, ret = find_dir_range(log, path, dirid,
&range_start, &range_end); &range_start, &range_end);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -2552,8 +2538,10 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans, ...@@ -2552,8 +2538,10 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
btrfs_item_key_to_cpu(path->nodes[0], &found_key, btrfs_item_key_to_cpu(path->nodes[0], &found_key,
path->slots[0]); path->slots[0]);
if (found_key.objectid != dirid || if (found_key.objectid != dirid ||
found_key.type != dir_key.type) found_key.type != dir_key.type) {
goto next_type; ret = 0;
goto out;
}
if (found_key.offset > range_end) if (found_key.offset > range_end)
break; break;
...@@ -2572,15 +2560,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans, ...@@ -2572,15 +2560,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
break; break;
range_start = range_end + 1; range_start = range_end + 1;
} }
next_type:
ret = 0; 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: out:
btrfs_release_path(path); btrfs_release_path(path);
btrfs_free_path(log_path); btrfs_free_path(log_path);
......
...@@ -146,7 +146,9 @@ ...@@ -146,7 +146,9 @@
/* /*
* dir items are the name -> inode pointers in a directory. There is one * 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_ITEM_KEY 60
#define BTRFS_DIR_LOG_INDEX_KEY 72 #define BTRFS_DIR_LOG_INDEX_KEY 72
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment