All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chandan Babu R <chandanrlinux@gmail.com>
To: linux-xfs@vger.kernel.org
Cc: Chandan Babu R <chandanrlinux@gmail.com>
Subject: [PATCH] xfs: Allow scrub to detect inodes with non-maximal sized extents
Date: Tue, 23 Feb 2021 13:56:29 +0530	[thread overview]
Message-ID: <20210223082629.16719-1-chandanrlinux@gmail.com> (raw)

This commit now makes it possible for scrub to check if an inode's extents are
maximally sized i.e. it checks if an inode's extent is contiguous (in terms of
both file offset and disk offset) with neighbouring extents and the total
length of both the extents is less than the maximum allowed extent
length (i.e. MAXEXTLEN).

Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com>
---
 fs/xfs/scrub/inode.c   | 11 +++++++----
 fs/xfs/xfs_bmap_util.c | 36 +++++++++++++++++++++++++++++++-----
 fs/xfs/xfs_bmap_util.h |  5 +++--
 fs/xfs/xfs_qm.c        |  2 +-
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index faf65eb5bd31..33b530785e36 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -478,23 +478,26 @@ xchk_inode_xref_bmap(
 	xfs_filblks_t		count;
 	xfs_filblks_t		acount;
 	int			error;
+	bool			maximal_sized_exts;
 
 	if (xchk_skip_xref(sc->sm))
 		return;
 
 	/* Walk all the extents to check nextents/naextents/nblocks. */
+	maximal_sized_exts = true;
 	error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_DATA_FORK,
-			&nextents, &count);
+			&nextents, &count, &maximal_sized_exts);
 	if (!xchk_should_check_xref(sc, &error, NULL))
 		return;
-	if (nextents < be32_to_cpu(dip->di_nextents))
+	if (nextents < be32_to_cpu(dip->di_nextents) || !maximal_sized_exts)
 		xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
 
+	maximal_sized_exts = true;
 	error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
-			&nextents, &acount);
+			&nextents, &acount, &maximal_sized_exts);
 	if (!xchk_should_check_xref(sc, &error, NULL))
 		return;
-	if (nextents != be16_to_cpu(dip->di_anextents))
+	if (nextents != be16_to_cpu(dip->di_anextents) || !maximal_sized_exts)
 		xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
 
 	/* Check nblocks against the inode. */
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index e7d68318e6a5..eca39677a46f 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -176,6 +176,25 @@ xfs_bmap_rtalloc(
  * Extent tree block counting routines.
  */
 
+STATIC bool
+is_maximal_extent(
+	struct xfs_ifork	*ifp,
+	struct xfs_iext_cursor	*icur,
+	struct xfs_bmbt_irec	*got)
+{
+	struct xfs_bmbt_irec	left;
+
+	if (xfs_iext_peek_prev_extent(ifp, icur, &left) &&
+		!isnullstartblock(left.br_startblock) &&
+		left.br_startoff + left.br_blockcount == got->br_startoff &&
+		left.br_startblock + left.br_blockcount == got->br_startblock &&
+		left.br_state == got->br_state &&
+		left.br_blockcount + got->br_blockcount <= MAXEXTLEN)
+		return false;
+	else
+		return true;
+}
+
 /*
  * Count leaf blocks given a range of extent records.  Delayed allocation
  * extents are not counted towards the totals.
@@ -183,7 +202,8 @@ xfs_bmap_rtalloc(
 xfs_extnum_t
 xfs_bmap_count_leaves(
 	struct xfs_ifork	*ifp,
-	xfs_filblks_t		*count)
+	xfs_filblks_t		*count,
+	bool			*maximal_sized_exts)
 {
 	struct xfs_iext_cursor	icur;
 	struct xfs_bmbt_irec	got;
@@ -191,6 +211,10 @@ xfs_bmap_count_leaves(
 
 	for_each_xfs_iext(ifp, &icur, &got) {
 		if (!isnullstartblock(got.br_startblock)) {
+			if (maximal_sized_exts)
+				*maximal_sized_exts =
+					is_maximal_extent(ifp, &icur, &got);
+
 			*count += got.br_blockcount;
 			numrecs++;
 		}
@@ -209,7 +233,8 @@ xfs_bmap_count_blocks(
 	struct xfs_inode	*ip,
 	int			whichfork,
 	xfs_extnum_t		*nextents,
-	xfs_filblks_t		*count)
+	xfs_filblks_t		*count,
+	bool			*maximal_sized_exts)
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -246,7 +271,8 @@ xfs_bmap_count_blocks(
 
 		/* fall through */
 	case XFS_DINODE_FMT_EXTENTS:
-		*nextents = xfs_bmap_count_leaves(ifp, count);
+		*nextents = xfs_bmap_count_leaves(ifp, count,
+				maximal_sized_exts);
 		break;
 	}
 
@@ -1442,14 +1468,14 @@ xfs_swap_extent_forks(
 	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
 	    ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
-				&aforkblks);
+				&aforkblks, NULL);
 		if (error)
 			return error;
 	}
 	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
 	    tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
-				&taforkblks);
+				&taforkblks, NULL);
 		if (error)
 			return error;
 	}
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 9f993168b55b..7b0ce227c7bd 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -71,10 +71,11 @@ int	xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
 
 xfs_daddr_t xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb);
 
-xfs_extnum_t xfs_bmap_count_leaves(struct xfs_ifork *ifp, xfs_filblks_t *count);
+xfs_extnum_t xfs_bmap_count_leaves(struct xfs_ifork *ifp, xfs_filblks_t *count,
+		bool *maximal_sized_exts);
 int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip,
 			  int whichfork, xfs_extnum_t *nextents,
-			  xfs_filblks_t *count);
+			  xfs_filblks_t *count, bool *maximal_sized_exts);
 
 int	xfs_flush_unmap_range(struct xfs_inode *ip, xfs_off_t offset,
 			      xfs_off_t len);
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 742d1413e2d0..04fcca5583b3 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1170,7 +1170,7 @@ xfs_qm_dqusage_adjust(
 				goto error0;
 		}
 
-		xfs_bmap_count_leaves(ifp, &rtblks);
+		xfs_bmap_count_leaves(ifp, &rtblks, NULL);
 	}
 
 	nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
-- 
2.29.2


             reply	other threads:[~2021-02-23  8:27 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-23  8:26 Chandan Babu R [this message]
2021-02-23 17:01 ` [PATCH] xfs: Allow scrub to detect inodes with non-maximal sized extents Darrick J. Wong
2021-02-23 20:30 ` Dave Chinner
2021-02-24  3:09   ` Chandan Babu R

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=20210223082629.16719-1-chandanrlinux@gmail.com \
    --to=chandanrlinux@gmail.com \
    --cc=linux-xfs@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.