From: Chandan Babu R <chandan.babu@oracle.com>
To: linux-xfs@vger.kernel.org
Cc: Chandan Babu R <chandan.babu@oracle.com>, djwong@kernel.org
Subject: [PATCH V3 06/12] xfs: xfs_dfork_nextents: Return extent count via an out argument
Date: Thu, 16 Sep 2021 15:36:41 +0530 [thread overview]
Message-ID: <20210916100647.176018-7-chandan.babu@oracle.com> (raw)
In-Reply-To: <20210916100647.176018-1-chandan.babu@oracle.com>
This commit changes xfs_dfork_nextents() to return an error code. The extent
count itself is now returned through an out argument. This facility will be
used by a future commit to indicate an inconsistent ondisk extent count.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
fs/xfs/libxfs/xfs_format.h | 14 ++---
fs/xfs/libxfs/xfs_inode_buf.c | 16 ++++--
fs/xfs/libxfs/xfs_inode_fork.c | 21 ++++++--
fs/xfs/scrub/inode.c | 94 +++++++++++++++++++++-------------
fs/xfs/scrub/inode_repair.c | 34 ++++++++----
5 files changed, 118 insertions(+), 61 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index b4638052801f..dba868f2c3e3 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -931,28 +931,30 @@ enum xfs_dinode_fmt {
(dip)->di_format : \
(dip)->di_aformat)
-static inline xfs_extnum_t
+static inline int
xfs_dfork_nextents(
struct xfs_dinode *dip,
- int whichfork)
+ int whichfork,
+ xfs_extnum_t *nextents)
{
- xfs_extnum_t nextents = 0;
+ int error = 0;
switch (whichfork) {
case XFS_DATA_FORK:
- nextents = be32_to_cpu(dip->di_nextents);
+ *nextents = be32_to_cpu(dip->di_nextents);
break;
case XFS_ATTR_FORK:
- nextents = be16_to_cpu(dip->di_anextents);
+ *nextents = be16_to_cpu(dip->di_anextents);
break;
default:
ASSERT(0);
+ error = -EFSCORRUPTED;
break;
}
- return nextents;
+ return error;
}
/*
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 176c98798aa4..dc511630cc7a 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -345,7 +345,8 @@ xfs_dinode_verify_fork(
xfs_extnum_t di_nextents;
xfs_extnum_t max_extents;
- di_nextents = xfs_dfork_nextents(dip, whichfork);
+ if (xfs_dfork_nextents(dip, whichfork, &di_nextents))
+ return __this_address;
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
@@ -477,6 +478,7 @@ xfs_dinode_verify(
uint64_t flags2;
uint64_t di_size;
xfs_extnum_t nextents;
+ xfs_extnum_t naextents;
xfs_rfsblock_t nblocks;
if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
@@ -508,8 +510,13 @@ xfs_dinode_verify(
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
return __this_address;
- nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- nextents += xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents))
+ return __this_address;
+
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents))
+ return __this_address;
+
+ nextents += naextents;
nblocks = be64_to_cpu(dip->di_nblocks);
/* Fork checks carried over from xfs_iformat_fork */
@@ -570,7 +577,8 @@ xfs_dinode_verify(
default:
return __this_address;
}
- if (xfs_dfork_nextents(dip, XFS_ATTR_FORK))
+
+ if (naextents)
return __this_address;
}
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 7d1efccfea59..435c343612e2 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -107,13 +107,20 @@ xfs_iformat_extents(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
int state = xfs_bmap_fork_to_state(whichfork);
- xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork);
- int size = nex * sizeof(xfs_bmbt_rec_t);
+ xfs_extnum_t nex;
+ int size;
struct xfs_iext_cursor icur;
struct xfs_bmbt_rec *dp;
struct xfs_bmbt_irec new;
+ int error;
int i;
+ error = xfs_dfork_nextents(dip, whichfork, &nex);
+ if (error)
+ return error;
+
+ size = nex * sizeof(struct xfs_bmbt_rec);
+
/*
* If the number of extents is unreasonable, then something is wrong and
* we just bail out rather than crash in kmem_alloc() or memcpy() below.
@@ -234,7 +241,9 @@ xfs_iformat_data_fork(
* depend on it.
*/
ip->i_df.if_format = dip->di_format;
- ip->i_df.if_nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK, &ip->i_df.if_nextents);
+ if (error)
+ return error;
switch (inode->i_mode & S_IFMT) {
case S_IFIFO:
@@ -302,9 +311,11 @@ xfs_iformat_attr_fork(
struct xfs_dinode *dip)
{
xfs_extnum_t naextents;
- int error = 0;
+ int error;
- naextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents);
+ if (error)
+ return error;
/*
* Initialize the extent count early, as the per-format routines may
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index 4177b85c941d..be43bd6be1ed 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -221,6 +221,38 @@ xchk_dinode_nsec(
xchk_ino_set_corrupt(sc, ino);
}
+STATIC void
+xchk_dinode_fork_recs(
+ struct xfs_scrub *sc,
+ struct xfs_dinode *dip,
+ xfs_ino_t ino,
+ xfs_extnum_t nextents,
+ int whichfork)
+{
+ struct xfs_mount *mp = sc->mp;
+ size_t fork_recs;
+ unsigned char format;
+
+ fork_recs = XFS_DFORK_SIZE(dip, mp, whichfork) /
+ sizeof(struct xfs_bmbt_rec);
+ format = XFS_DFORK_FORMAT(dip, whichfork);
+
+ switch (format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (nextents > fork_recs)
+ xchk_ino_set_corrupt(sc, ino);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (nextents <= fork_recs)
+ xchk_ino_set_corrupt(sc, ino);
+ break;
+ default:
+ if (nextents != 0)
+ xchk_ino_set_corrupt(sc, ino);
+ break;
+ }
+}
+
/* Scrub all the ondisk inode fields. */
STATIC void
xchk_dinode(
@@ -229,7 +261,6 @@ xchk_dinode(
xfs_ino_t ino)
{
struct xfs_mount *mp = sc->mp;
- size_t fork_recs;
unsigned long long isize;
uint64_t flags2;
xfs_extnum_t nextents;
@@ -237,6 +268,7 @@ xchk_dinode(
prid_t prid;
uint16_t flags;
uint16_t mode;
+ int error;
flags = be16_to_cpu(dip->di_flags);
if (dip->di_version >= 3)
@@ -392,33 +424,30 @@ xchk_dinode(
xchk_inode_extsize(sc, dip, ino, mode, flags);
/* di_nextents */
- nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- fork_recs = XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
- switch (dip->di_format) {
- case XFS_DINODE_FMT_EXTENTS:
- if (nextents > fork_recs)
- xchk_ino_set_corrupt(sc, ino);
- break;
- case XFS_DINODE_FMT_BTREE:
- if (nextents <= fork_recs)
- xchk_ino_set_corrupt(sc, ino);
- break;
- default:
- if (nextents != 0)
- xchk_ino_set_corrupt(sc, ino);
- break;
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents);
+ if (error) {
+ xchk_ino_set_corrupt(sc, ino);
+ return;
}
-
- naextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ xchk_dinode_fork_recs(sc, dip, ino, nextents, XFS_DATA_FORK);
/* di_forkoff */
if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
xchk_ino_set_corrupt(sc, ino);
- if (naextents != 0 && dip->di_forkoff == 0)
- xchk_ino_set_corrupt(sc, ino);
if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
xchk_ino_set_corrupt(sc, ino);
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents);
+ if (error) {
+ xchk_ino_set_corrupt(sc, ino);
+ return;
+ }
+
+ if (naextents != 0 && dip->di_forkoff == 0) {
+ xchk_ino_set_corrupt(sc, ino);
+ return;
+ }
+
/* di_aformat */
if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
@@ -426,20 +455,8 @@ xchk_dinode(
xchk_ino_set_corrupt(sc, ino);
/* di_anextents */
- fork_recs = XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
- switch (dip->di_aformat) {
- case XFS_DINODE_FMT_EXTENTS:
- if (naextents > fork_recs)
- xchk_ino_set_corrupt(sc, ino);
- break;
- case XFS_DINODE_FMT_BTREE:
- if (naextents <= fork_recs)
- xchk_ino_set_corrupt(sc, ino);
- break;
- default:
- if (naextents != 0)
- xchk_ino_set_corrupt(sc, ino);
- }
+ if (!error)
+ xchk_dinode_fork_recs(sc, dip, ino, naextents, XFS_ATTR_FORK);
if (dip->di_version >= 3) {
xchk_dinode_nsec(sc, ino, dip, dip->di_crtime);
@@ -502,6 +519,7 @@ xchk_inode_xref_bmap(
struct xfs_scrub *sc,
struct xfs_dinode *dip)
{
+ xfs_extnum_t dip_nextents;
xfs_extnum_t nextents;
xfs_filblks_t count;
xfs_filblks_t acount;
@@ -515,14 +533,18 @@ xchk_inode_xref_bmap(
&nextents, &count);
if (!xchk_should_check_xref(sc, &error, NULL))
return;
- if (nextents < xfs_dfork_nextents(dip, XFS_DATA_FORK))
+
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK, &dip_nextents);
+ if (error || nextents < dip_nextents)
xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
&nextents, &acount);
if (!xchk_should_check_xref(sc, &error, NULL))
return;
- if (nextents != xfs_dfork_nextents(dip, XFS_ATTR_FORK))
+
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &dip_nextents);
+ if (error || nextents < dip_nextents)
xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
/* Check nblocks against the inode. */
diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c
index ec8360b3b13b..4133a91c9a57 100644
--- a/fs/xfs/scrub/inode_repair.c
+++ b/fs/xfs/scrub/inode_repair.c
@@ -606,7 +606,9 @@ xrep_dinode_bad_extents_fork(
xfs_extnum_t nex;
int fork_size;
- nex = xfs_dfork_nextents(dip, whichfork);
+ if (xfs_dfork_nextents(dip, whichfork, &nex))
+ return true;
+
fork_size = nex * sizeof(struct xfs_bmbt_rec);
if (fork_size < 0 || fork_size > dfork_size)
return true;
@@ -637,11 +639,14 @@ xrep_dinode_bad_btree_fork(
int whichfork)
{
struct xfs_bmdr_block *dfp;
+ xfs_extnum_t nextents;
int nrecs;
int level;
- if (xfs_dfork_nextents(dip, whichfork) <=
- dfork_size / sizeof(struct xfs_bmbt_rec))
+ if (xfs_dfork_nextents(dip, whichfork, &nextents))
+ return true;
+
+ if (nextents <= dfork_size / sizeof(struct xfs_bmbt_rec))
return true;
if (dfork_size < sizeof(struct xfs_bmdr_block))
@@ -778,11 +783,15 @@ xrep_dinode_check_afork(
struct xfs_dinode *dip)
{
struct xfs_attr_shortform *sfp;
+ xfs_extnum_t nextents;
int size;
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &nextents))
+ return true;
+
if (XFS_DFORK_BOFF(dip) == 0)
return dip->di_aformat != XFS_DINODE_FMT_EXTENTS ||
- dip->di_anextents != 0;
+ nextents != 0;
size = XFS_DFORK_SIZE(dip, sc->mp, XFS_ATTR_FORK);
switch (XFS_DFORK_FORMAT(dip, XFS_ATTR_FORK)) {
@@ -839,11 +848,15 @@ xrep_dinode_ensure_forkoff(
size_t bmdr_minsz = xfs_bmdr_space_calc(1);
unsigned int lit_sz = XFS_LITINO(sc->mp);
unsigned int afork_min, dfork_min;
+ int error;
trace_xrep_dinode_ensure_forkoff(sc, dip);
- dnextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- anextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK, &dnextents);
+ ASSERT(error == 0);
+
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &anextents);
+ ASSERT(error == 0);
/*
* Before calling this function, xrep_dinode_core ensured that both
@@ -1031,6 +1044,7 @@ xrep_dinode_zap_forks(
uint16_t mode;
bool zap_datafork = false;
bool zap_attrfork = false;
+ int error;
trace_xrep_dinode_zap_forks(sc, dip);
@@ -1039,12 +1053,12 @@ xrep_dinode_zap_forks(
/* Inode counters don't make sense? */
nblocks = be64_to_cpu(dip->di_nblocks);
- nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- if (nextents > nblocks)
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents);
+ if (error || nextents > nblocks)
zap_datafork = true;
- naextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
- if (naextents > nblocks)
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents);
+ if (error || naextents > nblocks)
zap_attrfork = true;
if (nextents + naextents > nblocks)
--
2.30.2
next prev parent reply other threads:[~2021-09-16 10:07 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-16 10:06 [PATCH V3 00/12] xfs: Extend per-inode extent counters Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 01/12] xfs: Move extent count limits to xfs_format.h Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 02/12] xfs: Introduce xfs_iext_max_nextents() helper Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 03/12] xfs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32, XFS_IFORK_EXTCNT_MAXS16 Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 04/12] xfs: Use xfs_extnum_t instead of basic data types Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 05/12] xfs: Introduce xfs_dfork_nextents() helper Chandan Babu R
2021-09-27 22:46 ` Dave Chinner
2021-09-28 9:46 ` Chandan Babu R
2021-09-16 10:06 ` Chandan Babu R [this message]
2021-09-30 1:19 ` [PATCH V3 06/12] xfs: xfs_dfork_nextents: Return extent count via an out argument Dave Chinner
2021-09-16 10:06 ` [PATCH V3 07/12] xfs: Rename inode's extent counter fields based on their width Chandan Babu R
2021-09-27 23:46 ` Dave Chinner
2021-09-28 4:04 ` Dave Chinner
2021-09-29 17:03 ` Chandan Babu R
2021-09-30 0:40 ` Dave Chinner
2021-09-30 4:31 ` Dave Chinner
2021-09-30 7:30 ` Chandan Babu R
2021-09-30 22:55 ` Dave Chinner
2021-10-07 10:52 ` Chandan Babu R
2021-10-10 21:49 ` Dave Chinner
2021-10-13 14:44 ` Chandan Babu R
2021-10-14 2:00 ` Dave Chinner
2021-10-14 10:07 ` Chandan Babu R
2021-10-21 10:27 ` Chandan Babu R
2021-09-28 9:47 ` Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 08/12] xfs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits respectively Chandan Babu R
2021-09-28 0:47 ` Dave Chinner
2021-09-28 9:47 ` Chandan Babu R
2021-09-28 23:08 ` Dave Chinner
2021-09-29 17:04 ` Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 09/12] xfs: Enable bulkstat ioctl to support 64-bit per-inode extent counters Chandan Babu R
2021-09-27 23:06 ` Dave Chinner
2021-09-28 9:49 ` Chandan Babu R
2021-09-28 23:39 ` Dave Chinner
2021-09-29 17:04 ` Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 10/12] xfs: Extend per-inode extent counter widths Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 11/12] xfs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL Chandan Babu R
2021-09-16 10:06 ` [PATCH V3 12/12] xfs: Define max extent length based on on-disk format definition Chandan Babu R
2021-09-28 0:33 ` Dave Chinner
2021-09-28 10:07 ` Chandan Babu R
2021-09-18 0:03 ` [PATCH V3 00/12] xfs: Extend per-inode extent counters Darrick J. Wong
2021-09-18 3:36 ` [External] : " 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=20210916100647.176018-7-chandan.babu@oracle.com \
--to=chandan.babu@oracle.com \
--cc=djwong@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).