|
@@ -171,10 +171,40 @@ out_free:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static struct btrfs_dir_item *btrfs_lookup_match_dir(
|
|
|
+ struct btrfs_trans_handle *trans,
|
|
|
+ struct btrfs_root *root, struct btrfs_path *path,
|
|
|
+ struct btrfs_key *key, const char *name,
|
|
|
+ int name_len, int mod)
|
|
|
+{
|
|
|
+ const int ins_len = (mod < 0 ? -1 : 0);
|
|
|
+ const int cow = (mod != 0);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = btrfs_search_slot(trans, root, key, path, ins_len, cow);
|
|
|
+ if (ret < 0)
|
|
|
+ return ERR_PTR(ret);
|
|
|
+ if (ret > 0)
|
|
|
+ return ERR_PTR(-ENOENT);
|
|
|
+
|
|
|
+ return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
- * lookup a directory item based on name. 'dir' is the objectid
|
|
|
- * 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)
|
|
|
+ * Lookup for a directory item by name.
|
|
|
+ *
|
|
|
+ * @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_root *root,
|
|
@@ -182,23 +212,18 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
|
|
|
const char *name, int name_len,
|
|
|
int mod)
|
|
|
{
|
|
|
- int ret;
|
|
|
struct btrfs_key key;
|
|
|
- int ins_len = mod < 0 ? -1 : 0;
|
|
|
- int cow = mod != 0;
|
|
|
+ struct btrfs_dir_item *di;
|
|
|
|
|
|
key.objectid = dir;
|
|
|
key.type = BTRFS_DIR_ITEM_KEY;
|
|
|
-
|
|
|
key.offset = btrfs_name_hash(name, name_len);
|
|
|
|
|
|
- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
|
|
- if (ret < 0)
|
|
|
- return ERR_PTR(ret);
|
|
|
- if (ret > 0)
|
|
|
+ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
|
|
|
+ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
|
|
|
return NULL;
|
|
|
|
|
|
- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
|
|
|
+ return di;
|
|
|
}
|
|
|
|
|
|
int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
|
|
@@ -212,7 +237,6 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
|
|
|
int slot;
|
|
|
struct btrfs_path *path;
|
|
|
|
|
|
-
|
|
|
path = btrfs_alloc_path();
|
|
|
if (!path)
|
|
|
return -ENOMEM;
|
|
@@ -221,20 +245,20 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
|
|
|
key.type = BTRFS_DIR_ITEM_KEY;
|
|
|
key.offset = btrfs_name_hash(name, name_len);
|
|
|
|
|
|
- ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
|
|
-
|
|
|
- /* return back any errors */
|
|
|
- if (ret < 0)
|
|
|
- goto out;
|
|
|
+ di = btrfs_lookup_match_dir(NULL, root, path, &key, name, name_len, 0);
|
|
|
+ if (IS_ERR(di)) {
|
|
|
+ ret = PTR_ERR(di);
|
|
|
+ /* Nothing found, we're safe */
|
|
|
+ if (ret == -ENOENT) {
|
|
|
+ ret = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
- /* nothing found, we're safe */
|
|
|
- if (ret > 0) {
|
|
|
- ret = 0;
|
|
|
- goto out;
|
|
|
+ if (ret < 0)
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
/* we found an item, look for our name in the item */
|
|
|
- di = btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
|
|
|
if (di) {
|
|
|
/* our exact name was found */
|
|
|
ret = -EEXIST;
|
|
@@ -261,35 +285,42 @@ out:
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * lookup a directory item based on index. 'dir' is the objectid
|
|
|
- * 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)
|
|
|
+ * Lookup for a directory index item by name and index number.
|
|
|
+ *
|
|
|
+ * @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.
|
|
|
+ * @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.
|
|
|
*
|
|
|
- * The name is used to make sure the index really points to the name you were
|
|
|
- * looking for.
|
|
|
+ * 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 *
|
|
|
btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
|
|
|
struct btrfs_root *root,
|
|
|
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 ret;
|
|
|
+ struct btrfs_dir_item *di;
|
|
|
struct btrfs_key key;
|
|
|
- int ins_len = mod < 0 ? -1 : 0;
|
|
|
- int cow = mod != 0;
|
|
|
|
|
|
key.objectid = dir;
|
|
|
key.type = BTRFS_DIR_INDEX_KEY;
|
|
|
- key.offset = objectid;
|
|
|
+ key.offset = index;
|
|
|
|
|
|
- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
|
|
- if (ret < 0)
|
|
|
- return ERR_PTR(ret);
|
|
|
- if (ret > 0)
|
|
|
- return ERR_PTR(-ENOENT);
|
|
|
- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
|
|
|
+ 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 *
|
|
@@ -346,21 +377,18 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
|
|
|
const char *name, u16 name_len,
|
|
|
int mod)
|
|
|
{
|
|
|
- int ret;
|
|
|
struct btrfs_key key;
|
|
|
- int ins_len = mod < 0 ? -1 : 0;
|
|
|
- int cow = mod != 0;
|
|
|
+ struct btrfs_dir_item *di;
|
|
|
|
|
|
key.objectid = dir;
|
|
|
key.type = BTRFS_XATTR_ITEM_KEY;
|
|
|
key.offset = btrfs_name_hash(name, name_len);
|
|
|
- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
|
|
- if (ret < 0)
|
|
|
- return ERR_PTR(ret);
|
|
|
- if (ret > 0)
|
|
|
+
|
|
|
+ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
|
|
|
+ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
|
|
|
return NULL;
|
|
|
|
|
|
- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
|
|
|
+ return di;
|
|
|
}
|
|
|
|
|
|
/*
|