All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 3/4] btrfs-progs: check/lowmem: detect and report mixed inline and regular extents properly
Date: Tue,  4 May 2021 14:25:24 +0800	[thread overview]
Message-ID: <20210504062525.152540-4-wqu@suse.com> (raw)
In-Reply-To: <20210504062525.152540-1-wqu@suse.com>

[BUG]
When lowmem mode check is executed on a filesystem with mixed inline and
regular extent, it reports the error as file extent gap:

  [4/7] checking fs roots
  ERROR: root 5 EXTENT_DATA[257 4096] gap exists, expected: EXTENT_DATA[257 707]
  ERROR: errors found in fs roots
  found 135168 bytes used, error(s) found

Not detecting the mixed extent types.

[CAUSE]
The offending fs has the following data extents:

        item 9 key (257 INODE_REF 256) itemoff 15703 itemsize 14
                index 2 namelen 4 name: file
        item 10 key (257 EXTENT_DATA 0) itemoff 14975 itemsize 728
                generation 7 type 0 (inline)
                inline extent data size 707 ram_bytes 707 compression 0 (none)
        item 11 key (257 EXTENT_DATA 4096) itemoff 14922 itemsize 53
                generation 7 type 2 (prealloc)
                prealloc data disk byte 102457344 nr 4096
                prealloc data offset 0 nr 4096

The mixed extent type error is obvious, but for inline extent,
check_file_extent_inline() will increase the extent_end by inline size.

However for such mixed case, the regular extent will only start
sectorsize, leaving lowmem check only to report a hole gap.

[FIX]
This patch will fix it by:
- Introduce @found_inline parameter to detect mixed extent types
- Increase @end by sectorsize for check_file_extent_inline()

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 check/mode-lowmem.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 2531fde858b2..ed71833eb21e 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -2003,7 +2003,12 @@ static int check_file_extent_inline(struct btrfs_root *root,
 			}
 		}
 	}
-	*end += extent_num_bytes;
+	/*
+	 * For inline extent, we expect no more extents. But if there are
+	 * regular extents after inlined extent, they should start at
+	 * sectorsize, not the inline size.
+	 */
+	*end += root->fs_info->sectorsize;
 	*size += extent_num_bytes;
 
 	return err;
@@ -2022,7 +2027,7 @@ static int check_file_extent_inline(struct btrfs_root *root,
  */
 static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path,
 			     unsigned int nodatasum, u64 isize, u64 *size,
-			     u64 *end)
+			     u64 *end, bool *found_inline)
 {
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_key fkey;
@@ -2058,9 +2063,25 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path,
 	}
 
 	/* Check inline extent */
-	if (extent_type == BTRFS_FILE_EXTENT_INLINE)
+	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+		*found_inline = true;
 		return check_file_extent_inline(root, path, size, end);
+	}
 
+	/*
+	 * Here we hit a regular/prealloc file extent, if this inode already
+	 * has an inline extent, we have mixed inline and regular extents.
+	 */
+	if (*found_inline) {
+		err |= FILE_EXTENT_ERROR;
+		error(
+		"root %llu inode %llu has mixed inline and regular extents",
+		      root->objectid, fkey.objectid);
+		/*
+		 * We still want to continue checking, as mixed inline and
+		 * regular is just a minor problem.
+		 */
+	}
 	/* Check REG_EXTENT/PREALLOC_EXTENT */
 	gen = btrfs_file_extent_generation(node, fi);
 	disk_bytenr = btrfs_file_extent_disk_bytenr(node, fi);
@@ -2606,6 +2627,7 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path)
 	int slot;
 	int ret;
 	int err = 0;
+	bool found_inline = false;
 	char namebuf[BTRFS_NAME_LEN] = {0};
 	u32 name_len = 0;
 
@@ -2726,7 +2748,8 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path)
 					key.offset);
 			}
 			ret = check_file_extent(root, path, nodatasum, isize,
-						&extent_size, &extent_end);
+						&extent_size, &extent_end,
+						&found_inline);
 			err |= ret;
 			break;
 		case BTRFS_XATTR_ITEM_KEY:
-- 
2.31.1


  parent reply	other threads:[~2021-05-04  6:25 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-04  6:25 [PATCH 0/4] btrfs-progs: check: add the ability to detect and report mixed inline and regular data extents Qu Wenruo
2021-05-04  6:25 ` [PATCH 1/4] btrfs-progs: check/original: add the "0x" prefix for hex error number Qu Wenruo
2021-05-04  6:25 ` [PATCH 2/4] btrfs-progs: check/original: detect and report mixed inline and regular data extents Qu Wenruo
2021-05-04  6:25 ` Qu Wenruo [this message]
2021-05-04  6:25 ` [PATCH 4/4] btrfs-progs: fsck-tests: add test image for " Qu Wenruo
2021-05-04 13:30 ` [PATCH 0/4] btrfs-progs: check: add the ability to detect and report " Su Yue
2021-05-06 13:02 ` 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=20210504062525.152540-4-wqu@suse.com \
    --to=wqu@suse.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.