Commit 8dcbc261 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: unify lookup return value when dir entry is missing

btrfs_lookup_dir_index_item() and btrfs_lookup_dir_item() lookup for dir
entries and both are used during log replay or when updating a log tree
during an unlink.

However when the dir item does not exists, btrfs_lookup_dir_item() returns
NULL while btrfs_lookup_dir_index_item() returns PTR_ERR(-ENOENT), and if
the dir item exists but there is no matching entry for a given name or
index, both return NULL. This makes the call sites during log replay to
be more verbose than necessary and it makes it easy to miss this slight
difference. Since we don't need to distinguish between those two cases,
make btrfs_lookup_dir_index_item() always return NULL when there is no
matching directory entry - either because there isn't any dir entry or
because there is one but it does not match the given name and index.

Also rename the argument 'objectid' of btrfs_lookup_dir_index_item() to
'index' since it is supposed to match an index number, and the name
'objectid' is not very good because it can easily be confused with an
inode number (like the inode number a dir entry points to).

CC: stable@vger.kernel.org # 4.14+
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 52db7779
...@@ -3030,7 +3030,7 @@ struct btrfs_dir_item * ...@@ -3030,7 +3030,7 @@ struct btrfs_dir_item *
btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_path *path, u64 dir, struct btrfs_path *path, u64 dir,
u64 objectid, const char *name, int name_len, u64 index, const char *name, int name_len,
int mod); int mod);
struct btrfs_dir_item * struct btrfs_dir_item *
btrfs_search_dir_index_item(struct btrfs_root *root, btrfs_search_dir_index_item(struct btrfs_root *root,
......
...@@ -190,9 +190,20 @@ static struct btrfs_dir_item *btrfs_lookup_match_dir( ...@@ -190,9 +190,20 @@ static struct btrfs_dir_item *btrfs_lookup_match_dir(
} }
/* /*
* lookup a directory item based on name. 'dir' is the objectid * Lookup for a directory item by name.
* we're searching in, and 'mod' tells us if you plan on deleting the *
* item (use mod < 0) or changing the options (use mod > 0) * @trans: The transaction handle to use. Can be NULL if @mod is 0.
* @root: The root of the target tree.
* @path: Path to use for the search.
* @dir: The inode number (objectid) of the directory.
* @name: The name associated to the directory entry we are looking for.
* @name_len: The length of the name.
* @mod: Used to indicate if the tree search is meant for a read only
* lookup, for a modification lookup or for a deletion lookup, so
* its value should be 0, 1 or -1, respectively.
*
* Returns: NULL if the dir item does not exists, an error pointer if an error
* happened, or a pointer to a dir item if a dir item exists for the given name.
*/ */
struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
...@@ -273,27 +284,42 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, ...@@ -273,27 +284,42 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
} }
/* /*
* lookup a directory item based on index. 'dir' is the objectid * Lookup for a directory index item by name and index number.
* we're searching in, and 'mod' tells us if you plan on deleting the
* item (use mod < 0) or changing the options (use mod > 0)
* *
* The name is used to make sure the index really points to the name you were * @trans: The transaction handle to use. Can be NULL if @mod is 0.
* looking for. * @root: The root of the target tree.
* @path: Path to use for the search.
* @dir: The inode number (objectid) of the directory.
* @index: The index number.
* @name: The name associated to the directory entry we are looking for.
* @name_len: The length of the name.
* @mod: Used to indicate if the tree search is meant for a read only
* lookup, for a modification lookup or for a deletion lookup, so
* its value should be 0, 1 or -1, respectively.
*
* Returns: NULL if the dir index item does not exists, an error pointer if an
* error happened, or a pointer to a dir item if the dir index item exists and
* matches the criteria (name and index number).
*/ */
struct btrfs_dir_item * struct btrfs_dir_item *
btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_path *path, u64 dir, struct btrfs_path *path, u64 dir,
u64 objectid, const char *name, int name_len, u64 index, const char *name, int name_len,
int mod) int mod)
{ {
struct btrfs_dir_item *di;
struct btrfs_key key; struct btrfs_key key;
key.objectid = dir; key.objectid = dir;
key.type = BTRFS_DIR_INDEX_KEY; key.type = BTRFS_DIR_INDEX_KEY;
key.offset = objectid; key.offset = index;
return btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
if (di == ERR_PTR(-ENOENT))
return NULL;
return di;
} }
struct btrfs_dir_item * struct btrfs_dir_item *
......
...@@ -957,8 +957,7 @@ static noinline int inode_in_dir(struct btrfs_root *root, ...@@ -957,8 +957,7 @@ static noinline int inode_in_dir(struct btrfs_root *root,
di = btrfs_lookup_dir_index_item(NULL, root, path, dirid, di = btrfs_lookup_dir_index_item(NULL, root, path, dirid,
index, name, name_len, 0); index, name, name_len, 0);
if (IS_ERR(di)) { if (IS_ERR(di)) {
if (PTR_ERR(di) != -ENOENT) ret = PTR_ERR(di);
ret = PTR_ERR(di);
goto out; goto out;
} else if (di) { } else if (di) {
btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
...@@ -1191,8 +1190,7 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -1191,8 +1190,7 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir),
ref_index, name, namelen, 0); ref_index, name, namelen, 0);
if (IS_ERR(di)) { if (IS_ERR(di)) {
if (PTR_ERR(di) != -ENOENT) return PTR_ERR(di);
return PTR_ERR(di);
} else if (di) { } else if (di) {
ret = drop_one_dir_item(trans, root, path, dir, di); ret = drop_one_dir_item(trans, root, path, dir, di);
if (ret) if (ret)
...@@ -1994,9 +1992,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, ...@@ -1994,9 +1992,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
goto out; goto out;
} }
if (dst_di == ERR_PTR(-ENOENT))
dst_di = NULL;
if (IS_ERR(dst_di)) { if (IS_ERR(dst_di)) {
ret = PTR_ERR(dst_di); ret = PTR_ERR(dst_di);
goto out; goto out;
...@@ -2304,7 +2299,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans, ...@@ -2304,7 +2299,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
dir_key->offset, dir_key->offset,
name, name_len, 0); name, name_len, 0);
} }
if (!log_di || log_di == ERR_PTR(-ENOENT)) { 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);
...@@ -3563,8 +3558,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, ...@@ -3563,8 +3558,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
if (err == -ENOSPC) { if (err == -ENOSPC) {
btrfs_set_log_full_commit(trans); btrfs_set_log_full_commit(trans);
err = 0; err = 0;
} else if (err < 0 && err != -ENOENT) { } else if (err < 0) {
/* ENOENT can be returned if the entry hasn't been fsynced yet */
btrfs_abort_transaction(trans, err); btrfs_abort_transaction(trans, err);
} }
......
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