All of lore.kernel.org
 help / color / mirror / Atom feed
From: Su Yue <suy.fnst@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Cc: <suy.fnst@cn.fujitsu.com>
Subject: [PATCH 02/15] btrfs-progs: lowmem check: find and guess inode filetype
Date: Fri, 26 Jan 2018 16:35:06 +0800	[thread overview]
Message-ID: <20180126083519.28373-3-suy.fnst@cn.fujitsu.com> (raw)
In-Reply-To: <20180126083519.28373-1-suy.fnst@cn.fujitsu.com>

Introduce find_file_type_lowmem() and guess_file_type_lowmem().

find_file_type_lowmem() gets filetypes from inode_item, dir_item and
dir_index. If two of three's filetype are same and valid, it thinks
the value is correct.

guess_file_type_lowmem() searches file_extent and dir_item/index then
returns with filetype.

Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
---
 cmds-check.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)

diff --git a/cmds-check.c b/cmds-check.c
index e3505a7f9d6b..b200fdccf0e5 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -3306,6 +3306,199 @@ static int find_file_type(struct inode_record *rec, u8 *type)
 	return -ENOENT;
 }
 
+/*
+ * Fetch filetype from exited completed dir_item, dir_index and inode_item.
+ * If two of tree items'filetype are same, we think the type is trusted.
+ *
+ * Return 0 if file type is found and BTRFS_FT_* is stored into type.
+ * Return <0 if file type is not found.
+ */
+static int find_file_type_lowmem(struct btrfs_root *root, u64 ino, u8 *type)
+{
+	struct btrfs_key key;
+	struct btrfs_path path;
+	struct btrfs_path path2;
+	struct btrfs_inode_ref *iref;
+	struct btrfs_dir_item *dir_item;
+	struct btrfs_dir_item *dir_index;
+	struct extent_buffer *eb;
+	u64 dir;
+	u64 index;
+	char namebuf[BTRFS_NAME_LEN] = {0};
+	u32 namelen;
+	u8 inode_filetype = BTRFS_FT_UNKNOWN;
+	u8 dir_item_filetype;
+	u8 dir_index_filetype;
+	u8 true_file_type;
+	int slot;
+	int ret;
+
+	key.objectid = ino;
+	key.type = BTRFS_INODE_ITEM_KEY;
+	key.offset = 0;
+
+	btrfs_init_path(&path);
+	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		struct btrfs_inode_item *ii;
+
+		ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
+				    struct btrfs_inode_item);
+		inode_filetype = imode_to_type(btrfs_inode_mode(path.nodes[0],
+								ii));
+	}
+
+	key.objectid = ino;
+	key.type = BTRFS_INODE_REF_KEY;
+	key.offset = (u64)-1;
+
+	btrfs_release_path(&path);
+	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -EIO;
+		goto out;
+	}
+
+	btrfs_init_path(&path2);
+next:
+	btrfs_release_path(&path2);
+	ret = btrfs_previous_item(root, &path, ino, BTRFS_INODE_REF_KEY);
+	if (ret) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	eb = path.nodes[0];
+	slot = path.slots[0];
+	btrfs_item_key_to_cpu(eb, &key, slot);
+	dir = key.offset;
+	iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
+	index = btrfs_inode_ref_index(eb, iref);
+	namelen = btrfs_inode_ref_name_len(eb, iref);
+	read_extent_buffer(eb, namebuf, (unsigned long)(iref + 1), namelen);
+
+	dir_index = btrfs_lookup_dir_index(NULL, root, &path2, dir, namebuf,
+					   namelen, index, 0);
+	if (!dir_index)
+		goto next;
+	dir_index_filetype = btrfs_dir_type(path2.nodes[0], dir_index);
+	btrfs_release_path(&path2);
+	if (dir_index_filetype == inode_filetype) {
+		true_file_type = inode_filetype;
+		goto found;
+	}
+
+	dir_item = btrfs_lookup_dir_item(NULL, root, &path2, dir, namebuf,
+					 namelen, 0);
+	if (!dir_item)
+		goto next;
+	dir_item_filetype = btrfs_dir_type(path2.nodes[0], dir_item);
+	btrfs_release_path(&path2);
+	if (dir_item_filetype == inode_filetype) {
+		true_file_type = inode_filetype;
+		goto found;
+	}
+
+	if (dir_index_filetype == dir_item_filetype) {
+		true_file_type = dir_index_filetype;
+		goto found;
+	}
+	goto next;
+found:
+	/* rare case, two of three items are both corrupted */
+	if (true_file_type == BTRFS_FT_UNKNOWN ||
+	    true_file_type >= BTRFS_FT_MAX)
+		goto next;
+	*type = true_file_type;
+	ret = 0;
+out:
+	btrfs_release_path(&path);
+	return ret;
+}
+
+static int find_normal_file_extent(struct btrfs_root *root, u64 ino);
+/*
+ * Try to determine inode type if type not found.
+ *
+ * For found regular file extent, it must be FILE.
+ * For found dir_item/index, it must be DIR.
+ *
+ * Return 0 if file type is confirmed and BTRFS_FT_* is stored into type.
+ * Return <0 if file type is unknown.
+ */
+static int guess_file_type_lowmem(struct btrfs_root *root, u64 ino, u8 *type)
+{
+	struct btrfs_key key;
+	struct btrfs_path *path = NULL;
+	bool is_dir = false;
+	bool is_file = false;
+	int ret;
+
+	if (find_normal_file_extent(root, ino)) {
+		is_file = true;
+		goto out;
+	}
+
+	key.objectid = ino;
+	key.type = BTRFS_DIR_ITEM_KEY;
+	key.offset = (u64)-1;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		goto out;
+	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+	if (ret < 0)
+		goto out;
+	/*
+	 * (u64)-1 may hit the hashed value in offset.
+	 */
+	if (!ret) {
+		is_dir = true;
+		goto out;
+	}
+
+	ret = btrfs_previous_item(root, path, ino, BTRFS_DIR_ITEM_KEY);
+	if (!ret) {
+		is_dir = true;
+		goto out;
+	}
+
+	key.type = BTRFS_DIR_INDEX_KEY;
+	key.offset = (u64)-1;
+
+	btrfs_release_path(path);
+	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		is_dir = true;
+		goto out;
+	}
+	ret = btrfs_previous_item(root, path, ino, BTRFS_DIR_INDEX_KEY);
+	if (!ret) {
+		is_dir = true;
+		goto out;
+	}
+out:
+	if (path)
+		btrfs_release_path(path);
+
+	if (is_dir) {
+		*type = BTRFS_FT_DIR;
+		ret = 0;
+	} else if (is_file) {
+		*type = BTRFS_FT_REG_FILE;
+		ret = 0;
+	} else {
+		ret = -ENOENT;
+	}
+	return ret;
+}
+
 /*
  * To determine the file name for nlink repair
  *
-- 
2.16.1




  parent reply	other threads:[~2018-01-26  8:30 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-26  8:35 [PATCH 00/15] btrfs-progs: fix filetype mismatch in check Su Yue
2018-01-26  8:35 ` [PATCH 01/15] btrfs-progs: lowmem check: introduce repair_inode_item_mismatch() Su Yue
2018-01-26  8:35 ` Su Yue [this message]
2018-01-26  8:49   ` [PATCH 02/15] btrfs-progs: lowmem check: find and guess inode filetype Qu Wenruo
2018-01-26  9:14   ` Qu Wenruo
2018-01-26  9:21     ` Qu Wenruo
2018-01-26  9:31     ` Su Yue
2018-01-26  9:35       ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 03/15] btrfs-progs: lowmem check: find filetype in repair_inode_missing() Su Yue
2018-01-26  9:22   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 04/15] btrfs-progs: lowmem check: repair complex cases in repair_dir_item() Su Yue
2018-01-26  9:33   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 05/15] btrfs-progs: lowmem check: let check_dir_item() continue if find wrong inode_item Su Yue
2018-01-26  9:36   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 06/15] btrfs-progs: lowmem check: let check_dir_item() return if repaired Su Yue
2018-01-26  9:43   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 07/15] btrfs-progs: lowmem check: find_dir_item by di_key in check_dir_item() Su Yue
2018-01-26  9:37   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 08/15] btrfs-progs: lowmem check: call get_dir_isize() after repair Su Yue
2018-01-26  8:35 ` [PATCH 09/15] btrfs-progs: lowmem check: change logic of leaf process if repair Su Yue
2018-01-26 10:01   ` Qu Wenruo
2018-01-26 10:15     ` Su Yue
2018-01-26  8:35 ` [PATCH 10/15] btrfs-progs: check: clear I_ERR_FILE_EXTENT_DISCOUNT after repair Su Yue
2018-01-26 10:02   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 11/15] btrfs-progs: check: modify indoe_rec and backref " Su Yue
2018-01-26  8:35 ` [PATCH 12/15] btrfs-progs: check: increase counter error in check_inode_recs() Su Yue
2018-01-26 10:05   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 13/15] btrfs-progs: check: find inode filetype in create_inode_item() Su Yue
2018-01-26 10:11   ` Qu Wenruo
2018-01-26  8:35 ` [PATCH 14/15] btrfs-progs: check: handle mismatched filetype in repair_inode_backref Su Yue
2018-01-26  8:35 ` [PATCH 15/15] btrfs-progs: fsck-tests: add image for original and lowmem check Su Yue
2018-01-26 10:17   ` Qu Wenruo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180126083519.28373-3-suy.fnst@cn.fujitsu.com \
    --to=suy.fnst@cn.fujitsu.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.