@@ -2456,7 +2456,7 @@ static int reset_nlink(struct btrfs_trans_handle *trans,
list_for_each_entry(backref, &rec->backrefs, list) {
ret = btrfs_add_link(trans, root, rec->ino, backref->dir,
backref->name, backref->namelen,
- backref->filetype, &backref->index, 0);
+ &backref->index, 0);
if (ret < 0)
goto out;
}
@@ -464,7 +464,7 @@ int link_inode_to_lostfound(struct btrfs_trans_handle *trans,
goto out;
}
ret = btrfs_add_link(trans, root, ino, lost_found_ino,
- namebuf, name_len, filetype, NULL, 0);
+ namebuf, name_len, NULL, 0);
/*
* Add ".INO" suffix several times to handle case where
* "FILENAME.INO" is already taken by another file.
@@ -481,7 +481,7 @@ int link_inode_to_lostfound(struct btrfs_trans_handle *trans,
".%llu", ino);
name_len += count_digits(ino) + 1;
ret = btrfs_add_link(trans, root, ino, lost_found_ino, namebuf,
- name_len, filetype, NULL, 0);
+ name_len, NULL, 0);
}
if (ret < 0) {
errno = -ret;
@@ -1007,8 +1007,7 @@ out:
* returns not 0 means on error;
*/
static int repair_ternary_lowmem(struct btrfs_root *root, u64 dir_ino, u64 ino,
- u64 index, char *name, int name_len, u8 filetype,
- int err)
+ u64 index, char *name, int name_len, int err)
{
struct btrfs_trans_handle *trans;
int stage = 0;
@@ -1042,19 +1041,19 @@ static int repair_ternary_lowmem(struct btrfs_root *root, u64 dir_ino, u64 ino,
if (ret)
goto out;
ret = btrfs_add_link(trans, root, ino, dir_ino, name, name_len,
- filetype, &index, 1);
+ &index, 1);
goto out;
}
out:
btrfs_commit_transaction(trans, root);
if (ret)
- error("fail to repair inode %llu name %s filetype %u",
- ino, name, filetype);
+ error("fail to repair inode %llu name %s",
+ ino, name);
else
- printf("%s ref/dir_item of inode %llu name %s filetype %u\n",
+ printf("%s ref/dir_item of inode %llu name %s\n",
stage == 2 ? "Delete" : "Add",
- ino, name, filetype);
+ ino, name);
return ret;
}
@@ -1212,8 +1211,7 @@ end:
if (tmp_err && opt_check_repair) {
ret = repair_ternary_lowmem(root, ref_key->offset,
ref_key->objectid, index, namebuf,
- name_len, btrfs_inode_type(mode),
- tmp_err);
+ name_len, tmp_err);
if (!ret) {
need_research = 1;
goto begin;
@@ -1619,7 +1617,7 @@ static int repair_dir_item(struct btrfs_root *root, struct btrfs_key *di_key,
if (err & ~(INODE_ITEM_MISMATCH | INODE_ITEM_MISSING)) {
ret = repair_ternary_lowmem(root, dirid, ino, index, namebuf,
- name_len, filetype, err);
+ name_len, err);
if (!ret) {
err &= ~(DIR_INDEX_MISMATCH | DIR_INDEX_MISSING);
err &= ~(DIR_ITEM_MISMATCH | DIR_ITEM_MISSING);
@@ -841,7 +841,7 @@ static int create_image(struct btrfs_root *root,
goto out;
}
ret = btrfs_add_link(trans, root, ino, BTRFS_FIRST_FREE_OBJECTID, name,
- strlen(name), BTRFS_FT_REG_FILE, NULL, 0);
+ strlen(name), NULL, 0);
if (ret < 0) {
errno = -ret;
error("failed to link ino %llu to '/%s' in root %llu: %m",
@@ -1227,7 +1227,7 @@ int btrfs_change_inode_flags(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 ino, u64 flags);
int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
u64 ino, u64 parent_ino, char *name, int namelen,
- u8 type, u64 *index, int ignore_existed);
+ u64 *index, int ignore_existed);
int btrfs_unlink(struct btrfs_trans_handle *trans, struct btrfs_root *root,
u64 ino, u64 parent_ino, u64 index, const char *name,
int namelen, int add_orphan);
@@ -178,11 +178,12 @@ out:
*/
int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
u64 ino, u64 parent_ino, char *name, int namelen,
- u8 type, u64 *index, int ignore_existed)
+ u64 *index, int ignore_existed)
{
struct btrfs_path *path;
struct btrfs_key key;
struct btrfs_inode_item *inode_item;
+ u32 imode;
u32 nlink;
u64 inode_size;
u64 ret_index = 0;
@@ -192,6 +193,22 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (!path)
return -ENOMEM;
+ key.objectid = ino;
+ key.type = BTRFS_INODE_ITEM_KEY;
+ key.offset = 0;
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret > 0) {
+ ret = -ENOENT;
+ /* fallthrough */
+ }
+ if (ret < 0)
+ goto out;
+
+ inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+ struct btrfs_inode_item);
+ imode = btrfs_inode_mode(path->nodes[0], inode_item);
+ btrfs_release_path(path);
+
if (index && *index) {
ret_index = *index;
} else {
@@ -237,7 +254,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
ret = btrfs_insert_dir_item(trans, root, name, namelen, parent_ino,
- &key, type, ret_index);
+ &key, fs_umode_to_ftype(imode), ret_index);
if (ret < 0)
goto out;
@@ -580,7 +597,7 @@ int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (ret)
goto out;
ret = btrfs_add_link(trans, root, ret_ino, parent_ino, name, namelen,
- BTRFS_FT_DIR, NULL, 0);
+ NULL, 0);
if (ret)
goto out;
out:
The function btrfs_add_link() utilized @filetype parameter to insert the DIR_ITEM/DIR_INDEX. However for all call sites of btrfs_add_link() we already have the proper inode number of the child, and can grab the imode of that inode, then convert it to filetype. Thus no need to grab the @filetype parameter. This is still true for repair code, where if we hit a inode without its INODE_ITEM, the repair is always done by inserting a new INODE_ITEM first, then do btrfs_add_link(), thus we should still be able to grab the imode. Signed-off-by: Qu Wenruo <wqu@suse.com> --- check/main.c | 2 +- check/mode-common.c | 4 ++-- check/mode-lowmem.c | 18 ++++++++---------- convert/main.c | 2 +- kernel-shared/ctree.h | 2 +- kernel-shared/inode.c | 23 ++++++++++++++++++++--- 6 files changed, 33 insertions(+), 18 deletions(-)