All of lore.kernel.org
 help / color / mirror / Atom feed
* move the extent count and format into struct xfs_ifork
@ 2020-05-10  7:23 Christoph Hellwig
  2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
                   ` (5 more replies)
  0 siblings, 6 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:23 UTC (permalink / raw)
  To: linux-xfs

Hi all,

this series moves the extent count and format fields into the xfs_ifork
structure.  It is based on the "dinode reading cleanups v2" series.

Git tree:

    git://git.infradead.org/users/hch/xfs.git xfs-ifork-cleanup

Gitweb:

    http://git.infradead.org/users/hch/xfs.git/shortlog/refs/heads/xfs-ifork-cleanup

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
@ 2020-05-10  7:23 ` Christoph Hellwig
  2020-05-11 11:40   ` Chandan Babu R
  2020-05-16 18:42   ` [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q Darrick J. Wong
  2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:23 UTC (permalink / raw)
  To: linux-xfs

XFS_IFORK_Q is to be used in boolean context, not for a size.  This
doesn't make a difference in practice as size is only checked for
0, but this keeps the logic sane.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/scrub/bmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index add8598eacd5d..283424d6d2bb6 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
 		size = i_size_read(VFS_I(sc->ip));
 		break;
 	case XFS_ATTR_FORK:
-		size = XFS_IFORK_Q(sc->ip);
+		size = XFS_IFORK_BOFF(sc->ip);
 		break;
 	default:
 		size = 0;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
  2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
@ 2020-05-10  7:24 ` Christoph Hellwig
  2020-05-11 12:39   ` Chandan Babu R
                     ` (2 more replies)
  2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
                   ` (3 subsequent siblings)
  5 siblings, 3 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:24 UTC (permalink / raw)
  To: linux-xfs

Just checking di_forkoff directly is a little easier to follow.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_format.h    | 5 ++---
 fs/xfs/libxfs/xfs_inode_buf.c | 6 +++---
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 045556e78ee2c..3cc352000b8a1 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -964,13 +964,12 @@ enum xfs_dinode_fmt {
 /*
  * Inode data & attribute fork sizes, per inode.
  */
-#define XFS_DFORK_Q(dip)		((dip)->di_forkoff != 0)
 #define XFS_DFORK_BOFF(dip)		((int)((dip)->di_forkoff << 3))
 
 #define XFS_DFORK_DSIZE(dip,mp) \
-	(XFS_DFORK_Q(dip) ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
+	((dip)->di_forkoff ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
 #define XFS_DFORK_ASIZE(dip,mp) \
-	(XFS_DFORK_Q(dip) ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
+	((dip)->di_forkoff ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
 #define XFS_DFORK_SIZE(dip,mp,w) \
 	((w) == XFS_DATA_FORK ? \
 		XFS_DFORK_DSIZE(dip, mp) : \
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 05f939adea944..5547bbb3cf945 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -265,7 +265,7 @@ xfs_inode_from_disk(
 	error = xfs_iformat_data_fork(ip, from);
 	if (error)
 		return error;
-	if (XFS_DFORK_Q(from)) {
+	if (from->di_forkoff) {
 		error = xfs_iformat_attr_fork(ip, from);
 		if (error)
 			goto out_destroy_data_fork;
@@ -435,7 +435,7 @@ xfs_dinode_verify_forkoff(
 	struct xfs_dinode	*dip,
 	struct xfs_mount	*mp)
 {
-	if (!XFS_DFORK_Q(dip))
+	if (!dip->di_forkoff)
 		return NULL;
 
 	switch (dip->di_format)  {
@@ -538,7 +538,7 @@ xfs_dinode_verify(
 		return __this_address;
 	}
 
-	if (XFS_DFORK_Q(dip)) {
+	if (dip->di_forkoff) {
 		fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
 		if (fa)
 			return fa;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 3/6] xfs: remove xfs_ifree_local_data
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
  2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
  2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
@ 2020-05-10  7:24 ` Christoph Hellwig
  2020-05-11 16:32   ` Chandan Babu R
                     ` (2 more replies)
  2020-05-10  7:24 ` [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork Christoph Hellwig
                   ` (2 subsequent siblings)
  5 siblings, 3 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:24 UTC (permalink / raw)
  To: linux-xfs

xfs_ifree only need to free inline data in the data fork, as we've
already taken care of the attr fork before (and in fact freed the
fork structure).  Just open code the freeing of the inline data.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_inode.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 549ff468b7b60..7d3144dc99b72 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2711,24 +2711,6 @@ xfs_ifree_cluster(
 	return 0;
 }
 
-/*
- * Free any local-format buffers sitting around before we reset to
- * extents format.
- */
-static inline void
-xfs_ifree_local_data(
-	struct xfs_inode	*ip,
-	int			whichfork)
-{
-	struct xfs_ifork	*ifp;
-
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
-		return;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
-}
-
 /*
  * This is called to return an inode to the inode free list.
  * The inode should already be truncated to 0 length and have
@@ -2765,8 +2747,16 @@ xfs_ifree(
 	if (error)
 		return error;
 
-	xfs_ifree_local_data(ip, XFS_DATA_FORK);
-	xfs_ifree_local_data(ip, XFS_ATTR_FORK);
+	/*
+	 * Free any local-format data sitting around before we reset the
+	 * data fork to extents format.  Note that the attr fork data has
+	 * already been freed by xfs_attr_inactive.
+	 */
+	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		kmem_free(ip->i_df.if_u1.if_data);
+		ip->i_df.if_u1.if_data = NULL;
+		ip->i_df.if_bytes = 0;
+	}
 
 	VFS_I(ip)->i_mode = 0;		/* mark incore inode as free */
 	ip->i_d.di_flags = 0;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
                   ` (2 preceding siblings ...)
  2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
@ 2020-05-10  7:24 ` Christoph Hellwig
  2020-05-12  5:26   ` Chandan Babu R
  2020-05-12 16:10   ` Brian Foster
  2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
  2020-05-10  7:24 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
  5 siblings, 2 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:24 UTC (permalink / raw)
  To: linux-xfs

There are thee number of extents counters, one for each of the forks,
Two are in the legacy icdinode and one is directly in struct xfs_inode.
Switch to a single counter in the xfs_ifork structure where it uses up
padding at the end of the structure.  This simplifies various bits of
code that just wants the number of extents counter and can now directly
dereference it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_attr.c       |   4 +-
 fs/xfs/libxfs/xfs_attr_leaf.c  |   1 -
 fs/xfs/libxfs/xfs_bmap.c       | 126 ++++++++++++++-------------------
 fs/xfs/libxfs/xfs_dir2_block.c |   2 +-
 fs/xfs/libxfs/xfs_inode_buf.c  |   6 +-
 fs/xfs/libxfs/xfs_inode_buf.h  |   2 -
 fs/xfs/libxfs/xfs_inode_fork.c |  12 ++--
 fs/xfs/libxfs/xfs_inode_fork.h |  20 +++---
 fs/xfs/scrub/bmap.c            |   3 +-
 fs/xfs/scrub/parent.c          |   2 +-
 fs/xfs/xfs_bmap_util.c         |  28 ++++----
 fs/xfs/xfs_file.c              |   2 +-
 fs/xfs/xfs_icache.c            |   1 -
 fs/xfs/xfs_inode.c             |  19 +++--
 fs/xfs/xfs_inode.h             |   1 -
 fs/xfs/xfs_inode_item.c        |  14 ++--
 fs/xfs/xfs_ioctl.c             |  25 +++----
 fs/xfs/xfs_iomap.c             |   2 +-
 fs/xfs/xfs_iops.c              |   2 +-
 fs/xfs/xfs_itable.c            |   4 +-
 fs/xfs/xfs_qm_syscalls.c       |   2 +-
 fs/xfs/xfs_quotaops.c          |   2 +-
 fs/xfs/xfs_symlink.c           |   2 +-
 fs/xfs/xfs_trace.h             |   2 +-
 24 files changed, 122 insertions(+), 162 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index e4fe3dca9883b..1b01675e9c80b 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -62,7 +62,7 @@ xfs_inode_hasattr(
 {
 	if (!XFS_IFORK_Q(ip) ||
 	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
-	     ip->i_d.di_anextents == 0))
+	     ip->i_afp->if_nextents == 0))
 		return 0;
 	return 1;
 }
@@ -214,7 +214,7 @@ xfs_attr_set_args(
 	 */
 	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
 	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
-	     dp->i_d.di_anextents == 0)) {
+	     dp->i_afp->if_nextents == 0)) {
 
 		/*
 		 * Build initial attribute list (if required).
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 863444e2dda7e..64b172180c42c 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -723,7 +723,6 @@ xfs_attr_fork_remove(
 	ip->i_d.di_forkoff = 0;
 	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
 
-	ASSERT(ip->i_d.di_anextents == 0);
 	ASSERT(ip->i_afp == NULL);
 
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 34518a6dc7376..c1136be49abeb 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -61,10 +61,10 @@ xfs_bmap_compute_maxlevels(
 	int		sz;		/* root block size */
 
 	/*
-	 * The maximum number of extents in a file, hence the maximum
-	 * number of leaf entries, is controlled by the type of di_nextents
-	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
-	 * (a signed 16-bit number, xfs_aextnum_t).
+	 * The maximum number of extents in a file, hence the maximum number of
+	 * leaf entries, is controlled by the size of the on-disk extent count,
+	 * either a signed 32-bit number for the data fork, or a signed 16-bit
+	 * number for the attr fork.
 	 *
 	 * Note that we can no longer assume that if we are in ATTR1 that
 	 * the fork offset of all the inodes will be
@@ -120,10 +120,11 @@ xfs_bmbt_lookup_first(
  */
 static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
 {
+	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
+
 	return whichfork != XFS_COW_FORK &&
 		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-		XFS_IFORK_NEXTENTS(ip, whichfork) >
-			XFS_IFORK_MAXEXT(ip, whichfork);
+		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
 /*
@@ -131,10 +132,11 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
  */
 static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
 {
+	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
+
 	return whichfork != XFS_COW_FORK &&
 		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
-		XFS_IFORK_NEXTENTS(ip, whichfork) <=
-			XFS_IFORK_MAXEXT(ip, whichfork);
+		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
 /*
@@ -334,7 +336,7 @@ xfs_bmap_check_leaf_extents(
 	}
 
 	/* skip large extent count inodes */
-	if (ip->i_d.di_nextents > 10000)
+	if (ip->i_df.if_nextents > 10000)
 		return;
 
 	bno = NULLFSBLOCK;
@@ -750,7 +752,7 @@ xfs_bmap_extents_to_btree(
 		xfs_bmbt_disk_set_all(arp, &rec);
 		cnt++;
 	}
-	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
+	ASSERT(cnt == ifp->if_nextents);
 	xfs_btree_set_numrecs(ablock, cnt);
 
 	/*
@@ -802,7 +804,7 @@ xfs_bmap_local_to_extents_empty(
 	ASSERT(whichfork != XFS_COW_FORK);
 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
 	ASSERT(ifp->if_bytes == 0);
-	ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
+	ASSERT(ifp->if_nextents == 0);
 
 	xfs_bmap_forkoff_reset(ip, whichfork);
 	ifp->if_flags &= ~XFS_IFINLINE;
@@ -907,7 +909,7 @@ xfs_bmap_local_to_extents(
 	xfs_iext_first(ifp, &icur);
 	xfs_iext_insert(ip, &icur, &rec, 0);
 
-	XFS_IFORK_NEXT_SET(ip, whichfork, 1);
+	ifp->if_nextents = 1;
 	ip->i_d.di_nblocks = 1;
 	xfs_trans_mod_dquot_byino(tp, ip,
 		XFS_TRANS_DQ_BCOUNT, 1L);
@@ -972,7 +974,8 @@ xfs_bmap_add_attrfork_extents(
 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
 	int			error;		/* error return value */
 
-	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
+	if (ip->i_df.if_nextents * sizeof(struct xfs_bmbt_rec) <=
+	    XFS_IFORK_DSIZE(ip))
 		return 0;
 	cur = NULL;
 	error = xfs_bmap_extents_to_btree(tp, ip, &cur, 0, flags,
@@ -1091,10 +1094,6 @@ xfs_bmap_add_attrfork(
 		goto trans_cancel;
 	if (XFS_IFORK_Q(ip))
 		goto trans_cancel;
-	if (XFS_IS_CORRUPT(mp, ip->i_d.di_anextents != 0)) {
-		error = -EFSCORRUPTED;
-		goto trans_cancel;
-	}
 	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
 		/*
 		 * For inodes coming from pre-6.2 filesystems.
@@ -1183,13 +1182,13 @@ xfs_iread_bmbt_block(
 	xfs_extnum_t		num_recs;
 	xfs_extnum_t		j;
 	int			whichfork = cur->bc_ino.whichfork;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 
 	block = xfs_btree_get_block(cur, level, &bp);
 
 	/* Abort if we find more records than nextents. */
 	num_recs = xfs_btree_get_numrecs(block);
-	if (unlikely(ir->loaded + num_recs >
-		     XFS_IFORK_NEXTENTS(ip, whichfork))) {
+	if (unlikely(ir->loaded + num_recs > ifp->if_nextents)) {
 		xfs_warn(ip->i_mount, "corrupt dinode %llu, (btree extents).",
 				(unsigned long long)ip->i_ino);
 		xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, block,
@@ -1215,7 +1214,7 @@ xfs_iread_bmbt_block(
 				xfs_bmap_fork_to_state(whichfork));
 		trace_xfs_read_extent(ip, &ir->icur,
 				xfs_bmap_fork_to_state(whichfork), _THIS_IP_);
-		xfs_iext_next(XFS_IFORK_PTR(ip, whichfork), &ir->icur);
+		xfs_iext_next(ifp, &ir->icur);
 	}
 
 	return 0;
@@ -1254,8 +1253,7 @@ xfs_iread_extents(
 	if (error)
 		goto out;
 
-	if (XFS_IS_CORRUPT(mp,
-			   ir.loaded != XFS_IFORK_NEXTENTS(ip, whichfork))) {
+	if (XFS_IS_CORRUPT(mp, ir.loaded != ifp->if_nextents)) {
 		error = -EFSCORRUPTED;
 		goto out;
 	}
@@ -1463,23 +1461,22 @@ xfs_bmap_last_offset(
  */
 int					/* 1=>1 block, 0=>otherwise */
 xfs_bmap_one_block(
-	xfs_inode_t	*ip,		/* incore inode */
-	int		whichfork)	/* data or attr fork */
+	struct xfs_inode	*ip,		/* incore inode */
+	int			whichfork)	/* data or attr fork */
 {
-	struct xfs_ifork *ifp;		/* inode fork pointer */
-	int		rval;		/* return value */
-	xfs_bmbt_irec_t	s;		/* internal version of extent */
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
+	int			rval;		/* return value */
+	struct xfs_bmbt_irec	s;		/* internal version of extent */
 	struct xfs_iext_cursor icur;
 
 #ifndef DEBUG
 	if (whichfork == XFS_DATA_FORK)
 		return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
 #endif	/* !DEBUG */
-	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
+	if (ifp->if_nextents != 1)
 		return 0;
 	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
 		return 0;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
 	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 	xfs_iext_first(ifp, &icur);
 	xfs_iext_get_extent(ifp, &icur, &s);
@@ -1501,10 +1498,11 @@ xfs_bmap_add_extent_delay_real(
 	struct xfs_bmalloca	*bma,
 	int			whichfork)
 {
+	struct xfs_mount	*mp = bma->ip->i_mount;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
 	struct xfs_bmbt_irec	*new = &bma->got;
 	int			error;	/* error return value */
 	int			i;	/* temp state */
-	struct xfs_ifork	*ifp;	/* inode fork pointer */
 	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
 	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
 					/* left is 0, right is 1, prev is 2 */
@@ -1514,16 +1512,9 @@ xfs_bmap_add_extent_delay_real(
 	xfs_filblks_t		da_old; /* old count del alloc blocks used */
 	xfs_filblks_t		temp=0;	/* value for da_new calculations */
 	int			tmp_rval;	/* partial logging flags */
-	struct xfs_mount	*mp;
-	xfs_extnum_t		*nextents;
 	struct xfs_bmbt_irec	old;
 
-	mp = bma->ip->i_mount;
-	ifp = XFS_IFORK_PTR(bma->ip, whichfork);
 	ASSERT(whichfork != XFS_ATTR_FORK);
-	nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents :
-						&bma->ip->i_d.di_nextents);
-
 	ASSERT(!isnullstartblock(new->br_startblock));
 	ASSERT(!bma->cur ||
 	       (bma->cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL));
@@ -1614,7 +1605,7 @@ xfs_bmap_add_extent_delay_real(
 		xfs_iext_remove(bma->ip, &bma->icur, state);
 		xfs_iext_prev(ifp, &bma->icur);
 		xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT);
-		(*nextents)--;
+		ifp->if_nextents--;
 
 		if (bma->cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
@@ -1718,8 +1709,8 @@ xfs_bmap_add_extent_delay_real(
 		PREV.br_startblock = new->br_startblock;
 		PREV.br_state = new->br_state;
 		xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV);
+		ifp->if_nextents++;
 
-		(*nextents)++;
 		if (bma->cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -1784,7 +1775,8 @@ xfs_bmap_add_extent_delay_real(
 		 * The left neighbor is not contiguous.
 		 */
 		xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
-		(*nextents)++;
+		ifp->if_nextents++;
+
 		if (bma->cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -1870,7 +1862,8 @@ xfs_bmap_add_extent_delay_real(
 		 * The right neighbor is not contiguous.
 		 */
 		xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
-		(*nextents)++;
+		ifp->if_nextents++;
+
 		if (bma->cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -1955,7 +1948,7 @@ xfs_bmap_add_extent_delay_real(
 		xfs_iext_next(ifp, &bma->icur);
 		xfs_iext_insert(bma->ip, &bma->icur, &RIGHT, state);
 		xfs_iext_insert(bma->ip, &bma->icur, &LEFT, state);
-		(*nextents)++;
+		ifp->if_nextents++;
 
 		if (bma->cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
@@ -2159,8 +2152,7 @@ xfs_bmap_add_extent_unwritten_real(
 		xfs_iext_remove(ip, icur, state);
 		xfs_iext_prev(ifp, icur);
 		xfs_iext_update_extent(ip, state, icur, &LEFT);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) - 2);
+		ifp->if_nextents -= 2;
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2212,8 +2204,7 @@ xfs_bmap_add_extent_unwritten_real(
 		xfs_iext_remove(ip, icur, state);
 		xfs_iext_prev(ifp, icur);
 		xfs_iext_update_extent(ip, state, icur, &LEFT);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+		ifp->if_nextents--;
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2255,9 +2246,8 @@ xfs_bmap_add_extent_unwritten_real(
 		xfs_iext_remove(ip, icur, state);
 		xfs_iext_prev(ifp, icur);
 		xfs_iext_update_extent(ip, state, icur, &PREV);
+		ifp->if_nextents--;
 
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2364,8 +2354,8 @@ xfs_bmap_add_extent_unwritten_real(
 
 		xfs_iext_update_extent(ip, state, icur, &PREV);
 		xfs_iext_insert(ip, icur, new, state);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+		ifp->if_nextents++;
+
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2440,9 +2430,8 @@ xfs_bmap_add_extent_unwritten_real(
 		xfs_iext_update_extent(ip, state, icur, &PREV);
 		xfs_iext_next(ifp, icur);
 		xfs_iext_insert(ip, icur, new, state);
+		ifp->if_nextents++;
 
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2493,9 +2482,8 @@ xfs_bmap_add_extent_unwritten_real(
 		xfs_iext_next(ifp, icur);
 		xfs_iext_insert(ip, icur, &r[1], state);
 		xfs_iext_insert(ip, icur, &r[0], state);
+		ifp->if_nextents += 2;
 
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) + 2);
 		if (cur == NULL)
 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
@@ -2810,9 +2798,8 @@ xfs_bmap_add_extent_hole_real(
 		xfs_iext_remove(ip, icur, state);
 		xfs_iext_prev(ifp, icur);
 		xfs_iext_update_extent(ip, state, icur, &left);
+		ifp->if_nextents--;
 
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
 		if (cur == NULL) {
 			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
 		} else {
@@ -2910,8 +2897,8 @@ xfs_bmap_add_extent_hole_real(
 		 * Insert a new entry.
 		 */
 		xfs_iext_insert(ip, icur, new, state);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+		ifp->if_nextents++;
+
 		if (cur == NULL) {
 			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
 		} else {
@@ -4512,8 +4499,7 @@ xfs_bmapi_write(
 		goto error0;
 
 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
-	       XFS_IFORK_NEXTENTS(ip, whichfork) >
-		XFS_IFORK_MAXEXT(ip, whichfork));
+	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
 	xfs_bmapi_finish(&bma, whichfork, 0);
 	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
 		orig_nmap, *nmap);
@@ -5056,8 +5042,7 @@ xfs_bmap_del_extent_real(
 	 */
 	if (tp->t_blk_res == 0 &&
 	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_NEXTENTS(ip, whichfork) >=
-			XFS_IFORK_MAXEXT(ip, whichfork) &&
+	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
 	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
 		return -ENOSPC;
 
@@ -5109,8 +5094,8 @@ xfs_bmap_del_extent_real(
 		 */
 		xfs_iext_remove(ip, icur, state);
 		xfs_iext_prev(ifp, icur);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+		ifp->if_nextents--;
+
 		flags |= XFS_ILOG_CORE;
 		if (!cur) {
 			flags |= xfs_ilog_fext(whichfork);
@@ -5218,8 +5203,8 @@ xfs_bmap_del_extent_real(
 			}
 		} else
 			flags |= xfs_ilog_fext(whichfork);
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+
+		ifp->if_nextents++;
 		xfs_iext_next(ifp, icur);
 		xfs_iext_insert(ip, icur, &new, state);
 		break;
@@ -5667,6 +5652,7 @@ xfs_bmse_merge(
 	struct xfs_btree_cur		*cur,
 	int				*logflags)	/* output */
 {
+	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
 	struct xfs_bmbt_irec		new;
 	xfs_filblks_t			blockcount;
 	int				error, i;
@@ -5685,8 +5671,7 @@ xfs_bmse_merge(
 	 * Update the on-disk extent count, the btree if necessary and log the
 	 * inode.
 	 */
-	XFS_IFORK_NEXT_SET(ip, whichfork,
-			   XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+	ifp->if_nextents--;
 	*logflags |= XFS_ILOG_CORE;
 	if (!cur) {
 		*logflags |= XFS_ILOG_DEXT;
@@ -5724,7 +5709,7 @@ xfs_bmse_merge(
 
 done:
 	xfs_iext_remove(ip, icur, 0);
-	xfs_iext_prev(XFS_IFORK_PTR(ip, whichfork), icur);
+	xfs_iext_prev(ifp, icur);
 	xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), icur,
 			&new);
 
@@ -6074,8 +6059,7 @@ xfs_bmap_split_extent(
 	/* Add new extent */
 	xfs_iext_next(ifp, &icur);
 	xfs_iext_insert(ip, &icur, &new, 0);
-	XFS_IFORK_NEXT_SET(ip, whichfork,
-			   XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+	ifp->if_nextents++;
 
 	if (cur) {
 		error = xfs_bmbt_lookup_eq(cur, &new, &i);
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 1dbf2f980a26a..5b59d3f7746b3 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -1104,7 +1104,7 @@ xfs_dir2_sf_to_block(
 	ASSERT(ifp->if_bytes == dp->i_d.di_size);
 	ASSERT(ifp->if_u1.if_data != NULL);
 	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
-	ASSERT(dp->i_d.di_nextents == 0);
+	ASSERT(dp->i_df.if_nextents == 0);
 
 	/*
 	 * Copy the directory into a temporary buffer.
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 5547bbb3cf945..a374e2a81e764 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -245,8 +245,6 @@ xfs_inode_from_disk(
 	to->di_size = be64_to_cpu(from->di_size);
 	to->di_nblocks = be64_to_cpu(from->di_nblocks);
 	to->di_extsize = be32_to_cpu(from->di_extsize);
-	to->di_nextents = be32_to_cpu(from->di_nextents);
-	to->di_anextents = be16_to_cpu(from->di_anextents);
 	to->di_forkoff = from->di_forkoff;
 	to->di_aformat	= from->di_aformat;
 	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
@@ -311,8 +309,8 @@ xfs_inode_to_disk(
 	to->di_size = cpu_to_be64(from->di_size);
 	to->di_nblocks = cpu_to_be64(from->di_nblocks);
 	to->di_extsize = cpu_to_be32(from->di_extsize);
-	to->di_nextents = cpu_to_be32(from->di_nextents);
-	to->di_anextents = cpu_to_be16(from->di_anextents);
+	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
+	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
 	to->di_forkoff = from->di_forkoff;
 	to->di_aformat = from->di_aformat;
 	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index e4cbcaf62a32b..fecccfb26463c 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -22,8 +22,6 @@ struct xfs_icdinode {
 	xfs_fsize_t	di_size;	/* number of bytes in file */
 	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
 	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
-	xfs_extnum_t	di_nextents;	/* number of extents in data fork */
-	xfs_aextnum_t	di_anextents;	/* number of extents in attribute fork*/
 	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
 	int8_t		di_aformat;	/* format of attr fork's data */
 	uint32_t	di_dmevmask;	/* DMIG event mask */
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 2fe325e38fd88..195da3552c5b5 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -188,12 +188,11 @@ xfs_iformat_btree(
 	 * or the number of extents is greater than the number of
 	 * blocks.
 	 */
-	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
-					XFS_IFORK_MAXEXT(ip, whichfork) ||
+	if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
 		     nrecs == 0 ||
 		     XFS_BMDR_SPACE_CALC(nrecs) >
 					XFS_DFORK_SIZE(dip, mp, whichfork) ||
-		     XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
+		     ifp->if_nextents > ip->i_d.di_nblocks) ||
 		     level == 0 || level > XFS_BTREE_MAXLEVELS) {
 		xfs_warn(mp, "corrupt inode %Lu (btree).",
 					(unsigned long long) ip->i_ino);
@@ -229,6 +228,8 @@ xfs_iformat_data_fork(
 	struct inode		*inode = VFS_I(ip);
 	int			error;
 
+	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
+
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFIFO:
 	case S_IFCHR:
@@ -282,6 +283,8 @@ xfs_iformat_attr_fork(
 	int			error = 0;
 
 	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
+	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
+
 	switch (dip->di_aformat) {
 	case XFS_DINODE_FMT_LOCAL:
 		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
@@ -617,7 +620,7 @@ xfs_iflush_fork(
 		       !(iip->ili_fields & extflag[whichfork]));
 		if ((iip->ili_fields & extflag[whichfork]) &&
 		    (ifp->if_bytes > 0)) {
-			ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
+			ASSERT(ifp->if_nextents > 0);
 			(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
 				whichfork);
 		}
@@ -676,7 +679,6 @@ xfs_ifork_init_cow(
 				       KM_NOFS);
 	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
 	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
-	ip->i_cnextents = 0;
 }
 
 /* Verify the inline contents of the data fork of an inode. */
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index f46a8c1db5964..a69d425fe68df 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -23,6 +23,7 @@ struct xfs_ifork {
 	} if_u1;
 	short			if_broot_bytes;	/* bytes allocated for root */
 	unsigned char		if_flags;	/* per-fork flags */
+	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
 };
 
 /*
@@ -67,18 +68,6 @@ struct xfs_ifork {
 		((w) == XFS_ATTR_FORK ? \
 			((ip)->i_d.di_aformat = (n)) : \
 			((ip)->i_cformat = (n))))
-#define XFS_IFORK_NEXTENTS(ip,w) \
-	((w) == XFS_DATA_FORK ? \
-		(ip)->i_d.di_nextents : \
-		((w) == XFS_ATTR_FORK ? \
-			(ip)->i_d.di_anextents : \
-			(ip)->i_cnextents))
-#define XFS_IFORK_NEXT_SET(ip,w,n) \
-	((w) == XFS_DATA_FORK ? \
-		((ip)->i_d.di_nextents = (n)) : \
-		((w) == XFS_ATTR_FORK ? \
-			((ip)->i_d.di_anextents = (n)) : \
-			((ip)->i_cnextents = (n))))
 #define XFS_IFORK_MAXEXT(ip, w) \
 	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
 
@@ -86,6 +75,13 @@ struct xfs_ifork {
 	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
 	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
 
+static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
+{
+	if (!ifp)
+		return 0;
+	return ifp->if_nextents;
+}
+
 struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
 
 int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 283424d6d2bb6..157f72efec5e9 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -566,6 +566,7 @@ xchk_bmap_check_rmaps(
 	struct xfs_scrub	*sc,
 	int			whichfork)
 {
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
 	loff_t			size;
 	xfs_agnumber_t		agno;
 	int			error;
@@ -598,7 +599,7 @@ xchk_bmap_check_rmaps(
 		break;
 	}
 	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
+	    (size == 0 || ifp->if_nextents > 0))
 		return 0;
 
 	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index 5705adc43a75f..855aa8bcab64b 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -90,7 +90,7 @@ xchk_parent_count_parent_dentries(
 	 * if there is one.
 	 */
 	lock_mode = xfs_ilock_data_map_shared(parent);
-	if (parent->i_d.di_nextents > 0)
+	if (parent->i_df.if_nextents > 0)
 		error = xfs_dir3_data_readahead(parent, 0, 0);
 	xfs_iunlock(parent, lock_mode);
 	if (error)
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index cc23a3e23e2d1..4f277a6253b8d 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1220,7 +1220,7 @@ xfs_swap_extents_check_format(
 	 * if the target inode has less extents that then temporary inode then
 	 * why did userspace call us?
 	 */
-	if (ip->i_d.di_nextents < tip->i_d.di_nextents)
+	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
 		return -EINVAL;
 
 	/*
@@ -1241,14 +1241,12 @@ xfs_swap_extents_check_format(
 
 	/* Check temp in extent form to max in target */
 	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) >
-			XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
+	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
 		return -EINVAL;
 
 	/* Check target in extent form to max in temp */
 	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) >
-			XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
+	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
 		return -EINVAL;
 
 	/*
@@ -1264,7 +1262,7 @@ xfs_swap_extents_check_format(
 		if (XFS_IFORK_Q(ip) &&
 		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
 			return -EINVAL;
-		if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
+		if (tip->i_df.if_nextents <=
 		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
 			return -EINVAL;
 	}
@@ -1274,7 +1272,7 @@ xfs_swap_extents_check_format(
 		if (XFS_IFORK_Q(tip) &&
 		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
 			return -EINVAL;
-		if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
+		if (ip->i_df.if_nextents <=
 		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
 			return -EINVAL;
 	}
@@ -1427,15 +1425,15 @@ xfs_swap_extent_forks(
 	/*
 	 * Count the number of extended attribute blocks
 	 */
-	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
-	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
+	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
+	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
 				&aforkblks);
 		if (error)
 			return error;
 	}
-	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
-	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
+	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
+	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
 				&taforkblks);
 		if (error)
@@ -1468,7 +1466,6 @@ xfs_swap_extent_forks(
 	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
 	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
 
-	swap(ip->i_d.di_nextents, tip->i_d.di_nextents);
 	swap(ip->i_d.di_format, tip->i_d.di_format);
 
 	/*
@@ -1615,9 +1612,9 @@ xfs_swap_extents(
 	 * performed with log redo items!
 	 */
 	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
-		int		w	= XFS_DATA_FORK;
-		uint32_t	ipnext	= XFS_IFORK_NEXTENTS(ip, w);
-		uint32_t	tipnext	= XFS_IFORK_NEXTENTS(tip, w);
+		int		w = XFS_DATA_FORK;
+		uint32_t	ipnext = ip->i_df.if_nextents;
+		uint32_t	tipnext	= tip->i_df.if_nextents;
 
 		/*
 		 * Conceptually this shouldn't affect the shape of either bmbt,
@@ -1720,7 +1717,6 @@ xfs_swap_extents(
 		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
 		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
 
-		swap(ip->i_cnextents, tip->i_cnextents);
 		swap(ip->i_cowfp, tip->i_cowfp);
 
 		if (ip->i_cowfp && ip->i_cowfp->if_bytes)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 4b8bdecc38635..403c90309a8ff 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1102,7 +1102,7 @@ xfs_dir_open(
 	 * certain to have the next operation be a read there.
 	 */
 	mode = xfs_ilock_data_map_shared(ip);
-	if (ip->i_d.di_nextents > 0)
+	if (ip->i_df.if_nextents > 0)
 		error = xfs_dir3_data_readahead(ip, 0, 0);
 	xfs_iunlock(ip, mode);
 	return error;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 5a3a520b95288..791d5d5e318cf 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -63,7 +63,6 @@ xfs_inode_alloc(
 	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
 	ip->i_afp = NULL;
 	ip->i_cowfp = NULL;
-	ip->i_cnextents = 0;
 	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
 	memset(&ip->i_df, 0, sizeof(ip->i_df));
 	ip->i_flags = 0;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 7d3144dc99b72..1677c4e7207ed 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -825,7 +825,7 @@ xfs_ialloc(
 		inode->i_mode &= ~S_ISGID;
 
 	ip->i_d.di_size = 0;
-	ip->i_d.di_nextents = 0;
+	ip->i_df.if_nextents = 0;
 	ASSERT(ip->i_d.di_nblocks == 0);
 
 	tv = current_time(inode);
@@ -919,7 +919,6 @@ xfs_ialloc(
 	 * Attribute fork settings for new inode.
 	 */
 	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
-	ip->i_d.di_anextents = 0;
 
 	/*
 	 * Log the new values stuffed into the inode.
@@ -1686,7 +1685,7 @@ xfs_inactive_truncate(
 	if (error)
 		goto error_trans_cancel;
 
-	ASSERT(ip->i_d.di_nextents == 0);
+	ASSERT(ip->i_df.if_nextents == 0);
 
 	error = xfs_trans_commit(tp);
 	if (error)
@@ -1836,7 +1835,7 @@ xfs_inactive(
 
 	if (S_ISREG(VFS_I(ip)->i_mode) &&
 	    (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
-	     ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
+	     ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
 		truncate = 1;
 
 	error = xfs_qm_dqattach(ip);
@@ -1862,7 +1861,6 @@ xfs_inactive(
 	}
 
 	ASSERT(!ip->i_afp);
-	ASSERT(ip->i_d.di_anextents == 0);
 	ASSERT(ip->i_d.di_forkoff == 0);
 
 	/*
@@ -2731,8 +2729,7 @@ xfs_ifree(
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 	ASSERT(VFS_I(ip)->i_nlink == 0);
-	ASSERT(ip->i_d.di_nextents == 0);
-	ASSERT(ip->i_d.di_anextents == 0);
+	ASSERT(ip->i_df.if_nextents == 0);
 	ASSERT(ip->i_d.di_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
 	ASSERT(ip->i_d.di_nblocks == 0);
 
@@ -3628,7 +3625,7 @@ xfs_iflush(
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
 	ASSERT(xfs_isiflocked(ip));
 	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
-	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
+	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 
 	*bpp = NULL;
 
@@ -3710,7 +3707,7 @@ xfs_iflush_int(
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
 	ASSERT(xfs_isiflocked(ip));
 	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
-	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
+	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 	ASSERT(iip != NULL && iip->ili_fields != 0);
 
 	dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
@@ -3751,13 +3748,13 @@ xfs_iflush_int(
 			goto flush_out;
 		}
 	}
-	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
+	if (XFS_TEST_ERROR(ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp) >
 				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5)) {
 		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
 			"%s: detected corrupt incore inode %Lu, "
 			"total extents = %d, nblocks = %Ld, ptr "PTR_FMT,
 			__func__, ip->i_ino,
-			ip->i_d.di_nextents + ip->i_d.di_anextents,
+			ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp),
 			ip->i_d.di_nblocks, ip);
 		goto flush_out;
 	}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index ff846197941e4..24dae63ba16c0 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -57,7 +57,6 @@ typedef struct xfs_inode {
 
 	struct xfs_icdinode	i_d;		/* most of ondisk inode */
 
-	xfs_extnum_t		i_cnextents;	/* # of extents in cow fork */
 	unsigned int		i_cformat;	/* format of cow fork */
 
 	/* VFS inode */
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index cefa2484f0dbf..401ba26aeed7b 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -39,7 +39,7 @@ xfs_inode_item_data_fork_size(
 	switch (ip->i_d.di_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
-		    ip->i_d.di_nextents > 0 &&
+		    ip->i_df.if_nextents > 0 &&
 		    ip->i_df.if_bytes > 0) {
 			/* worst case, doesn't subtract delalloc extents */
 			*nbytes += XFS_IFORK_DSIZE(ip);
@@ -80,7 +80,7 @@ xfs_inode_item_attr_fork_size(
 	switch (ip->i_d.di_aformat) {
 	case XFS_DINODE_FMT_EXTENTS:
 		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
-		    ip->i_d.di_anextents > 0 &&
+		    ip->i_afp->if_nextents > 0 &&
 		    ip->i_afp->if_bytes > 0) {
 			/* worst case, doesn't subtract unused space */
 			*nbytes += XFS_IFORK_ASIZE(ip);
@@ -148,7 +148,7 @@ xfs_inode_item_format_data_fork(
 			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
 
 		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
-		    ip->i_d.di_nextents > 0 &&
+		    ip->i_df.if_nextents > 0 &&
 		    ip->i_df.if_bytes > 0) {
 			struct xfs_bmbt_rec *p;
 
@@ -233,12 +233,12 @@ xfs_inode_item_format_attr_fork(
 			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
 
 		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
-		    ip->i_d.di_anextents > 0 &&
+		    ip->i_afp->if_nextents > 0 &&
 		    ip->i_afp->if_bytes > 0) {
 			struct xfs_bmbt_rec *p;
 
 			ASSERT(xfs_iext_count(ip->i_afp) ==
-				ip->i_d.di_anextents);
+				ip->i_afp->if_nextents);
 
 			p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT);
 			data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK);
@@ -326,8 +326,8 @@ xfs_inode_to_log_dinode(
 	to->di_size = from->di_size;
 	to->di_nblocks = from->di_nblocks;
 	to->di_extsize = from->di_extsize;
-	to->di_nextents = from->di_nextents;
-	to->di_anextents = from->di_anextents;
+	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
+	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
 	to->di_forkoff = from->di_forkoff;
 	to->di_aformat = from->di_aformat;
 	to->di_dmevmask = from->di_dmevmask;
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 4ee0d13232f3f..7a71c03e9022b 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1104,26 +1104,17 @@ xfs_fill_fsxattr(
 	bool			attr,
 	struct fsxattr		*fa)
 {
+	struct xfs_ifork	*ifp = attr ? ip->i_afp : &ip->i_df;
+
 	simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
 	fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
 	fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
 			ip->i_mount->m_sb.sb_blocklog;
 	fa->fsx_projid = ip->i_d.di_projid;
-
-	if (attr) {
-		if (ip->i_afp) {
-			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
-				fa->fsx_nextents = xfs_iext_count(ip->i_afp);
-			else
-				fa->fsx_nextents = ip->i_d.di_anextents;
-		} else
-			fa->fsx_nextents = 0;
-	} else {
-		if (ip->i_df.if_flags & XFS_IFEXTENTS)
-			fa->fsx_nextents = xfs_iext_count(&ip->i_df);
-		else
-			fa->fsx_nextents = ip->i_d.di_nextents;
-	}
+	if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
+		fa->fsx_nextents = xfs_iext_count(ifp);
+	else
+		fa->fsx_nextents = xfs_ifork_nextents(ifp);
 }
 
 STATIC int
@@ -1211,7 +1202,7 @@ xfs_ioctl_setattr_xflags(
 	uint64_t		di_flags2;
 
 	/* Can't change realtime flag if any extents are allocated. */
-	if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
+	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
 	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
 		return -EINVAL;
 
@@ -1389,7 +1380,7 @@ xfs_ioctl_setattr_check_extsize(
 	xfs_extlen_t		size;
 	xfs_fsblock_t		extsize_fsb;
 
-	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
+	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
 	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
 		return -EINVAL;
 
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index bb590a267a7f9..b4fd918749e5f 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1258,7 +1258,7 @@ xfs_xattr_iomap_begin(
 	lockmode = xfs_ilock_attr_map_shared(ip);
 
 	/* if there are no attribute fork or extents, return ENOENT */
-	if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
+	if (!XFS_IFORK_Q(ip) || !ip->i_afp->if_nextents) {
 		error = -ENOENT;
 		goto out_unlock;
 	}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 26a71237d70f6..d66528fa36570 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -872,7 +872,7 @@ xfs_setattr_size(
 	/*
 	 * Short circuit the truncate case for zero length files.
 	 */
-	if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
+	if (newsize == 0 && oldsize == 0 && ip->i_df.if_nextents == 0) {
 		if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
 			return 0;
 
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index ff2da28fed90e..80da86c5703fb 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -104,9 +104,9 @@ xfs_bulkstat_one_int(
 
 	buf->bs_xflags = xfs_ip2xflags(ip);
 	buf->bs_extsize_blks = dic->di_extsize;
-	buf->bs_extents = dic->di_nextents;
+	buf->bs_extents = xfs_ifork_nextents(&ip->i_df);
 	xfs_bulkstat_health(ip, buf);
-	buf->bs_aextents = dic->di_anextents;
+	buf->bs_aextents = xfs_ifork_nextents(ip->i_afp);
 	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
 	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
 
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 944486f2b2874..9edf761eec739 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -302,7 +302,7 @@ xfs_qm_scall_trunc_qfile(
 		goto out_unlock;
 	}
 
-	ASSERT(ip->i_d.di_nextents == 0);
+	ASSERT(ip->i_df.if_nextents == 0);
 
 	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	error = xfs_trans_commit(tp);
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 38669e8272060..b5d10ecb54743 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -36,7 +36,7 @@ xfs_qm_fill_state(
 	}
 	tstate->flags |= QCI_SYSFILE;
 	tstate->blocks = ip->i_d.di_nblocks;
-	tstate->nextents = ip->i_d.di_nextents;
+	tstate->nextents = ip->i_df.if_nextents;
 	tstate->spc_timelimit = (u32)q->qi_btimelimit;
 	tstate->ino_timelimit = (u32)q->qi_itimelimit;
 	tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit;
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 973441992b084..8cf2fcb509c12 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -384,7 +384,7 @@ xfs_inactive_symlink_rmt(
 	 * either 1 or 2 extents and that we can
 	 * free them all in one bunmapi call.
 	 */
-	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
+	ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
 
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
 	if (error)
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index a4323a63438d8..ba2ab69e1fc7d 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1898,7 +1898,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
 		__entry->which = which;
 		__entry->ino = ip->i_ino;
 		__entry->format = ip->i_d.di_format;
-		__entry->nex = ip->i_d.di_nextents;
+		__entry->nex = ip->i_df.if_nextents;
 		__entry->broot_size = ip->i_df.if_broot_bytes;
 		__entry->fork_off = XFS_IFORK_BOFF(ip);
 	),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
                   ` (3 preceding siblings ...)
  2020-05-10  7:24 ` [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork Christoph Hellwig
@ 2020-05-10  7:24 ` Christoph Hellwig
  2020-05-12  9:37   ` Chandan Babu R
                     ` (2 more replies)
  2020-05-10  7:24 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
  5 siblings, 3 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:24 UTC (permalink / raw)
  To: linux-xfs

Both the data and attr fork have a format that is stored in the legacy
idinode.  Move it into the xfs_ifork structure instead, where it uses
up padding.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_attr.c           |  12 +--
 fs/xfs/libxfs/xfs_attr_leaf.c      |  32 ++++----
 fs/xfs/libxfs/xfs_bmap.c           | 120 +++++++++++++----------------
 fs/xfs/libxfs/xfs_bmap_btree.c     |   5 +-
 fs/xfs/libxfs/xfs_dir2.c           |   8 +-
 fs/xfs/libxfs/xfs_dir2_sf.c        |  13 ++--
 fs/xfs/libxfs/xfs_inode_buf.c      |   6 +-
 fs/xfs/libxfs/xfs_inode_buf.h      |   2 -
 fs/xfs/libxfs/xfs_inode_fork.c     |  14 ++--
 fs/xfs/libxfs/xfs_inode_fork.h     |  28 ++++---
 fs/xfs/libxfs/xfs_symlink_remote.c |  16 ++--
 fs/xfs/scrub/bmap.c                |   4 +-
 fs/xfs/scrub/dabtree.c             |   2 +-
 fs/xfs/scrub/dir.c                 |   7 +-
 fs/xfs/xfs_aops.c                  |   2 +-
 fs/xfs/xfs_attr_inactive.c         |   2 +-
 fs/xfs/xfs_attr_list.c             |   4 +-
 fs/xfs/xfs_bmap_util.c             |  56 +++++++-------
 fs/xfs/xfs_dir2_readdir.c          |   2 +-
 fs/xfs/xfs_icache.c                |   1 -
 fs/xfs/xfs_inode.c                 |  36 ++++-----
 fs/xfs/xfs_inode.h                 |   2 -
 fs/xfs/xfs_inode_item.c            |  12 +--
 fs/xfs/xfs_iomap.c                 |   4 +-
 fs/xfs/xfs_itable.c                |   2 +-
 fs/xfs/xfs_symlink.c               |   2 +-
 fs/xfs/xfs_trace.h                 |   2 +-
 27 files changed, 181 insertions(+), 215 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 1b01675e9c80b..3b1bd6e112f89 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -61,7 +61,7 @@ xfs_inode_hasattr(
 	struct xfs_inode	*ip)
 {
 	if (!XFS_IFORK_Q(ip) ||
-	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+	    (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
 	     ip->i_afp->if_nextents == 0))
 		return 0;
 	return 1;
@@ -84,7 +84,7 @@ xfs_attr_get_ilocked(
 	if (!xfs_inode_hasattr(args->dp))
 		return -ENOATTR;
 
-	if (args->dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
+	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
 		return xfs_attr_shortform_getvalue(args);
 	if (xfs_bmap_one_block(args->dp, XFS_ATTR_FORK))
 		return xfs_attr_leaf_get(args);
@@ -212,14 +212,14 @@ xfs_attr_set_args(
 	 * If the attribute list is non-existent or a shortform list,
 	 * upgrade it to a single-leaf-block attribute list.
 	 */
-	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
-	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
+	    (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
 	     dp->i_afp->if_nextents == 0)) {
 
 		/*
 		 * Build initial attribute list (if required).
 		 */
-		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
+		if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
 			xfs_attr_shortform_create(args);
 
 		/*
@@ -272,7 +272,7 @@ xfs_attr_remove_args(
 
 	if (!xfs_inode_hasattr(dp)) {
 		error = -ENOATTR;
-	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+	} else if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
 		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
 		error = xfs_attr_shortform_remove(args);
 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 64b172180c42c..d7f3173ce3c31 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -539,7 +539,7 @@ xfs_attr_shortform_bytesfit(
 	/* rounded down */
 	offset = (XFS_LITINO(mp) - bytes) >> 3;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_DEV) {
 		minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
 		return (offset >= minforkoff) ? minforkoff : 0;
 	}
@@ -567,7 +567,7 @@ xfs_attr_shortform_bytesfit(
 
 	dsize = dp->i_df.if_bytes;
 
-	switch (dp->i_d.di_format) {
+	switch (dp->i_df.if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		/*
 		 * If there is no attr fork and the data fork is extents, 
@@ -636,22 +636,19 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
  * Create the initial contents of a shortform attribute list.
  */
 void
-xfs_attr_shortform_create(xfs_da_args_t *args)
+xfs_attr_shortform_create(
+	struct xfs_da_args	*args)
 {
-	xfs_attr_sf_hdr_t *hdr;
-	xfs_inode_t *dp;
-	struct xfs_ifork *ifp;
+	struct xfs_inode	*dp = args->dp;
+	struct xfs_ifork	*ifp = dp->i_afp;
+	struct xfs_attr_sf_hdr	*hdr;
 
 	trace_xfs_attr_sf_create(args);
 
-	dp = args->dp;
-	ASSERT(dp != NULL);
-	ifp = dp->i_afp;
-	ASSERT(ifp != NULL);
 	ASSERT(ifp->if_bytes == 0);
-	if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
+	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS) {
 		ifp->if_flags &= ~XFS_IFEXTENTS;	/* just in case */
-		dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
+		ifp->if_format = XFS_DINODE_FMT_LOCAL;
 		ifp->if_flags |= XFS_IFINLINE;
 	} else {
 		ASSERT(ifp->if_flags & XFS_IFINLINE);
@@ -721,7 +718,6 @@ xfs_attr_fork_remove(
 {
 	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
 	ip->i_d.di_forkoff = 0;
-	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
 
 	ASSERT(ip->i_afp == NULL);
 
@@ -774,7 +770,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
 	totsize -= size;
 	if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
 	    (mp->m_flags & XFS_MOUNT_ATTR2) &&
-	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
+	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
 	    !(args->op_flags & XFS_DA_OP_ADDNAME)) {
 		xfs_attr_fork_remove(dp, args->trans);
 	} else {
@@ -784,7 +780,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
 		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
 				(args->op_flags & XFS_DA_OP_ADDNAME) ||
 				!(mp->m_flags & XFS_MOUNT_ATTR2) ||
-				dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
+				dp->i_df.if_format == XFS_DINODE_FMT_BTREE);
 		xfs_trans_log_inode(args->trans, dp,
 					XFS_ILOG_CORE | XFS_ILOG_ADATA);
 	}
@@ -961,7 +957,7 @@ xfs_attr_shortform_allfit(
 				+ be16_to_cpu(name_loc->valuelen);
 	}
 	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
-	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
+	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
 	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
 		return -1;
 	return xfs_attr_shortform_bytesfit(dp, bytes);
@@ -980,7 +976,7 @@ xfs_attr_shortform_verify(
 	int				i;
 	int64_t				size;
 
-	ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL);
+	ASSERT(ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL);
 	ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK);
 	sfp = (struct xfs_attr_shortform *)ifp->if_u1.if_data;
 	size = ifp->if_bytes;
@@ -1084,7 +1080,7 @@ xfs_attr3_leaf_to_shortform(
 
 	if (forkoff == -1) {
 		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
-		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
+		ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE);
 		xfs_attr_fork_remove(dp, args->trans);
 		goto out;
 	}
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index c1136be49abeb..edc63dba007f4 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -123,7 +123,7 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
 	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
 
 	return whichfork != XFS_COW_FORK &&
-		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
+		ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
 		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
@@ -135,7 +135,7 @@ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
 	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
 
 	return whichfork != XFS_COW_FORK &&
-		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
+		ifp->if_format == XFS_DINODE_FMT_BTREE &&
 		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
@@ -215,8 +215,8 @@ xfs_bmap_forkoff_reset(
 	int		whichfork)
 {
 	if (whichfork == XFS_ATTR_FORK &&
-	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
-	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
+	    ip->i_df.if_format != XFS_DINODE_FMT_DEV &&
+	    ip->i_df.if_format != XFS_DINODE_FMT_BTREE) {
 		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
 
 		if (dfl_forkoff > ip->i_d.di_forkoff)
@@ -317,31 +317,28 @@ xfs_bmap_check_leaf_extents(
 	xfs_inode_t		*ip,		/* incore inode pointer */
 	int			whichfork)	/* data or attr fork */
 {
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 	struct xfs_btree_block	*block;	/* current btree block */
 	xfs_fsblock_t		bno;	/* block # of "block" */
 	xfs_buf_t		*bp;	/* buffer for "block" */
 	int			error;	/* error return value */
 	xfs_extnum_t		i=0, j;	/* index into the extents list */
-	struct xfs_ifork	*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
-	xfs_mount_t		*mp;	/* file system mount structure */
 	__be64			*pp;	/* pointer to block address */
 	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
 	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
 	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
 	int			bp_release = 0;
 
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
+	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
 		return;
-	}
 
 	/* skip large extent count inodes */
 	if (ip->i_df.if_nextents > 10000)
 		return;
 
 	bno = NULLFSBLOCK;
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
 	block = ifp->if_broot;
 	/*
 	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
@@ -606,7 +603,7 @@ xfs_bmap_btree_to_extents(
 	ASSERT(cur);
 	ASSERT(whichfork != XFS_COW_FORK);
 	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
 	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
 	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
 	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
@@ -634,7 +631,7 @@ xfs_bmap_btree_to_extents(
 	xfs_iroot_realloc(ip, -1, whichfork);
 	ASSERT(ifp->if_broot == NULL);
 	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
 	*logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
 	return 0;
 }
@@ -670,7 +667,7 @@ xfs_bmap_extents_to_btree(
 	mp = ip->i_mount;
 	ASSERT(whichfork != XFS_COW_FORK);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
 
 	/*
 	 * Make space in the inode incore. This needs to be undone if we fail
@@ -694,7 +691,7 @@ xfs_bmap_extents_to_btree(
 	/*
 	 * Convert to a btree with two levels, one record in root.
 	 */
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+	ifp->if_format = XFS_DINODE_FMT_BTREE;
 	memset(&args, 0, sizeof(args));
 	args.tp = tp;
 	args.mp = mp;
@@ -780,7 +777,7 @@ xfs_bmap_extents_to_btree(
 	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 out_root_realloc:
 	xfs_iroot_realloc(ip, -1, whichfork);
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
 	ASSERT(ifp->if_broot == NULL);
 	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 
@@ -802,7 +799,7 @@ xfs_bmap_local_to_extents_empty(
 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 
 	ASSERT(whichfork != XFS_COW_FORK);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 	ASSERT(ifp->if_bytes == 0);
 	ASSERT(ifp->if_nextents == 0);
 
@@ -811,7 +808,7 @@ xfs_bmap_local_to_extents_empty(
 	ifp->if_flags |= XFS_IFEXTENTS;
 	ifp->if_u1.if_root = NULL;
 	ifp->if_height = 0;
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
@@ -842,7 +839,7 @@ xfs_bmap_local_to_extents(
 	 */
 	ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 
 	if (!ifp->if_bytes) {
 		xfs_bmap_local_to_extents_empty(tp, ip, whichfork);
@@ -1036,7 +1033,7 @@ xfs_bmap_set_attrforkoff(
 	int			size,
 	int			*version)
 {
-	switch (ip->i_d.di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_DEV:
 		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
 		break;
@@ -1094,13 +1091,6 @@ xfs_bmap_add_attrfork(
 		goto trans_cancel;
 	if (XFS_IFORK_Q(ip))
 		goto trans_cancel;
-	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
-		/*
-		 * For inodes coming from pre-6.2 filesystems.
-		 */
-		ASSERT(ip->i_d.di_aformat == 0);
-		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
-	}
 
 	xfs_trans_ijoin(tp, ip, 0);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -1109,9 +1099,10 @@ xfs_bmap_add_attrfork(
 		goto trans_cancel;
 	ASSERT(ip->i_afp == NULL);
 	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, 0);
+	ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
 	ip->i_afp->if_flags = XFS_IFEXTENTS;
 	logflags = 0;
-	switch (ip->i_d.di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_LOCAL:
 		error = xfs_bmap_add_attrfork_local(tp, ip, &logflags);
 		break;
@@ -1237,9 +1228,7 @@ xfs_iread_extents(
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
-	if (XFS_IS_CORRUPT(mp,
-			   XFS_IFORK_FORMAT(ip, whichfork) !=
-			   XFS_DINODE_FMT_BTREE)) {
+	if (XFS_IS_CORRUPT(mp, ifp->if_format != XFS_DINODE_FMT_BTREE)) {
 		error = -EFSCORRUPTED;
 		goto out;
 	}
@@ -1287,14 +1276,13 @@ xfs_bmap_first_unused(
 	xfs_fileoff_t		lowest, max;
 	int			error;
 
-	ASSERT(xfs_ifork_has_extents(ip, whichfork) ||
-	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
-
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
 		*first_unused = 0;
 		return 0;
 	}
 
+	ASSERT(xfs_ifork_has_extents(ifp));
+
 	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
 		error = xfs_iread_extents(tp, ip, whichfork);
 		if (error)
@@ -1335,7 +1323,7 @@ xfs_bmap_last_before(
 	struct xfs_iext_cursor	icur;
 	int			error;
 
-	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+	switch (ifp->if_format) {
 	case XFS_DINODE_FMT_LOCAL:
 		*last_block = 0;
 		return 0;
@@ -1434,16 +1422,17 @@ xfs_bmap_last_offset(
 	xfs_fileoff_t		*last_block,
 	int			whichfork)
 {
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 	struct xfs_bmbt_irec	rec;
 	int			is_empty;
 	int			error;
 
 	*last_block = 0;
 
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
+	if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
 		return 0;
 
-	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ip, whichfork)))
+	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ifp)))
 		return -EFSCORRUPTED;
 
 	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
@@ -1475,7 +1464,7 @@ xfs_bmap_one_block(
 #endif	/* !DEBUG */
 	if (ifp->if_nextents != 1)
 		return 0;
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS)
 		return 0;
 	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 	xfs_iext_first(ifp, &icur);
@@ -3895,10 +3884,9 @@ xfs_bmapi_read(
 	if (WARN_ON_ONCE(!ifp))
 		return -EFSCORRUPTED;
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
-	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
 		return -EFSCORRUPTED;
-	}
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
@@ -4281,11 +4269,13 @@ xfs_bmapi_minleft(
 	struct xfs_inode	*ip,
 	int			fork)
 {
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, fork);
+
 	if (tp && tp->t_firstblock != NULLFSBLOCK)
 		return 0;
-	if (XFS_IFORK_FORMAT(ip, fork) != XFS_DINODE_FMT_BTREE)
+	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
 		return 1;
-	return be16_to_cpu(XFS_IFORK_PTR(ip, fork)->if_broot->bb_level) + 1;
+	return be16_to_cpu(ifp->if_broot->bb_level) + 1;
 }
 
 /*
@@ -4300,11 +4290,13 @@ xfs_bmapi_finish(
 	int			whichfork,
 	int			error)
 {
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+
 	if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
-	    XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
 		bma->logflags &= ~xfs_ilog_fext(whichfork);
 	else if ((bma->logflags & xfs_ilog_fbroot(whichfork)) &&
-		 XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_BTREE)
+		 ifp->if_format != XFS_DINODE_FMT_BTREE)
 		bma->logflags &= ~xfs_ilog_fbroot(whichfork);
 
 	if (bma->logflags)
@@ -4336,13 +4328,13 @@ xfs_bmapi_write(
 		.total		= total,
 	};
 	struct xfs_mount	*mp = ip->i_mount;
-	struct xfs_ifork	*ifp;
+	int			whichfork = xfs_bmapi_whichfork(flags);
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 	xfs_fileoff_t		end;		/* end of mapped file region */
 	bool			eof = false;	/* after the end of extents */
 	int			error;		/* error return */
 	int			n;		/* current extent index */
 	xfs_fileoff_t		obno;		/* old block number (offset) */
-	int			whichfork;	/* data or attr fork */
 
 #ifdef DEBUG
 	xfs_fileoff_t		orig_bno;	/* original block number value */
@@ -4357,13 +4349,12 @@ xfs_bmapi_write(
 	orig_mval = mval;
 	orig_nmap = *nmap;
 #endif
-	whichfork = xfs_bmapi_whichfork(flags);
 
 	ASSERT(*nmap >= 1);
 	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
 	ASSERT(tp != NULL);
 	ASSERT(len > 0);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
+	ASSERT(ifp->if_format != XFS_DINODE_FMT_LOCAL);
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 	ASSERT(!(flags & XFS_BMAPI_REMAP));
 
@@ -4379,7 +4370,7 @@ xfs_bmapi_write(
 	ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
 			(XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		return -EFSCORRUPTED;
 	}
@@ -4387,8 +4378,6 @@ xfs_bmapi_write(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-
 	XFS_STATS_INC(mp, xs_blk_mapw);
 
 	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
@@ -4498,7 +4487,7 @@ xfs_bmapi_write(
 	if (error)
 		goto error0;
 
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
+	ASSERT(ifp->if_format != XFS_DINODE_FMT_BTREE ||
 	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
 	xfs_bmapi_finish(&bma, whichfork, 0);
 	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
@@ -4645,7 +4634,7 @@ xfs_bmapi_remap(
 	ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) !=
 			(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC));
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		return -EFSCORRUPTED;
 	}
@@ -4689,9 +4678,9 @@ xfs_bmapi_remap(
 	error = xfs_bmap_btree_to_extents(tp, ip, cur, &logflags, whichfork);
 
 error0:
-	if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS)
+	if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS)
 		logflags &= ~XFS_ILOG_DEXT;
-	else if (ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
+	else if (ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
 		logflags &= ~XFS_ILOG_DBROOT;
 
 	if (logflags)
@@ -5041,7 +5030,7 @@ xfs_bmap_del_extent_real(
 	 * conversion to btree format, since the transaction will be dirty then.
 	 */
 	if (tp->t_blk_res == 0 &&
-	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
+	    ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
 	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
 	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
 		return -ENOSPC;
@@ -5284,7 +5273,7 @@ __xfs_bunmapi(
 	whichfork = xfs_bmapi_whichfork(flags);
 	ASSERT(whichfork != XFS_COW_FORK);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)))
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
 		return -EFSCORRUPTED;
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
@@ -5322,7 +5311,7 @@ __xfs_bunmapi(
 
 	logflags = 0;
 	if (ifp->if_flags & XFS_IFBROOT) {
-		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+		ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
 		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
 		cur->bc_ino.flags = 0;
 	} else
@@ -5567,10 +5556,10 @@ __xfs_bunmapi(
 	 * logging the extent records if we've converted to btree format.
 	 */
 	if ((logflags & xfs_ilog_fext(whichfork)) &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
 		logflags &= ~xfs_ilog_fext(whichfork);
 	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
-		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
+		 ifp->if_format != XFS_DINODE_FMT_BTREE)
 		logflags &= ~xfs_ilog_fbroot(whichfork);
 	/*
 	 * Log inode even in the error case, if the transaction
@@ -5781,7 +5770,7 @@ xfs_bmap_collapse_extents(
 	int			error = 0;
 	int			logflags = 0;
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		return -EFSCORRUPTED;
 	}
@@ -5898,7 +5887,7 @@ xfs_bmap_insert_extents(
 	int			error = 0;
 	int			logflags = 0;
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		return -EFSCORRUPTED;
 	}
@@ -5992,18 +5981,18 @@ xfs_bmap_split_extent(
 	xfs_fileoff_t		split_fsb)
 {
 	int				whichfork = XFS_DATA_FORK;
+	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
 	struct xfs_btree_cur		*cur = NULL;
 	struct xfs_bmbt_irec		got;
 	struct xfs_bmbt_irec		new; /* split extent */
 	struct xfs_mount		*mp = ip->i_mount;
-	struct xfs_ifork		*ifp;
 	xfs_fsblock_t			gotblkcnt; /* new block count for got */
 	struct xfs_iext_cursor		icur;
 	int				error = 0;
 	int				logflags = 0;
 	int				i = 0;
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		return -EFSCORRUPTED;
 	}
@@ -6011,7 +6000,6 @@ xfs_bmap_split_extent(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
-	ifp = XFS_IFORK_PTR(ip, whichfork);
 	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
 		/* Read in all the extents */
 		error = xfs_iread_extents(tp, ip, whichfork);
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 295a59cf88407..d9c63f17d2dec 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -636,10 +636,7 @@ xfs_bmbt_change_owner(
 
 	ASSERT(tp || buffer_list);
 	ASSERT(!(tp && buffer_list));
-	if (whichfork == XFS_DATA_FORK)
-		ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE);
-	else
-		ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE);
+	ASSERT(XFS_IFORK_PTR(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
 
 	cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
 	if (!cur)
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index dd6fcaaea318a..612a9c5e41b1c 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -278,7 +278,7 @@ xfs_dir_createname(
 	if (!inum)
 		args->op_flags |= XFS_DA_OP_JUSTCHECK;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 		rval = xfs_dir2_sf_addname(args);
 		goto out_free;
 	}
@@ -373,7 +373,7 @@ xfs_dir_lookup(
 		args->op_flags |= XFS_DA_OP_CILOOKUP;
 
 	lock_mode = xfs_ilock_data_map_shared(dp);
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 		rval = xfs_dir2_sf_lookup(args);
 		goto out_check_rval;
 	}
@@ -443,7 +443,7 @@ xfs_dir_removename(
 	args->whichfork = XFS_DATA_FORK;
 	args->trans = tp;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 		rval = xfs_dir2_sf_removename(args);
 		goto out_free;
 	}
@@ -504,7 +504,7 @@ xfs_dir_replace(
 	args->whichfork = XFS_DATA_FORK;
 	args->trans = tp;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 		rval = xfs_dir2_sf_replace(args);
 		goto out_free;
 	}
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index 7b7f6fb2ea3b2..2463b5d734472 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -343,7 +343,7 @@ xfs_dir2_block_to_sf(
 	 */
 	ASSERT(dp->i_df.if_bytes == 0);
 	xfs_init_local_fork(dp, XFS_DATA_FORK, sfp, size);
-	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+	dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
 	dp->i_d.di_size = size;
 
 	logflags |= XFS_ILOG_DDATA;
@@ -710,11 +710,11 @@ xfs_dir2_sf_verify(
 	struct xfs_inode		*ip)
 {
 	struct xfs_mount		*mp = ip->i_mount;
+	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 	struct xfs_dir2_sf_hdr		*sfp;
 	struct xfs_dir2_sf_entry	*sfep;
 	struct xfs_dir2_sf_entry	*next_sfep;
 	char				*endp;
-	struct xfs_ifork		*ifp;
 	xfs_ino_t			ino;
 	int				i;
 	int				i8count;
@@ -723,9 +723,8 @@ xfs_dir2_sf_verify(
 	int				error;
 	uint8_t				filetype;
 
-	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 
-	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 	sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
 	size = ifp->if_bytes;
 
@@ -827,9 +826,9 @@ xfs_dir2_sf_create(
 	 * If it's currently a zero-length extent file,
 	 * convert it to local format.
 	 */
-	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
+	if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS) {
 		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
-		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+		dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
 		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
 		dp->i_df.if_flags |= XFS_IFINLINE;
 	}
@@ -1027,7 +1026,7 @@ xfs_dir2_sf_replace_needblock(
 	int			newsize;
 	struct xfs_dir2_sf_hdr	*sfp;
 
-	if (dp->i_d.di_format != XFS_DINODE_FMT_LOCAL)
+	if (dp->i_df.if_format != XFS_DINODE_FMT_LOCAL)
 		return false;
 
 	sfp = (struct xfs_dir2_sf_hdr *)dp->i_df.if_u1.if_data;
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index a374e2a81e764..ab555671e1543 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -225,7 +225,6 @@ xfs_inode_from_disk(
 					be16_to_cpu(from->di_projid_lo);
 	}
 
-	to->di_format = from->di_format;
 	i_uid_write(inode, be32_to_cpu(from->di_uid));
 	i_gid_write(inode, be32_to_cpu(from->di_gid));
 
@@ -246,7 +245,6 @@ xfs_inode_from_disk(
 	to->di_nblocks = be64_to_cpu(from->di_nblocks);
 	to->di_extsize = be32_to_cpu(from->di_extsize);
 	to->di_forkoff = from->di_forkoff;
-	to->di_aformat	= from->di_aformat;
 	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
 	to->di_dmstate	= be16_to_cpu(from->di_dmstate);
 	to->di_flags	= be16_to_cpu(from->di_flags);
@@ -289,7 +287,7 @@ xfs_inode_to_disk(
 	to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
 	to->di_onlink = 0;
 
-	to->di_format = from->di_format;
+	to->di_format = xfs_ifork_format(&ip->i_df);
 	to->di_uid = cpu_to_be32(i_uid_read(inode));
 	to->di_gid = cpu_to_be32(i_gid_read(inode));
 	to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
@@ -312,7 +310,7 @@ xfs_inode_to_disk(
 	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
 	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
 	to->di_forkoff = from->di_forkoff;
-	to->di_aformat = from->di_aformat;
+	to->di_aformat = xfs_ifork_format(ip->i_afp);
 	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
 	to->di_dmstate = cpu_to_be16(from->di_dmstate);
 	to->di_flags = cpu_to_be16(from->di_flags);
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index fecccfb26463c..865ac493c72a2 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -16,14 +16,12 @@ struct xfs_dinode;
  * format specific structures at the appropriate time.
  */
 struct xfs_icdinode {
-	int8_t		di_format;	/* format of di_c data */
 	uint16_t	di_flushiter;	/* incremented on flush */
 	uint32_t	di_projid;	/* owner's project id */
 	xfs_fsize_t	di_size;	/* number of bytes in file */
 	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
 	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
 	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
-	int8_t		di_aformat;	/* format of attr fork's data */
 	uint32_t	di_dmevmask;	/* DMIG event mask */
 	uint16_t	di_dmstate;	/* DMIG state info */
 	uint16_t	di_flags;	/* random flags, XFS_DIFLAG_... */
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 195da3552c5b5..6562f2bcd15cc 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -228,6 +228,7 @@ xfs_iformat_data_fork(
 	struct inode		*inode = VFS_I(ip);
 	int			error;
 
+	ip->i_df.if_format = dip->di_format;
 	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
 
 	switch (inode->i_mode & S_IFMT) {
@@ -241,7 +242,7 @@ xfs_iformat_data_fork(
 	case S_IFREG:
 	case S_IFLNK:
 	case S_IFDIR:
-		switch (dip->di_format) {
+		switch (ip->i_df.if_format) {
 		case XFS_DINODE_FMT_LOCAL:
 			error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
 					be64_to_cpu(dip->di_size));
@@ -283,9 +284,12 @@ xfs_iformat_attr_fork(
 	int			error = 0;
 
 	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
+	ip->i_afp->if_format = dip->di_aformat;
+	if (unlikely(ip->i_afp->if_format == 0)) /* pre IRIX 6.2 file system */
+		ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
 	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
 
-	switch (dip->di_aformat) {
+	switch (ip->i_afp->if_format) {
 	case XFS_DINODE_FMT_LOCAL:
 		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
 				xfs_dfork_attr_shortform_size(dip));
@@ -508,7 +512,7 @@ xfs_idestroy_fork(
 	 * not local then we may or may not have an extents list,
 	 * so check and free it up if we do.
 	 */
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
 		if (ifp->if_u1.if_data != NULL) {
 			kmem_free(ifp->if_u1.if_data);
 			ifp->if_u1.if_data = NULL;
@@ -605,7 +609,7 @@ xfs_iflush_fork(
 	}
 	cp = XFS_DFORK_PTR(dip, whichfork);
 	mp = ip->i_mount;
-	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+	switch (ifp->if_format) {
 	case XFS_DINODE_FMT_LOCAL:
 		if ((iip->ili_fields & dataflag[whichfork]) &&
 		    (ifp->if_bytes > 0)) {
@@ -678,7 +682,7 @@ xfs_ifork_init_cow(
 	ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
 				       KM_NOFS);
 	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
-	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
+	ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
 }
 
 /* Verify the inline contents of the data fork of an inode. */
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index a69d425fe68df..d849cca103edd 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -23,6 +23,7 @@ struct xfs_ifork {
 	} if_u1;
 	short			if_broot_bytes;	/* bytes allocated for root */
 	unsigned char		if_flags;	/* per-fork flags */
+	int8_t			if_format;	/* format of this fork */
 	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
 };
 
@@ -56,24 +57,14 @@ struct xfs_ifork {
 		((w) == XFS_ATTR_FORK ? \
 			XFS_IFORK_ASIZE(ip) : \
 			0))
-#define XFS_IFORK_FORMAT(ip,w) \
-	((w) == XFS_DATA_FORK ? \
-		(ip)->i_d.di_format : \
-		((w) == XFS_ATTR_FORK ? \
-			(ip)->i_d.di_aformat : \
-			(ip)->i_cformat))
-#define XFS_IFORK_FMT_SET(ip,w,n) \
-	((w) == XFS_DATA_FORK ? \
-		((ip)->i_d.di_format = (n)) : \
-		((w) == XFS_ATTR_FORK ? \
-			((ip)->i_d.di_aformat = (n)) : \
-			((ip)->i_cformat = (n))))
 #define XFS_IFORK_MAXEXT(ip, w) \
 	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
 
-#define xfs_ifork_has_extents(ip, w) \
-	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
-	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
+static inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp)
+{
+	return ifp->if_format == XFS_DINODE_FMT_EXTENTS ||
+		ifp->if_format == XFS_DINODE_FMT_BTREE;
+}
 
 static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
 {
@@ -82,6 +73,13 @@ static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
 	return ifp->if_nextents;
 }
 
+static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
+{
+	if (!ifp)
+		return XFS_DINODE_FMT_EXTENTS;
+	return ifp->if_format;
+}
+
 struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
 
 int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index 3b8260ca7d1b8..594bc447a7dd2 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -204,16 +204,12 @@ xfs_failaddr_t
 xfs_symlink_shortform_verify(
 	struct xfs_inode	*ip)
 {
-	char			*sfp;
-	char			*endp;
-	struct xfs_ifork	*ifp;
-	int			size;
-
-	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
-	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
-	sfp = (char *)ifp->if_u1.if_data;
-	size = ifp->if_bytes;
-	endp = sfp + size;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	char			*sfp = (char *)ifp->if_u1.if_data;
+	int			size = ifp->if_bytes;
+	char			*endp = sfp + size;
+
+	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 
 	/*
 	 * Zero length symlinks should never occur in memory as they are
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 157f72efec5e9..dfa1533b4edfc 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
 		size = 0;
 		break;
 	}
-	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
 	    (size == 0 || ifp->if_nextents > 0))
 		return 0;
 
@@ -664,7 +664,7 @@ xchk_bmap(
 	}
 
 	/* Check the fork values */
-	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+	switch (ifp->if_format) {
 	case XFS_DINODE_FMT_UUID:
 	case XFS_DINODE_FMT_DEV:
 	case XFS_DINODE_FMT_LOCAL:
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index 9a2e27ac13003..44b15015021f3 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -468,7 +468,7 @@ xchk_da_btree(
 	int				error;
 
 	/* Skip short format data structures; no btree to scan. */
-	if (!xfs_ifork_has_extents(sc->ip, whichfork))
+	if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
 		return 0;
 
 	/* Set up initial da state. */
diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
index fe2a6e030c8a0..7c432997edade 100644
--- a/fs/xfs/scrub/dir.c
+++ b/fs/xfs/scrub/dir.c
@@ -635,7 +635,7 @@ xchk_directory_blocks(
 {
 	struct xfs_bmbt_irec	got;
 	struct xfs_da_args	args;
-	struct xfs_ifork	*ifp;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
 	struct xfs_mount	*mp = sc->mp;
 	xfs_fileoff_t		leaf_lblk;
 	xfs_fileoff_t		free_lblk;
@@ -647,11 +647,10 @@ xchk_directory_blocks(
 	int			error;
 
 	/* Ignore local format directories. */
-	if (sc->ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
-	    sc->ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
+	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
+	    ifp->if_format != XFS_DINODE_FMT_BTREE)
 		return 0;
 
-	ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
 	lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
 	leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
 	free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 9d9cebf187268..2834cbf1212e5 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -382,7 +382,7 @@ xfs_map_blocks(
 	 */
 retry:
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
-	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
 	       (ip->i_df.if_flags & XFS_IFEXTENTS));
 
 	/*
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index c42f90e16b4fa..00ffc46c0bf71 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -367,7 +367,7 @@ xfs_attr_inactive(
 	 * removal below.
 	 */
 	if (xfs_inode_hasattr(dp) &&
-	    dp->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
+	    dp->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_attr3_root_inactive(&trans, dp);
 		if (error)
 			goto out_cancel;
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 5ff1d929d3b5f..e380bd1a9bfc9 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -512,9 +512,9 @@ xfs_attr_list_ilocked(
 	 */
 	if (!xfs_inode_hasattr(dp))
 		return 0;
-	else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
+	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
 		return xfs_attr_shortform_list(context);
-	else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
+	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
 		return xfs_attr_leaf_list(context);
 	return xfs_attr_node_list(context);
 }
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 4f277a6253b8d..5e32c3cf8e8c1 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -223,7 +223,7 @@ xfs_bmap_count_blocks(
 	if (!ifp)
 		return 0;
 
-	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+	switch (ifp->if_format) {
 	case XFS_DINODE_FMT_BTREE:
 		if (!(ifp->if_flags & XFS_IFEXTENTS)) {
 			error = xfs_iread_extents(tp, ip, whichfork);
@@ -449,7 +449,7 @@ xfs_getbmap(
 		break;
 	}
 
-	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+	switch (ifp->if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 	case XFS_DINODE_FMT_BTREE:
 		break;
@@ -1210,17 +1210,19 @@ xfs_swap_extents_check_format(
 	struct xfs_inode	*ip,	/* target inode */
 	struct xfs_inode	*tip)	/* tmp inode */
 {
+	struct xfs_ifork	*ifp = &ip->i_df;
+	struct xfs_ifork	*tifp = &tip->i_df;
 
 	/* Should never get a local format */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
-	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL)
+	if (ifp->if_format == XFS_DINODE_FMT_LOCAL ||
+	    tifp->if_format == XFS_DINODE_FMT_LOCAL)
 		return -EINVAL;
 
 	/*
 	 * if the target inode has less extents that then temporary inode then
 	 * why did userspace call us?
 	 */
-	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
+	if (ifp->if_nextents < tifp->if_nextents)
 		return -EINVAL;
 
 	/*
@@ -1235,18 +1237,18 @@ xfs_swap_extents_check_format(
 	 * form then we will end up with the target inode in the wrong format
 	 * as we already know there are less extents in the temp inode.
 	 */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-	    tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
+	    tifp->if_format == XFS_DINODE_FMT_BTREE)
 		return -EINVAL;
 
 	/* Check temp in extent form to max in target */
-	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
+	if (tifp->if_format == XFS_DINODE_FMT_EXTENTS &&
+	    tifp->if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
 		return -EINVAL;
 
 	/* Check target in extent form to max in temp */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
+	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
+	    ifp->if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
 		return -EINVAL;
 
 	/*
@@ -1258,22 +1260,20 @@ xfs_swap_extents_check_format(
 	 * (a common defrag case) which will occur when the temp inode is in
 	 * extent format...
 	 */
-	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
+	if (tifp->if_format == XFS_DINODE_FMT_BTREE) {
 		if (XFS_IFORK_Q(ip) &&
-		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
+		    XFS_BMAP_BMDR_SPACE(tifp->if_broot) > XFS_IFORK_BOFF(ip))
 			return -EINVAL;
-		if (tip->i_df.if_nextents <=
-		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
+		if (tifp->if_nextents <= XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
 			return -EINVAL;
 	}
 
 	/* Reciprocal target->temp btree format checks */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
+	if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
 		if (XFS_IFORK_Q(tip) &&
 		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
 			return -EINVAL;
-		if (ip->i_df.if_nextents <=
-		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
+		if (ifp->if_nextents <= XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
 			return -EINVAL;
 	}
 
@@ -1426,14 +1426,14 @@ xfs_swap_extent_forks(
 	 * Count the number of extended attribute blocks
 	 */
 	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
-	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
+	    ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
 				&aforkblks);
 		if (error)
 			return error;
 	}
 	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
-	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
+	    tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
 		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
 				&taforkblks);
 		if (error)
@@ -1448,9 +1448,9 @@ xfs_swap_extent_forks(
 	 * bmbt scan as the last step.
 	 */
 	if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
-		if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+		if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
 			(*target_log_flags) |= XFS_ILOG_DOWNER;
-		if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+		if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
 			(*src_log_flags) |= XFS_ILOG_DOWNER;
 	}
 
@@ -1466,8 +1466,6 @@ xfs_swap_extent_forks(
 	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
 	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
 
-	swap(ip->i_d.di_format, tip->i_d.di_format);
-
 	/*
 	 * The extents in the source inode could still contain speculative
 	 * preallocation beyond EOF (e.g. the file is open but not modified
@@ -1481,7 +1479,7 @@ xfs_swap_extent_forks(
 	tip->i_delayed_blks = ip->i_delayed_blks;
 	ip->i_delayed_blks = 0;
 
-	switch (ip->i_d.di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		(*src_log_flags) |= XFS_ILOG_DEXT;
 		break;
@@ -1492,7 +1490,7 @@ xfs_swap_extent_forks(
 		break;
 	}
 
-	switch (tip->i_d.di_format) {
+	switch (tip->i_df.if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		(*target_log_flags) |= XFS_ILOG_DEXT;
 		break;
@@ -1714,8 +1712,10 @@ xfs_swap_extents(
 
 	/* Swap the cow forks. */
 	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
-		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
-		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
+		ASSERT(!ip->i_cowfp ||
+		       ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
+		ASSERT(!tip->i_cowfp ||
+		       tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
 
 		swap(ip->i_cowfp, tip->i_cowfp);
 
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index 871ec22c9aee9..66deddd5e2969 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -524,7 +524,7 @@ xfs_readdir(
 	args.geo = dp->i_mount->m_dir_geo;
 	args.trans = tp;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
+	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_getdents(&args, ctx);
 	else if ((rval = xfs_dir2_isblock(&args, &v)))
 		;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 791d5d5e318cf..c09b3e9eab1da 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -63,7 +63,6 @@ xfs_inode_alloc(
 	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
 	ip->i_afp = NULL;
 	ip->i_cowfp = NULL;
-	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
 	memset(&ip->i_df, 0, sizeof(ip->i_df));
 	ip->i_flags = 0;
 	ip->i_delayed_blks = 0;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 1677c4e7207ed..64f5f9a440aed 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -112,7 +112,7 @@ xfs_ilock_data_map_shared(
 {
 	uint			lock_mode = XFS_ILOCK_SHARED;
 
-	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
+	if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE &&
 	    (ip->i_df.if_flags & XFS_IFEXTENTS) == 0)
 		lock_mode = XFS_ILOCK_EXCL;
 	xfs_ilock(ip, lock_mode);
@@ -125,7 +125,8 @@ xfs_ilock_attr_map_shared(
 {
 	uint			lock_mode = XFS_ILOCK_SHARED;
 
-	if (ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE &&
+	if (ip->i_afp &&
+	    ip->i_afp->if_format == XFS_DINODE_FMT_BTREE &&
 	    (ip->i_afp->if_flags & XFS_IFEXTENTS) == 0)
 		lock_mode = XFS_ILOCK_EXCL;
 	xfs_ilock(ip, lock_mode);
@@ -851,7 +852,7 @@ xfs_ialloc(
 	case S_IFCHR:
 	case S_IFBLK:
 	case S_IFSOCK:
-		ip->i_d.di_format = XFS_DINODE_FMT_DEV;
+		ip->i_df.if_format = XFS_DINODE_FMT_DEV;
 		ip->i_df.if_flags = 0;
 		flags |= XFS_ILOG_DEV;
 		break;
@@ -907,7 +908,7 @@ xfs_ialloc(
 		}
 		/* FALLTHROUGH */
 	case S_IFLNK:
-		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
+		ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
 		ip->i_df.if_flags = XFS_IFEXTENTS;
 		ip->i_df.if_bytes = 0;
 		ip->i_df.if_u1.if_root = NULL;
@@ -915,10 +916,6 @@ xfs_ialloc(
 	default:
 		ASSERT(0);
 	}
-	/*
-	 * Attribute fork settings for new inode.
-	 */
-	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
 
 	/*
 	 * Log the new values stuffed into the inode.
@@ -2749,7 +2746,7 @@ xfs_ifree(
 	 * data fork to extents format.  Note that the attr fork data has
 	 * already been freed by xfs_attr_inactive.
 	 */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 		kmem_free(ip->i_df.if_u1.if_data);
 		ip->i_df.if_u1.if_data = NULL;
 		ip->i_df.if_bytes = 0;
@@ -2760,8 +2757,7 @@ xfs_ifree(
 	ip->i_d.di_flags2 = 0;
 	ip->i_d.di_dmevmask = 0;
 	ip->i_d.di_forkoff = 0;		/* mark the attr fork not in use */
-	ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
-	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
+	ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
 
 	/* Don't attempt to replay owner changes for a deleted inode */
 	ip->i_itemp->ili_fields &= ~(XFS_ILOG_AOWNER|XFS_ILOG_DOWNER);
@@ -3624,7 +3620,7 @@ xfs_iflush(
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
 	ASSERT(xfs_isiflocked(ip));
-	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
 	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 
 	*bpp = NULL;
@@ -3706,7 +3702,7 @@ xfs_iflush_int(
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
 	ASSERT(xfs_isiflocked(ip));
-	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
 	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 	ASSERT(iip != NULL && iip->ili_fields != 0);
 
@@ -3728,8 +3724,8 @@ xfs_iflush_int(
 	}
 	if (S_ISREG(VFS_I(ip)->i_mode)) {
 		if (XFS_TEST_ERROR(
-		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
-		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
+		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
+		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE,
 		    mp, XFS_ERRTAG_IFLUSH_3)) {
 			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
 				"%s: Bad regular inode %Lu, ptr "PTR_FMT,
@@ -3738,9 +3734,9 @@ xfs_iflush_int(
 		}
 	} else if (S_ISDIR(VFS_I(ip)->i_mode)) {
 		if (XFS_TEST_ERROR(
-		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
-		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
-		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
+		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
+		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE &&
+		    ip->i_df.if_format != XFS_DINODE_FMT_LOCAL,
 		    mp, XFS_ERRTAG_IFLUSH_4)) {
 			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
 				"%s: Bad directory inode %Lu, ptr "PTR_FMT,
@@ -3782,10 +3778,10 @@ xfs_iflush_int(
 	 * If there are inline format data / attr forks attached to this inode,
 	 * make sure they are not corrupt.
 	 */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
+	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL &&
 	    xfs_ifork_verify_local_data(ip))
 		goto flush_out;
-	if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
+	if (ip->i_afp && ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL &&
 	    xfs_ifork_verify_local_attr(ip))
 		goto flush_out;
 
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 24dae63ba16c0..dadcf19458960 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -57,8 +57,6 @@ typedef struct xfs_inode {
 
 	struct xfs_icdinode	i_d;		/* most of ondisk inode */
 
-	unsigned int		i_cformat;	/* format of cow fork */
-
 	/* VFS inode */
 	struct inode		i_vnode;	/* embedded VFS inode */
 
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 401ba26aeed7b..ba47bf65b772b 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -36,7 +36,7 @@ xfs_inode_item_data_fork_size(
 {
 	struct xfs_inode	*ip = iip->ili_inode;
 
-	switch (ip->i_d.di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
 		    ip->i_df.if_nextents > 0 &&
@@ -77,7 +77,7 @@ xfs_inode_item_attr_fork_size(
 {
 	struct xfs_inode	*ip = iip->ili_inode;
 
-	switch (ip->i_d.di_aformat) {
+	switch (ip->i_afp->if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
 		    ip->i_afp->if_nextents > 0 &&
@@ -142,7 +142,7 @@ xfs_inode_item_format_data_fork(
 	struct xfs_inode	*ip = iip->ili_inode;
 	size_t			data_bytes;
 
-	switch (ip->i_d.di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		iip->ili_fields &=
 			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
@@ -227,7 +227,7 @@ xfs_inode_item_format_attr_fork(
 	struct xfs_inode	*ip = iip->ili_inode;
 	size_t			data_bytes;
 
-	switch (ip->i_d.di_aformat) {
+	switch (ip->i_afp->if_format) {
 	case XFS_DINODE_FMT_EXTENTS:
 		iip->ili_fields &=
 			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
@@ -305,7 +305,7 @@ xfs_inode_to_log_dinode(
 	struct inode		*inode = VFS_I(ip);
 
 	to->di_magic = XFS_DINODE_MAGIC;
-	to->di_format = from->di_format;
+	to->di_format = xfs_ifork_format(&ip->i_df);
 	to->di_uid = i_uid_read(inode);
 	to->di_gid = i_gid_read(inode);
 	to->di_projid_lo = from->di_projid & 0xffff;
@@ -329,7 +329,7 @@ xfs_inode_to_log_dinode(
 	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
 	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
 	to->di_forkoff = from->di_forkoff;
-	to->di_aformat = from->di_aformat;
+	to->di_aformat = xfs_ifork_format(ip->i_afp);
 	to->di_dmevmask = from->di_dmevmask;
 	to->di_dmstate = from->di_dmstate;
 	to->di_flags = from->di_flags;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index b4fd918749e5f..6ae3a2457777a 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -856,7 +856,7 @@ xfs_buffered_write_iomap_begin(
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 
-	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, XFS_DATA_FORK)) ||
+	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(&ip->i_df)) ||
 	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
 		error = -EFSCORRUPTED;
 		goto out_unlock;
@@ -1263,7 +1263,7 @@ xfs_xattr_iomap_begin(
 		goto out_unlock;
 	}
 
-	ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
+	ASSERT(ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL);
 	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
 			       &nimaps, XFS_BMAPI_ATTRFORK);
 out_unlock:
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 80da86c5703fb..16ca97a7ff00f 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -115,7 +115,7 @@ xfs_bulkstat_one_int(
 			buf->bs_cowextsize_blks = dic->di_cowextsize;
 	}
 
-	switch (dic->di_format) {
+	switch (ip->i_df.if_format) {
 	case XFS_DINODE_FMT_DEV:
 		buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
 		buf->bs_blksize = BLKDEV_IOSIZE;
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 8cf2fcb509c12..8e88a7ca387ea 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -251,7 +251,7 @@ xfs_symlink(
 		xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
 
 		ip->i_d.di_size = pathlen;
-		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+		ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
 	} else {
 		int	offset;
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index ba2ab69e1fc7d..460136628a795 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1897,7 +1897,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
 		__entry->dev = VFS_I(ip)->i_sb->s_dev;
 		__entry->which = which;
 		__entry->ino = ip->i_ino;
-		__entry->format = ip->i_d.di_format;
+		__entry->format = ip->i_df.if_format;
 		__entry->nex = ip->i_df.if_nextents;
 		__entry->broot_size = ip->i_df.if_broot_bytes;
 		__entry->fork_off = XFS_IFORK_BOFF(ip);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
                   ` (4 preceding siblings ...)
  2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
@ 2020-05-10  7:24 ` Christoph Hellwig
  2020-05-12  9:48   ` Chandan Babu R
  2020-05-12 18:54   ` Brian Foster
  5 siblings, 2 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-10  7:24 UTC (permalink / raw)
  To: linux-xfs

Move freeing the dynamically allocated attr and COW fork, as well
as zeroing the pointers where actually needed into the callers, and
just pass the xfs_ifork structure to xfs_idestroy_fork.  Simplify
the kmem_free calls by not checking for NULL first, and not zeroing
the pointers in structure that are about to be freed (either the
ifork or the containing inode in case of the data fork).

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
 fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
 fs/xfs/libxfs/xfs_inode_fork.c | 36 +++++++++-------------------------
 fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
 fs/xfs/xfs_attr_inactive.c     |  7 +++++--
 fs/xfs/xfs_icache.c            | 15 ++++++++------
 6 files changed, 28 insertions(+), 41 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index d7f3173ce3c31..8d775942f1c6c 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -716,11 +716,10 @@ xfs_attr_fork_remove(
 	struct xfs_inode	*ip,
 	struct xfs_trans	*tp)
 {
-	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+	xfs_idestroy_fork(ip->i_afp);
+	kmem_cache_free(xfs_ifork_zone, ip->i_afp);
+	ip->i_afp = NULL;
 	ip->i_d.di_forkoff = 0;
-
-	ASSERT(ip->i_afp == NULL);
-
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index ab555671e1543..6f84ea85fdd83 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -271,7 +271,7 @@ xfs_inode_from_disk(
 	return 0;
 
 out_destroy_data_fork:
-	xfs_idestroy_fork(ip, XFS_DATA_FORK);
+	xfs_idestroy_fork(&ip->i_df);
 	return error;
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 6562f2bcd15cc..577cc20e03170 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -495,38 +495,20 @@ xfs_idata_realloc(
 
 void
 xfs_idestroy_fork(
-	xfs_inode_t	*ip,
-	int		whichfork)
+	struct xfs_ifork	*ifp)
 {
-	struct xfs_ifork	*ifp;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (ifp->if_broot != NULL) {
-		kmem_free(ifp->if_broot);
-		ifp->if_broot = NULL;
-	}
+	kmem_free(ifp->if_broot);
 
 	/*
-	 * If the format is local, then we can't have an extents
-	 * array so just look for an inline data array.  If we're
-	 * not local then we may or may not have an extents list,
-	 * so check and free it up if we do.
+	 * If the format is local, then we can't have an extents array so just
+	 * look for an inline data array.  If we're not local then we may or may
+	 * not have an extents list, so check and free it up if we do.
 	 */
 	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
-		if (ifp->if_u1.if_data != NULL) {
-			kmem_free(ifp->if_u1.if_data);
-			ifp->if_u1.if_data = NULL;
-		}
-	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
-		xfs_iext_destroy(ifp);
-	}
-
-	if (whichfork == XFS_ATTR_FORK) {
-		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
-		ip->i_afp = NULL;
-	} else if (whichfork == XFS_COW_FORK) {
-		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
-		ip->i_cowfp = NULL;
+		kmem_free(ifp->if_u1.if_data);
+	} else if (ifp->if_flags & XFS_IFEXTENTS) {
+		if (ifp->if_height)
+			xfs_iext_destroy(ifp);
 	}
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index d849cca103edd..a4953e95c4f3f 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
 int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
 void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
 				struct xfs_inode_log_item *, int);
-void		xfs_idestroy_fork(struct xfs_inode *, int);
+void		xfs_idestroy_fork(struct xfs_ifork *ifp);
 void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
 				int whichfork);
 void		xfs_iroot_realloc(struct xfs_inode *, int, int);
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index 00ffc46c0bf71..bfad669e6b2f8 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -388,8 +388,11 @@ xfs_attr_inactive(
 	xfs_trans_cancel(trans);
 out_destroy_fork:
 	/* kill the in-core attr fork before we drop the inode lock */
-	if (dp->i_afp)
-		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
+	if (dp->i_afp) {
+		xfs_idestroy_fork(dp->i_afp);
+		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
+		dp->i_afp = NULL;
+	}
 	if (lock_mode)
 		xfs_iunlock(dp, lock_mode);
 	return error;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index c09b3e9eab1da..d806d3bfa8936 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -87,15 +87,18 @@ xfs_inode_free_callback(
 	case S_IFREG:
 	case S_IFDIR:
 	case S_IFLNK:
-		xfs_idestroy_fork(ip, XFS_DATA_FORK);
+		xfs_idestroy_fork(&ip->i_df);
 		break;
 	}
 
-	if (ip->i_afp)
-		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-	if (ip->i_cowfp)
-		xfs_idestroy_fork(ip, XFS_COW_FORK);
-
+	if (ip->i_afp) {
+		xfs_idestroy_fork(ip->i_afp);
+		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
+	}
+	if (ip->i_cowfp) {
+		xfs_idestroy_fork(ip->i_cowfp);
+		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
+	}
 	if (ip->i_itemp) {
 		ASSERT(!test_bit(XFS_LI_IN_AIL,
 				 &ip->i_itemp->ili_item.li_flags));
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
@ 2020-05-11 11:40   ` Chandan Babu R
  2020-05-12 15:31     ` Brian Foster
  2020-05-16 18:42   ` [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q Darrick J. Wong
  1 sibling, 1 reply; 41+ messages in thread
From: Chandan Babu R @ 2020-05-11 11:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> doesn't make a difference in practice as size is only checked for
> 0, but this keeps the logic sane.
>

Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
attr fork inside an inode's literal area?

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/scrub/bmap.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index add8598eacd5d..283424d6d2bb6 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
>  		size = i_size_read(VFS_I(sc->ip));
>  		break;
>  	case XFS_ATTR_FORK:
> -		size = XFS_IFORK_Q(sc->ip);
> +		size = XFS_IFORK_BOFF(sc->ip);
>  		break;
>  	default:
>  		size = 0;
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro
  2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
@ 2020-05-11 12:39   ` Chandan Babu R
  2020-05-12 15:31   ` Brian Foster
  2020-05-16 18:02   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Chandan Babu R @ 2020-05-11 12:39 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:54:00 PM IST Christoph Hellwig wrote:
> Just checking di_forkoff directly is a little easier to follow.
>

Looks good to me.

Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_format.h    | 5 ++---
>  fs/xfs/libxfs/xfs_inode_buf.c | 6 +++---
>  2 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 045556e78ee2c..3cc352000b8a1 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -964,13 +964,12 @@ enum xfs_dinode_fmt {
>  /*
>   * Inode data & attribute fork sizes, per inode.
>   */
> -#define XFS_DFORK_Q(dip)		((dip)->di_forkoff != 0)
>  #define XFS_DFORK_BOFF(dip)		((int)((dip)->di_forkoff << 3))
>  
>  #define XFS_DFORK_DSIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
> +	((dip)->di_forkoff ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
>  #define XFS_DFORK_ASIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
> +	((dip)->di_forkoff ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
>  #define XFS_DFORK_SIZE(dip,mp,w) \
>  	((w) == XFS_DATA_FORK ? \
>  		XFS_DFORK_DSIZE(dip, mp) : \
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index 05f939adea944..5547bbb3cf945 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -265,7 +265,7 @@ xfs_inode_from_disk(
>  	error = xfs_iformat_data_fork(ip, from);
>  	if (error)
>  		return error;
> -	if (XFS_DFORK_Q(from)) {
> +	if (from->di_forkoff) {
>  		error = xfs_iformat_attr_fork(ip, from);
>  		if (error)
>  			goto out_destroy_data_fork;
> @@ -435,7 +435,7 @@ xfs_dinode_verify_forkoff(
>  	struct xfs_dinode	*dip,
>  	struct xfs_mount	*mp)
>  {
> -	if (!XFS_DFORK_Q(dip))
> +	if (!dip->di_forkoff)
>  		return NULL;
>  
>  	switch (dip->di_format)  {
> @@ -538,7 +538,7 @@ xfs_dinode_verify(
>  		return __this_address;
>  	}
>  
> -	if (XFS_DFORK_Q(dip)) {
> +	if (dip->di_forkoff) {
>  		fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
>  		if (fa)
>  			return fa;
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 3/6] xfs: remove xfs_ifree_local_data
  2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
@ 2020-05-11 16:32   ` Chandan Babu R
  2020-05-12 15:31   ` Brian Foster
  2020-05-16 18:07   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Chandan Babu R @ 2020-05-11 16:32 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:54:01 PM IST Christoph Hellwig wrote:
> xfs_ifree only need to free inline data in the data fork, as we've
> already taken care of the attr fork before (and in fact freed the
> fork structure).  Just open code the freeing of the inline data.
>

xfs_inactive() => xfs_attr_inactive() would have freed the attr fork. Hence
the changes made in this patch are correct.

Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/xfs_inode.c | 30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 549ff468b7b60..7d3144dc99b72 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2711,24 +2711,6 @@ xfs_ifree_cluster(
>  	return 0;
>  }
>  
> -/*
> - * Free any local-format buffers sitting around before we reset to
> - * extents format.
> - */
> -static inline void
> -xfs_ifree_local_data(
> -	struct xfs_inode	*ip,
> -	int			whichfork)
> -{
> -	struct xfs_ifork	*ifp;
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
> -		return;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
> -}
> -
>  /*
>   * This is called to return an inode to the inode free list.
>   * The inode should already be truncated to 0 length and have
> @@ -2765,8 +2747,16 @@ xfs_ifree(
>  	if (error)
>  		return error;
>  
> -	xfs_ifree_local_data(ip, XFS_DATA_FORK);
> -	xfs_ifree_local_data(ip, XFS_ATTR_FORK);
> +	/*
> +	 * Free any local-format data sitting around before we reset the
> +	 * data fork to extents format.  Note that the attr fork data has
> +	 * already been freed by xfs_attr_inactive.
> +	 */
> +	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +		kmem_free(ip->i_df.if_u1.if_data);
> +		ip->i_df.if_u1.if_data = NULL;
> +		ip->i_df.if_bytes = 0;
> +	}
>  
>  	VFS_I(ip)->i_mode = 0;		/* mark incore inode as free */
>  	ip->i_d.di_flags = 0;
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork
  2020-05-10  7:24 ` [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork Christoph Hellwig
@ 2020-05-12  5:26   ` Chandan Babu R
  2020-05-12 16:10   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Chandan Babu R @ 2020-05-12  5:26 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:54:02 PM IST Christoph Hellwig wrote:
> There are thee number of extents counters, one for each of the forks,

... three number of ....

The patch itself looks good to me.

Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>

> Two are in the legacy icdinode and one is directly in struct xfs_inode.
> Switch to a single counter in the xfs_ifork structure where it uses up
> padding at the end of the structure.  This simplifies various bits of
> code that just wants the number of extents counter and can now directly
> dereference it.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr.c       |   4 +-
>  fs/xfs/libxfs/xfs_attr_leaf.c  |   1 -
>  fs/xfs/libxfs/xfs_bmap.c       | 126 ++++++++++++++-------------------
>  fs/xfs/libxfs/xfs_dir2_block.c |   2 +-
>  fs/xfs/libxfs/xfs_inode_buf.c  |   6 +-
>  fs/xfs/libxfs/xfs_inode_buf.h  |   2 -
>  fs/xfs/libxfs/xfs_inode_fork.c |  12 ++--
>  fs/xfs/libxfs/xfs_inode_fork.h |  20 +++---
>  fs/xfs/scrub/bmap.c            |   3 +-
>  fs/xfs/scrub/parent.c          |   2 +-
>  fs/xfs/xfs_bmap_util.c         |  28 ++++----
>  fs/xfs/xfs_file.c              |   2 +-
>  fs/xfs/xfs_icache.c            |   1 -
>  fs/xfs/xfs_inode.c             |  19 +++--
>  fs/xfs/xfs_inode.h             |   1 -
>  fs/xfs/xfs_inode_item.c        |  14 ++--
>  fs/xfs/xfs_ioctl.c             |  25 +++----
>  fs/xfs/xfs_iomap.c             |   2 +-
>  fs/xfs/xfs_iops.c              |   2 +-
>  fs/xfs/xfs_itable.c            |   4 +-
>  fs/xfs/xfs_qm_syscalls.c       |   2 +-
>  fs/xfs/xfs_quotaops.c          |   2 +-
>  fs/xfs/xfs_symlink.c           |   2 +-
>  fs/xfs/xfs_trace.h             |   2 +-
>  24 files changed, 122 insertions(+), 162 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index e4fe3dca9883b..1b01675e9c80b 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -62,7 +62,7 @@ xfs_inode_hasattr(
>  {
>  	if (!XFS_IFORK_Q(ip) ||
>  	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> -	     ip->i_d.di_anextents == 0))
> +	     ip->i_afp->if_nextents == 0))
>  		return 0;
>  	return 1;
>  }
> @@ -214,7 +214,7 @@ xfs_attr_set_args(
>  	 */
>  	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
>  	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> -	     dp->i_d.di_anextents == 0)) {
> +	     dp->i_afp->if_nextents == 0)) {
>  
>  		/*
>  		 * Build initial attribute list (if required).
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index 863444e2dda7e..64b172180c42c 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -723,7 +723,6 @@ xfs_attr_fork_remove(
>  	ip->i_d.di_forkoff = 0;
>  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
> -	ASSERT(ip->i_d.di_anextents == 0);
>  	ASSERT(ip->i_afp == NULL);
>  
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 34518a6dc7376..c1136be49abeb 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -61,10 +61,10 @@ xfs_bmap_compute_maxlevels(
>  	int		sz;		/* root block size */
>  
>  	/*
> -	 * The maximum number of extents in a file, hence the maximum
> -	 * number of leaf entries, is controlled by the type of di_nextents
> -	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
> -	 * (a signed 16-bit number, xfs_aextnum_t).
> +	 * The maximum number of extents in a file, hence the maximum number of
> +	 * leaf entries, is controlled by the size of the on-disk extent count,
> +	 * either a signed 32-bit number for the data fork, or a signed 16-bit
> +	 * number for the attr fork.
>  	 *
>  	 * Note that we can no longer assume that if we are in ATTR1 that
>  	 * the fork offset of all the inodes will be
> @@ -120,10 +120,11 @@ xfs_bmbt_lookup_first(
>   */
>  static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
>  {
> +	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
> +
>  	return whichfork != XFS_COW_FORK &&
>  		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> -		XFS_IFORK_NEXTENTS(ip, whichfork) >
> -			XFS_IFORK_MAXEXT(ip, whichfork);
> +		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
>  /*
> @@ -131,10 +132,11 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
>   */
>  static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
>  {
> +	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
> +
>  	return whichfork != XFS_COW_FORK &&
>  		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
> -		XFS_IFORK_NEXTENTS(ip, whichfork) <=
> -			XFS_IFORK_MAXEXT(ip, whichfork);
> +		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
>  /*
> @@ -334,7 +336,7 @@ xfs_bmap_check_leaf_extents(
>  	}
>  
>  	/* skip large extent count inodes */
> -	if (ip->i_d.di_nextents > 10000)
> +	if (ip->i_df.if_nextents > 10000)
>  		return;
>  
>  	bno = NULLFSBLOCK;
> @@ -750,7 +752,7 @@ xfs_bmap_extents_to_btree(
>  		xfs_bmbt_disk_set_all(arp, &rec);
>  		cnt++;
>  	}
> -	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
> +	ASSERT(cnt == ifp->if_nextents);
>  	xfs_btree_set_numrecs(ablock, cnt);
>  
>  	/*
> @@ -802,7 +804,7 @@ xfs_bmap_local_to_extents_empty(
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
>  	ASSERT(ifp->if_bytes == 0);
> -	ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
> +	ASSERT(ifp->if_nextents == 0);
>  
>  	xfs_bmap_forkoff_reset(ip, whichfork);
>  	ifp->if_flags &= ~XFS_IFINLINE;
> @@ -907,7 +909,7 @@ xfs_bmap_local_to_extents(
>  	xfs_iext_first(ifp, &icur);
>  	xfs_iext_insert(ip, &icur, &rec, 0);
>  
> -	XFS_IFORK_NEXT_SET(ip, whichfork, 1);
> +	ifp->if_nextents = 1;
>  	ip->i_d.di_nblocks = 1;
>  	xfs_trans_mod_dquot_byino(tp, ip,
>  		XFS_TRANS_DQ_BCOUNT, 1L);
> @@ -972,7 +974,8 @@ xfs_bmap_add_attrfork_extents(
>  	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
>  	int			error;		/* error return value */
>  
> -	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
> +	if (ip->i_df.if_nextents * sizeof(struct xfs_bmbt_rec) <=
> +	    XFS_IFORK_DSIZE(ip))
>  		return 0;
>  	cur = NULL;
>  	error = xfs_bmap_extents_to_btree(tp, ip, &cur, 0, flags,
> @@ -1091,10 +1094,6 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	if (XFS_IFORK_Q(ip))
>  		goto trans_cancel;
> -	if (XFS_IS_CORRUPT(mp, ip->i_d.di_anextents != 0)) {
> -		error = -EFSCORRUPTED;
> -		goto trans_cancel;
> -	}
>  	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
>  		/*
>  		 * For inodes coming from pre-6.2 filesystems.
> @@ -1183,13 +1182,13 @@ xfs_iread_bmbt_block(
>  	xfs_extnum_t		num_recs;
>  	xfs_extnum_t		j;
>  	int			whichfork = cur->bc_ino.whichfork;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	block = xfs_btree_get_block(cur, level, &bp);
>  
>  	/* Abort if we find more records than nextents. */
>  	num_recs = xfs_btree_get_numrecs(block);
> -	if (unlikely(ir->loaded + num_recs >
> -		     XFS_IFORK_NEXTENTS(ip, whichfork))) {
> +	if (unlikely(ir->loaded + num_recs > ifp->if_nextents)) {
>  		xfs_warn(ip->i_mount, "corrupt dinode %llu, (btree extents).",
>  				(unsigned long long)ip->i_ino);
>  		xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, block,
> @@ -1215,7 +1214,7 @@ xfs_iread_bmbt_block(
>  				xfs_bmap_fork_to_state(whichfork));
>  		trace_xfs_read_extent(ip, &ir->icur,
>  				xfs_bmap_fork_to_state(whichfork), _THIS_IP_);
> -		xfs_iext_next(XFS_IFORK_PTR(ip, whichfork), &ir->icur);
> +		xfs_iext_next(ifp, &ir->icur);
>  	}
>  
>  	return 0;
> @@ -1254,8 +1253,7 @@ xfs_iread_extents(
>  	if (error)
>  		goto out;
>  
> -	if (XFS_IS_CORRUPT(mp,
> -			   ir.loaded != XFS_IFORK_NEXTENTS(ip, whichfork))) {
> +	if (XFS_IS_CORRUPT(mp, ir.loaded != ifp->if_nextents)) {
>  		error = -EFSCORRUPTED;
>  		goto out;
>  	}
> @@ -1463,23 +1461,22 @@ xfs_bmap_last_offset(
>   */
>  int					/* 1=>1 block, 0=>otherwise */
>  xfs_bmap_one_block(
> -	xfs_inode_t	*ip,		/* incore inode */
> -	int		whichfork)	/* data or attr fork */
> +	struct xfs_inode	*ip,		/* incore inode */
> +	int			whichfork)	/* data or attr fork */
>  {
> -	struct xfs_ifork *ifp;		/* inode fork pointer */
> -	int		rval;		/* return value */
> -	xfs_bmbt_irec_t	s;		/* internal version of extent */
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
> +	int			rval;		/* return value */
> +	struct xfs_bmbt_irec	s;		/* internal version of extent */
>  	struct xfs_iext_cursor icur;
>  
>  #ifndef DEBUG
>  	if (whichfork == XFS_DATA_FORK)
>  		return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
>  #endif	/* !DEBUG */
> -	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
> +	if (ifp->if_nextents != 1)
>  		return 0;
>  	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
>  		return 0;
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
>  	xfs_iext_first(ifp, &icur);
>  	xfs_iext_get_extent(ifp, &icur, &s);
> @@ -1501,10 +1498,11 @@ xfs_bmap_add_extent_delay_real(
>  	struct xfs_bmalloca	*bma,
>  	int			whichfork)
>  {
> +	struct xfs_mount	*mp = bma->ip->i_mount;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
>  	struct xfs_bmbt_irec	*new = &bma->got;
>  	int			error;	/* error return value */
>  	int			i;	/* temp state */
> -	struct xfs_ifork	*ifp;	/* inode fork pointer */
>  	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
>  	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
>  					/* left is 0, right is 1, prev is 2 */
> @@ -1514,16 +1512,9 @@ xfs_bmap_add_extent_delay_real(
>  	xfs_filblks_t		da_old; /* old count del alloc blocks used */
>  	xfs_filblks_t		temp=0;	/* value for da_new calculations */
>  	int			tmp_rval;	/* partial logging flags */
> -	struct xfs_mount	*mp;
> -	xfs_extnum_t		*nextents;
>  	struct xfs_bmbt_irec	old;
>  
> -	mp = bma->ip->i_mount;
> -	ifp = XFS_IFORK_PTR(bma->ip, whichfork);
>  	ASSERT(whichfork != XFS_ATTR_FORK);
> -	nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents :
> -						&bma->ip->i_d.di_nextents);
> -
>  	ASSERT(!isnullstartblock(new->br_startblock));
>  	ASSERT(!bma->cur ||
>  	       (bma->cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL));
> @@ -1614,7 +1605,7 @@ xfs_bmap_add_extent_delay_real(
>  		xfs_iext_remove(bma->ip, &bma->icur, state);
>  		xfs_iext_prev(ifp, &bma->icur);
>  		xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT);
> -		(*nextents)--;
> +		ifp->if_nextents--;
>  
>  		if (bma->cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
> @@ -1718,8 +1709,8 @@ xfs_bmap_add_extent_delay_real(
>  		PREV.br_startblock = new->br_startblock;
>  		PREV.br_state = new->br_state;
>  		xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV);
> +		ifp->if_nextents++;
>  
> -		(*nextents)++;
>  		if (bma->cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -1784,7 +1775,8 @@ xfs_bmap_add_extent_delay_real(
>  		 * The left neighbor is not contiguous.
>  		 */
>  		xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
> -		(*nextents)++;
> +		ifp->if_nextents++;
> +
>  		if (bma->cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -1870,7 +1862,8 @@ xfs_bmap_add_extent_delay_real(
>  		 * The right neighbor is not contiguous.
>  		 */
>  		xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
> -		(*nextents)++;
> +		ifp->if_nextents++;
> +
>  		if (bma->cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -1955,7 +1948,7 @@ xfs_bmap_add_extent_delay_real(
>  		xfs_iext_next(ifp, &bma->icur);
>  		xfs_iext_insert(bma->ip, &bma->icur, &RIGHT, state);
>  		xfs_iext_insert(bma->ip, &bma->icur, &LEFT, state);
> -		(*nextents)++;
> +		ifp->if_nextents++;
>  
>  		if (bma->cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
> @@ -2159,8 +2152,7 @@ xfs_bmap_add_extent_unwritten_real(
>  		xfs_iext_remove(ip, icur, state);
>  		xfs_iext_prev(ifp, icur);
>  		xfs_iext_update_extent(ip, state, icur, &LEFT);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) - 2);
> +		ifp->if_nextents -= 2;
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2212,8 +2204,7 @@ xfs_bmap_add_extent_unwritten_real(
>  		xfs_iext_remove(ip, icur, state);
>  		xfs_iext_prev(ifp, icur);
>  		xfs_iext_update_extent(ip, state, icur, &LEFT);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
> +		ifp->if_nextents--;
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2255,9 +2246,8 @@ xfs_bmap_add_extent_unwritten_real(
>  		xfs_iext_remove(ip, icur, state);
>  		xfs_iext_prev(ifp, icur);
>  		xfs_iext_update_extent(ip, state, icur, &PREV);
> +		ifp->if_nextents--;
>  
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2364,8 +2354,8 @@ xfs_bmap_add_extent_unwritten_real(
>  
>  		xfs_iext_update_extent(ip, state, icur, &PREV);
>  		xfs_iext_insert(ip, icur, new, state);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
> +		ifp->if_nextents++;
> +
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2440,9 +2430,8 @@ xfs_bmap_add_extent_unwritten_real(
>  		xfs_iext_update_extent(ip, state, icur, &PREV);
>  		xfs_iext_next(ifp, icur);
>  		xfs_iext_insert(ip, icur, new, state);
> +		ifp->if_nextents++;
>  
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2493,9 +2482,8 @@ xfs_bmap_add_extent_unwritten_real(
>  		xfs_iext_next(ifp, icur);
>  		xfs_iext_insert(ip, icur, &r[1], state);
>  		xfs_iext_insert(ip, icur, &r[0], state);
> +		ifp->if_nextents += 2;
>  
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -				XFS_IFORK_NEXTENTS(ip, whichfork) + 2);
>  		if (cur == NULL)
>  			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
>  		else {
> @@ -2810,9 +2798,8 @@ xfs_bmap_add_extent_hole_real(
>  		xfs_iext_remove(ip, icur, state);
>  		xfs_iext_prev(ifp, icur);
>  		xfs_iext_update_extent(ip, state, icur, &left);
> +		ifp->if_nextents--;
>  
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
>  		if (cur == NULL) {
>  			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
>  		} else {
> @@ -2910,8 +2897,8 @@ xfs_bmap_add_extent_hole_real(
>  		 * Insert a new entry.
>  		 */
>  		xfs_iext_insert(ip, icur, new, state);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
> +		ifp->if_nextents++;
> +
>  		if (cur == NULL) {
>  			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
>  		} else {
> @@ -4512,8 +4499,7 @@ xfs_bmapi_write(
>  		goto error0;
>  
>  	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
> -	       XFS_IFORK_NEXTENTS(ip, whichfork) >
> -		XFS_IFORK_MAXEXT(ip, whichfork));
> +	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
>  	xfs_bmapi_finish(&bma, whichfork, 0);
>  	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
>  		orig_nmap, *nmap);
> @@ -5056,8 +5042,7 @@ xfs_bmap_del_extent_real(
>  	 */
>  	if (tp->t_blk_res == 0 &&
>  	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> -	    XFS_IFORK_NEXTENTS(ip, whichfork) >=
> -			XFS_IFORK_MAXEXT(ip, whichfork) &&
> +	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
>  	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
>  		return -ENOSPC;
>  
> @@ -5109,8 +5094,8 @@ xfs_bmap_del_extent_real(
>  		 */
>  		xfs_iext_remove(ip, icur, state);
>  		xfs_iext_prev(ifp, icur);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
> +		ifp->if_nextents--;
> +
>  		flags |= XFS_ILOG_CORE;
>  		if (!cur) {
>  			flags |= xfs_ilog_fext(whichfork);
> @@ -5218,8 +5203,8 @@ xfs_bmap_del_extent_real(
>  			}
>  		} else
>  			flags |= xfs_ilog_fext(whichfork);
> -		XFS_IFORK_NEXT_SET(ip, whichfork,
> -			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
> +
> +		ifp->if_nextents++;
>  		xfs_iext_next(ifp, icur);
>  		xfs_iext_insert(ip, icur, &new, state);
>  		break;
> @@ -5667,6 +5652,7 @@ xfs_bmse_merge(
>  	struct xfs_btree_cur		*cur,
>  	int				*logflags)	/* output */
>  {
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_bmbt_irec		new;
>  	xfs_filblks_t			blockcount;
>  	int				error, i;
> @@ -5685,8 +5671,7 @@ xfs_bmse_merge(
>  	 * Update the on-disk extent count, the btree if necessary and log the
>  	 * inode.
>  	 */
> -	XFS_IFORK_NEXT_SET(ip, whichfork,
> -			   XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
> +	ifp->if_nextents--;
>  	*logflags |= XFS_ILOG_CORE;
>  	if (!cur) {
>  		*logflags |= XFS_ILOG_DEXT;
> @@ -5724,7 +5709,7 @@ xfs_bmse_merge(
>  
>  done:
>  	xfs_iext_remove(ip, icur, 0);
> -	xfs_iext_prev(XFS_IFORK_PTR(ip, whichfork), icur);
> +	xfs_iext_prev(ifp, icur);
>  	xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), icur,
>  			&new);
>  
> @@ -6074,8 +6059,7 @@ xfs_bmap_split_extent(
>  	/* Add new extent */
>  	xfs_iext_next(ifp, &icur);
>  	xfs_iext_insert(ip, &icur, &new, 0);
> -	XFS_IFORK_NEXT_SET(ip, whichfork,
> -			   XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
> +	ifp->if_nextents++;
>  
>  	if (cur) {
>  		error = xfs_bmbt_lookup_eq(cur, &new, &i);
> diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
> index 1dbf2f980a26a..5b59d3f7746b3 100644
> --- a/fs/xfs/libxfs/xfs_dir2_block.c
> +++ b/fs/xfs/libxfs/xfs_dir2_block.c
> @@ -1104,7 +1104,7 @@ xfs_dir2_sf_to_block(
>  	ASSERT(ifp->if_bytes == dp->i_d.di_size);
>  	ASSERT(ifp->if_u1.if_data != NULL);
>  	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
> -	ASSERT(dp->i_d.di_nextents == 0);
> +	ASSERT(dp->i_df.if_nextents == 0);
>  
>  	/*
>  	 * Copy the directory into a temporary buffer.
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index 5547bbb3cf945..a374e2a81e764 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -245,8 +245,6 @@ xfs_inode_from_disk(
>  	to->di_size = be64_to_cpu(from->di_size);
>  	to->di_nblocks = be64_to_cpu(from->di_nblocks);
>  	to->di_extsize = be32_to_cpu(from->di_extsize);
> -	to->di_nextents = be32_to_cpu(from->di_nextents);
> -	to->di_anextents = be16_to_cpu(from->di_anextents);
>  	to->di_forkoff = from->di_forkoff;
>  	to->di_aformat	= from->di_aformat;
>  	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
> @@ -311,8 +309,8 @@ xfs_inode_to_disk(
>  	to->di_size = cpu_to_be64(from->di_size);
>  	to->di_nblocks = cpu_to_be64(from->di_nblocks);
>  	to->di_extsize = cpu_to_be32(from->di_extsize);
> -	to->di_nextents = cpu_to_be32(from->di_nextents);
> -	to->di_anextents = cpu_to_be16(from->di_anextents);
> +	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
> +	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
>  	to->di_forkoff = from->di_forkoff;
>  	to->di_aformat = from->di_aformat;
>  	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
> index e4cbcaf62a32b..fecccfb26463c 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.h
> +++ b/fs/xfs/libxfs/xfs_inode_buf.h
> @@ -22,8 +22,6 @@ struct xfs_icdinode {
>  	xfs_fsize_t	di_size;	/* number of bytes in file */
>  	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
>  	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
> -	xfs_extnum_t	di_nextents;	/* number of extents in data fork */
> -	xfs_aextnum_t	di_anextents;	/* number of extents in attribute fork*/
>  	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
>  	int8_t		di_aformat;	/* format of attr fork's data */
>  	uint32_t	di_dmevmask;	/* DMIG event mask */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 2fe325e38fd88..195da3552c5b5 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -188,12 +188,11 @@ xfs_iformat_btree(
>  	 * or the number of extents is greater than the number of
>  	 * blocks.
>  	 */
> -	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
> -					XFS_IFORK_MAXEXT(ip, whichfork) ||
> +	if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
>  		     nrecs == 0 ||
>  		     XFS_BMDR_SPACE_CALC(nrecs) >
>  					XFS_DFORK_SIZE(dip, mp, whichfork) ||
> -		     XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
> +		     ifp->if_nextents > ip->i_d.di_nblocks) ||
>  		     level == 0 || level > XFS_BTREE_MAXLEVELS) {
>  		xfs_warn(mp, "corrupt inode %Lu (btree).",
>  					(unsigned long long) ip->i_ino);
> @@ -229,6 +228,8 @@ xfs_iformat_data_fork(
>  	struct inode		*inode = VFS_I(ip);
>  	int			error;
>  
> +	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
> +
>  	switch (inode->i_mode & S_IFMT) {
>  	case S_IFIFO:
>  	case S_IFCHR:
> @@ -282,6 +283,8 @@ xfs_iformat_attr_fork(
>  	int			error = 0;
>  
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> +	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
> +
>  	switch (dip->di_aformat) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
> @@ -617,7 +620,7 @@ xfs_iflush_fork(
>  		       !(iip->ili_fields & extflag[whichfork]));
>  		if ((iip->ili_fields & extflag[whichfork]) &&
>  		    (ifp->if_bytes > 0)) {
> -			ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
> +			ASSERT(ifp->if_nextents > 0);
>  			(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
>  				whichfork);
>  		}
> @@ -676,7 +679,6 @@ xfs_ifork_init_cow(
>  				       KM_NOFS);
>  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
>  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_cnextents = 0;
>  }
>  
>  /* Verify the inline contents of the data fork of an inode. */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index f46a8c1db5964..a69d425fe68df 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -23,6 +23,7 @@ struct xfs_ifork {
>  	} if_u1;
>  	short			if_broot_bytes;	/* bytes allocated for root */
>  	unsigned char		if_flags;	/* per-fork flags */
> +	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
>  };
>  
>  /*
> @@ -67,18 +68,6 @@ struct xfs_ifork {
>  		((w) == XFS_ATTR_FORK ? \
>  			((ip)->i_d.di_aformat = (n)) : \
>  			((ip)->i_cformat = (n))))
> -#define XFS_IFORK_NEXTENTS(ip,w) \
> -	((w) == XFS_DATA_FORK ? \
> -		(ip)->i_d.di_nextents : \
> -		((w) == XFS_ATTR_FORK ? \
> -			(ip)->i_d.di_anextents : \
> -			(ip)->i_cnextents))
> -#define XFS_IFORK_NEXT_SET(ip,w,n) \
> -	((w) == XFS_DATA_FORK ? \
> -		((ip)->i_d.di_nextents = (n)) : \
> -		((w) == XFS_ATTR_FORK ? \
> -			((ip)->i_d.di_anextents = (n)) : \
> -			((ip)->i_cnextents = (n))))
>  #define XFS_IFORK_MAXEXT(ip, w) \
>  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
>  
> @@ -86,6 +75,13 @@ struct xfs_ifork {
>  	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
>  	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
>  
> +static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
> +{
> +	if (!ifp)
> +		return 0;
> +	return ifp->if_nextents;
> +}
> +
>  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
>  
>  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index 283424d6d2bb6..157f72efec5e9 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -566,6 +566,7 @@ xchk_bmap_check_rmaps(
>  	struct xfs_scrub	*sc,
>  	int			whichfork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
>  	loff_t			size;
>  	xfs_agnumber_t		agno;
>  	int			error;
> @@ -598,7 +599,7 @@ xchk_bmap_check_rmaps(
>  		break;
>  	}
>  	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> -	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
> +	    (size == 0 || ifp->if_nextents > 0))
>  		return 0;
>  
>  	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
> diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
> index 5705adc43a75f..855aa8bcab64b 100644
> --- a/fs/xfs/scrub/parent.c
> +++ b/fs/xfs/scrub/parent.c
> @@ -90,7 +90,7 @@ xchk_parent_count_parent_dentries(
>  	 * if there is one.
>  	 */
>  	lock_mode = xfs_ilock_data_map_shared(parent);
> -	if (parent->i_d.di_nextents > 0)
> +	if (parent->i_df.if_nextents > 0)
>  		error = xfs_dir3_data_readahead(parent, 0, 0);
>  	xfs_iunlock(parent, lock_mode);
>  	if (error)
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index cc23a3e23e2d1..4f277a6253b8d 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -1220,7 +1220,7 @@ xfs_swap_extents_check_format(
>  	 * if the target inode has less extents that then temporary inode then
>  	 * why did userspace call us?
>  	 */
> -	if (ip->i_d.di_nextents < tip->i_d.di_nextents)
> +	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
>  		return -EINVAL;
>  
>  	/*
> @@ -1241,14 +1241,12 @@ xfs_swap_extents_check_format(
>  
>  	/* Check temp in extent form to max in target */
>  	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) >
> -			XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/* Check target in extent form to max in temp */
>  	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) >
> -			XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/*
> @@ -1264,7 +1262,7 @@ xfs_swap_extents_check_format(
>  		if (XFS_IFORK_Q(ip) &&
>  		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
>  			return -EINVAL;
> -		if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
> +		if (tip->i_df.if_nextents <=
>  		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
> @@ -1274,7 +1272,7 @@ xfs_swap_extents_check_format(
>  		if (XFS_IFORK_Q(tip) &&
>  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
>  			return -EINVAL;
> -		if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
> +		if (ip->i_df.if_nextents <=
>  		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
> @@ -1427,15 +1425,15 @@ xfs_swap_extent_forks(
>  	/*
>  	 * Count the number of extended attribute blocks
>  	 */
> -	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
> -	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> +	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> +	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
>  				&aforkblks);
>  		if (error)
>  			return error;
>  	}
> -	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
> -	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> +	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> +	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
>  				&taforkblks);
>  		if (error)
> @@ -1468,7 +1466,6 @@ xfs_swap_extent_forks(
>  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
>  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
>  
> -	swap(ip->i_d.di_nextents, tip->i_d.di_nextents);
>  	swap(ip->i_d.di_format, tip->i_d.di_format);
>  
>  	/*
> @@ -1615,9 +1612,9 @@ xfs_swap_extents(
>  	 * performed with log redo items!
>  	 */
>  	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
> -		int		w	= XFS_DATA_FORK;
> -		uint32_t	ipnext	= XFS_IFORK_NEXTENTS(ip, w);
> -		uint32_t	tipnext	= XFS_IFORK_NEXTENTS(tip, w);
> +		int		w = XFS_DATA_FORK;
> +		uint32_t	ipnext = ip->i_df.if_nextents;
> +		uint32_t	tipnext	= tip->i_df.if_nextents;
>  
>  		/*
>  		 * Conceptually this shouldn't affect the shape of either bmbt,
> @@ -1720,7 +1717,6 @@ xfs_swap_extents(
>  		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
>  		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
>  
> -		swap(ip->i_cnextents, tip->i_cnextents);
>  		swap(ip->i_cowfp, tip->i_cowfp);
>  
>  		if (ip->i_cowfp && ip->i_cowfp->if_bytes)
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 4b8bdecc38635..403c90309a8ff 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1102,7 +1102,7 @@ xfs_dir_open(
>  	 * certain to have the next operation be a read there.
>  	 */
>  	mode = xfs_ilock_data_map_shared(ip);
> -	if (ip->i_d.di_nextents > 0)
> +	if (ip->i_df.if_nextents > 0)
>  		error = xfs_dir3_data_readahead(ip, 0, 0);
>  	xfs_iunlock(ip, mode);
>  	return error;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 5a3a520b95288..791d5d5e318cf 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -63,7 +63,6 @@ xfs_inode_alloc(
>  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
>  	ip->i_afp = NULL;
>  	ip->i_cowfp = NULL;
> -	ip->i_cnextents = 0;
>  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
>  	memset(&ip->i_df, 0, sizeof(ip->i_df));
>  	ip->i_flags = 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 7d3144dc99b72..1677c4e7207ed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -825,7 +825,7 @@ xfs_ialloc(
>  		inode->i_mode &= ~S_ISGID;
>  
>  	ip->i_d.di_size = 0;
> -	ip->i_d.di_nextents = 0;
> +	ip->i_df.if_nextents = 0;
>  	ASSERT(ip->i_d.di_nblocks == 0);
>  
>  	tv = current_time(inode);
> @@ -919,7 +919,6 @@ xfs_ialloc(
>  	 * Attribute fork settings for new inode.
>  	 */
>  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_d.di_anextents = 0;
>  
>  	/*
>  	 * Log the new values stuffed into the inode.
> @@ -1686,7 +1685,7 @@ xfs_inactive_truncate(
>  	if (error)
>  		goto error_trans_cancel;
>  
> -	ASSERT(ip->i_d.di_nextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  
>  	error = xfs_trans_commit(tp);
>  	if (error)
> @@ -1836,7 +1835,7 @@ xfs_inactive(
>  
>  	if (S_ISREG(VFS_I(ip)->i_mode) &&
>  	    (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
> -	     ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
> +	     ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
>  		truncate = 1;
>  
>  	error = xfs_qm_dqattach(ip);
> @@ -1862,7 +1861,6 @@ xfs_inactive(
>  	}
>  
>  	ASSERT(!ip->i_afp);
> -	ASSERT(ip->i_d.di_anextents == 0);
>  	ASSERT(ip->i_d.di_forkoff == 0);
>  
>  	/*
> @@ -2731,8 +2729,7 @@ xfs_ifree(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(VFS_I(ip)->i_nlink == 0);
> -	ASSERT(ip->i_d.di_nextents == 0);
> -	ASSERT(ip->i_d.di_anextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  	ASSERT(ip->i_d.di_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
>  	ASSERT(ip->i_d.di_nblocks == 0);
>  
> @@ -3628,7 +3625,7 @@ xfs_iflush(
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
>  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  
>  	*bpp = NULL;
>  
> @@ -3710,7 +3707,7 @@ xfs_iflush_int(
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
>  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  	ASSERT(iip != NULL && iip->ili_fields != 0);
>  
>  	dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
> @@ -3751,13 +3748,13 @@ xfs_iflush_int(
>  			goto flush_out;
>  		}
>  	}
> -	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
> +	if (XFS_TEST_ERROR(ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp) >
>  				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5)) {
>  		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  			"%s: detected corrupt incore inode %Lu, "
>  			"total extents = %d, nblocks = %Ld, ptr "PTR_FMT,
>  			__func__, ip->i_ino,
> -			ip->i_d.di_nextents + ip->i_d.di_anextents,
> +			ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp),
>  			ip->i_d.di_nblocks, ip);
>  		goto flush_out;
>  	}
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index ff846197941e4..24dae63ba16c0 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -57,7 +57,6 @@ typedef struct xfs_inode {
>  
>  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
>  
> -	xfs_extnum_t		i_cnextents;	/* # of extents in cow fork */
>  	unsigned int		i_cformat;	/* format of cow fork */
>  
>  	/* VFS inode */
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index cefa2484f0dbf..401ba26aeed7b 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -39,7 +39,7 @@ xfs_inode_item_data_fork_size(
>  	switch (ip->i_d.di_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> -		    ip->i_d.di_nextents > 0 &&
> +		    ip->i_df.if_nextents > 0 &&
>  		    ip->i_df.if_bytes > 0) {
>  			/* worst case, doesn't subtract delalloc extents */
>  			*nbytes += XFS_IFORK_DSIZE(ip);
> @@ -80,7 +80,7 @@ xfs_inode_item_attr_fork_size(
>  	switch (ip->i_d.di_aformat) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> -		    ip->i_d.di_anextents > 0 &&
> +		    ip->i_afp->if_nextents > 0 &&
>  		    ip->i_afp->if_bytes > 0) {
>  			/* worst case, doesn't subtract unused space */
>  			*nbytes += XFS_IFORK_ASIZE(ip);
> @@ -148,7 +148,7 @@ xfs_inode_item_format_data_fork(
>  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
>  
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> -		    ip->i_d.di_nextents > 0 &&
> +		    ip->i_df.if_nextents > 0 &&
>  		    ip->i_df.if_bytes > 0) {
>  			struct xfs_bmbt_rec *p;
>  
> @@ -233,12 +233,12 @@ xfs_inode_item_format_attr_fork(
>  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
>  
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> -		    ip->i_d.di_anextents > 0 &&
> +		    ip->i_afp->if_nextents > 0 &&
>  		    ip->i_afp->if_bytes > 0) {
>  			struct xfs_bmbt_rec *p;
>  
>  			ASSERT(xfs_iext_count(ip->i_afp) ==
> -				ip->i_d.di_anextents);
> +				ip->i_afp->if_nextents);
>  
>  			p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT);
>  			data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK);
> @@ -326,8 +326,8 @@ xfs_inode_to_log_dinode(
>  	to->di_size = from->di_size;
>  	to->di_nblocks = from->di_nblocks;
>  	to->di_extsize = from->di_extsize;
> -	to->di_nextents = from->di_nextents;
> -	to->di_anextents = from->di_anextents;
> +	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
> +	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
>  	to->di_forkoff = from->di_forkoff;
>  	to->di_aformat = from->di_aformat;
>  	to->di_dmevmask = from->di_dmevmask;
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 4ee0d13232f3f..7a71c03e9022b 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -1104,26 +1104,17 @@ xfs_fill_fsxattr(
>  	bool			attr,
>  	struct fsxattr		*fa)
>  {
> +	struct xfs_ifork	*ifp = attr ? ip->i_afp : &ip->i_df;
> +
>  	simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
>  	fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
>  	fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
>  			ip->i_mount->m_sb.sb_blocklog;
>  	fa->fsx_projid = ip->i_d.di_projid;
> -
> -	if (attr) {
> -		if (ip->i_afp) {
> -			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
> -				fa->fsx_nextents = xfs_iext_count(ip->i_afp);
> -			else
> -				fa->fsx_nextents = ip->i_d.di_anextents;
> -		} else
> -			fa->fsx_nextents = 0;
> -	} else {
> -		if (ip->i_df.if_flags & XFS_IFEXTENTS)
> -			fa->fsx_nextents = xfs_iext_count(&ip->i_df);
> -		else
> -			fa->fsx_nextents = ip->i_d.di_nextents;
> -	}
> +	if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
> +		fa->fsx_nextents = xfs_iext_count(ifp);
> +	else
> +		fa->fsx_nextents = xfs_ifork_nextents(ifp);
>  }
>  
>  STATIC int
> @@ -1211,7 +1202,7 @@ xfs_ioctl_setattr_xflags(
>  	uint64_t		di_flags2;
>  
>  	/* Can't change realtime flag if any extents are allocated. */
> -	if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
> +	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
>  	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
>  		return -EINVAL;
>  
> @@ -1389,7 +1380,7 @@ xfs_ioctl_setattr_check_extsize(
>  	xfs_extlen_t		size;
>  	xfs_fsblock_t		extsize_fsb;
>  
> -	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
> +	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
>  	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
>  		return -EINVAL;
>  
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index bb590a267a7f9..b4fd918749e5f 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -1258,7 +1258,7 @@ xfs_xattr_iomap_begin(
>  	lockmode = xfs_ilock_attr_map_shared(ip);
>  
>  	/* if there are no attribute fork or extents, return ENOENT */
> -	if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
> +	if (!XFS_IFORK_Q(ip) || !ip->i_afp->if_nextents) {
>  		error = -ENOENT;
>  		goto out_unlock;
>  	}
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 26a71237d70f6..d66528fa36570 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -872,7 +872,7 @@ xfs_setattr_size(
>  	/*
>  	 * Short circuit the truncate case for zero length files.
>  	 */
> -	if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
> +	if (newsize == 0 && oldsize == 0 && ip->i_df.if_nextents == 0) {
>  		if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
>  			return 0;
>  
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index ff2da28fed90e..80da86c5703fb 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -104,9 +104,9 @@ xfs_bulkstat_one_int(
>  
>  	buf->bs_xflags = xfs_ip2xflags(ip);
>  	buf->bs_extsize_blks = dic->di_extsize;
> -	buf->bs_extents = dic->di_nextents;
> +	buf->bs_extents = xfs_ifork_nextents(&ip->i_df);
>  	xfs_bulkstat_health(ip, buf);
> -	buf->bs_aextents = dic->di_anextents;
> +	buf->bs_aextents = xfs_ifork_nextents(ip->i_afp);
>  	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
>  	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
>  
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index 944486f2b2874..9edf761eec739 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -302,7 +302,7 @@ xfs_qm_scall_trunc_qfile(
>  		goto out_unlock;
>  	}
>  
> -	ASSERT(ip->i_d.di_nextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  
>  	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
>  	error = xfs_trans_commit(tp);
> diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
> index 38669e8272060..b5d10ecb54743 100644
> --- a/fs/xfs/xfs_quotaops.c
> +++ b/fs/xfs/xfs_quotaops.c
> @@ -36,7 +36,7 @@ xfs_qm_fill_state(
>  	}
>  	tstate->flags |= QCI_SYSFILE;
>  	tstate->blocks = ip->i_d.di_nblocks;
> -	tstate->nextents = ip->i_d.di_nextents;
> +	tstate->nextents = ip->i_df.if_nextents;
>  	tstate->spc_timelimit = (u32)q->qi_btimelimit;
>  	tstate->ino_timelimit = (u32)q->qi_itimelimit;
>  	tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 973441992b084..8cf2fcb509c12 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -384,7 +384,7 @@ xfs_inactive_symlink_rmt(
>  	 * either 1 or 2 extents and that we can
>  	 * free them all in one bunmapi call.
>  	 */
> -	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
> +	ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
>  
>  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
>  	if (error)
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index a4323a63438d8..ba2ab69e1fc7d 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -1898,7 +1898,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
>  		__entry->which = which;
>  		__entry->ino = ip->i_ino;
>  		__entry->format = ip->i_d.di_format;
> -		__entry->nex = ip->i_d.di_nextents;
> +		__entry->nex = ip->i_df.if_nextents;
>  		__entry->broot_size = ip->i_df.if_broot_bytes;
>  		__entry->fork_off = XFS_IFORK_BOFF(ip);
>  	),
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
@ 2020-05-12  9:37   ` Chandan Babu R
  2020-05-12 18:53   ` Brian Foster
  2020-05-14 21:25   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Chandan Babu R @ 2020-05-12  9:37 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:54:03 PM IST Christoph Hellwig wrote:
> Both the data and attr fork have a format that is stored in the legacy
> idinode.  Move it into the xfs_ifork structure instead, where it uses
> up padding.
>

The changes look good to me.

Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr.c           |  12 +--
>  fs/xfs/libxfs/xfs_attr_leaf.c      |  32 ++++----
>  fs/xfs/libxfs/xfs_bmap.c           | 120 +++++++++++++----------------
>  fs/xfs/libxfs/xfs_bmap_btree.c     |   5 +-
>  fs/xfs/libxfs/xfs_dir2.c           |   8 +-
>  fs/xfs/libxfs/xfs_dir2_sf.c        |  13 ++--
>  fs/xfs/libxfs/xfs_inode_buf.c      |   6 +-
>  fs/xfs/libxfs/xfs_inode_buf.h      |   2 -
>  fs/xfs/libxfs/xfs_inode_fork.c     |  14 ++--
>  fs/xfs/libxfs/xfs_inode_fork.h     |  28 ++++---
>  fs/xfs/libxfs/xfs_symlink_remote.c |  16 ++--
>  fs/xfs/scrub/bmap.c                |   4 +-
>  fs/xfs/scrub/dabtree.c             |   2 +-
>  fs/xfs/scrub/dir.c                 |   7 +-
>  fs/xfs/xfs_aops.c                  |   2 +-
>  fs/xfs/xfs_attr_inactive.c         |   2 +-
>  fs/xfs/xfs_attr_list.c             |   4 +-
>  fs/xfs/xfs_bmap_util.c             |  56 +++++++-------
>  fs/xfs/xfs_dir2_readdir.c          |   2 +-
>  fs/xfs/xfs_icache.c                |   1 -
>  fs/xfs/xfs_inode.c                 |  36 ++++-----
>  fs/xfs/xfs_inode.h                 |   2 -
>  fs/xfs/xfs_inode_item.c            |  12 +--
>  fs/xfs/xfs_iomap.c                 |   4 +-
>  fs/xfs/xfs_itable.c                |   2 +-
>  fs/xfs/xfs_symlink.c               |   2 +-
>  fs/xfs/xfs_trace.h                 |   2 +-
>  27 files changed, 181 insertions(+), 215 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 1b01675e9c80b..3b1bd6e112f89 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -61,7 +61,7 @@ xfs_inode_hasattr(
>  	struct xfs_inode	*ip)
>  {
>  	if (!XFS_IFORK_Q(ip) ||
> -	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	    (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     ip->i_afp->if_nextents == 0))
>  		return 0;
>  	return 1;
> @@ -84,7 +84,7 @@ xfs_attr_get_ilocked(
>  	if (!xfs_inode_hasattr(args->dp))
>  		return -ENOATTR;
>  
> -	if (args->dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_getvalue(args);
>  	if (xfs_bmap_one_block(args->dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_get(args);
> @@ -212,14 +212,14 @@ xfs_attr_set_args(
>  	 * If the attribute list is non-existent or a shortform list,
>  	 * upgrade it to a single-leaf-block attribute list.
>  	 */
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
> -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     dp->i_afp->if_nextents == 0)) {
>  
>  		/*
>  		 * Build initial attribute list (if required).
>  		 */
> -		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
> +		if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
>  			xfs_attr_shortform_create(args);
>  
>  		/*
> @@ -272,7 +272,7 @@ xfs_attr_remove_args(
>  
>  	if (!xfs_inode_hasattr(dp)) {
>  		error = -ENOATTR;
> -	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
> +	} else if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
>  		error = xfs_attr_shortform_remove(args);
>  	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index 64b172180c42c..d7f3173ce3c31 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -539,7 +539,7 @@ xfs_attr_shortform_bytesfit(
>  	/* rounded down */
>  	offset = (XFS_LITINO(mp) - bytes) >> 3;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_DEV) {
>  		minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		return (offset >= minforkoff) ? minforkoff : 0;
>  	}
> @@ -567,7 +567,7 @@ xfs_attr_shortform_bytesfit(
>  
>  	dsize = dp->i_df.if_bytes;
>  
> -	switch (dp->i_d.di_format) {
> +	switch (dp->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		/*
>  		 * If there is no attr fork and the data fork is extents, 
> @@ -636,22 +636,19 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
>   * Create the initial contents of a shortform attribute list.
>   */
>  void
> -xfs_attr_shortform_create(xfs_da_args_t *args)
> +xfs_attr_shortform_create(
> +	struct xfs_da_args	*args)
>  {
> -	xfs_attr_sf_hdr_t *hdr;
> -	xfs_inode_t *dp;
> -	struct xfs_ifork *ifp;
> +	struct xfs_inode	*dp = args->dp;
> +	struct xfs_ifork	*ifp = dp->i_afp;
> +	struct xfs_attr_sf_hdr	*hdr;
>  
>  	trace_xfs_attr_sf_create(args);
>  
> -	dp = args->dp;
> -	ASSERT(dp != NULL);
> -	ifp = dp->i_afp;
> -	ASSERT(ifp != NULL);
>  	ASSERT(ifp->if_bytes == 0);
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS) {
>  		ifp->if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
> +		ifp->if_format = XFS_DINODE_FMT_LOCAL;
>  		ifp->if_flags |= XFS_IFINLINE;
>  	} else {
>  		ASSERT(ifp->if_flags & XFS_IFINLINE);
> @@ -721,7 +718,6 @@ xfs_attr_fork_remove(
>  {
>  	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
>  	ip->i_d.di_forkoff = 0;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	ASSERT(ip->i_afp == NULL);
>  
> @@ -774,7 +770,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  	totsize -= size;
>  	if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
>  	    (mp->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    !(args->op_flags & XFS_DA_OP_ADDNAME)) {
>  		xfs_attr_fork_remove(dp, args->trans);
>  	} else {
> @@ -784,7 +780,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
>  				(args->op_flags & XFS_DA_OP_ADDNAME) ||
>  				!(mp->m_flags & XFS_MOUNT_ATTR2) ||
> -				dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
> +				dp->i_df.if_format == XFS_DINODE_FMT_BTREE);
>  		xfs_trans_log_inode(args->trans, dp,
>  					XFS_ILOG_CORE | XFS_ILOG_ADATA);
>  	}
> @@ -961,7 +957,7 @@ xfs_attr_shortform_allfit(
>  				+ be16_to_cpu(name_loc->valuelen);
>  	}
>  	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
>  		return -1;
>  	return xfs_attr_shortform_bytesfit(dp, bytes);
> @@ -980,7 +976,7 @@ xfs_attr_shortform_verify(
>  	int				i;
>  	int64_t				size;
>  
> -	ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK);
>  	sfp = (struct xfs_attr_shortform *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
> @@ -1084,7 +1080,7 @@ xfs_attr3_leaf_to_shortform(
>  
>  	if (forkoff == -1) {
>  		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
> -		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
> +		ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE);
>  		xfs_attr_fork_remove(dp, args->trans);
>  		goto out;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index c1136be49abeb..edc63dba007f4 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -123,7 +123,7 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +		ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -135,7 +135,7 @@ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
> +		ifp->if_format == XFS_DINODE_FMT_BTREE &&
>  		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -215,8 +215,8 @@ xfs_bmap_forkoff_reset(
>  	int		whichfork)
>  {
>  	if (whichfork == XFS_ATTR_FORK &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
> +	    ip->i_df.if_format != XFS_DINODE_FMT_DEV &&
> +	    ip->i_df.if_format != XFS_DINODE_FMT_BTREE) {
>  		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
>  
>  		if (dfl_forkoff > ip->i_d.di_forkoff)
> @@ -317,31 +317,28 @@ xfs_bmap_check_leaf_extents(
>  	xfs_inode_t		*ip,		/* incore inode pointer */
>  	int			whichfork)	/* data or attr fork */
>  {
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_block	*block;	/* current btree block */
>  	xfs_fsblock_t		bno;	/* block # of "block" */
>  	xfs_buf_t		*bp;	/* buffer for "block" */
>  	int			error;	/* error return value */
>  	xfs_extnum_t		i=0, j;	/* index into the extents list */
> -	struct xfs_ifork	*ifp;	/* fork structure */
>  	int			level;	/* btree level, for checking */
> -	xfs_mount_t		*mp;	/* file system mount structure */
>  	__be64			*pp;	/* pointer to block address */
>  	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
>  	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
>  	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
>  	int			bp_release = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return;
> -	}
>  
>  	/* skip large extent count inodes */
>  	if (ip->i_df.if_nextents > 10000)
>  		return;
>  
>  	bno = NULLFSBLOCK;
> -	mp = ip->i_mount;
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	block = ifp->if_broot;
>  	/*
>  	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
> @@ -606,7 +603,7 @@ xfs_bmap_btree_to_extents(
>  	ASSERT(cur);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
>  	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
>  	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
> @@ -634,7 +631,7 @@ xfs_bmap_btree_to_extents(
>  	xfs_iroot_realloc(ip, -1, whichfork);
>  	ASSERT(ifp->if_broot == NULL);
>  	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	*logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
>  	return 0;
>  }
> @@ -670,7 +667,7 @@ xfs_bmap_extents_to_btree(
>  	mp = ip->i_mount;
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  	/*
>  	 * Make space in the inode incore. This needs to be undone if we fail
> @@ -694,7 +691,7 @@ xfs_bmap_extents_to_btree(
>  	/*
>  	 * Convert to a btree with two levels, one record in root.
>  	 */
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
> +	ifp->if_format = XFS_DINODE_FMT_BTREE;
>  	memset(&args, 0, sizeof(args));
>  	args.tp = tp;
>  	args.mp = mp;
> @@ -780,7 +777,7 @@ xfs_bmap_extents_to_btree(
>  	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
>  out_root_realloc:
>  	xfs_iroot_realloc(ip, -1, whichfork);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ASSERT(ifp->if_broot == NULL);
>  	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
>  
> @@ -802,7 +799,7 @@ xfs_bmap_local_to_extents_empty(
>  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	ASSERT(whichfork != XFS_COW_FORK);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ASSERT(ifp->if_bytes == 0);
>  	ASSERT(ifp->if_nextents == 0);
>  
> @@ -811,7 +808,7 @@ xfs_bmap_local_to_extents_empty(
>  	ifp->if_flags |= XFS_IFEXTENTS;
>  	ifp->if_u1.if_root = NULL;
>  	ifp->if_height = 0;
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  }
>  
> @@ -842,7 +839,7 @@ xfs_bmap_local_to_extents(
>  	 */
>  	ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	if (!ifp->if_bytes) {
>  		xfs_bmap_local_to_extents_empty(tp, ip, whichfork);
> @@ -1036,7 +1033,7 @@ xfs_bmap_set_attrforkoff(
>  	int			size,
>  	int			*version)
>  {
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		break;
> @@ -1094,13 +1091,6 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	if (XFS_IFORK_Q(ip))
>  		goto trans_cancel;
> -	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
> -		/*
> -		 * For inodes coming from pre-6.2 filesystems.
> -		 */
> -		ASSERT(ip->i_d.di_aformat == 0);
> -		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> -	}
>  
>  	xfs_trans_ijoin(tp, ip, 0);
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> @@ -1109,9 +1099,10 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	ASSERT(ip->i_afp == NULL);
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, 0);
> +	ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_flags = XFS_IFEXTENTS;
>  	logflags = 0;
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_bmap_add_attrfork_local(tp, ip, &logflags);
>  		break;
> @@ -1237,9 +1228,7 @@ xfs_iread_extents(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  
> -	if (XFS_IS_CORRUPT(mp,
> -			   XFS_IFORK_FORMAT(ip, whichfork) !=
> -			   XFS_DINODE_FMT_BTREE)) {
> +	if (XFS_IS_CORRUPT(mp, ifp->if_format != XFS_DINODE_FMT_BTREE)) {
>  		error = -EFSCORRUPTED;
>  		goto out;
>  	}
> @@ -1287,14 +1276,13 @@ xfs_bmap_first_unused(
>  	xfs_fileoff_t		lowest, max;
>  	int			error;
>  
> -	ASSERT(xfs_ifork_has_extents(ip, whichfork) ||
> -	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		*first_unused = 0;
>  		return 0;
>  	}
>  
> +	ASSERT(xfs_ifork_has_extents(ifp));
> +
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		error = xfs_iread_extents(tp, ip, whichfork);
>  		if (error)
> @@ -1335,7 +1323,7 @@ xfs_bmap_last_before(
>  	struct xfs_iext_cursor	icur;
>  	int			error;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		*last_block = 0;
>  		return 0;
> @@ -1434,16 +1422,17 @@ xfs_bmap_last_offset(
>  	xfs_fileoff_t		*last_block,
>  	int			whichfork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_bmbt_irec	rec;
>  	int			is_empty;
>  	int			error;
>  
>  	*last_block = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return 0;
>  
> -	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  
>  	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
> @@ -1475,7 +1464,7 @@ xfs_bmap_one_block(
>  #endif	/* !DEBUG */
>  	if (ifp->if_nextents != 1)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		return 0;
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
>  	xfs_iext_first(ifp, &icur);
> @@ -3895,10 +3884,9 @@ xfs_bmapi_read(
>  	if (WARN_ON_ONCE(!ifp))
>  		return -EFSCORRUPTED;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> -	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
> +	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
>  		return -EFSCORRUPTED;
> -	}
>  
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -4281,11 +4269,13 @@ xfs_bmapi_minleft(
>  	struct xfs_inode	*ip,
>  	int			fork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, fork);
> +
>  	if (tp && tp->t_firstblock != NULLFSBLOCK)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, fork) != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 1;
> -	return be16_to_cpu(XFS_IFORK_PTR(ip, fork)->if_broot->bb_level) + 1;
> +	return be16_to_cpu(ifp->if_broot->bb_level) + 1;
>  }
>  
>  /*
> @@ -4300,11 +4290,13 @@ xfs_bmapi_finish(
>  	int			whichfork,
>  	int			error)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
> +
>  	if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		bma->logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((bma->logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		bma->logflags &= ~xfs_ilog_fbroot(whichfork);
>  
>  	if (bma->logflags)
> @@ -4336,13 +4328,13 @@ xfs_bmapi_write(
>  		.total		= total,
>  	};
>  	struct xfs_mount	*mp = ip->i_mount;
> -	struct xfs_ifork	*ifp;
> +	int			whichfork = xfs_bmapi_whichfork(flags);
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	xfs_fileoff_t		end;		/* end of mapped file region */
>  	bool			eof = false;	/* after the end of extents */
>  	int			error;		/* error return */
>  	int			n;		/* current extent index */
>  	xfs_fileoff_t		obno;		/* old block number (offset) */
> -	int			whichfork;	/* data or attr fork */
>  
>  #ifdef DEBUG
>  	xfs_fileoff_t		orig_bno;	/* original block number value */
> @@ -4357,13 +4349,12 @@ xfs_bmapi_write(
>  	orig_mval = mval;
>  	orig_nmap = *nmap;
>  #endif
> -	whichfork = xfs_bmapi_whichfork(flags);
>  
>  	ASSERT(*nmap >= 1);
>  	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
>  	ASSERT(tp != NULL);
>  	ASSERT(len > 0);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_LOCAL);
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(!(flags & XFS_BMAPI_REMAP));
>  
> @@ -4379,7 +4370,7 @@ xfs_bmapi_write(
>  	ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
>  			(XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4387,8 +4378,6 @@ xfs_bmapi_write(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -
>  	XFS_STATS_INC(mp, xs_blk_mapw);
>  
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
> @@ -4498,7 +4487,7 @@ xfs_bmapi_write(
>  	if (error)
>  		goto error0;
>  
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_BTREE ||
>  	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
>  	xfs_bmapi_finish(&bma, whichfork, 0);
>  	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
> @@ -4645,7 +4634,7 @@ xfs_bmapi_remap(
>  	ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) !=
>  			(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4689,9 +4678,9 @@ xfs_bmapi_remap(
>  	error = xfs_bmap_btree_to_extents(tp, ip, cur, &logflags, whichfork);
>  
>  error0:
> -	if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS)
> +	if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~XFS_ILOG_DEXT;
> -	else if (ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	else if (ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~XFS_ILOG_DBROOT;
>  
>  	if (logflags)
> @@ -5041,7 +5030,7 @@ xfs_bmap_del_extent_real(
>  	 * conversion to btree format, since the transaction will be dirty then.
>  	 */
>  	if (tp->t_blk_res == 0 &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
>  	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
>  		return -ENOSPC;
> @@ -5284,7 +5273,7 @@ __xfs_bunmapi(
>  	whichfork = xfs_bmapi_whichfork(flags);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -5322,7 +5311,7 @@ __xfs_bunmapi(
>  
>  	logflags = 0;
>  	if (ifp->if_flags & XFS_IFBROOT) {
> -		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +		ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
>  		cur->bc_ino.flags = 0;
>  	} else
> @@ -5567,10 +5556,10 @@ __xfs_bunmapi(
>  	 * logging the extent records if we've converted to btree format.
>  	 */
>  	if ((logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~xfs_ilog_fbroot(whichfork);
>  	/*
>  	 * Log inode even in the error case, if the transaction
> @@ -5781,7 +5770,7 @@ xfs_bmap_collapse_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5898,7 +5887,7 @@ xfs_bmap_insert_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5992,18 +5981,18 @@ xfs_bmap_split_extent(
>  	xfs_fileoff_t		split_fsb)
>  {
>  	int				whichfork = XFS_DATA_FORK;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_cur		*cur = NULL;
>  	struct xfs_bmbt_irec		got;
>  	struct xfs_bmbt_irec		new; /* split extent */
>  	struct xfs_mount		*mp = ip->i_mount;
> -	struct xfs_ifork		*ifp;
>  	xfs_fsblock_t			gotblkcnt; /* new block count for got */
>  	struct xfs_iext_cursor		icur;
>  	int				error = 0;
>  	int				logflags = 0;
>  	int				i = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -6011,7 +6000,6 @@ xfs_bmap_split_extent(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		/* Read in all the extents */
>  		error = xfs_iread_extents(tp, ip, whichfork);
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index 295a59cf88407..d9c63f17d2dec 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -636,10 +636,7 @@ xfs_bmbt_change_owner(
>  
>  	ASSERT(tp || buffer_list);
>  	ASSERT(!(tp && buffer_list));
> -	if (whichfork == XFS_DATA_FORK)
> -		ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE);
> -	else
> -		ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE);
> +	ASSERT(XFS_IFORK_PTR(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
>  
>  	cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
>  	if (!cur)
> diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
> index dd6fcaaea318a..612a9c5e41b1c 100644
> --- a/fs/xfs/libxfs/xfs_dir2.c
> +++ b/fs/xfs/libxfs/xfs_dir2.c
> @@ -278,7 +278,7 @@ xfs_dir_createname(
>  	if (!inum)
>  		args->op_flags |= XFS_DA_OP_JUSTCHECK;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_addname(args);
>  		goto out_free;
>  	}
> @@ -373,7 +373,7 @@ xfs_dir_lookup(
>  		args->op_flags |= XFS_DA_OP_CILOOKUP;
>  
>  	lock_mode = xfs_ilock_data_map_shared(dp);
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_lookup(args);
>  		goto out_check_rval;
>  	}
> @@ -443,7 +443,7 @@ xfs_dir_removename(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_removename(args);
>  		goto out_free;
>  	}
> @@ -504,7 +504,7 @@ xfs_dir_replace(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_replace(args);
>  		goto out_free;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
> index 7b7f6fb2ea3b2..2463b5d734472 100644
> --- a/fs/xfs/libxfs/xfs_dir2_sf.c
> +++ b/fs/xfs/libxfs/xfs_dir2_sf.c
> @@ -343,7 +343,7 @@ xfs_dir2_block_to_sf(
>  	 */
>  	ASSERT(dp->i_df.if_bytes == 0);
>  	xfs_init_local_fork(dp, XFS_DATA_FORK, sfp, size);
> -	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +	dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  	dp->i_d.di_size = size;
>  
>  	logflags |= XFS_ILOG_DDATA;
> @@ -710,11 +710,11 @@ xfs_dir2_sf_verify(
>  	struct xfs_inode		*ip)
>  {
>  	struct xfs_mount		*mp = ip->i_mount;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	struct xfs_dir2_sf_hdr		*sfp;
>  	struct xfs_dir2_sf_entry	*sfep;
>  	struct xfs_dir2_sf_entry	*next_sfep;
>  	char				*endp;
> -	struct xfs_ifork		*ifp;
>  	xfs_ino_t			ino;
>  	int				i;
>  	int				i8count;
> @@ -723,9 +723,8 @@ xfs_dir2_sf_verify(
>  	int				error;
>  	uint8_t				filetype;
>  
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
>  
> @@ -827,9 +826,9 @@ xfs_dir2_sf_create(
>  	 * If it's currently a zero-length extent file,
>  	 * convert it to local format.
>  	 */
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS) {
>  		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
>  		dp->i_df.if_flags |= XFS_IFINLINE;
>  	}
> @@ -1027,7 +1026,7 @@ xfs_dir2_sf_replace_needblock(
>  	int			newsize;
>  	struct xfs_dir2_sf_hdr	*sfp;
>  
> -	if (dp->i_d.di_format != XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format != XFS_DINODE_FMT_LOCAL)
>  		return false;
>  
>  	sfp = (struct xfs_dir2_sf_hdr *)dp->i_df.if_u1.if_data;
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index a374e2a81e764..ab555671e1543 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -225,7 +225,6 @@ xfs_inode_from_disk(
>  					be16_to_cpu(from->di_projid_lo);
>  	}
>  
> -	to->di_format = from->di_format;
>  	i_uid_write(inode, be32_to_cpu(from->di_uid));
>  	i_gid_write(inode, be32_to_cpu(from->di_gid));
>  
> @@ -246,7 +245,6 @@ xfs_inode_from_disk(
>  	to->di_nblocks = be64_to_cpu(from->di_nblocks);
>  	to->di_extsize = be32_to_cpu(from->di_extsize);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat	= from->di_aformat;
>  	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
>  	to->di_dmstate	= be16_to_cpu(from->di_dmstate);
>  	to->di_flags	= be16_to_cpu(from->di_flags);
> @@ -289,7 +287,7 @@ xfs_inode_to_disk(
>  	to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
>  	to->di_onlink = 0;
>  
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = cpu_to_be32(i_uid_read(inode));
>  	to->di_gid = cpu_to_be32(i_gid_read(inode));
>  	to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
> @@ -312,7 +310,7 @@ xfs_inode_to_disk(
>  	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
>  	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
>  	to->di_dmstate = cpu_to_be16(from->di_dmstate);
>  	to->di_flags = cpu_to_be16(from->di_flags);
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
> index fecccfb26463c..865ac493c72a2 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.h
> +++ b/fs/xfs/libxfs/xfs_inode_buf.h
> @@ -16,14 +16,12 @@ struct xfs_dinode;
>   * format specific structures at the appropriate time.
>   */
>  struct xfs_icdinode {
> -	int8_t		di_format;	/* format of di_c data */
>  	uint16_t	di_flushiter;	/* incremented on flush */
>  	uint32_t	di_projid;	/* owner's project id */
>  	xfs_fsize_t	di_size;	/* number of bytes in file */
>  	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
>  	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
>  	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
> -	int8_t		di_aformat;	/* format of attr fork's data */
>  	uint32_t	di_dmevmask;	/* DMIG event mask */
>  	uint16_t	di_dmstate;	/* DMIG state info */
>  	uint16_t	di_flags;	/* random flags, XFS_DIFLAG_... */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 195da3552c5b5..6562f2bcd15cc 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -228,6 +228,7 @@ xfs_iformat_data_fork(
>  	struct inode		*inode = VFS_I(ip);
>  	int			error;
>  
> +	ip->i_df.if_format = dip->di_format;
>  	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
>  
>  	switch (inode->i_mode & S_IFMT) {
> @@ -241,7 +242,7 @@ xfs_iformat_data_fork(
>  	case S_IFREG:
>  	case S_IFLNK:
>  	case S_IFDIR:
> -		switch (dip->di_format) {
> +		switch (ip->i_df.if_format) {
>  		case XFS_DINODE_FMT_LOCAL:
>  			error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
>  					be64_to_cpu(dip->di_size));
> @@ -283,9 +284,12 @@ xfs_iformat_attr_fork(
>  	int			error = 0;
>  
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> +	ip->i_afp->if_format = dip->di_aformat;
> +	if (unlikely(ip->i_afp->if_format == 0)) /* pre IRIX 6.2 file system */
> +		ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
>  
> -	switch (dip->di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
>  				xfs_dfork_attr_shortform_size(dip));
> @@ -508,7 +512,7 @@ xfs_idestroy_fork(
>  	 * not local then we may or may not have an extents list,
>  	 * so check and free it up if we do.
>  	 */
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		if (ifp->if_u1.if_data != NULL) {
>  			kmem_free(ifp->if_u1.if_data);
>  			ifp->if_u1.if_data = NULL;
> @@ -605,7 +609,7 @@ xfs_iflush_fork(
>  	}
>  	cp = XFS_DFORK_PTR(dip, whichfork);
>  	mp = ip->i_mount;
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		if ((iip->ili_fields & dataflag[whichfork]) &&
>  		    (ifp->if_bytes > 0)) {
> @@ -678,7 +682,7 @@ xfs_ifork_init_cow(
>  	ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
>  				       KM_NOFS);
>  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
>  }
>  
>  /* Verify the inline contents of the data fork of an inode. */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index a69d425fe68df..d849cca103edd 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -23,6 +23,7 @@ struct xfs_ifork {
>  	} if_u1;
>  	short			if_broot_bytes;	/* bytes allocated for root */
>  	unsigned char		if_flags;	/* per-fork flags */
> +	int8_t			if_format;	/* format of this fork */
>  	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
>  };
>  
> @@ -56,24 +57,14 @@ struct xfs_ifork {
>  		((w) == XFS_ATTR_FORK ? \
>  			XFS_IFORK_ASIZE(ip) : \
>  			0))
> -#define XFS_IFORK_FORMAT(ip,w) \
> -	((w) == XFS_DATA_FORK ? \
> -		(ip)->i_d.di_format : \
> -		((w) == XFS_ATTR_FORK ? \
> -			(ip)->i_d.di_aformat : \
> -			(ip)->i_cformat))
> -#define XFS_IFORK_FMT_SET(ip,w,n) \
> -	((w) == XFS_DATA_FORK ? \
> -		((ip)->i_d.di_format = (n)) : \
> -		((w) == XFS_ATTR_FORK ? \
> -			((ip)->i_d.di_aformat = (n)) : \
> -			((ip)->i_cformat = (n))))
>  #define XFS_IFORK_MAXEXT(ip, w) \
>  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
>  
> -#define xfs_ifork_has_extents(ip, w) \
> -	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
> -	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
> +static inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp)
> +{
> +	return ifp->if_format == XFS_DINODE_FMT_EXTENTS ||
> +		ifp->if_format == XFS_DINODE_FMT_BTREE;
> +}
>  
>  static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  {
> @@ -82,6 +73,13 @@ static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  	return ifp->if_nextents;
>  }
>  
> +static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
> +{
> +	if (!ifp)
> +		return XFS_DINODE_FMT_EXTENTS;
> +	return ifp->if_format;
> +}
> +
>  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
>  
>  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
> index 3b8260ca7d1b8..594bc447a7dd2 100644
> --- a/fs/xfs/libxfs/xfs_symlink_remote.c
> +++ b/fs/xfs/libxfs/xfs_symlink_remote.c
> @@ -204,16 +204,12 @@ xfs_failaddr_t
>  xfs_symlink_shortform_verify(
>  	struct xfs_inode	*ip)
>  {
> -	char			*sfp;
> -	char			*endp;
> -	struct xfs_ifork	*ifp;
> -	int			size;
> -
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> -	sfp = (char *)ifp->if_u1.if_data;
> -	size = ifp->if_bytes;
> -	endp = sfp + size;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +	char			*sfp = (char *)ifp->if_u1.if_data;
> +	int			size = ifp->if_bytes;
> +	char			*endp = sfp + size;
> +
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	/*
>  	 * Zero length symlinks should never occur in memory as they are
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index 157f72efec5e9..dfa1533b4edfc 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
>  		size = 0;
>  		break;
>  	}
> -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
>  	    (size == 0 || ifp->if_nextents > 0))
>  		return 0;
>  
> @@ -664,7 +664,7 @@ xchk_bmap(
>  	}
>  
>  	/* Check the fork values */
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_UUID:
>  	case XFS_DINODE_FMT_DEV:
>  	case XFS_DINODE_FMT_LOCAL:
> diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
> index 9a2e27ac13003..44b15015021f3 100644
> --- a/fs/xfs/scrub/dabtree.c
> +++ b/fs/xfs/scrub/dabtree.c
> @@ -468,7 +468,7 @@ xchk_da_btree(
>  	int				error;
>  
>  	/* Skip short format data structures; no btree to scan. */
> -	if (!xfs_ifork_has_extents(sc->ip, whichfork))
> +	if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
>  		return 0;
>  
>  	/* Set up initial da state. */
> diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
> index fe2a6e030c8a0..7c432997edade 100644
> --- a/fs/xfs/scrub/dir.c
> +++ b/fs/xfs/scrub/dir.c
> @@ -635,7 +635,7 @@ xchk_directory_blocks(
>  {
>  	struct xfs_bmbt_irec	got;
>  	struct xfs_da_args	args;
> -	struct xfs_ifork	*ifp;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	struct xfs_mount	*mp = sc->mp;
>  	xfs_fileoff_t		leaf_lblk;
>  	xfs_fileoff_t		free_lblk;
> @@ -647,11 +647,10 @@ xchk_directory_blocks(
>  	int			error;
>  
>  	/* Ignore local format directories. */
> -	if (sc->ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
> -	    sc->ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 0;
>  
> -	ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
>  	leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
>  	free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 9d9cebf187268..2834cbf1212e5 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -382,7 +382,7 @@ xfs_map_blocks(
>  	 */
>  retry:
>  	xfs_ilock(ip, XFS_ILOCK_SHARED);
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       (ip->i_df.if_flags & XFS_IFEXTENTS));
>  
>  	/*
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index c42f90e16b4fa..00ffc46c0bf71 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -367,7 +367,7 @@ xfs_attr_inactive(
>  	 * removal below.
>  	 */
>  	if (xfs_inode_hasattr(dp) &&
> -	    dp->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    dp->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_attr3_root_inactive(&trans, dp);
>  		if (error)
>  			goto out_cancel;
> diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
> index 5ff1d929d3b5f..e380bd1a9bfc9 100644
> --- a/fs/xfs/xfs_attr_list.c
> +++ b/fs/xfs/xfs_attr_list.c
> @@ -512,9 +512,9 @@ xfs_attr_list_ilocked(
>  	 */
>  	if (!xfs_inode_hasattr(dp))
>  		return 0;
> -	else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_list(context);
> -	else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
> +	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_list(context);
>  	return xfs_attr_node_list(context);
>  }
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 4f277a6253b8d..5e32c3cf8e8c1 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -223,7 +223,7 @@ xfs_bmap_count_blocks(
>  	if (!ifp)
>  		return 0;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_BTREE:
>  		if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  			error = xfs_iread_extents(tp, ip, whichfork);
> @@ -449,7 +449,7 @@ xfs_getbmap(
>  		break;
>  	}
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  	case XFS_DINODE_FMT_BTREE:
>  		break;
> @@ -1210,17 +1210,19 @@ xfs_swap_extents_check_format(
>  	struct xfs_inode	*ip,	/* target inode */
>  	struct xfs_inode	*tip)	/* tmp inode */
>  {
> +	struct xfs_ifork	*ifp = &ip->i_df;
> +	struct xfs_ifork	*tifp = &tip->i_df;
>  
>  	/* Should never get a local format */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
> -	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    tifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return -EINVAL;
>  
>  	/*
>  	 * if the target inode has less extents that then temporary inode then
>  	 * why did userspace call us?
>  	 */
> -	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
> +	if (ifp->if_nextents < tifp->if_nextents)
>  		return -EINVAL;
>  
>  	/*
> @@ -1235,18 +1237,18 @@ xfs_swap_extents_check_format(
>  	 * form then we will end up with the target inode in the wrong format
>  	 * as we already know there are less extents in the temp inode.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_format == XFS_DINODE_FMT_BTREE)
>  		return -EINVAL;
>  
>  	/* Check temp in extent form to max in target */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +	if (tifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/* Check target in extent form to max in temp */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/*
> @@ -1258,22 +1260,20 @@ xfs_swap_extents_check_format(
>  	 * (a common defrag case) which will occur when the temp inode is in
>  	 * extent format...
>  	 */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (tifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(ip) &&
> -		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
> +		    XFS_BMAP_BMDR_SPACE(tifp->if_broot) > XFS_IFORK_BOFF(ip))
>  			return -EINVAL;
> -		if (tip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +		if (tifp->if_nextents <= XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
>  	/* Reciprocal target->temp btree format checks */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(tip) &&
>  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
>  			return -EINVAL;
> -		if (ip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +		if (ifp->if_nextents <= XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
> @@ -1426,14 +1426,14 @@ xfs_swap_extent_forks(
>  	 * Count the number of extended attribute blocks
>  	 */
>  	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> -	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
>  				&aforkblks);
>  		if (error)
>  			return error;
>  	}
>  	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> -	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
>  				&taforkblks);
>  		if (error)
> @@ -1448,9 +1448,9 @@ xfs_swap_extent_forks(
>  	 * bmbt scan as the last step.
>  	 */
>  	if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
> -		if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*target_log_flags) |= XFS_ILOG_DOWNER;
> -		if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*src_log_flags) |= XFS_ILOG_DOWNER;
>  	}
>  
> @@ -1466,8 +1466,6 @@ xfs_swap_extent_forks(
>  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
>  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
>  
> -	swap(ip->i_d.di_format, tip->i_d.di_format);
> -
>  	/*
>  	 * The extents in the source inode could still contain speculative
>  	 * preallocation beyond EOF (e.g. the file is open but not modified
> @@ -1481,7 +1479,7 @@ xfs_swap_extent_forks(
>  	tip->i_delayed_blks = ip->i_delayed_blks;
>  	ip->i_delayed_blks = 0;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*src_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1492,7 +1490,7 @@ xfs_swap_extent_forks(
>  		break;
>  	}
>  
> -	switch (tip->i_d.di_format) {
> +	switch (tip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*target_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1714,8 +1712,10 @@ xfs_swap_extents(
>  
>  	/* Swap the cow forks. */
>  	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
> -		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> -		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!ip->i_cowfp ||
> +		       ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!tip->i_cowfp ||
> +		       tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  		swap(ip->i_cowfp, tip->i_cowfp);
>  
> diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
> index 871ec22c9aee9..66deddd5e2969 100644
> --- a/fs/xfs/xfs_dir2_readdir.c
> +++ b/fs/xfs/xfs_dir2_readdir.c
> @@ -524,7 +524,7 @@ xfs_readdir(
>  	args.geo = dp->i_mount->m_dir_geo;
>  	args.trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
>  		rval = xfs_dir2_sf_getdents(&args, ctx);
>  	else if ((rval = xfs_dir2_isblock(&args, &v)))
>  		;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 791d5d5e318cf..c09b3e9eab1da 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -63,7 +63,6 @@ xfs_inode_alloc(
>  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
>  	ip->i_afp = NULL;
>  	ip->i_cowfp = NULL;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
>  	memset(&ip->i_df, 0, sizeof(ip->i_df));
>  	ip->i_flags = 0;
>  	ip->i_delayed_blks = 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 1677c4e7207ed..64f5f9a440aed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -112,7 +112,7 @@ xfs_ilock_data_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_df.if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -125,7 +125,8 @@ xfs_ilock_attr_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_afp &&
> +	    ip->i_afp->if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_afp->if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -851,7 +852,7 @@ xfs_ialloc(
>  	case S_IFCHR:
>  	case S_IFBLK:
>  	case S_IFSOCK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_DEV;
> +		ip->i_df.if_format = XFS_DINODE_FMT_DEV;
>  		ip->i_df.if_flags = 0;
>  		flags |= XFS_ILOG_DEV;
>  		break;
> @@ -907,7 +908,7 @@ xfs_ialloc(
>  		}
>  		/* FALLTHROUGH */
>  	case S_IFLNK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> +		ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  		ip->i_df.if_flags = XFS_IFEXTENTS;
>  		ip->i_df.if_bytes = 0;
>  		ip->i_df.if_u1.if_root = NULL;
> @@ -915,10 +916,6 @@ xfs_ialloc(
>  	default:
>  		ASSERT(0);
>  	}
> -	/*
> -	 * Attribute fork settings for new inode.
> -	 */
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	/*
>  	 * Log the new values stuffed into the inode.
> @@ -2749,7 +2746,7 @@ xfs_ifree(
>  	 * data fork to extents format.  Note that the attr fork data has
>  	 * already been freed by xfs_attr_inactive.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		kmem_free(ip->i_df.if_u1.if_data);
>  		ip->i_df.if_u1.if_data = NULL;
>  		ip->i_df.if_bytes = 0;
> @@ -2760,8 +2757,7 @@ xfs_ifree(
>  	ip->i_d.di_flags2 = 0;
>  	ip->i_d.di_dmevmask = 0;
>  	ip->i_d.di_forkoff = 0;		/* mark the attr fork not in use */
> -	ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  
>  	/* Don't attempt to replay owner changes for a deleted inode */
>  	ip->i_itemp->ili_fields &= ~(XFS_ILOG_AOWNER|XFS_ILOG_DOWNER);
> @@ -3624,7 +3620,7 @@ xfs_iflush(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  
>  	*bpp = NULL;
> @@ -3706,7 +3702,7 @@ xfs_iflush_int(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  	ASSERT(iip != NULL && iip->ili_fields != 0);
>  
> @@ -3728,8 +3724,8 @@ xfs_iflush_int(
>  	}
>  	if (S_ISREG(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE,
>  		    mp, XFS_ERRTAG_IFLUSH_3)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad regular inode %Lu, ptr "PTR_FMT,
> @@ -3738,9 +3734,9 @@ xfs_iflush_int(
>  		}
>  	} else if (S_ISDIR(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_LOCAL,
>  		    mp, XFS_ERRTAG_IFLUSH_4)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad directory inode %Lu, ptr "PTR_FMT,
> @@ -3782,10 +3778,10 @@ xfs_iflush_int(
>  	 * If there are inline format data / attr forks attached to this inode,
>  	 * make sure they are not corrupt.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_data(ip))
>  		goto flush_out;
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_afp && ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_attr(ip))
>  		goto flush_out;
>  
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 24dae63ba16c0..dadcf19458960 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -57,8 +57,6 @@ typedef struct xfs_inode {
>  
>  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
>  
> -	unsigned int		i_cformat;	/* format of cow fork */
> -
>  	/* VFS inode */
>  	struct inode		i_vnode;	/* embedded VFS inode */
>  
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index 401ba26aeed7b..ba47bf65b772b 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -36,7 +36,7 @@ xfs_inode_item_data_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
>  		    ip->i_df.if_nextents > 0 &&
> @@ -77,7 +77,7 @@ xfs_inode_item_attr_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
>  		    ip->i_afp->if_nextents > 0 &&
> @@ -142,7 +142,7 @@ xfs_inode_item_format_data_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
> @@ -227,7 +227,7 @@ xfs_inode_item_format_attr_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
> @@ -305,7 +305,7 @@ xfs_inode_to_log_dinode(
>  	struct inode		*inode = VFS_I(ip);
>  
>  	to->di_magic = XFS_DINODE_MAGIC;
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = i_uid_read(inode);
>  	to->di_gid = i_gid_read(inode);
>  	to->di_projid_lo = from->di_projid & 0xffff;
> @@ -329,7 +329,7 @@ xfs_inode_to_log_dinode(
>  	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
>  	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = from->di_dmevmask;
>  	to->di_dmstate = from->di_dmstate;
>  	to->di_flags = from->di_flags;
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index b4fd918749e5f..6ae3a2457777a 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -856,7 +856,7 @@ xfs_buffered_write_iomap_begin(
>  
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, XFS_DATA_FORK)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(&ip->i_df)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		error = -EFSCORRUPTED;
>  		goto out_unlock;
> @@ -1263,7 +1263,7 @@ xfs_xattr_iomap_begin(
>  		goto out_unlock;
>  	}
>  
> -	ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL);
>  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
>  			       &nimaps, XFS_BMAPI_ATTRFORK);
>  out_unlock:
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 80da86c5703fb..16ca97a7ff00f 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -115,7 +115,7 @@ xfs_bulkstat_one_int(
>  			buf->bs_cowextsize_blks = dic->di_cowextsize;
>  	}
>  
> -	switch (dic->di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
>  		buf->bs_blksize = BLKDEV_IOSIZE;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 8cf2fcb509c12..8e88a7ca387ea 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -251,7 +251,7 @@ xfs_symlink(
>  		xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
>  
>  		ip->i_d.di_size = pathlen;
> -		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
>  	} else {
>  		int	offset;
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index ba2ab69e1fc7d..460136628a795 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -1897,7 +1897,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
>  		__entry->dev = VFS_I(ip)->i_sb->s_dev;
>  		__entry->which = which;
>  		__entry->ino = ip->i_ino;
> -		__entry->format = ip->i_d.di_format;
> +		__entry->format = ip->i_df.if_format;
>  		__entry->nex = ip->i_df.if_nextents;
>  		__entry->broot_size = ip->i_df.if_broot_bytes;
>  		__entry->fork_off = XFS_IFORK_BOFF(ip);
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-10  7:24 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
@ 2020-05-12  9:48   ` Chandan Babu R
  2020-05-12 18:54   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Chandan Babu R @ 2020-05-12  9:48 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sunday 10 May 2020 12:54:04 PM IST Christoph Hellwig wrote:
> Move freeing the dynamically allocated attr and COW fork, as well
> as zeroing the pointers where actually needed into the callers, and
> just pass the xfs_ifork structure to xfs_idestroy_fork.  Simplify
> the kmem_free calls by not checking for NULL first, and not zeroing
> the pointers in structure that are about to be freed (either the
> ifork or the containing inode in case of the data fork).
>

The changes look good to me.

Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
>  fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
>  fs/xfs/libxfs/xfs_inode_fork.c | 36 +++++++++-------------------------
>  fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
>  fs/xfs/xfs_attr_inactive.c     |  7 +++++--
>  fs/xfs/xfs_icache.c            | 15 ++++++++------
>  6 files changed, 28 insertions(+), 41 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index d7f3173ce3c31..8d775942f1c6c 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -716,11 +716,10 @@ xfs_attr_fork_remove(
>  	struct xfs_inode	*ip,
>  	struct xfs_trans	*tp)
>  {
> -	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> +	xfs_idestroy_fork(ip->i_afp);
> +	kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> +	ip->i_afp = NULL;
>  	ip->i_d.di_forkoff = 0;
> -
> -	ASSERT(ip->i_afp == NULL);
> -
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index ab555671e1543..6f84ea85fdd83 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -271,7 +271,7 @@ xfs_inode_from_disk(
>  	return 0;
>  
>  out_destroy_data_fork:
> -	xfs_idestroy_fork(ip, XFS_DATA_FORK);
> +	xfs_idestroy_fork(&ip->i_df);
>  	return error;
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 6562f2bcd15cc..577cc20e03170 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -495,38 +495,20 @@ xfs_idata_realloc(
>  
>  void
>  xfs_idestroy_fork(
> -	xfs_inode_t	*ip,
> -	int		whichfork)
> +	struct xfs_ifork	*ifp)
>  {
> -	struct xfs_ifork	*ifp;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	if (ifp->if_broot != NULL) {
> -		kmem_free(ifp->if_broot);
> -		ifp->if_broot = NULL;
> -	}
> +	kmem_free(ifp->if_broot);
>  
>  	/*
> -	 * If the format is local, then we can't have an extents
> -	 * array so just look for an inline data array.  If we're
> -	 * not local then we may or may not have an extents list,
> -	 * so check and free it up if we do.
> +	 * If the format is local, then we can't have an extents array so just
> +	 * look for an inline data array.  If we're not local then we may or may
> +	 * not have an extents list, so check and free it up if we do.
>  	 */
>  	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
> -		if (ifp->if_u1.if_data != NULL) {
> -			kmem_free(ifp->if_u1.if_data);
> -			ifp->if_u1.if_data = NULL;
> -		}
> -	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
> -		xfs_iext_destroy(ifp);
> -	}
> -
> -	if (whichfork == XFS_ATTR_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> -		ip->i_afp = NULL;
> -	} else if (whichfork == XFS_COW_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> -		ip->i_cowfp = NULL;
> +		kmem_free(ifp->if_u1.if_data);
> +	} else if (ifp->if_flags & XFS_IFEXTENTS) {
> +		if (ifp->if_height)
> +			xfs_iext_destroy(ifp);
>  	}
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index d849cca103edd..a4953e95c4f3f 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
>  int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
>  void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
>  				struct xfs_inode_log_item *, int);
> -void		xfs_idestroy_fork(struct xfs_inode *, int);
> +void		xfs_idestroy_fork(struct xfs_ifork *ifp);
>  void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
>  				int whichfork);
>  void		xfs_iroot_realloc(struct xfs_inode *, int, int);
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index 00ffc46c0bf71..bfad669e6b2f8 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -388,8 +388,11 @@ xfs_attr_inactive(
>  	xfs_trans_cancel(trans);
>  out_destroy_fork:
>  	/* kill the in-core attr fork before we drop the inode lock */
> -	if (dp->i_afp)
> -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
> +	if (dp->i_afp) {
> +		xfs_idestroy_fork(dp->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
> +		dp->i_afp = NULL;
> +	}
>  	if (lock_mode)
>  		xfs_iunlock(dp, lock_mode);
>  	return error;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index c09b3e9eab1da..d806d3bfa8936 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -87,15 +87,18 @@ xfs_inode_free_callback(
>  	case S_IFREG:
>  	case S_IFDIR:
>  	case S_IFLNK:
> -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
> +		xfs_idestroy_fork(&ip->i_df);
>  		break;
>  	}
>  
> -	if (ip->i_afp)
> -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> -	if (ip->i_cowfp)
> -		xfs_idestroy_fork(ip, XFS_COW_FORK);
> -
> +	if (ip->i_afp) {
> +		xfs_idestroy_fork(ip->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> +	}
> +	if (ip->i_cowfp) {
> +		xfs_idestroy_fork(ip->i_cowfp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> +	}
>  	if (ip->i_itemp) {
>  		ASSERT(!test_bit(XFS_LI_IN_AIL,
>  				 &ip->i_itemp->ili_item.li_flags));
> 


-- 
chandan




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-11 11:40   ` Chandan Babu R
@ 2020-05-12 15:31     ` Brian Foster
  2020-05-12 15:38       ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Brian Foster @ 2020-05-12 15:31 UTC (permalink / raw)
  To: Chandan Babu R; +Cc: Christoph Hellwig, linux-xfs

On Mon, May 11, 2020 at 05:10:04PM +0530, Chandan Babu R wrote:
> On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> > XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> > doesn't make a difference in practice as size is only checked for
> > 0, but this keeps the logic sane.
> >
> 
> Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
> attr fork inside an inode's literal area?
> 

I had the same thought. It's not clear to me what size is really
supposed to be between the file size for a data fork and fork offset for
the attr fork. I was also wondering if this should use
XFS_IFORK_DSIZE(), but that won't be conditional based on population of
the fork. At the same time, I don't think i_size != 0 necessarily
correlates with the existence of blocks. The file could be completely
sparse or could have any number of post-eof preallocated extents.

Brian

> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  fs/xfs/scrub/bmap.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > index add8598eacd5d..283424d6d2bb6 100644
> > --- a/fs/xfs/scrub/bmap.c
> > +++ b/fs/xfs/scrub/bmap.c
> > @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
> >  		size = i_size_read(VFS_I(sc->ip));
> >  		break;
> >  	case XFS_ATTR_FORK:
> > -		size = XFS_IFORK_Q(sc->ip);
> > +		size = XFS_IFORK_BOFF(sc->ip);
> >  		break;
> >  	default:
> >  		size = 0;
> > 
> 
> 
> -- 
> chandan
> 
> 
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro
  2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
  2020-05-11 12:39   ` Chandan Babu R
@ 2020-05-12 15:31   ` Brian Foster
  2020-05-16 18:02   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2020-05-12 15:31 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:00AM +0200, Christoph Hellwig wrote:
> Just checking di_forkoff directly is a little easier to follow.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_format.h    | 5 ++---
>  fs/xfs/libxfs/xfs_inode_buf.c | 6 +++---
>  2 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 045556e78ee2c..3cc352000b8a1 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -964,13 +964,12 @@ enum xfs_dinode_fmt {
>  /*
>   * Inode data & attribute fork sizes, per inode.
>   */
> -#define XFS_DFORK_Q(dip)		((dip)->di_forkoff != 0)
>  #define XFS_DFORK_BOFF(dip)		((int)((dip)->di_forkoff << 3))
>  
>  #define XFS_DFORK_DSIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
> +	((dip)->di_forkoff ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
>  #define XFS_DFORK_ASIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
> +	((dip)->di_forkoff ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
>  #define XFS_DFORK_SIZE(dip,mp,w) \
>  	((w) == XFS_DATA_FORK ? \
>  		XFS_DFORK_DSIZE(dip, mp) : \
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index 05f939adea944..5547bbb3cf945 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -265,7 +265,7 @@ xfs_inode_from_disk(
>  	error = xfs_iformat_data_fork(ip, from);
>  	if (error)
>  		return error;
> -	if (XFS_DFORK_Q(from)) {
> +	if (from->di_forkoff) {
>  		error = xfs_iformat_attr_fork(ip, from);
>  		if (error)
>  			goto out_destroy_data_fork;
> @@ -435,7 +435,7 @@ xfs_dinode_verify_forkoff(
>  	struct xfs_dinode	*dip,
>  	struct xfs_mount	*mp)
>  {
> -	if (!XFS_DFORK_Q(dip))
> +	if (!dip->di_forkoff)
>  		return NULL;
>  
>  	switch (dip->di_format)  {
> @@ -538,7 +538,7 @@ xfs_dinode_verify(
>  		return __this_address;
>  	}
>  
> -	if (XFS_DFORK_Q(dip)) {
> +	if (dip->di_forkoff) {
>  		fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
>  		if (fa)
>  			return fa;
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 3/6] xfs: remove xfs_ifree_local_data
  2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
  2020-05-11 16:32   ` Chandan Babu R
@ 2020-05-12 15:31   ` Brian Foster
  2020-05-16 18:07   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2020-05-12 15:31 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:01AM +0200, Christoph Hellwig wrote:
> xfs_ifree only need to free inline data in the data fork, as we've
> already taken care of the attr fork before (and in fact freed the
> fork structure).  Just open code the freeing of the inline data.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_inode.c | 30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 549ff468b7b60..7d3144dc99b72 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2711,24 +2711,6 @@ xfs_ifree_cluster(
>  	return 0;
>  }
>  
> -/*
> - * Free any local-format buffers sitting around before we reset to
> - * extents format.
> - */
> -static inline void
> -xfs_ifree_local_data(
> -	struct xfs_inode	*ip,
> -	int			whichfork)
> -{
> -	struct xfs_ifork	*ifp;
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
> -		return;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
> -}
> -
>  /*
>   * This is called to return an inode to the inode free list.
>   * The inode should already be truncated to 0 length and have
> @@ -2765,8 +2747,16 @@ xfs_ifree(
>  	if (error)
>  		return error;
>  
> -	xfs_ifree_local_data(ip, XFS_DATA_FORK);
> -	xfs_ifree_local_data(ip, XFS_ATTR_FORK);
> +	/*
> +	 * Free any local-format data sitting around before we reset the
> +	 * data fork to extents format.  Note that the attr fork data has
> +	 * already been freed by xfs_attr_inactive.
> +	 */
> +	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +		kmem_free(ip->i_df.if_u1.if_data);
> +		ip->i_df.if_u1.if_data = NULL;
> +		ip->i_df.if_bytes = 0;
> +	}
>  
>  	VFS_I(ip)->i_mode = 0;		/* mark incore inode as free */
>  	ip->i_d.di_flags = 0;
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-12 15:31     ` Brian Foster
@ 2020-05-12 15:38       ` Darrick J. Wong
  2020-05-12 16:14         ` Brian Foster
  0 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-12 15:38 UTC (permalink / raw)
  To: Brian Foster; +Cc: Chandan Babu R, Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 11:31:32AM -0400, Brian Foster wrote:
> On Mon, May 11, 2020 at 05:10:04PM +0530, Chandan Babu R wrote:
> > On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> > > XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> > > doesn't make a difference in practice as size is only checked for
> > > 0, but this keeps the logic sane.
> > >
> > 
> > Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
> > attr fork inside an inode's literal area?
> > 
> 
> I had the same thought. It's not clear to me what size is really
> supposed to be between the file size for a data fork and fork offset for
> the attr fork. I was also wondering if this should use
> XFS_IFORK_DSIZE(), but that won't be conditional based on population of
> the fork. At the same time, I don't think i_size != 0 necessarily
> correlates with the existence of blocks. The file could be completely
> sparse or could have any number of post-eof preallocated extents.

TBH I should have made that variable "bool empty" or something.

case XFS_DATA_FORK:
	empty = i_size_read() == 0;

case XFS_ATTR_FORK:
	empty = !XFS_IFORK_Q();

default:
	empty = true;

if ((is not btree) && (empty || nextents > 0))
	return 0;

--D

> Brian
> 
> > > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > > ---
> > >  fs/xfs/scrub/bmap.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > index add8598eacd5d..283424d6d2bb6 100644
> > > --- a/fs/xfs/scrub/bmap.c
> > > +++ b/fs/xfs/scrub/bmap.c
> > > @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
> > >  		size = i_size_read(VFS_I(sc->ip));
> > >  		break;
> > >  	case XFS_ATTR_FORK:
> > > -		size = XFS_IFORK_Q(sc->ip);
> > > +		size = XFS_IFORK_BOFF(sc->ip);
> > >  		break;
> > >  	default:
> > >  		size = 0;
> > > 
> > 
> > 
> > -- 
> > chandan
> > 
> > 
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork
  2020-05-10  7:24 ` [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork Christoph Hellwig
  2020-05-12  5:26   ` Chandan Babu R
@ 2020-05-12 16:10   ` Brian Foster
  2020-05-16 18:09     ` Darrick J. Wong
  2020-05-17  8:12     ` Christoph Hellwig
  1 sibling, 2 replies; 41+ messages in thread
From: Brian Foster @ 2020-05-12 16:10 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:02AM +0200, Christoph Hellwig wrote:
> There are thee number of extents counters, one for each of the forks,
> Two are in the legacy icdinode and one is directly in struct xfs_inode.
> Switch to a single counter in the xfs_ifork structure where it uses up
> padding at the end of the structure.  This simplifies various bits of
> code that just wants the number of extents counter and can now directly
> dereference it.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr.c       |   4 +-
>  fs/xfs/libxfs/xfs_attr_leaf.c  |   1 -
>  fs/xfs/libxfs/xfs_bmap.c       | 126 ++++++++++++++-------------------
>  fs/xfs/libxfs/xfs_dir2_block.c |   2 +-
>  fs/xfs/libxfs/xfs_inode_buf.c  |   6 +-
>  fs/xfs/libxfs/xfs_inode_buf.h  |   2 -
>  fs/xfs/libxfs/xfs_inode_fork.c |  12 ++--
>  fs/xfs/libxfs/xfs_inode_fork.h |  20 +++---
>  fs/xfs/scrub/bmap.c            |   3 +-
>  fs/xfs/scrub/parent.c          |   2 +-
>  fs/xfs/xfs_bmap_util.c         |  28 ++++----
>  fs/xfs/xfs_file.c              |   2 +-
>  fs/xfs/xfs_icache.c            |   1 -
>  fs/xfs/xfs_inode.c             |  19 +++--
>  fs/xfs/xfs_inode.h             |   1 -
>  fs/xfs/xfs_inode_item.c        |  14 ++--
>  fs/xfs/xfs_ioctl.c             |  25 +++----
>  fs/xfs/xfs_iomap.c             |   2 +-
>  fs/xfs/xfs_iops.c              |   2 +-
>  fs/xfs/xfs_itable.c            |   4 +-
>  fs/xfs/xfs_qm_syscalls.c       |   2 +-
>  fs/xfs/xfs_quotaops.c          |   2 +-
>  fs/xfs/xfs_symlink.c           |   2 +-
>  fs/xfs/xfs_trace.h             |   2 +-
>  24 files changed, 122 insertions(+), 162 deletions(-)
> 
...
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index 863444e2dda7e..64b172180c42c 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -723,7 +723,6 @@ xfs_attr_fork_remove(
>  	ip->i_d.di_forkoff = 0;
>  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
> -	ASSERT(ip->i_d.di_anextents == 0);

Perhaps we could create an analogous assert in xfs_idestroy_fork()?

>  	ASSERT(ip->i_afp == NULL);
>  
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
...
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 2fe325e38fd88..195da3552c5b5 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -188,12 +188,11 @@ xfs_iformat_btree(
>  	 * or the number of extents is greater than the number of
>  	 * blocks.
>  	 */
> -	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
> -					XFS_IFORK_MAXEXT(ip, whichfork) ||
> +	if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
>  		     nrecs == 0 ||
>  		     XFS_BMDR_SPACE_CALC(nrecs) >
>  					XFS_DFORK_SIZE(dip, mp, whichfork) ||
> -		     XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
> +		     ifp->if_nextents > ip->i_d.di_nblocks) ||
>  		     level == 0 || level > XFS_BTREE_MAXLEVELS) {
>  		xfs_warn(mp, "corrupt inode %Lu (btree).",
>  					(unsigned long long) ip->i_ino);
> @@ -229,6 +228,8 @@ xfs_iformat_data_fork(
>  	struct inode		*inode = VFS_I(ip);
>  	int			error;
>  
> +	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
> +

Could use a comment here that the format calls below might depend on
this being set (i.e. xfs_iformat_btree() just above).

>  	switch (inode->i_mode & S_IFMT) {
>  	case S_IFIFO:
>  	case S_IFCHR:
> @@ -282,6 +283,8 @@ xfs_iformat_attr_fork(
>  	int			error = 0;
>  
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> +	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
> +

Same here. Otherwise LGTM:

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  	switch (dip->di_aformat) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
> @@ -617,7 +620,7 @@ xfs_iflush_fork(
>  		       !(iip->ili_fields & extflag[whichfork]));
>  		if ((iip->ili_fields & extflag[whichfork]) &&
>  		    (ifp->if_bytes > 0)) {
> -			ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
> +			ASSERT(ifp->if_nextents > 0);
>  			(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
>  				whichfork);
>  		}
> @@ -676,7 +679,6 @@ xfs_ifork_init_cow(
>  				       KM_NOFS);
>  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
>  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_cnextents = 0;
>  }
>  
>  /* Verify the inline contents of the data fork of an inode. */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index f46a8c1db5964..a69d425fe68df 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -23,6 +23,7 @@ struct xfs_ifork {
>  	} if_u1;
>  	short			if_broot_bytes;	/* bytes allocated for root */
>  	unsigned char		if_flags;	/* per-fork flags */
> +	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
>  };
>  
>  /*
> @@ -67,18 +68,6 @@ struct xfs_ifork {
>  		((w) == XFS_ATTR_FORK ? \
>  			((ip)->i_d.di_aformat = (n)) : \
>  			((ip)->i_cformat = (n))))
> -#define XFS_IFORK_NEXTENTS(ip,w) \
> -	((w) == XFS_DATA_FORK ? \
> -		(ip)->i_d.di_nextents : \
> -		((w) == XFS_ATTR_FORK ? \
> -			(ip)->i_d.di_anextents : \
> -			(ip)->i_cnextents))
> -#define XFS_IFORK_NEXT_SET(ip,w,n) \
> -	((w) == XFS_DATA_FORK ? \
> -		((ip)->i_d.di_nextents = (n)) : \
> -		((w) == XFS_ATTR_FORK ? \
> -			((ip)->i_d.di_anextents = (n)) : \
> -			((ip)->i_cnextents = (n))))
>  #define XFS_IFORK_MAXEXT(ip, w) \
>  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
>  
> @@ -86,6 +75,13 @@ struct xfs_ifork {
>  	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
>  	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
>  
> +static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
> +{
> +	if (!ifp)
> +		return 0;
> +	return ifp->if_nextents;
> +}
> +
>  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
>  
>  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index 283424d6d2bb6..157f72efec5e9 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -566,6 +566,7 @@ xchk_bmap_check_rmaps(
>  	struct xfs_scrub	*sc,
>  	int			whichfork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
>  	loff_t			size;
>  	xfs_agnumber_t		agno;
>  	int			error;
> @@ -598,7 +599,7 @@ xchk_bmap_check_rmaps(
>  		break;
>  	}
>  	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> -	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
> +	    (size == 0 || ifp->if_nextents > 0))
>  		return 0;
>  
>  	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
> diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
> index 5705adc43a75f..855aa8bcab64b 100644
> --- a/fs/xfs/scrub/parent.c
> +++ b/fs/xfs/scrub/parent.c
> @@ -90,7 +90,7 @@ xchk_parent_count_parent_dentries(
>  	 * if there is one.
>  	 */
>  	lock_mode = xfs_ilock_data_map_shared(parent);
> -	if (parent->i_d.di_nextents > 0)
> +	if (parent->i_df.if_nextents > 0)
>  		error = xfs_dir3_data_readahead(parent, 0, 0);
>  	xfs_iunlock(parent, lock_mode);
>  	if (error)
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index cc23a3e23e2d1..4f277a6253b8d 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -1220,7 +1220,7 @@ xfs_swap_extents_check_format(
>  	 * if the target inode has less extents that then temporary inode then
>  	 * why did userspace call us?
>  	 */
> -	if (ip->i_d.di_nextents < tip->i_d.di_nextents)
> +	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
>  		return -EINVAL;
>  
>  	/*
> @@ -1241,14 +1241,12 @@ xfs_swap_extents_check_format(
>  
>  	/* Check temp in extent form to max in target */
>  	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) >
> -			XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/* Check target in extent form to max in temp */
>  	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) >
> -			XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/*
> @@ -1264,7 +1262,7 @@ xfs_swap_extents_check_format(
>  		if (XFS_IFORK_Q(ip) &&
>  		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
>  			return -EINVAL;
> -		if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
> +		if (tip->i_df.if_nextents <=
>  		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
> @@ -1274,7 +1272,7 @@ xfs_swap_extents_check_format(
>  		if (XFS_IFORK_Q(tip) &&
>  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
>  			return -EINVAL;
> -		if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
> +		if (ip->i_df.if_nextents <=
>  		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
> @@ -1427,15 +1425,15 @@ xfs_swap_extent_forks(
>  	/*
>  	 * Count the number of extended attribute blocks
>  	 */
> -	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
> -	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> +	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> +	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
>  				&aforkblks);
>  		if (error)
>  			return error;
>  	}
> -	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
> -	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> +	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> +	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
>  				&taforkblks);
>  		if (error)
> @@ -1468,7 +1466,6 @@ xfs_swap_extent_forks(
>  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
>  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
>  
> -	swap(ip->i_d.di_nextents, tip->i_d.di_nextents);
>  	swap(ip->i_d.di_format, tip->i_d.di_format);
>  
>  	/*
> @@ -1615,9 +1612,9 @@ xfs_swap_extents(
>  	 * performed with log redo items!
>  	 */
>  	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
> -		int		w	= XFS_DATA_FORK;
> -		uint32_t	ipnext	= XFS_IFORK_NEXTENTS(ip, w);
> -		uint32_t	tipnext	= XFS_IFORK_NEXTENTS(tip, w);
> +		int		w = XFS_DATA_FORK;
> +		uint32_t	ipnext = ip->i_df.if_nextents;
> +		uint32_t	tipnext	= tip->i_df.if_nextents;
>  
>  		/*
>  		 * Conceptually this shouldn't affect the shape of either bmbt,
> @@ -1720,7 +1717,6 @@ xfs_swap_extents(
>  		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
>  		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
>  
> -		swap(ip->i_cnextents, tip->i_cnextents);
>  		swap(ip->i_cowfp, tip->i_cowfp);
>  
>  		if (ip->i_cowfp && ip->i_cowfp->if_bytes)
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 4b8bdecc38635..403c90309a8ff 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1102,7 +1102,7 @@ xfs_dir_open(
>  	 * certain to have the next operation be a read there.
>  	 */
>  	mode = xfs_ilock_data_map_shared(ip);
> -	if (ip->i_d.di_nextents > 0)
> +	if (ip->i_df.if_nextents > 0)
>  		error = xfs_dir3_data_readahead(ip, 0, 0);
>  	xfs_iunlock(ip, mode);
>  	return error;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 5a3a520b95288..791d5d5e318cf 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -63,7 +63,6 @@ xfs_inode_alloc(
>  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
>  	ip->i_afp = NULL;
>  	ip->i_cowfp = NULL;
> -	ip->i_cnextents = 0;
>  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
>  	memset(&ip->i_df, 0, sizeof(ip->i_df));
>  	ip->i_flags = 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 7d3144dc99b72..1677c4e7207ed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -825,7 +825,7 @@ xfs_ialloc(
>  		inode->i_mode &= ~S_ISGID;
>  
>  	ip->i_d.di_size = 0;
> -	ip->i_d.di_nextents = 0;
> +	ip->i_df.if_nextents = 0;
>  	ASSERT(ip->i_d.di_nblocks == 0);
>  
>  	tv = current_time(inode);
> @@ -919,7 +919,6 @@ xfs_ialloc(
>  	 * Attribute fork settings for new inode.
>  	 */
>  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_d.di_anextents = 0;
>  
>  	/*
>  	 * Log the new values stuffed into the inode.
> @@ -1686,7 +1685,7 @@ xfs_inactive_truncate(
>  	if (error)
>  		goto error_trans_cancel;
>  
> -	ASSERT(ip->i_d.di_nextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  
>  	error = xfs_trans_commit(tp);
>  	if (error)
> @@ -1836,7 +1835,7 @@ xfs_inactive(
>  
>  	if (S_ISREG(VFS_I(ip)->i_mode) &&
>  	    (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
> -	     ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
> +	     ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
>  		truncate = 1;
>  
>  	error = xfs_qm_dqattach(ip);
> @@ -1862,7 +1861,6 @@ xfs_inactive(
>  	}
>  
>  	ASSERT(!ip->i_afp);
> -	ASSERT(ip->i_d.di_anextents == 0);
>  	ASSERT(ip->i_d.di_forkoff == 0);
>  
>  	/*
> @@ -2731,8 +2729,7 @@ xfs_ifree(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(VFS_I(ip)->i_nlink == 0);
> -	ASSERT(ip->i_d.di_nextents == 0);
> -	ASSERT(ip->i_d.di_anextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  	ASSERT(ip->i_d.di_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
>  	ASSERT(ip->i_d.di_nblocks == 0);
>  
> @@ -3628,7 +3625,7 @@ xfs_iflush(
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
>  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  
>  	*bpp = NULL;
>  
> @@ -3710,7 +3707,7 @@ xfs_iflush_int(
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
>  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  	ASSERT(iip != NULL && iip->ili_fields != 0);
>  
>  	dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
> @@ -3751,13 +3748,13 @@ xfs_iflush_int(
>  			goto flush_out;
>  		}
>  	}
> -	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
> +	if (XFS_TEST_ERROR(ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp) >
>  				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5)) {
>  		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  			"%s: detected corrupt incore inode %Lu, "
>  			"total extents = %d, nblocks = %Ld, ptr "PTR_FMT,
>  			__func__, ip->i_ino,
> -			ip->i_d.di_nextents + ip->i_d.di_anextents,
> +			ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp),
>  			ip->i_d.di_nblocks, ip);
>  		goto flush_out;
>  	}
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index ff846197941e4..24dae63ba16c0 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -57,7 +57,6 @@ typedef struct xfs_inode {
>  
>  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
>  
> -	xfs_extnum_t		i_cnextents;	/* # of extents in cow fork */
>  	unsigned int		i_cformat;	/* format of cow fork */
>  
>  	/* VFS inode */
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index cefa2484f0dbf..401ba26aeed7b 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -39,7 +39,7 @@ xfs_inode_item_data_fork_size(
>  	switch (ip->i_d.di_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> -		    ip->i_d.di_nextents > 0 &&
> +		    ip->i_df.if_nextents > 0 &&
>  		    ip->i_df.if_bytes > 0) {
>  			/* worst case, doesn't subtract delalloc extents */
>  			*nbytes += XFS_IFORK_DSIZE(ip);
> @@ -80,7 +80,7 @@ xfs_inode_item_attr_fork_size(
>  	switch (ip->i_d.di_aformat) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> -		    ip->i_d.di_anextents > 0 &&
> +		    ip->i_afp->if_nextents > 0 &&
>  		    ip->i_afp->if_bytes > 0) {
>  			/* worst case, doesn't subtract unused space */
>  			*nbytes += XFS_IFORK_ASIZE(ip);
> @@ -148,7 +148,7 @@ xfs_inode_item_format_data_fork(
>  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
>  
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> -		    ip->i_d.di_nextents > 0 &&
> +		    ip->i_df.if_nextents > 0 &&
>  		    ip->i_df.if_bytes > 0) {
>  			struct xfs_bmbt_rec *p;
>  
> @@ -233,12 +233,12 @@ xfs_inode_item_format_attr_fork(
>  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
>  
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> -		    ip->i_d.di_anextents > 0 &&
> +		    ip->i_afp->if_nextents > 0 &&
>  		    ip->i_afp->if_bytes > 0) {
>  			struct xfs_bmbt_rec *p;
>  
>  			ASSERT(xfs_iext_count(ip->i_afp) ==
> -				ip->i_d.di_anextents);
> +				ip->i_afp->if_nextents);
>  
>  			p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT);
>  			data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK);
> @@ -326,8 +326,8 @@ xfs_inode_to_log_dinode(
>  	to->di_size = from->di_size;
>  	to->di_nblocks = from->di_nblocks;
>  	to->di_extsize = from->di_extsize;
> -	to->di_nextents = from->di_nextents;
> -	to->di_anextents = from->di_anextents;
> +	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
> +	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
>  	to->di_forkoff = from->di_forkoff;
>  	to->di_aformat = from->di_aformat;
>  	to->di_dmevmask = from->di_dmevmask;
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 4ee0d13232f3f..7a71c03e9022b 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -1104,26 +1104,17 @@ xfs_fill_fsxattr(
>  	bool			attr,
>  	struct fsxattr		*fa)
>  {
> +	struct xfs_ifork	*ifp = attr ? ip->i_afp : &ip->i_df;
> +
>  	simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
>  	fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
>  	fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
>  			ip->i_mount->m_sb.sb_blocklog;
>  	fa->fsx_projid = ip->i_d.di_projid;
> -
> -	if (attr) {
> -		if (ip->i_afp) {
> -			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
> -				fa->fsx_nextents = xfs_iext_count(ip->i_afp);
> -			else
> -				fa->fsx_nextents = ip->i_d.di_anextents;
> -		} else
> -			fa->fsx_nextents = 0;
> -	} else {
> -		if (ip->i_df.if_flags & XFS_IFEXTENTS)
> -			fa->fsx_nextents = xfs_iext_count(&ip->i_df);
> -		else
> -			fa->fsx_nextents = ip->i_d.di_nextents;
> -	}
> +	if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
> +		fa->fsx_nextents = xfs_iext_count(ifp);
> +	else
> +		fa->fsx_nextents = xfs_ifork_nextents(ifp);
>  }
>  
>  STATIC int
> @@ -1211,7 +1202,7 @@ xfs_ioctl_setattr_xflags(
>  	uint64_t		di_flags2;
>  
>  	/* Can't change realtime flag if any extents are allocated. */
> -	if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
> +	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
>  	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
>  		return -EINVAL;
>  
> @@ -1389,7 +1380,7 @@ xfs_ioctl_setattr_check_extsize(
>  	xfs_extlen_t		size;
>  	xfs_fsblock_t		extsize_fsb;
>  
> -	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
> +	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
>  	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
>  		return -EINVAL;
>  
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index bb590a267a7f9..b4fd918749e5f 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -1258,7 +1258,7 @@ xfs_xattr_iomap_begin(
>  	lockmode = xfs_ilock_attr_map_shared(ip);
>  
>  	/* if there are no attribute fork or extents, return ENOENT */
> -	if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
> +	if (!XFS_IFORK_Q(ip) || !ip->i_afp->if_nextents) {
>  		error = -ENOENT;
>  		goto out_unlock;
>  	}
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 26a71237d70f6..d66528fa36570 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -872,7 +872,7 @@ xfs_setattr_size(
>  	/*
>  	 * Short circuit the truncate case for zero length files.
>  	 */
> -	if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
> +	if (newsize == 0 && oldsize == 0 && ip->i_df.if_nextents == 0) {
>  		if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
>  			return 0;
>  
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index ff2da28fed90e..80da86c5703fb 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -104,9 +104,9 @@ xfs_bulkstat_one_int(
>  
>  	buf->bs_xflags = xfs_ip2xflags(ip);
>  	buf->bs_extsize_blks = dic->di_extsize;
> -	buf->bs_extents = dic->di_nextents;
> +	buf->bs_extents = xfs_ifork_nextents(&ip->i_df);
>  	xfs_bulkstat_health(ip, buf);
> -	buf->bs_aextents = dic->di_anextents;
> +	buf->bs_aextents = xfs_ifork_nextents(ip->i_afp);
>  	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
>  	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
>  
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index 944486f2b2874..9edf761eec739 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -302,7 +302,7 @@ xfs_qm_scall_trunc_qfile(
>  		goto out_unlock;
>  	}
>  
> -	ASSERT(ip->i_d.di_nextents == 0);
> +	ASSERT(ip->i_df.if_nextents == 0);
>  
>  	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
>  	error = xfs_trans_commit(tp);
> diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
> index 38669e8272060..b5d10ecb54743 100644
> --- a/fs/xfs/xfs_quotaops.c
> +++ b/fs/xfs/xfs_quotaops.c
> @@ -36,7 +36,7 @@ xfs_qm_fill_state(
>  	}
>  	tstate->flags |= QCI_SYSFILE;
>  	tstate->blocks = ip->i_d.di_nblocks;
> -	tstate->nextents = ip->i_d.di_nextents;
> +	tstate->nextents = ip->i_df.if_nextents;
>  	tstate->spc_timelimit = (u32)q->qi_btimelimit;
>  	tstate->ino_timelimit = (u32)q->qi_itimelimit;
>  	tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 973441992b084..8cf2fcb509c12 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -384,7 +384,7 @@ xfs_inactive_symlink_rmt(
>  	 * either 1 or 2 extents and that we can
>  	 * free them all in one bunmapi call.
>  	 */
> -	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
> +	ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
>  
>  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
>  	if (error)
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index a4323a63438d8..ba2ab69e1fc7d 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -1898,7 +1898,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
>  		__entry->which = which;
>  		__entry->ino = ip->i_ino;
>  		__entry->format = ip->i_d.di_format;
> -		__entry->nex = ip->i_d.di_nextents;
> +		__entry->nex = ip->i_df.if_nextents;
>  		__entry->broot_size = ip->i_df.if_broot_bytes;
>  		__entry->fork_off = XFS_IFORK_BOFF(ip);
>  	),
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-12 15:38       ` Darrick J. Wong
@ 2020-05-12 16:14         ` Brian Foster
  2020-05-12 19:16           ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Brian Foster @ 2020-05-12 16:14 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Chandan Babu R, Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 08:38:54AM -0700, Darrick J. Wong wrote:
> On Tue, May 12, 2020 at 11:31:32AM -0400, Brian Foster wrote:
> > On Mon, May 11, 2020 at 05:10:04PM +0530, Chandan Babu R wrote:
> > > On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> > > > XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> > > > doesn't make a difference in practice as size is only checked for
> > > > 0, but this keeps the logic sane.
> > > >
> > > 
> > > Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
> > > attr fork inside an inode's literal area?
> > > 
> > 
> > I had the same thought. It's not clear to me what size is really
> > supposed to be between the file size for a data fork and fork offset for
> > the attr fork. I was also wondering if this should use
> > XFS_IFORK_DSIZE(), but that won't be conditional based on population of
> > the fork. At the same time, I don't think i_size != 0 necessarily
> > correlates with the existence of blocks. The file could be completely
> > sparse or could have any number of post-eof preallocated extents.
> 
> TBH I should have made that variable "bool empty" or something.
> 
> case XFS_DATA_FORK:
> 	empty = i_size_read() == 0;
> 

Even that is somewhat unclear because it's tied to i_size. What about
size == 0 && <post-eof extents>?

Brian

> case XFS_ATTR_FORK:
> 	empty = !XFS_IFORK_Q();
> 
> default:
> 	empty = true;
> 
> if ((is not btree) && (empty || nextents > 0))
> 	return 0;
> 
> --D
> 
> > Brian
> > 
> > > > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > > > ---
> > > >  fs/xfs/scrub/bmap.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > 
> > > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > > index add8598eacd5d..283424d6d2bb6 100644
> > > > --- a/fs/xfs/scrub/bmap.c
> > > > +++ b/fs/xfs/scrub/bmap.c
> > > > @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
> > > >  		size = i_size_read(VFS_I(sc->ip));
> > > >  		break;
> > > >  	case XFS_ATTR_FORK:
> > > > -		size = XFS_IFORK_Q(sc->ip);
> > > > +		size = XFS_IFORK_BOFF(sc->ip);
> > > >  		break;
> > > >  	default:
> > > >  		size = 0;
> > > > 
> > > 
> > > 
> > > -- 
> > > chandan
> > > 
> > > 
> > > 
> > 
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
  2020-05-12  9:37   ` Chandan Babu R
@ 2020-05-12 18:53   ` Brian Foster
  2020-05-14 21:25   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2020-05-12 18:53 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:03AM +0200, Christoph Hellwig wrote:
> Both the data and attr fork have a format that is stored in the legacy
> idinode.  Move it into the xfs_ifork structure instead, where it uses
> up padding.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_attr.c           |  12 +--
>  fs/xfs/libxfs/xfs_attr_leaf.c      |  32 ++++----
>  fs/xfs/libxfs/xfs_bmap.c           | 120 +++++++++++++----------------
>  fs/xfs/libxfs/xfs_bmap_btree.c     |   5 +-
>  fs/xfs/libxfs/xfs_dir2.c           |   8 +-
>  fs/xfs/libxfs/xfs_dir2_sf.c        |  13 ++--
>  fs/xfs/libxfs/xfs_inode_buf.c      |   6 +-
>  fs/xfs/libxfs/xfs_inode_buf.h      |   2 -
>  fs/xfs/libxfs/xfs_inode_fork.c     |  14 ++--
>  fs/xfs/libxfs/xfs_inode_fork.h     |  28 ++++---
>  fs/xfs/libxfs/xfs_symlink_remote.c |  16 ++--
>  fs/xfs/scrub/bmap.c                |   4 +-
>  fs/xfs/scrub/dabtree.c             |   2 +-
>  fs/xfs/scrub/dir.c                 |   7 +-
>  fs/xfs/xfs_aops.c                  |   2 +-
>  fs/xfs/xfs_attr_inactive.c         |   2 +-
>  fs/xfs/xfs_attr_list.c             |   4 +-
>  fs/xfs/xfs_bmap_util.c             |  56 +++++++-------
>  fs/xfs/xfs_dir2_readdir.c          |   2 +-
>  fs/xfs/xfs_icache.c                |   1 -
>  fs/xfs/xfs_inode.c                 |  36 ++++-----
>  fs/xfs/xfs_inode.h                 |   2 -
>  fs/xfs/xfs_inode_item.c            |  12 +--
>  fs/xfs/xfs_iomap.c                 |   4 +-
>  fs/xfs/xfs_itable.c                |   2 +-
>  fs/xfs/xfs_symlink.c               |   2 +-
>  fs/xfs/xfs_trace.h                 |   2 +-
>  27 files changed, 181 insertions(+), 215 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 1b01675e9c80b..3b1bd6e112f89 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -61,7 +61,7 @@ xfs_inode_hasattr(
>  	struct xfs_inode	*ip)
>  {
>  	if (!XFS_IFORK_Q(ip) ||
> -	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	    (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     ip->i_afp->if_nextents == 0))
>  		return 0;
>  	return 1;
> @@ -84,7 +84,7 @@ xfs_attr_get_ilocked(
>  	if (!xfs_inode_hasattr(args->dp))
>  		return -ENOATTR;
>  
> -	if (args->dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_getvalue(args);
>  	if (xfs_bmap_one_block(args->dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_get(args);
> @@ -212,14 +212,14 @@ xfs_attr_set_args(
>  	 * If the attribute list is non-existent or a shortform list,
>  	 * upgrade it to a single-leaf-block attribute list.
>  	 */
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
> -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     dp->i_afp->if_nextents == 0)) {
>  
>  		/*
>  		 * Build initial attribute list (if required).
>  		 */
> -		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
> +		if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
>  			xfs_attr_shortform_create(args);
>  
>  		/*
> @@ -272,7 +272,7 @@ xfs_attr_remove_args(
>  
>  	if (!xfs_inode_hasattr(dp)) {
>  		error = -ENOATTR;
> -	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
> +	} else if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
>  		error = xfs_attr_shortform_remove(args);
>  	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index 64b172180c42c..d7f3173ce3c31 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -539,7 +539,7 @@ xfs_attr_shortform_bytesfit(
>  	/* rounded down */
>  	offset = (XFS_LITINO(mp) - bytes) >> 3;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_DEV) {
>  		minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		return (offset >= minforkoff) ? minforkoff : 0;
>  	}
> @@ -567,7 +567,7 @@ xfs_attr_shortform_bytesfit(
>  
>  	dsize = dp->i_df.if_bytes;
>  
> -	switch (dp->i_d.di_format) {
> +	switch (dp->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		/*
>  		 * If there is no attr fork and the data fork is extents, 
> @@ -636,22 +636,19 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
>   * Create the initial contents of a shortform attribute list.
>   */
>  void
> -xfs_attr_shortform_create(xfs_da_args_t *args)
> +xfs_attr_shortform_create(
> +	struct xfs_da_args	*args)
>  {
> -	xfs_attr_sf_hdr_t *hdr;
> -	xfs_inode_t *dp;
> -	struct xfs_ifork *ifp;
> +	struct xfs_inode	*dp = args->dp;
> +	struct xfs_ifork	*ifp = dp->i_afp;
> +	struct xfs_attr_sf_hdr	*hdr;
>  
>  	trace_xfs_attr_sf_create(args);
>  
> -	dp = args->dp;
> -	ASSERT(dp != NULL);
> -	ifp = dp->i_afp;
> -	ASSERT(ifp != NULL);
>  	ASSERT(ifp->if_bytes == 0);
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS) {
>  		ifp->if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
> +		ifp->if_format = XFS_DINODE_FMT_LOCAL;
>  		ifp->if_flags |= XFS_IFINLINE;
>  	} else {
>  		ASSERT(ifp->if_flags & XFS_IFINLINE);
> @@ -721,7 +718,6 @@ xfs_attr_fork_remove(
>  {
>  	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
>  	ip->i_d.di_forkoff = 0;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	ASSERT(ip->i_afp == NULL);
>  
> @@ -774,7 +770,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  	totsize -= size;
>  	if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
>  	    (mp->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    !(args->op_flags & XFS_DA_OP_ADDNAME)) {
>  		xfs_attr_fork_remove(dp, args->trans);
>  	} else {
> @@ -784,7 +780,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
>  				(args->op_flags & XFS_DA_OP_ADDNAME) ||
>  				!(mp->m_flags & XFS_MOUNT_ATTR2) ||
> -				dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
> +				dp->i_df.if_format == XFS_DINODE_FMT_BTREE);
>  		xfs_trans_log_inode(args->trans, dp,
>  					XFS_ILOG_CORE | XFS_ILOG_ADATA);
>  	}
> @@ -961,7 +957,7 @@ xfs_attr_shortform_allfit(
>  				+ be16_to_cpu(name_loc->valuelen);
>  	}
>  	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
>  		return -1;
>  	return xfs_attr_shortform_bytesfit(dp, bytes);
> @@ -980,7 +976,7 @@ xfs_attr_shortform_verify(
>  	int				i;
>  	int64_t				size;
>  
> -	ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK);
>  	sfp = (struct xfs_attr_shortform *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
> @@ -1084,7 +1080,7 @@ xfs_attr3_leaf_to_shortform(
>  
>  	if (forkoff == -1) {
>  		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
> -		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
> +		ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE);
>  		xfs_attr_fork_remove(dp, args->trans);
>  		goto out;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index c1136be49abeb..edc63dba007f4 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -123,7 +123,7 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +		ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -135,7 +135,7 @@ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
> +		ifp->if_format == XFS_DINODE_FMT_BTREE &&
>  		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -215,8 +215,8 @@ xfs_bmap_forkoff_reset(
>  	int		whichfork)
>  {
>  	if (whichfork == XFS_ATTR_FORK &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
> +	    ip->i_df.if_format != XFS_DINODE_FMT_DEV &&
> +	    ip->i_df.if_format != XFS_DINODE_FMT_BTREE) {
>  		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
>  
>  		if (dfl_forkoff > ip->i_d.di_forkoff)
> @@ -317,31 +317,28 @@ xfs_bmap_check_leaf_extents(
>  	xfs_inode_t		*ip,		/* incore inode pointer */
>  	int			whichfork)	/* data or attr fork */
>  {
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_block	*block;	/* current btree block */
>  	xfs_fsblock_t		bno;	/* block # of "block" */
>  	xfs_buf_t		*bp;	/* buffer for "block" */
>  	int			error;	/* error return value */
>  	xfs_extnum_t		i=0, j;	/* index into the extents list */
> -	struct xfs_ifork	*ifp;	/* fork structure */
>  	int			level;	/* btree level, for checking */
> -	xfs_mount_t		*mp;	/* file system mount structure */
>  	__be64			*pp;	/* pointer to block address */
>  	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
>  	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
>  	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
>  	int			bp_release = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return;
> -	}
>  
>  	/* skip large extent count inodes */
>  	if (ip->i_df.if_nextents > 10000)
>  		return;
>  
>  	bno = NULLFSBLOCK;
> -	mp = ip->i_mount;
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	block = ifp->if_broot;
>  	/*
>  	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
> @@ -606,7 +603,7 @@ xfs_bmap_btree_to_extents(
>  	ASSERT(cur);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
>  	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
>  	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
> @@ -634,7 +631,7 @@ xfs_bmap_btree_to_extents(
>  	xfs_iroot_realloc(ip, -1, whichfork);
>  	ASSERT(ifp->if_broot == NULL);
>  	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	*logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
>  	return 0;
>  }
> @@ -670,7 +667,7 @@ xfs_bmap_extents_to_btree(
>  	mp = ip->i_mount;
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  	/*
>  	 * Make space in the inode incore. This needs to be undone if we fail
> @@ -694,7 +691,7 @@ xfs_bmap_extents_to_btree(
>  	/*
>  	 * Convert to a btree with two levels, one record in root.
>  	 */
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
> +	ifp->if_format = XFS_DINODE_FMT_BTREE;
>  	memset(&args, 0, sizeof(args));
>  	args.tp = tp;
>  	args.mp = mp;
> @@ -780,7 +777,7 @@ xfs_bmap_extents_to_btree(
>  	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
>  out_root_realloc:
>  	xfs_iroot_realloc(ip, -1, whichfork);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ASSERT(ifp->if_broot == NULL);
>  	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
>  
> @@ -802,7 +799,7 @@ xfs_bmap_local_to_extents_empty(
>  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	ASSERT(whichfork != XFS_COW_FORK);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ASSERT(ifp->if_bytes == 0);
>  	ASSERT(ifp->if_nextents == 0);
>  
> @@ -811,7 +808,7 @@ xfs_bmap_local_to_extents_empty(
>  	ifp->if_flags |= XFS_IFEXTENTS;
>  	ifp->if_u1.if_root = NULL;
>  	ifp->if_height = 0;
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  }
>  
> @@ -842,7 +839,7 @@ xfs_bmap_local_to_extents(
>  	 */
>  	ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	if (!ifp->if_bytes) {
>  		xfs_bmap_local_to_extents_empty(tp, ip, whichfork);
> @@ -1036,7 +1033,7 @@ xfs_bmap_set_attrforkoff(
>  	int			size,
>  	int			*version)
>  {
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		break;
> @@ -1094,13 +1091,6 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	if (XFS_IFORK_Q(ip))
>  		goto trans_cancel;
> -	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
> -		/*
> -		 * For inodes coming from pre-6.2 filesystems.
> -		 */
> -		ASSERT(ip->i_d.di_aformat == 0);
> -		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> -	}
>  
>  	xfs_trans_ijoin(tp, ip, 0);
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> @@ -1109,9 +1099,10 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	ASSERT(ip->i_afp == NULL);
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, 0);
> +	ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_flags = XFS_IFEXTENTS;
>  	logflags = 0;
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_bmap_add_attrfork_local(tp, ip, &logflags);
>  		break;
> @@ -1237,9 +1228,7 @@ xfs_iread_extents(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  
> -	if (XFS_IS_CORRUPT(mp,
> -			   XFS_IFORK_FORMAT(ip, whichfork) !=
> -			   XFS_DINODE_FMT_BTREE)) {
> +	if (XFS_IS_CORRUPT(mp, ifp->if_format != XFS_DINODE_FMT_BTREE)) {
>  		error = -EFSCORRUPTED;
>  		goto out;
>  	}
> @@ -1287,14 +1276,13 @@ xfs_bmap_first_unused(
>  	xfs_fileoff_t		lowest, max;
>  	int			error;
>  
> -	ASSERT(xfs_ifork_has_extents(ip, whichfork) ||
> -	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		*first_unused = 0;
>  		return 0;
>  	}
>  
> +	ASSERT(xfs_ifork_has_extents(ifp));
> +
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		error = xfs_iread_extents(tp, ip, whichfork);
>  		if (error)
> @@ -1335,7 +1323,7 @@ xfs_bmap_last_before(
>  	struct xfs_iext_cursor	icur;
>  	int			error;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		*last_block = 0;
>  		return 0;
> @@ -1434,16 +1422,17 @@ xfs_bmap_last_offset(
>  	xfs_fileoff_t		*last_block,
>  	int			whichfork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_bmbt_irec	rec;
>  	int			is_empty;
>  	int			error;
>  
>  	*last_block = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return 0;
>  
> -	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  
>  	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
> @@ -1475,7 +1464,7 @@ xfs_bmap_one_block(
>  #endif	/* !DEBUG */
>  	if (ifp->if_nextents != 1)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		return 0;
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
>  	xfs_iext_first(ifp, &icur);
> @@ -3895,10 +3884,9 @@ xfs_bmapi_read(
>  	if (WARN_ON_ONCE(!ifp))
>  		return -EFSCORRUPTED;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> -	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
> +	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
>  		return -EFSCORRUPTED;
> -	}
>  
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -4281,11 +4269,13 @@ xfs_bmapi_minleft(
>  	struct xfs_inode	*ip,
>  	int			fork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, fork);
> +
>  	if (tp && tp->t_firstblock != NULLFSBLOCK)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, fork) != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 1;
> -	return be16_to_cpu(XFS_IFORK_PTR(ip, fork)->if_broot->bb_level) + 1;
> +	return be16_to_cpu(ifp->if_broot->bb_level) + 1;
>  }
>  
>  /*
> @@ -4300,11 +4290,13 @@ xfs_bmapi_finish(
>  	int			whichfork,
>  	int			error)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
> +
>  	if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		bma->logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((bma->logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		bma->logflags &= ~xfs_ilog_fbroot(whichfork);
>  
>  	if (bma->logflags)
> @@ -4336,13 +4328,13 @@ xfs_bmapi_write(
>  		.total		= total,
>  	};
>  	struct xfs_mount	*mp = ip->i_mount;
> -	struct xfs_ifork	*ifp;
> +	int			whichfork = xfs_bmapi_whichfork(flags);
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	xfs_fileoff_t		end;		/* end of mapped file region */
>  	bool			eof = false;	/* after the end of extents */
>  	int			error;		/* error return */
>  	int			n;		/* current extent index */
>  	xfs_fileoff_t		obno;		/* old block number (offset) */
> -	int			whichfork;	/* data or attr fork */
>  
>  #ifdef DEBUG
>  	xfs_fileoff_t		orig_bno;	/* original block number value */
> @@ -4357,13 +4349,12 @@ xfs_bmapi_write(
>  	orig_mval = mval;
>  	orig_nmap = *nmap;
>  #endif
> -	whichfork = xfs_bmapi_whichfork(flags);
>  
>  	ASSERT(*nmap >= 1);
>  	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
>  	ASSERT(tp != NULL);
>  	ASSERT(len > 0);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_LOCAL);
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(!(flags & XFS_BMAPI_REMAP));
>  
> @@ -4379,7 +4370,7 @@ xfs_bmapi_write(
>  	ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
>  			(XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4387,8 +4378,6 @@ xfs_bmapi_write(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -
>  	XFS_STATS_INC(mp, xs_blk_mapw);
>  
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
> @@ -4498,7 +4487,7 @@ xfs_bmapi_write(
>  	if (error)
>  		goto error0;
>  
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_BTREE ||
>  	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
>  	xfs_bmapi_finish(&bma, whichfork, 0);
>  	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
> @@ -4645,7 +4634,7 @@ xfs_bmapi_remap(
>  	ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) !=
>  			(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4689,9 +4678,9 @@ xfs_bmapi_remap(
>  	error = xfs_bmap_btree_to_extents(tp, ip, cur, &logflags, whichfork);
>  
>  error0:
> -	if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS)
> +	if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~XFS_ILOG_DEXT;
> -	else if (ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	else if (ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~XFS_ILOG_DBROOT;
>  
>  	if (logflags)
> @@ -5041,7 +5030,7 @@ xfs_bmap_del_extent_real(
>  	 * conversion to btree format, since the transaction will be dirty then.
>  	 */
>  	if (tp->t_blk_res == 0 &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
>  	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
>  		return -ENOSPC;
> @@ -5284,7 +5273,7 @@ __xfs_bunmapi(
>  	whichfork = xfs_bmapi_whichfork(flags);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -5322,7 +5311,7 @@ __xfs_bunmapi(
>  
>  	logflags = 0;
>  	if (ifp->if_flags & XFS_IFBROOT) {
> -		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +		ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
>  		cur->bc_ino.flags = 0;
>  	} else
> @@ -5567,10 +5556,10 @@ __xfs_bunmapi(
>  	 * logging the extent records if we've converted to btree format.
>  	 */
>  	if ((logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~xfs_ilog_fbroot(whichfork);
>  	/*
>  	 * Log inode even in the error case, if the transaction
> @@ -5781,7 +5770,7 @@ xfs_bmap_collapse_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5898,7 +5887,7 @@ xfs_bmap_insert_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5992,18 +5981,18 @@ xfs_bmap_split_extent(
>  	xfs_fileoff_t		split_fsb)
>  {
>  	int				whichfork = XFS_DATA_FORK;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_cur		*cur = NULL;
>  	struct xfs_bmbt_irec		got;
>  	struct xfs_bmbt_irec		new; /* split extent */
>  	struct xfs_mount		*mp = ip->i_mount;
> -	struct xfs_ifork		*ifp;
>  	xfs_fsblock_t			gotblkcnt; /* new block count for got */
>  	struct xfs_iext_cursor		icur;
>  	int				error = 0;
>  	int				logflags = 0;
>  	int				i = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -6011,7 +6000,6 @@ xfs_bmap_split_extent(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		/* Read in all the extents */
>  		error = xfs_iread_extents(tp, ip, whichfork);
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index 295a59cf88407..d9c63f17d2dec 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -636,10 +636,7 @@ xfs_bmbt_change_owner(
>  
>  	ASSERT(tp || buffer_list);
>  	ASSERT(!(tp && buffer_list));
> -	if (whichfork == XFS_DATA_FORK)
> -		ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE);
> -	else
> -		ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE);
> +	ASSERT(XFS_IFORK_PTR(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
>  
>  	cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
>  	if (!cur)
> diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
> index dd6fcaaea318a..612a9c5e41b1c 100644
> --- a/fs/xfs/libxfs/xfs_dir2.c
> +++ b/fs/xfs/libxfs/xfs_dir2.c
> @@ -278,7 +278,7 @@ xfs_dir_createname(
>  	if (!inum)
>  		args->op_flags |= XFS_DA_OP_JUSTCHECK;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_addname(args);
>  		goto out_free;
>  	}
> @@ -373,7 +373,7 @@ xfs_dir_lookup(
>  		args->op_flags |= XFS_DA_OP_CILOOKUP;
>  
>  	lock_mode = xfs_ilock_data_map_shared(dp);
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_lookup(args);
>  		goto out_check_rval;
>  	}
> @@ -443,7 +443,7 @@ xfs_dir_removename(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_removename(args);
>  		goto out_free;
>  	}
> @@ -504,7 +504,7 @@ xfs_dir_replace(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_replace(args);
>  		goto out_free;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
> index 7b7f6fb2ea3b2..2463b5d734472 100644
> --- a/fs/xfs/libxfs/xfs_dir2_sf.c
> +++ b/fs/xfs/libxfs/xfs_dir2_sf.c
> @@ -343,7 +343,7 @@ xfs_dir2_block_to_sf(
>  	 */
>  	ASSERT(dp->i_df.if_bytes == 0);
>  	xfs_init_local_fork(dp, XFS_DATA_FORK, sfp, size);
> -	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +	dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  	dp->i_d.di_size = size;
>  
>  	logflags |= XFS_ILOG_DDATA;
> @@ -710,11 +710,11 @@ xfs_dir2_sf_verify(
>  	struct xfs_inode		*ip)
>  {
>  	struct xfs_mount		*mp = ip->i_mount;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	struct xfs_dir2_sf_hdr		*sfp;
>  	struct xfs_dir2_sf_entry	*sfep;
>  	struct xfs_dir2_sf_entry	*next_sfep;
>  	char				*endp;
> -	struct xfs_ifork		*ifp;
>  	xfs_ino_t			ino;
>  	int				i;
>  	int				i8count;
> @@ -723,9 +723,8 @@ xfs_dir2_sf_verify(
>  	int				error;
>  	uint8_t				filetype;
>  
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
>  
> @@ -827,9 +826,9 @@ xfs_dir2_sf_create(
>  	 * If it's currently a zero-length extent file,
>  	 * convert it to local format.
>  	 */
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS) {
>  		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
>  		dp->i_df.if_flags |= XFS_IFINLINE;
>  	}
> @@ -1027,7 +1026,7 @@ xfs_dir2_sf_replace_needblock(
>  	int			newsize;
>  	struct xfs_dir2_sf_hdr	*sfp;
>  
> -	if (dp->i_d.di_format != XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format != XFS_DINODE_FMT_LOCAL)
>  		return false;
>  
>  	sfp = (struct xfs_dir2_sf_hdr *)dp->i_df.if_u1.if_data;
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index a374e2a81e764..ab555671e1543 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -225,7 +225,6 @@ xfs_inode_from_disk(
>  					be16_to_cpu(from->di_projid_lo);
>  	}
>  
> -	to->di_format = from->di_format;
>  	i_uid_write(inode, be32_to_cpu(from->di_uid));
>  	i_gid_write(inode, be32_to_cpu(from->di_gid));
>  
> @@ -246,7 +245,6 @@ xfs_inode_from_disk(
>  	to->di_nblocks = be64_to_cpu(from->di_nblocks);
>  	to->di_extsize = be32_to_cpu(from->di_extsize);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat	= from->di_aformat;
>  	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
>  	to->di_dmstate	= be16_to_cpu(from->di_dmstate);
>  	to->di_flags	= be16_to_cpu(from->di_flags);
> @@ -289,7 +287,7 @@ xfs_inode_to_disk(
>  	to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
>  	to->di_onlink = 0;
>  
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = cpu_to_be32(i_uid_read(inode));
>  	to->di_gid = cpu_to_be32(i_gid_read(inode));
>  	to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
> @@ -312,7 +310,7 @@ xfs_inode_to_disk(
>  	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
>  	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
>  	to->di_dmstate = cpu_to_be16(from->di_dmstate);
>  	to->di_flags = cpu_to_be16(from->di_flags);
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
> index fecccfb26463c..865ac493c72a2 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.h
> +++ b/fs/xfs/libxfs/xfs_inode_buf.h
> @@ -16,14 +16,12 @@ struct xfs_dinode;
>   * format specific structures at the appropriate time.
>   */
>  struct xfs_icdinode {
> -	int8_t		di_format;	/* format of di_c data */
>  	uint16_t	di_flushiter;	/* incremented on flush */
>  	uint32_t	di_projid;	/* owner's project id */
>  	xfs_fsize_t	di_size;	/* number of bytes in file */
>  	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
>  	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
>  	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
> -	int8_t		di_aformat;	/* format of attr fork's data */
>  	uint32_t	di_dmevmask;	/* DMIG event mask */
>  	uint16_t	di_dmstate;	/* DMIG state info */
>  	uint16_t	di_flags;	/* random flags, XFS_DIFLAG_... */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 195da3552c5b5..6562f2bcd15cc 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -228,6 +228,7 @@ xfs_iformat_data_fork(
>  	struct inode		*inode = VFS_I(ip);
>  	int			error;
>  
> +	ip->i_df.if_format = dip->di_format;
>  	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
>  
>  	switch (inode->i_mode & S_IFMT) {
> @@ -241,7 +242,7 @@ xfs_iformat_data_fork(
>  	case S_IFREG:
>  	case S_IFLNK:
>  	case S_IFDIR:
> -		switch (dip->di_format) {
> +		switch (ip->i_df.if_format) {
>  		case XFS_DINODE_FMT_LOCAL:
>  			error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
>  					be64_to_cpu(dip->di_size));
> @@ -283,9 +284,12 @@ xfs_iformat_attr_fork(
>  	int			error = 0;
>  
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> +	ip->i_afp->if_format = dip->di_aformat;
> +	if (unlikely(ip->i_afp->if_format == 0)) /* pre IRIX 6.2 file system */
> +		ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
>  
> -	switch (dip->di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
>  				xfs_dfork_attr_shortform_size(dip));
> @@ -508,7 +512,7 @@ xfs_idestroy_fork(
>  	 * not local then we may or may not have an extents list,
>  	 * so check and free it up if we do.
>  	 */
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		if (ifp->if_u1.if_data != NULL) {
>  			kmem_free(ifp->if_u1.if_data);
>  			ifp->if_u1.if_data = NULL;
> @@ -605,7 +609,7 @@ xfs_iflush_fork(
>  	}
>  	cp = XFS_DFORK_PTR(dip, whichfork);
>  	mp = ip->i_mount;
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		if ((iip->ili_fields & dataflag[whichfork]) &&
>  		    (ifp->if_bytes > 0)) {
> @@ -678,7 +682,7 @@ xfs_ifork_init_cow(
>  	ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
>  				       KM_NOFS);
>  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
>  }
>  
>  /* Verify the inline contents of the data fork of an inode. */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index a69d425fe68df..d849cca103edd 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -23,6 +23,7 @@ struct xfs_ifork {
>  	} if_u1;
>  	short			if_broot_bytes;	/* bytes allocated for root */
>  	unsigned char		if_flags;	/* per-fork flags */
> +	int8_t			if_format;	/* format of this fork */
>  	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
>  };
>  
> @@ -56,24 +57,14 @@ struct xfs_ifork {
>  		((w) == XFS_ATTR_FORK ? \
>  			XFS_IFORK_ASIZE(ip) : \
>  			0))
> -#define XFS_IFORK_FORMAT(ip,w) \
> -	((w) == XFS_DATA_FORK ? \
> -		(ip)->i_d.di_format : \
> -		((w) == XFS_ATTR_FORK ? \
> -			(ip)->i_d.di_aformat : \
> -			(ip)->i_cformat))
> -#define XFS_IFORK_FMT_SET(ip,w,n) \
> -	((w) == XFS_DATA_FORK ? \
> -		((ip)->i_d.di_format = (n)) : \
> -		((w) == XFS_ATTR_FORK ? \
> -			((ip)->i_d.di_aformat = (n)) : \
> -			((ip)->i_cformat = (n))))
>  #define XFS_IFORK_MAXEXT(ip, w) \
>  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
>  
> -#define xfs_ifork_has_extents(ip, w) \
> -	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
> -	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
> +static inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp)
> +{
> +	return ifp->if_format == XFS_DINODE_FMT_EXTENTS ||
> +		ifp->if_format == XFS_DINODE_FMT_BTREE;
> +}
>  
>  static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  {
> @@ -82,6 +73,13 @@ static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  	return ifp->if_nextents;
>  }
>  
> +static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
> +{
> +	if (!ifp)
> +		return XFS_DINODE_FMT_EXTENTS;
> +	return ifp->if_format;
> +}
> +
>  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
>  
>  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
> index 3b8260ca7d1b8..594bc447a7dd2 100644
> --- a/fs/xfs/libxfs/xfs_symlink_remote.c
> +++ b/fs/xfs/libxfs/xfs_symlink_remote.c
> @@ -204,16 +204,12 @@ xfs_failaddr_t
>  xfs_symlink_shortform_verify(
>  	struct xfs_inode	*ip)
>  {
> -	char			*sfp;
> -	char			*endp;
> -	struct xfs_ifork	*ifp;
> -	int			size;
> -
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> -	sfp = (char *)ifp->if_u1.if_data;
> -	size = ifp->if_bytes;
> -	endp = sfp + size;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +	char			*sfp = (char *)ifp->if_u1.if_data;
> +	int			size = ifp->if_bytes;
> +	char			*endp = sfp + size;
> +
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	/*
>  	 * Zero length symlinks should never occur in memory as they are
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index 157f72efec5e9..dfa1533b4edfc 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
>  		size = 0;
>  		break;
>  	}
> -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
>  	    (size == 0 || ifp->if_nextents > 0))
>  		return 0;
>  
> @@ -664,7 +664,7 @@ xchk_bmap(
>  	}
>  
>  	/* Check the fork values */
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_UUID:
>  	case XFS_DINODE_FMT_DEV:
>  	case XFS_DINODE_FMT_LOCAL:
> diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
> index 9a2e27ac13003..44b15015021f3 100644
> --- a/fs/xfs/scrub/dabtree.c
> +++ b/fs/xfs/scrub/dabtree.c
> @@ -468,7 +468,7 @@ xchk_da_btree(
>  	int				error;
>  
>  	/* Skip short format data structures; no btree to scan. */
> -	if (!xfs_ifork_has_extents(sc->ip, whichfork))
> +	if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
>  		return 0;
>  
>  	/* Set up initial da state. */
> diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
> index fe2a6e030c8a0..7c432997edade 100644
> --- a/fs/xfs/scrub/dir.c
> +++ b/fs/xfs/scrub/dir.c
> @@ -635,7 +635,7 @@ xchk_directory_blocks(
>  {
>  	struct xfs_bmbt_irec	got;
>  	struct xfs_da_args	args;
> -	struct xfs_ifork	*ifp;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	struct xfs_mount	*mp = sc->mp;
>  	xfs_fileoff_t		leaf_lblk;
>  	xfs_fileoff_t		free_lblk;
> @@ -647,11 +647,10 @@ xchk_directory_blocks(
>  	int			error;
>  
>  	/* Ignore local format directories. */
> -	if (sc->ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
> -	    sc->ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 0;
>  
> -	ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
>  	leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
>  	free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 9d9cebf187268..2834cbf1212e5 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -382,7 +382,7 @@ xfs_map_blocks(
>  	 */
>  retry:
>  	xfs_ilock(ip, XFS_ILOCK_SHARED);
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       (ip->i_df.if_flags & XFS_IFEXTENTS));
>  
>  	/*
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index c42f90e16b4fa..00ffc46c0bf71 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -367,7 +367,7 @@ xfs_attr_inactive(
>  	 * removal below.
>  	 */
>  	if (xfs_inode_hasattr(dp) &&
> -	    dp->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    dp->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_attr3_root_inactive(&trans, dp);
>  		if (error)
>  			goto out_cancel;
> diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
> index 5ff1d929d3b5f..e380bd1a9bfc9 100644
> --- a/fs/xfs/xfs_attr_list.c
> +++ b/fs/xfs/xfs_attr_list.c
> @@ -512,9 +512,9 @@ xfs_attr_list_ilocked(
>  	 */
>  	if (!xfs_inode_hasattr(dp))
>  		return 0;
> -	else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_list(context);
> -	else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
> +	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_list(context);
>  	return xfs_attr_node_list(context);
>  }
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 4f277a6253b8d..5e32c3cf8e8c1 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -223,7 +223,7 @@ xfs_bmap_count_blocks(
>  	if (!ifp)
>  		return 0;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_BTREE:
>  		if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  			error = xfs_iread_extents(tp, ip, whichfork);
> @@ -449,7 +449,7 @@ xfs_getbmap(
>  		break;
>  	}
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  	case XFS_DINODE_FMT_BTREE:
>  		break;
> @@ -1210,17 +1210,19 @@ xfs_swap_extents_check_format(
>  	struct xfs_inode	*ip,	/* target inode */
>  	struct xfs_inode	*tip)	/* tmp inode */
>  {
> +	struct xfs_ifork	*ifp = &ip->i_df;
> +	struct xfs_ifork	*tifp = &tip->i_df;
>  
>  	/* Should never get a local format */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
> -	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    tifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return -EINVAL;
>  
>  	/*
>  	 * if the target inode has less extents that then temporary inode then
>  	 * why did userspace call us?
>  	 */
> -	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
> +	if (ifp->if_nextents < tifp->if_nextents)
>  		return -EINVAL;
>  
>  	/*
> @@ -1235,18 +1237,18 @@ xfs_swap_extents_check_format(
>  	 * form then we will end up with the target inode in the wrong format
>  	 * as we already know there are less extents in the temp inode.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_format == XFS_DINODE_FMT_BTREE)
>  		return -EINVAL;
>  
>  	/* Check temp in extent form to max in target */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +	if (tifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/* Check target in extent form to max in temp */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/*
> @@ -1258,22 +1260,20 @@ xfs_swap_extents_check_format(
>  	 * (a common defrag case) which will occur when the temp inode is in
>  	 * extent format...
>  	 */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (tifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(ip) &&
> -		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
> +		    XFS_BMAP_BMDR_SPACE(tifp->if_broot) > XFS_IFORK_BOFF(ip))
>  			return -EINVAL;
> -		if (tip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +		if (tifp->if_nextents <= XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
>  	/* Reciprocal target->temp btree format checks */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(tip) &&
>  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
>  			return -EINVAL;
> -		if (ip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +		if (ifp->if_nextents <= XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
> @@ -1426,14 +1426,14 @@ xfs_swap_extent_forks(
>  	 * Count the number of extended attribute blocks
>  	 */
>  	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> -	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
>  				&aforkblks);
>  		if (error)
>  			return error;
>  	}
>  	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> -	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
>  				&taforkblks);
>  		if (error)
> @@ -1448,9 +1448,9 @@ xfs_swap_extent_forks(
>  	 * bmbt scan as the last step.
>  	 */
>  	if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
> -		if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*target_log_flags) |= XFS_ILOG_DOWNER;
> -		if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*src_log_flags) |= XFS_ILOG_DOWNER;
>  	}
>  
> @@ -1466,8 +1466,6 @@ xfs_swap_extent_forks(
>  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
>  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
>  
> -	swap(ip->i_d.di_format, tip->i_d.di_format);
> -
>  	/*
>  	 * The extents in the source inode could still contain speculative
>  	 * preallocation beyond EOF (e.g. the file is open but not modified
> @@ -1481,7 +1479,7 @@ xfs_swap_extent_forks(
>  	tip->i_delayed_blks = ip->i_delayed_blks;
>  	ip->i_delayed_blks = 0;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*src_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1492,7 +1490,7 @@ xfs_swap_extent_forks(
>  		break;
>  	}
>  
> -	switch (tip->i_d.di_format) {
> +	switch (tip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*target_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1714,8 +1712,10 @@ xfs_swap_extents(
>  
>  	/* Swap the cow forks. */
>  	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
> -		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> -		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!ip->i_cowfp ||
> +		       ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!tip->i_cowfp ||
> +		       tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  		swap(ip->i_cowfp, tip->i_cowfp);
>  
> diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
> index 871ec22c9aee9..66deddd5e2969 100644
> --- a/fs/xfs/xfs_dir2_readdir.c
> +++ b/fs/xfs/xfs_dir2_readdir.c
> @@ -524,7 +524,7 @@ xfs_readdir(
>  	args.geo = dp->i_mount->m_dir_geo;
>  	args.trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
>  		rval = xfs_dir2_sf_getdents(&args, ctx);
>  	else if ((rval = xfs_dir2_isblock(&args, &v)))
>  		;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 791d5d5e318cf..c09b3e9eab1da 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -63,7 +63,6 @@ xfs_inode_alloc(
>  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
>  	ip->i_afp = NULL;
>  	ip->i_cowfp = NULL;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
>  	memset(&ip->i_df, 0, sizeof(ip->i_df));
>  	ip->i_flags = 0;
>  	ip->i_delayed_blks = 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 1677c4e7207ed..64f5f9a440aed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -112,7 +112,7 @@ xfs_ilock_data_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_df.if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -125,7 +125,8 @@ xfs_ilock_attr_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_afp &&
> +	    ip->i_afp->if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_afp->if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -851,7 +852,7 @@ xfs_ialloc(
>  	case S_IFCHR:
>  	case S_IFBLK:
>  	case S_IFSOCK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_DEV;
> +		ip->i_df.if_format = XFS_DINODE_FMT_DEV;
>  		ip->i_df.if_flags = 0;
>  		flags |= XFS_ILOG_DEV;
>  		break;
> @@ -907,7 +908,7 @@ xfs_ialloc(
>  		}
>  		/* FALLTHROUGH */
>  	case S_IFLNK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> +		ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  		ip->i_df.if_flags = XFS_IFEXTENTS;
>  		ip->i_df.if_bytes = 0;
>  		ip->i_df.if_u1.if_root = NULL;
> @@ -915,10 +916,6 @@ xfs_ialloc(
>  	default:
>  		ASSERT(0);
>  	}
> -	/*
> -	 * Attribute fork settings for new inode.
> -	 */
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	/*
>  	 * Log the new values stuffed into the inode.
> @@ -2749,7 +2746,7 @@ xfs_ifree(
>  	 * data fork to extents format.  Note that the attr fork data has
>  	 * already been freed by xfs_attr_inactive.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		kmem_free(ip->i_df.if_u1.if_data);
>  		ip->i_df.if_u1.if_data = NULL;
>  		ip->i_df.if_bytes = 0;
> @@ -2760,8 +2757,7 @@ xfs_ifree(
>  	ip->i_d.di_flags2 = 0;
>  	ip->i_d.di_dmevmask = 0;
>  	ip->i_d.di_forkoff = 0;		/* mark the attr fork not in use */
> -	ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  
>  	/* Don't attempt to replay owner changes for a deleted inode */
>  	ip->i_itemp->ili_fields &= ~(XFS_ILOG_AOWNER|XFS_ILOG_DOWNER);
> @@ -3624,7 +3620,7 @@ xfs_iflush(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  
>  	*bpp = NULL;
> @@ -3706,7 +3702,7 @@ xfs_iflush_int(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  	ASSERT(iip != NULL && iip->ili_fields != 0);
>  
> @@ -3728,8 +3724,8 @@ xfs_iflush_int(
>  	}
>  	if (S_ISREG(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE,
>  		    mp, XFS_ERRTAG_IFLUSH_3)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad regular inode %Lu, ptr "PTR_FMT,
> @@ -3738,9 +3734,9 @@ xfs_iflush_int(
>  		}
>  	} else if (S_ISDIR(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_LOCAL,
>  		    mp, XFS_ERRTAG_IFLUSH_4)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad directory inode %Lu, ptr "PTR_FMT,
> @@ -3782,10 +3778,10 @@ xfs_iflush_int(
>  	 * If there are inline format data / attr forks attached to this inode,
>  	 * make sure they are not corrupt.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_data(ip))
>  		goto flush_out;
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_afp && ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_attr(ip))
>  		goto flush_out;
>  
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 24dae63ba16c0..dadcf19458960 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -57,8 +57,6 @@ typedef struct xfs_inode {
>  
>  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
>  
> -	unsigned int		i_cformat;	/* format of cow fork */
> -
>  	/* VFS inode */
>  	struct inode		i_vnode;	/* embedded VFS inode */
>  
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index 401ba26aeed7b..ba47bf65b772b 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -36,7 +36,7 @@ xfs_inode_item_data_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
>  		    ip->i_df.if_nextents > 0 &&
> @@ -77,7 +77,7 @@ xfs_inode_item_attr_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
>  		    ip->i_afp->if_nextents > 0 &&
> @@ -142,7 +142,7 @@ xfs_inode_item_format_data_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
> @@ -227,7 +227,7 @@ xfs_inode_item_format_attr_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
> @@ -305,7 +305,7 @@ xfs_inode_to_log_dinode(
>  	struct inode		*inode = VFS_I(ip);
>  
>  	to->di_magic = XFS_DINODE_MAGIC;
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = i_uid_read(inode);
>  	to->di_gid = i_gid_read(inode);
>  	to->di_projid_lo = from->di_projid & 0xffff;
> @@ -329,7 +329,7 @@ xfs_inode_to_log_dinode(
>  	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
>  	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = from->di_dmevmask;
>  	to->di_dmstate = from->di_dmstate;
>  	to->di_flags = from->di_flags;
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index b4fd918749e5f..6ae3a2457777a 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -856,7 +856,7 @@ xfs_buffered_write_iomap_begin(
>  
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, XFS_DATA_FORK)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(&ip->i_df)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		error = -EFSCORRUPTED;
>  		goto out_unlock;
> @@ -1263,7 +1263,7 @@ xfs_xattr_iomap_begin(
>  		goto out_unlock;
>  	}
>  
> -	ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL);
>  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
>  			       &nimaps, XFS_BMAPI_ATTRFORK);
>  out_unlock:
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 80da86c5703fb..16ca97a7ff00f 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -115,7 +115,7 @@ xfs_bulkstat_one_int(
>  			buf->bs_cowextsize_blks = dic->di_cowextsize;
>  	}
>  
> -	switch (dic->di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
>  		buf->bs_blksize = BLKDEV_IOSIZE;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 8cf2fcb509c12..8e88a7ca387ea 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -251,7 +251,7 @@ xfs_symlink(
>  		xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
>  
>  		ip->i_d.di_size = pathlen;
> -		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
>  	} else {
>  		int	offset;
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index ba2ab69e1fc7d..460136628a795 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -1897,7 +1897,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
>  		__entry->dev = VFS_I(ip)->i_sb->s_dev;
>  		__entry->which = which;
>  		__entry->ino = ip->i_ino;
> -		__entry->format = ip->i_d.di_format;
> +		__entry->format = ip->i_df.if_format;
>  		__entry->nex = ip->i_df.if_nextents;
>  		__entry->broot_size = ip->i_df.if_broot_bytes;
>  		__entry->fork_off = XFS_IFORK_BOFF(ip);
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-10  7:24 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
  2020-05-12  9:48   ` Chandan Babu R
@ 2020-05-12 18:54   ` Brian Foster
  2020-05-16 18:10     ` Darrick J. Wong
  1 sibling, 1 reply; 41+ messages in thread
From: Brian Foster @ 2020-05-12 18:54 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:04AM +0200, Christoph Hellwig wrote:
> Move freeing the dynamically allocated attr and COW fork, as well
> as zeroing the pointers where actually needed into the callers, and
> just pass the xfs_ifork structure to xfs_idestroy_fork.  Simplify
> the kmem_free calls by not checking for NULL first, and not zeroing
> the pointers in structure that are about to be freed (either the
> ifork or the containing inode in case of the data fork).
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
>  fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
>  fs/xfs/libxfs/xfs_inode_fork.c | 36 +++++++++-------------------------
>  fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
>  fs/xfs/xfs_attr_inactive.c     |  7 +++++--
>  fs/xfs/xfs_icache.c            | 15 ++++++++------
>  6 files changed, 28 insertions(+), 41 deletions(-)
> 
...
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 6562f2bcd15cc..577cc20e03170 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -495,38 +495,20 @@ xfs_idata_realloc(
>  
>  void
>  xfs_idestroy_fork(
> -	xfs_inode_t	*ip,
> -	int		whichfork)
> +	struct xfs_ifork	*ifp)
>  {
> -	struct xfs_ifork	*ifp;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	if (ifp->if_broot != NULL) {
> -		kmem_free(ifp->if_broot);
> -		ifp->if_broot = NULL;
> -	}
> +	kmem_free(ifp->if_broot);

I think this function should still reset the pointers within the ifp
that it frees (if_broot and if_data below), particularly as long as
there are multiple callers that pass the data fork because it is not
immediately/independently freed. IOW, it's not clear if something
happens to reset i_mode between when xfs_inode_from_disk() might fail
and destroy the data fork, and when the inode is ultimately freed and we
look at i_mode to determine whether to destroy the data fork.

Brian

>  
>  	/*
> -	 * If the format is local, then we can't have an extents
> -	 * array so just look for an inline data array.  If we're
> -	 * not local then we may or may not have an extents list,
> -	 * so check and free it up if we do.
> +	 * If the format is local, then we can't have an extents array so just
> +	 * look for an inline data array.  If we're not local then we may or may
> +	 * not have an extents list, so check and free it up if we do.
>  	 */
>  	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
> -		if (ifp->if_u1.if_data != NULL) {
> -			kmem_free(ifp->if_u1.if_data);
> -			ifp->if_u1.if_data = NULL;
> -		}
> -	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
> -		xfs_iext_destroy(ifp);
> -	}
> -
> -	if (whichfork == XFS_ATTR_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> -		ip->i_afp = NULL;
> -	} else if (whichfork == XFS_COW_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> -		ip->i_cowfp = NULL;
> +		kmem_free(ifp->if_u1.if_data);
> +	} else if (ifp->if_flags & XFS_IFEXTENTS) {
> +		if (ifp->if_height)
> +			xfs_iext_destroy(ifp);
>  	}
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index d849cca103edd..a4953e95c4f3f 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
>  int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
>  void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
>  				struct xfs_inode_log_item *, int);
> -void		xfs_idestroy_fork(struct xfs_inode *, int);
> +void		xfs_idestroy_fork(struct xfs_ifork *ifp);
>  void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
>  				int whichfork);
>  void		xfs_iroot_realloc(struct xfs_inode *, int, int);
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index 00ffc46c0bf71..bfad669e6b2f8 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -388,8 +388,11 @@ xfs_attr_inactive(
>  	xfs_trans_cancel(trans);
>  out_destroy_fork:
>  	/* kill the in-core attr fork before we drop the inode lock */
> -	if (dp->i_afp)
> -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
> +	if (dp->i_afp) {
> +		xfs_idestroy_fork(dp->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
> +		dp->i_afp = NULL;
> +	}
>  	if (lock_mode)
>  		xfs_iunlock(dp, lock_mode);
>  	return error;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index c09b3e9eab1da..d806d3bfa8936 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -87,15 +87,18 @@ xfs_inode_free_callback(
>  	case S_IFREG:
>  	case S_IFDIR:
>  	case S_IFLNK:
> -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
> +		xfs_idestroy_fork(&ip->i_df);
>  		break;
>  	}
>  
> -	if (ip->i_afp)
> -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> -	if (ip->i_cowfp)
> -		xfs_idestroy_fork(ip, XFS_COW_FORK);
> -
> +	if (ip->i_afp) {
> +		xfs_idestroy_fork(ip->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> +	}
> +	if (ip->i_cowfp) {
> +		xfs_idestroy_fork(ip->i_cowfp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> +	}
>  	if (ip->i_itemp) {
>  		ASSERT(!test_bit(XFS_LI_IN_AIL,
>  				 &ip->i_itemp->ili_item.li_flags));
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-12 16:14         ` Brian Foster
@ 2020-05-12 19:16           ` Darrick J. Wong
  2020-05-13 13:19             ` Brian Foster
  0 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-12 19:16 UTC (permalink / raw)
  To: Brian Foster; +Cc: Chandan Babu R, Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 12:14:10PM -0400, Brian Foster wrote:
> On Tue, May 12, 2020 at 08:38:54AM -0700, Darrick J. Wong wrote:
> > On Tue, May 12, 2020 at 11:31:32AM -0400, Brian Foster wrote:
> > > On Mon, May 11, 2020 at 05:10:04PM +0530, Chandan Babu R wrote:
> > > > On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> > > > > XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> > > > > doesn't make a difference in practice as size is only checked for
> > > > > 0, but this keeps the logic sane.
> > > > >
> > > > 
> > > > Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
> > > > attr fork inside an inode's literal area?
> > > > 
> > > 
> > > I had the same thought. It's not clear to me what size is really
> > > supposed to be between the file size for a data fork and fork offset for
> > > the attr fork. I was also wondering if this should use
> > > XFS_IFORK_DSIZE(), but that won't be conditional based on population of
> > > the fork. At the same time, I don't think i_size != 0 necessarily
> > > correlates with the existence of blocks. The file could be completely
> > > sparse or could have any number of post-eof preallocated extents.
> > 
> > TBH I should have made that variable "bool empty" or something.
> > 
> > case XFS_DATA_FORK:
> > 	empty = i_size_read() == 0;
> > 
> 
> Even that is somewhat unclear because it's tied to i_size. What about
> size == 0 && <post-eof extents>?

/me stumbles around trying to remember under what circumstances do we
actually scan all the rmaps to make sure there's a corresponding bmap.
I think we're trying to avoid doing it for every file in the filesystem
because it's very slow...

Oh right -- we do that for btree format forks because there are a lot of
extent records and therefore a high(er) chance of something getting
lost; or

We scan all the rmaps for files that have nonzero size but zero extents,
because the (forthcoming) inode fork repair will reset damaged forks
back to extents format with zero extents, and this is how we will
trigger the bmap repair to get the extents mapped back into the file.

--D

> 
> Brian
> 
> > case XFS_ATTR_FORK:
> > 	empty = !XFS_IFORK_Q();
> > 
> > default:
> > 	empty = true;
> > 
> > if ((is not btree) && (empty || nextents > 0))
> > 	return 0;
> > 
> > --D
> > 
> > > Brian
> > > 
> > > > > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > > > > ---
> > > > >  fs/xfs/scrub/bmap.c | 2 +-
> > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > 
> > > > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > > > index add8598eacd5d..283424d6d2bb6 100644
> > > > > --- a/fs/xfs/scrub/bmap.c
> > > > > +++ b/fs/xfs/scrub/bmap.c
> > > > > @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
> > > > >  		size = i_size_read(VFS_I(sc->ip));
> > > > >  		break;
> > > > >  	case XFS_ATTR_FORK:
> > > > > -		size = XFS_IFORK_Q(sc->ip);
> > > > > +		size = XFS_IFORK_BOFF(sc->ip);
> > > > >  		break;
> > > > >  	default:
> > > > >  		size = 0;
> > > > > 
> > > > 
> > > > 
> > > > -- 
> > > > chandan
> > > > 
> > > > 
> > > > 
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-12 19:16           ` Darrick J. Wong
@ 2020-05-13 13:19             ` Brian Foster
  2020-05-13 13:21               ` Christoph Hellwig
  0 siblings, 1 reply; 41+ messages in thread
From: Brian Foster @ 2020-05-13 13:19 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Chandan Babu R, Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 12:16:15PM -0700, Darrick J. Wong wrote:
> On Tue, May 12, 2020 at 12:14:10PM -0400, Brian Foster wrote:
> > On Tue, May 12, 2020 at 08:38:54AM -0700, Darrick J. Wong wrote:
> > > On Tue, May 12, 2020 at 11:31:32AM -0400, Brian Foster wrote:
> > > > On Mon, May 11, 2020 at 05:10:04PM +0530, Chandan Babu R wrote:
> > > > > On Sunday 10 May 2020 12:53:59 PM IST Christoph Hellwig wrote:
> > > > > > XFS_IFORK_Q is to be used in boolean context, not for a size.  This
> > > > > > doesn't make a difference in practice as size is only checked for
> > > > > > 0, but this keeps the logic sane.
> > > > > >
> > > > > 
> > > > > Wouldn't XFS_IFORK_ASIZE() be a better fit since it gives the space used by the
> > > > > attr fork inside an inode's literal area?
> > > > > 
> > > > 
> > > > I had the same thought. It's not clear to me what size is really
> > > > supposed to be between the file size for a data fork and fork offset for
> > > > the attr fork. I was also wondering if this should use
> > > > XFS_IFORK_DSIZE(), but that won't be conditional based on population of
> > > > the fork. At the same time, I don't think i_size != 0 necessarily
> > > > correlates with the existence of blocks. The file could be completely
> > > > sparse or could have any number of post-eof preallocated extents.
> > > 
> > > TBH I should have made that variable "bool empty" or something.
> > > 
> > > case XFS_DATA_FORK:
> > > 	empty = i_size_read() == 0;
> > > 
> > 
> > Even that is somewhat unclear because it's tied to i_size. What about
> > size == 0 && <post-eof extents>?
> 
> /me stumbles around trying to remember under what circumstances do we
> actually scan all the rmaps to make sure there's a corresponding bmap.
> I think we're trying to avoid doing it for every file in the filesystem
> because it's very slow...
> 
> Oh right -- we do that for btree format forks because there are a lot of
> extent records and therefore a high(er) chance of something getting
> lost; or
> 
> We scan all the rmaps for files that have nonzero size but zero extents,
> because the (forthcoming) inode fork repair will reset damaged forks
> back to extents format with zero extents, and this is how we will
> trigger the bmap repair to get the extents mapped back into the file.
> 

Not sure I follow. Does this mean we're basically looking at sparse
files as "suspect" because we'd expect them to have extents? Why are we
looking at i_size here instead of fork size like for the attr fork, for
example? Either way it sounds like we're getting into some twisty repair
logic so perhaps this is beyond the scope of Christoph's patches..

Brian

> --D
> 
> > 
> > Brian
> > 
> > > case XFS_ATTR_FORK:
> > > 	empty = !XFS_IFORK_Q();
> > > 
> > > default:
> > > 	empty = true;
> > > 
> > > if ((is not btree) && (empty || nextents > 0))
> > > 	return 0;
> > > 
> > > --D
> > > 
> > > > Brian
> > > > 
> > > > > > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > > > > > ---
> > > > > >  fs/xfs/scrub/bmap.c | 2 +-
> > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > 
> > > > > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > > > > index add8598eacd5d..283424d6d2bb6 100644
> > > > > > --- a/fs/xfs/scrub/bmap.c
> > > > > > +++ b/fs/xfs/scrub/bmap.c
> > > > > > @@ -591,7 +591,7 @@ xchk_bmap_check_rmaps(
> > > > > >  		size = i_size_read(VFS_I(sc->ip));
> > > > > >  		break;
> > > > > >  	case XFS_ATTR_FORK:
> > > > > > -		size = XFS_IFORK_Q(sc->ip);
> > > > > > +		size = XFS_IFORK_BOFF(sc->ip);
> > > > > >  		break;
> > > > > >  	default:
> > > > > >  		size = 0;
> > > > > > 
> > > > > 
> > > > > 
> > > > > -- 
> > > > > chandan
> > > > > 
> > > > > 
> > > > > 
> > > > 
> > > 
> > 
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps
  2020-05-13 13:19             ` Brian Foster
@ 2020-05-13 13:21               ` Christoph Hellwig
  0 siblings, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-13 13:21 UTC (permalink / raw)
  To: Brian Foster
  Cc: Darrick J. Wong, Chandan Babu R, Christoph Hellwig, linux-xfs

On Wed, May 13, 2020 at 09:19:50AM -0400, Brian Foster wrote:
> > We scan all the rmaps for files that have nonzero size but zero extents,
> > because the (forthcoming) inode fork repair will reset damaged forks
> > back to extents format with zero extents, and this is how we will
> > trigger the bmap repair to get the extents mapped back into the file.
> > 
> 
> Not sure I follow. Does this mean we're basically looking at sparse
> files as "suspect" because we'd expect them to have extents? Why are we
> looking at i_size here instead of fork size like for the attr fork, for
> example? Either way it sounds like we're getting into some twisty repair
> logic so perhaps this is beyond the scope of Christoph's patches..

The patch can be easily dropped from the series.  I just noticed
something fishy while looking over the code and though the fix would
be easy enough..

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
  2020-05-12  9:37   ` Chandan Babu R
  2020-05-12 18:53   ` Brian Foster
@ 2020-05-14 21:25   ` Darrick J. Wong
  2020-05-16 13:58     ` Christoph Hellwig
  2 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-14 21:25 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:03AM +0200, Christoph Hellwig wrote:
> Both the data and attr fork have a format that is stored in the legacy
> idinode.  Move it into the xfs_ifork structure instead, where it uses
> up padding.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_attr.c           |  12 +--
>  fs/xfs/libxfs/xfs_attr_leaf.c      |  32 ++++----
>  fs/xfs/libxfs/xfs_bmap.c           | 120 +++++++++++++----------------
>  fs/xfs/libxfs/xfs_bmap_btree.c     |   5 +-
>  fs/xfs/libxfs/xfs_dir2.c           |   8 +-
>  fs/xfs/libxfs/xfs_dir2_sf.c        |  13 ++--
>  fs/xfs/libxfs/xfs_inode_buf.c      |   6 +-
>  fs/xfs/libxfs/xfs_inode_buf.h      |   2 -
>  fs/xfs/libxfs/xfs_inode_fork.c     |  14 ++--
>  fs/xfs/libxfs/xfs_inode_fork.h     |  28 ++++---
>  fs/xfs/libxfs/xfs_symlink_remote.c |  16 ++--
>  fs/xfs/scrub/bmap.c                |   4 +-
>  fs/xfs/scrub/dabtree.c             |   2 +-
>  fs/xfs/scrub/dir.c                 |   7 +-
>  fs/xfs/xfs_aops.c                  |   2 +-
>  fs/xfs/xfs_attr_inactive.c         |   2 +-
>  fs/xfs/xfs_attr_list.c             |   4 +-
>  fs/xfs/xfs_bmap_util.c             |  56 +++++++-------
>  fs/xfs/xfs_dir2_readdir.c          |   2 +-
>  fs/xfs/xfs_icache.c                |   1 -
>  fs/xfs/xfs_inode.c                 |  36 ++++-----
>  fs/xfs/xfs_inode.h                 |   2 -
>  fs/xfs/xfs_inode_item.c            |  12 +--
>  fs/xfs/xfs_iomap.c                 |   4 +-
>  fs/xfs/xfs_itable.c                |   2 +-
>  fs/xfs/xfs_symlink.c               |   2 +-
>  fs/xfs/xfs_trace.h                 |   2 +-
>  27 files changed, 181 insertions(+), 215 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 1b01675e9c80b..3b1bd6e112f89 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -61,7 +61,7 @@ xfs_inode_hasattr(
>  	struct xfs_inode	*ip)
>  {
>  	if (!XFS_IFORK_Q(ip) ||
> -	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	    (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     ip->i_afp->if_nextents == 0))
>  		return 0;
>  	return 1;
> @@ -84,7 +84,7 @@ xfs_attr_get_ilocked(
>  	if (!xfs_inode_hasattr(args->dp))
>  		return -ENOATTR;
>  
> -	if (args->dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_getvalue(args);
>  	if (xfs_bmap_one_block(args->dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_get(args);
> @@ -212,14 +212,14 @@ xfs_attr_set_args(
>  	 * If the attribute list is non-existent or a shortform list,
>  	 * upgrade it to a single-leaf-block attribute list.
>  	 */
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
> -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	     dp->i_afp->if_nextents == 0)) {
>  
>  		/*
>  		 * Build initial attribute list (if required).
>  		 */
> -		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
> +		if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
>  			xfs_attr_shortform_create(args);
>  
>  		/*
> @@ -272,7 +272,7 @@ xfs_attr_remove_args(
>  
>  	if (!xfs_inode_hasattr(dp)) {
>  		error = -ENOATTR;
> -	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
> +	} else if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
>  		error = xfs_attr_shortform_remove(args);
>  	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index 64b172180c42c..d7f3173ce3c31 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -539,7 +539,7 @@ xfs_attr_shortform_bytesfit(
>  	/* rounded down */
>  	offset = (XFS_LITINO(mp) - bytes) >> 3;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_DEV) {
>  		minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		return (offset >= minforkoff) ? minforkoff : 0;
>  	}
> @@ -567,7 +567,7 @@ xfs_attr_shortform_bytesfit(
>  
>  	dsize = dp->i_df.if_bytes;
>  
> -	switch (dp->i_d.di_format) {
> +	switch (dp->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		/*
>  		 * If there is no attr fork and the data fork is extents, 
> @@ -636,22 +636,19 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
>   * Create the initial contents of a shortform attribute list.
>   */
>  void
> -xfs_attr_shortform_create(xfs_da_args_t *args)
> +xfs_attr_shortform_create(
> +	struct xfs_da_args	*args)
>  {
> -	xfs_attr_sf_hdr_t *hdr;
> -	xfs_inode_t *dp;
> -	struct xfs_ifork *ifp;
> +	struct xfs_inode	*dp = args->dp;
> +	struct xfs_ifork	*ifp = dp->i_afp;
> +	struct xfs_attr_sf_hdr	*hdr;
>  
>  	trace_xfs_attr_sf_create(args);
>  
> -	dp = args->dp;
> -	ASSERT(dp != NULL);
> -	ifp = dp->i_afp;
> -	ASSERT(ifp != NULL);
>  	ASSERT(ifp->if_bytes == 0);
> -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS) {
>  		ifp->if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
> +		ifp->if_format = XFS_DINODE_FMT_LOCAL;
>  		ifp->if_flags |= XFS_IFINLINE;
>  	} else {
>  		ASSERT(ifp->if_flags & XFS_IFINLINE);
> @@ -721,7 +718,6 @@ xfs_attr_fork_remove(
>  {
>  	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
>  	ip->i_d.di_forkoff = 0;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	ASSERT(ip->i_afp == NULL);
>  
> @@ -774,7 +770,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  	totsize -= size;
>  	if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
>  	    (mp->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    !(args->op_flags & XFS_DA_OP_ADDNAME)) {
>  		xfs_attr_fork_remove(dp, args->trans);
>  	} else {
> @@ -784,7 +780,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
>  		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
>  				(args->op_flags & XFS_DA_OP_ADDNAME) ||
>  				!(mp->m_flags & XFS_MOUNT_ATTR2) ||
> -				dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
> +				dp->i_df.if_format == XFS_DINODE_FMT_BTREE);
>  		xfs_trans_log_inode(args->trans, dp,
>  					XFS_ILOG_CORE | XFS_ILOG_ADATA);
>  	}
> @@ -961,7 +957,7 @@ xfs_attr_shortform_allfit(
>  				+ be16_to_cpu(name_loc->valuelen);
>  	}
>  	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
> -	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> +	    (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
>  	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
>  		return -1;
>  	return xfs_attr_shortform_bytesfit(dp, bytes);
> @@ -980,7 +976,7 @@ xfs_attr_shortform_verify(
>  	int				i;
>  	int64_t				size;
>  
> -	ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK);
>  	sfp = (struct xfs_attr_shortform *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
> @@ -1084,7 +1080,7 @@ xfs_attr3_leaf_to_shortform(
>  
>  	if (forkoff == -1) {
>  		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
> -		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
> +		ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE);
>  		xfs_attr_fork_remove(dp, args->trans);
>  		goto out;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index c1136be49abeb..edc63dba007f4 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -123,7 +123,7 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +		ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  		ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -135,7 +135,7 @@ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
>  	struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	return whichfork != XFS_COW_FORK &&
> -		XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
> +		ifp->if_format == XFS_DINODE_FMT_BTREE &&
>  		ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
>  }
>  
> @@ -215,8 +215,8 @@ xfs_bmap_forkoff_reset(
>  	int		whichfork)
>  {
>  	if (whichfork == XFS_ATTR_FORK &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
> -	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
> +	    ip->i_df.if_format != XFS_DINODE_FMT_DEV &&
> +	    ip->i_df.if_format != XFS_DINODE_FMT_BTREE) {
>  		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
>  
>  		if (dfl_forkoff > ip->i_d.di_forkoff)
> @@ -317,31 +317,28 @@ xfs_bmap_check_leaf_extents(
>  	xfs_inode_t		*ip,		/* incore inode pointer */
>  	int			whichfork)	/* data or attr fork */
>  {
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_block	*block;	/* current btree block */
>  	xfs_fsblock_t		bno;	/* block # of "block" */
>  	xfs_buf_t		*bp;	/* buffer for "block" */
>  	int			error;	/* error return value */
>  	xfs_extnum_t		i=0, j;	/* index into the extents list */
> -	struct xfs_ifork	*ifp;	/* fork structure */
>  	int			level;	/* btree level, for checking */
> -	xfs_mount_t		*mp;	/* file system mount structure */
>  	__be64			*pp;	/* pointer to block address */
>  	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
>  	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
>  	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
>  	int			bp_release = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return;
> -	}
>  
>  	/* skip large extent count inodes */
>  	if (ip->i_df.if_nextents > 10000)
>  		return;
>  
>  	bno = NULLFSBLOCK;
> -	mp = ip->i_mount;
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	block = ifp->if_broot;
>  	/*
>  	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
> @@ -606,7 +603,7 @@ xfs_bmap_btree_to_extents(
>  	ASSERT(cur);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
>  	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
>  	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
> @@ -634,7 +631,7 @@ xfs_bmap_btree_to_extents(
>  	xfs_iroot_realloc(ip, -1, whichfork);
>  	ASSERT(ifp->if_broot == NULL);
>  	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	*logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
>  	return 0;
>  }
> @@ -670,7 +667,7 @@ xfs_bmap_extents_to_btree(
>  	mp = ip->i_mount;
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  	/*
>  	 * Make space in the inode incore. This needs to be undone if we fail
> @@ -694,7 +691,7 @@ xfs_bmap_extents_to_btree(
>  	/*
>  	 * Convert to a btree with two levels, one record in root.
>  	 */
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
> +	ifp->if_format = XFS_DINODE_FMT_BTREE;
>  	memset(&args, 0, sizeof(args));
>  	args.tp = tp;
>  	args.mp = mp;
> @@ -780,7 +777,7 @@ xfs_bmap_extents_to_btree(
>  	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
>  out_root_realloc:
>  	xfs_iroot_realloc(ip, -1, whichfork);
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ASSERT(ifp->if_broot == NULL);
>  	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
>  
> @@ -802,7 +799,7 @@ xfs_bmap_local_to_extents_empty(
>  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  
>  	ASSERT(whichfork != XFS_COW_FORK);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  	ASSERT(ifp->if_bytes == 0);
>  	ASSERT(ifp->if_nextents == 0);
>  
> @@ -811,7 +808,7 @@ xfs_bmap_local_to_extents_empty(
>  	ifp->if_flags |= XFS_IFEXTENTS;
>  	ifp->if_u1.if_root = NULL;
>  	ifp->if_height = 0;
> -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
> +	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  }
>  
> @@ -842,7 +839,7 @@ xfs_bmap_local_to_extents(
>  	 */
>  	ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	if (!ifp->if_bytes) {
>  		xfs_bmap_local_to_extents_empty(tp, ip, whichfork);
> @@ -1036,7 +1033,7 @@ xfs_bmap_set_attrforkoff(
>  	int			size,
>  	int			*version)
>  {
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
>  		break;
> @@ -1094,13 +1091,6 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	if (XFS_IFORK_Q(ip))
>  		goto trans_cancel;
> -	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
> -		/*
> -		 * For inodes coming from pre-6.2 filesystems.
> -		 */
> -		ASSERT(ip->i_d.di_aformat == 0);
> -		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> -	}
>  
>  	xfs_trans_ijoin(tp, ip, 0);
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> @@ -1109,9 +1099,10 @@ xfs_bmap_add_attrfork(
>  		goto trans_cancel;
>  	ASSERT(ip->i_afp == NULL);
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, 0);
> +	ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_flags = XFS_IFEXTENTS;
>  	logflags = 0;
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_bmap_add_attrfork_local(tp, ip, &logflags);
>  		break;
> @@ -1237,9 +1228,7 @@ xfs_iread_extents(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  
> -	if (XFS_IS_CORRUPT(mp,
> -			   XFS_IFORK_FORMAT(ip, whichfork) !=
> -			   XFS_DINODE_FMT_BTREE)) {
> +	if (XFS_IS_CORRUPT(mp, ifp->if_format != XFS_DINODE_FMT_BTREE)) {
>  		error = -EFSCORRUPTED;
>  		goto out;
>  	}
> @@ -1287,14 +1276,13 @@ xfs_bmap_first_unused(
>  	xfs_fileoff_t		lowest, max;
>  	int			error;
>  
> -	ASSERT(xfs_ifork_has_extents(ip, whichfork) ||
> -	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		*first_unused = 0;
>  		return 0;
>  	}
>  
> +	ASSERT(xfs_ifork_has_extents(ifp));
> +
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		error = xfs_iread_extents(tp, ip, whichfork);
>  		if (error)
> @@ -1335,7 +1323,7 @@ xfs_bmap_last_before(
>  	struct xfs_iext_cursor	icur;
>  	int			error;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		*last_block = 0;
>  		return 0;
> @@ -1434,16 +1422,17 @@ xfs_bmap_last_offset(
>  	xfs_fileoff_t		*last_block,
>  	int			whichfork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_bmbt_irec	rec;
>  	int			is_empty;
>  	int			error;
>  
>  	*last_block = 0;
>  
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return 0;
>  
> -	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  
>  	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
> @@ -1475,7 +1464,7 @@ xfs_bmap_one_block(
>  #endif	/* !DEBUG */
>  	if (ifp->if_nextents != 1)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		return 0;
>  	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
>  	xfs_iext_first(ifp, &icur);
> @@ -3895,10 +3884,9 @@ xfs_bmapi_read(
>  	if (WARN_ON_ONCE(!ifp))
>  		return -EFSCORRUPTED;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> -	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
> +	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
>  		return -EFSCORRUPTED;
> -	}
>  
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -4281,11 +4269,13 @@ xfs_bmapi_minleft(
>  	struct xfs_inode	*ip,
>  	int			fork)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, fork);
> +
>  	if (tp && tp->t_firstblock != NULLFSBLOCK)
>  		return 0;
> -	if (XFS_IFORK_FORMAT(ip, fork) != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 1;
> -	return be16_to_cpu(XFS_IFORK_PTR(ip, fork)->if_broot->bb_level) + 1;
> +	return be16_to_cpu(ifp->if_broot->bb_level) + 1;
>  }
>  
>  /*
> @@ -4300,11 +4290,13 @@ xfs_bmapi_finish(
>  	int			whichfork,
>  	int			error)
>  {
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
> +
>  	if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		bma->logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((bma->logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		bma->logflags &= ~xfs_ilog_fbroot(whichfork);
>  
>  	if (bma->logflags)
> @@ -4336,13 +4328,13 @@ xfs_bmapi_write(
>  		.total		= total,
>  	};
>  	struct xfs_mount	*mp = ip->i_mount;
> -	struct xfs_ifork	*ifp;
> +	int			whichfork = xfs_bmapi_whichfork(flags);
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	xfs_fileoff_t		end;		/* end of mapped file region */
>  	bool			eof = false;	/* after the end of extents */
>  	int			error;		/* error return */
>  	int			n;		/* current extent index */
>  	xfs_fileoff_t		obno;		/* old block number (offset) */
> -	int			whichfork;	/* data or attr fork */
>  
>  #ifdef DEBUG
>  	xfs_fileoff_t		orig_bno;	/* original block number value */
> @@ -4357,13 +4349,12 @@ xfs_bmapi_write(
>  	orig_mval = mval;
>  	orig_nmap = *nmap;
>  #endif
> -	whichfork = xfs_bmapi_whichfork(flags);
>  
>  	ASSERT(*nmap >= 1);
>  	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
>  	ASSERT(tp != NULL);
>  	ASSERT(len > 0);
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_LOCAL);
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(!(flags & XFS_BMAPI_REMAP));
>  
> @@ -4379,7 +4370,7 @@ xfs_bmapi_write(
>  	ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
>  			(XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4387,8 +4378,6 @@ xfs_bmapi_write(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -
>  	XFS_STATS_INC(mp, xs_blk_mapw);
>  
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
> @@ -4498,7 +4487,7 @@ xfs_bmapi_write(
>  	if (error)
>  		goto error0;
>  
> -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ifp->if_format != XFS_DINODE_FMT_BTREE ||
>  	       ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
>  	xfs_bmapi_finish(&bma, whichfork, 0);
>  	xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
> @@ -4645,7 +4634,7 @@ xfs_bmapi_remap(
>  	ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) !=
>  			(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC));
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -4689,9 +4678,9 @@ xfs_bmapi_remap(
>  	error = xfs_bmap_btree_to_extents(tp, ip, cur, &logflags, whichfork);
>  
>  error0:
> -	if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS)
> +	if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~XFS_ILOG_DEXT;
> -	else if (ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	else if (ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~XFS_ILOG_DBROOT;
>  
>  	if (logflags)
> @@ -5041,7 +5030,7 @@ xfs_bmap_del_extent_real(
>  	 * conversion to btree format, since the transaction will be dirty then.
>  	 */
>  	if (tp->t_blk_res == 0 &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
>  	    ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
>  	    del->br_startoff > got.br_startoff && del_endoff < got_endoff)
>  		return -ENOSPC;
> @@ -5284,7 +5273,7 @@ __xfs_bunmapi(
>  	whichfork = xfs_bmapi_whichfork(flags);
>  	ASSERT(whichfork != XFS_COW_FORK);
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)))
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
>  		return -EFSCORRUPTED;
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
> @@ -5322,7 +5311,7 @@ __xfs_bunmapi(
>  
>  	logflags = 0;
>  	if (ifp->if_flags & XFS_IFBROOT) {
> -		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
> +		ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
>  		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
>  		cur->bc_ino.flags = 0;
>  	} else
> @@ -5567,10 +5556,10 @@ __xfs_bunmapi(
>  	 * logging the extent records if we've converted to btree format.
>  	 */
>  	if ((logflags & xfs_ilog_fext(whichfork)) &&
> -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
> +	    ifp->if_format != XFS_DINODE_FMT_EXTENTS)
>  		logflags &= ~xfs_ilog_fext(whichfork);
>  	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
> -		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
> +		 ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		logflags &= ~xfs_ilog_fbroot(whichfork);
>  	/*
>  	 * Log inode even in the error case, if the transaction
> @@ -5781,7 +5770,7 @@ xfs_bmap_collapse_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5898,7 +5887,7 @@ xfs_bmap_insert_extents(
>  	int			error = 0;
>  	int			logflags = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -5992,18 +5981,18 @@ xfs_bmap_split_extent(
>  	xfs_fileoff_t		split_fsb)
>  {
>  	int				whichfork = XFS_DATA_FORK;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, whichfork);
>  	struct xfs_btree_cur		*cur = NULL;
>  	struct xfs_bmbt_irec		got;
>  	struct xfs_bmbt_irec		new; /* split extent */
>  	struct xfs_mount		*mp = ip->i_mount;
> -	struct xfs_ifork		*ifp;
>  	xfs_fsblock_t			gotblkcnt; /* new block count for got */
>  	struct xfs_iext_cursor		icur;
>  	int				error = 0;
>  	int				logflags = 0;
>  	int				i = 0;
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		return -EFSCORRUPTED;
>  	}
> @@ -6011,7 +6000,6 @@ xfs_bmap_split_extent(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  		/* Read in all the extents */
>  		error = xfs_iread_extents(tp, ip, whichfork);
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index 295a59cf88407..d9c63f17d2dec 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -636,10 +636,7 @@ xfs_bmbt_change_owner(
>  
>  	ASSERT(tp || buffer_list);
>  	ASSERT(!(tp && buffer_list));
> -	if (whichfork == XFS_DATA_FORK)
> -		ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE);
> -	else
> -		ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE);
> +	ASSERT(XFS_IFORK_PTR(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
>  
>  	cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
>  	if (!cur)
> diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
> index dd6fcaaea318a..612a9c5e41b1c 100644
> --- a/fs/xfs/libxfs/xfs_dir2.c
> +++ b/fs/xfs/libxfs/xfs_dir2.c
> @@ -278,7 +278,7 @@ xfs_dir_createname(
>  	if (!inum)
>  		args->op_flags |= XFS_DA_OP_JUSTCHECK;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_addname(args);
>  		goto out_free;
>  	}
> @@ -373,7 +373,7 @@ xfs_dir_lookup(
>  		args->op_flags |= XFS_DA_OP_CILOOKUP;
>  
>  	lock_mode = xfs_ilock_data_map_shared(dp);
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_lookup(args);
>  		goto out_check_rval;
>  	}
> @@ -443,7 +443,7 @@ xfs_dir_removename(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_removename(args);
>  		goto out_free;
>  	}
> @@ -504,7 +504,7 @@ xfs_dir_replace(
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		rval = xfs_dir2_sf_replace(args);
>  		goto out_free;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
> index 7b7f6fb2ea3b2..2463b5d734472 100644
> --- a/fs/xfs/libxfs/xfs_dir2_sf.c
> +++ b/fs/xfs/libxfs/xfs_dir2_sf.c
> @@ -343,7 +343,7 @@ xfs_dir2_block_to_sf(
>  	 */
>  	ASSERT(dp->i_df.if_bytes == 0);
>  	xfs_init_local_fork(dp, XFS_DATA_FORK, sfp, size);
> -	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +	dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  	dp->i_d.di_size = size;
>  
>  	logflags |= XFS_ILOG_DDATA;
> @@ -710,11 +710,11 @@ xfs_dir2_sf_verify(
>  	struct xfs_inode		*ip)
>  {
>  	struct xfs_mount		*mp = ip->i_mount;
> +	struct xfs_ifork		*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	struct xfs_dir2_sf_hdr		*sfp;
>  	struct xfs_dir2_sf_entry	*sfep;
>  	struct xfs_dir2_sf_entry	*next_sfep;
>  	char				*endp;
> -	struct xfs_ifork		*ifp;
>  	xfs_ino_t			ino;
>  	int				i;
>  	int				i8count;
> @@ -723,9 +723,8 @@ xfs_dir2_sf_verify(
>  	int				error;
>  	uint8_t				filetype;
>  
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
>  	sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
>  	size = ifp->if_bytes;
>  
> @@ -827,9 +826,9 @@ xfs_dir2_sf_create(
>  	 * If it's currently a zero-length extent file,
>  	 * convert it to local format.
>  	 */
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS) {
>  		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
> -		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		dp->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
>  		dp->i_df.if_flags |= XFS_IFINLINE;
>  	}
> @@ -1027,7 +1026,7 @@ xfs_dir2_sf_replace_needblock(
>  	int			newsize;
>  	struct xfs_dir2_sf_hdr	*sfp;
>  
> -	if (dp->i_d.di_format != XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format != XFS_DINODE_FMT_LOCAL)
>  		return false;
>  
>  	sfp = (struct xfs_dir2_sf_hdr *)dp->i_df.if_u1.if_data;
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index a374e2a81e764..ab555671e1543 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -225,7 +225,6 @@ xfs_inode_from_disk(
>  					be16_to_cpu(from->di_projid_lo);
>  	}
>  
> -	to->di_format = from->di_format;
>  	i_uid_write(inode, be32_to_cpu(from->di_uid));
>  	i_gid_write(inode, be32_to_cpu(from->di_gid));
>  
> @@ -246,7 +245,6 @@ xfs_inode_from_disk(
>  	to->di_nblocks = be64_to_cpu(from->di_nblocks);
>  	to->di_extsize = be32_to_cpu(from->di_extsize);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat	= from->di_aformat;
>  	to->di_dmevmask	= be32_to_cpu(from->di_dmevmask);
>  	to->di_dmstate	= be16_to_cpu(from->di_dmstate);
>  	to->di_flags	= be16_to_cpu(from->di_flags);
> @@ -289,7 +287,7 @@ xfs_inode_to_disk(
>  	to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
>  	to->di_onlink = 0;
>  
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = cpu_to_be32(i_uid_read(inode));
>  	to->di_gid = cpu_to_be32(i_gid_read(inode));
>  	to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
> @@ -312,7 +310,7 @@ xfs_inode_to_disk(
>  	to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
>  	to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
>  	to->di_dmstate = cpu_to_be16(from->di_dmstate);
>  	to->di_flags = cpu_to_be16(from->di_flags);
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
> index fecccfb26463c..865ac493c72a2 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.h
> +++ b/fs/xfs/libxfs/xfs_inode_buf.h
> @@ -16,14 +16,12 @@ struct xfs_dinode;
>   * format specific structures at the appropriate time.
>   */
>  struct xfs_icdinode {
> -	int8_t		di_format;	/* format of di_c data */
>  	uint16_t	di_flushiter;	/* incremented on flush */
>  	uint32_t	di_projid;	/* owner's project id */
>  	xfs_fsize_t	di_size;	/* number of bytes in file */
>  	xfs_rfsblock_t	di_nblocks;	/* # of direct & btree blocks used */
>  	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
>  	uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
> -	int8_t		di_aformat;	/* format of attr fork's data */
>  	uint32_t	di_dmevmask;	/* DMIG event mask */
>  	uint16_t	di_dmstate;	/* DMIG state info */
>  	uint16_t	di_flags;	/* random flags, XFS_DIFLAG_... */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 195da3552c5b5..6562f2bcd15cc 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -228,6 +228,7 @@ xfs_iformat_data_fork(
>  	struct inode		*inode = VFS_I(ip);
>  	int			error;
>  
> +	ip->i_df.if_format = dip->di_format;
>  	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
>  
>  	switch (inode->i_mode & S_IFMT) {
> @@ -241,7 +242,7 @@ xfs_iformat_data_fork(
>  	case S_IFREG:
>  	case S_IFLNK:
>  	case S_IFDIR:
> -		switch (dip->di_format) {
> +		switch (ip->i_df.if_format) {
>  		case XFS_DINODE_FMT_LOCAL:
>  			error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
>  					be64_to_cpu(dip->di_size));
> @@ -283,9 +284,12 @@ xfs_iformat_attr_fork(
>  	int			error = 0;
>  
>  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> +	ip->i_afp->if_format = dip->di_aformat;
> +	if (unlikely(ip->i_afp->if_format == 0)) /* pre IRIX 6.2 file system */
> +		ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
>  	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
>  
> -	switch (dip->di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
>  				xfs_dfork_attr_shortform_size(dip));
> @@ -508,7 +512,7 @@ xfs_idestroy_fork(
>  	 * not local then we may or may not have an extents list,
>  	 * so check and free it up if we do.
>  	 */
> -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
>  		if (ifp->if_u1.if_data != NULL) {
>  			kmem_free(ifp->if_u1.if_data);
>  			ifp->if_u1.if_data = NULL;
> @@ -605,7 +609,7 @@ xfs_iflush_fork(
>  	}
>  	cp = XFS_DFORK_PTR(dip, whichfork);
>  	mp = ip->i_mount;
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_LOCAL:
>  		if ((iip->ili_fields & dataflag[whichfork]) &&
>  		    (ifp->if_bytes > 0)) {
> @@ -678,7 +682,7 @@ xfs_ifork_init_cow(
>  	ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
>  				       KM_NOFS);
>  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
>  }
>  
>  /* Verify the inline contents of the data fork of an inode. */
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index a69d425fe68df..d849cca103edd 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -23,6 +23,7 @@ struct xfs_ifork {
>  	} if_u1;
>  	short			if_broot_bytes;	/* bytes allocated for root */
>  	unsigned char		if_flags;	/* per-fork flags */
> +	int8_t			if_format;	/* format of this fork */
>  	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
>  };
>  
> @@ -56,24 +57,14 @@ struct xfs_ifork {
>  		((w) == XFS_ATTR_FORK ? \
>  			XFS_IFORK_ASIZE(ip) : \
>  			0))
> -#define XFS_IFORK_FORMAT(ip,w) \
> -	((w) == XFS_DATA_FORK ? \
> -		(ip)->i_d.di_format : \
> -		((w) == XFS_ATTR_FORK ? \
> -			(ip)->i_d.di_aformat : \
> -			(ip)->i_cformat))
> -#define XFS_IFORK_FMT_SET(ip,w,n) \
> -	((w) == XFS_DATA_FORK ? \
> -		((ip)->i_d.di_format = (n)) : \
> -		((w) == XFS_ATTR_FORK ? \
> -			((ip)->i_d.di_aformat = (n)) : \
> -			((ip)->i_cformat = (n))))
>  #define XFS_IFORK_MAXEXT(ip, w) \
>  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
>  
> -#define xfs_ifork_has_extents(ip, w) \
> -	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
> -	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
> +static inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp)
> +{
> +	return ifp->if_format == XFS_DINODE_FMT_EXTENTS ||
> +		ifp->if_format == XFS_DINODE_FMT_BTREE;
> +}
>  
>  static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  {
> @@ -82,6 +73,13 @@ static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
>  	return ifp->if_nextents;
>  }
>  
> +static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
> +{
> +	if (!ifp)
> +		return XFS_DINODE_FMT_EXTENTS;
> +	return ifp->if_format;
> +}
> +
>  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
>  
>  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
> index 3b8260ca7d1b8..594bc447a7dd2 100644
> --- a/fs/xfs/libxfs/xfs_symlink_remote.c
> +++ b/fs/xfs/libxfs/xfs_symlink_remote.c
> @@ -204,16 +204,12 @@ xfs_failaddr_t
>  xfs_symlink_shortform_verify(
>  	struct xfs_inode	*ip)
>  {
> -	char			*sfp;
> -	char			*endp;
> -	struct xfs_ifork	*ifp;
> -	int			size;
> -
> -	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
> -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> -	sfp = (char *)ifp->if_u1.if_data;
> -	size = ifp->if_bytes;
> -	endp = sfp + size;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +	char			*sfp = (char *)ifp->if_u1.if_data;
> +	int			size = ifp->if_bytes;
> +	char			*endp = sfp + size;
> +
> +	ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
>  
>  	/*
>  	 * Zero length symlinks should never occur in memory as they are
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index 157f72efec5e9..dfa1533b4edfc 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
>  		size = 0;
>  		break;
>  	}
> -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&

ifp can be null here if bmapbt scrub is called on a file that has no
xattrs; this crashed my test vm immediately...

--D

>  	    (size == 0 || ifp->if_nextents > 0))
>  		return 0;
>  
> @@ -664,7 +664,7 @@ xchk_bmap(
>  	}
>  
>  	/* Check the fork values */
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_UUID:
>  	case XFS_DINODE_FMT_DEV:
>  	case XFS_DINODE_FMT_LOCAL:
> diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
> index 9a2e27ac13003..44b15015021f3 100644
> --- a/fs/xfs/scrub/dabtree.c
> +++ b/fs/xfs/scrub/dabtree.c
> @@ -468,7 +468,7 @@ xchk_da_btree(
>  	int				error;
>  
>  	/* Skip short format data structures; no btree to scan. */
> -	if (!xfs_ifork_has_extents(sc->ip, whichfork))
> +	if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
>  		return 0;
>  
>  	/* Set up initial da state. */
> diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
> index fe2a6e030c8a0..7c432997edade 100644
> --- a/fs/xfs/scrub/dir.c
> +++ b/fs/xfs/scrub/dir.c
> @@ -635,7 +635,7 @@ xchk_directory_blocks(
>  {
>  	struct xfs_bmbt_irec	got;
>  	struct xfs_da_args	args;
> -	struct xfs_ifork	*ifp;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	struct xfs_mount	*mp = sc->mp;
>  	xfs_fileoff_t		leaf_lblk;
>  	xfs_fileoff_t		free_lblk;
> @@ -647,11 +647,10 @@ xchk_directory_blocks(
>  	int			error;
>  
>  	/* Ignore local format directories. */
> -	if (sc->ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
> -	    sc->ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_format != XFS_DINODE_FMT_BTREE)
>  		return 0;
>  
> -	ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK);
>  	lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
>  	leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
>  	free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 9d9cebf187268..2834cbf1212e5 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -382,7 +382,7 @@ xfs_map_blocks(
>  	 */
>  retry:
>  	xfs_ilock(ip, XFS_ILOCK_SHARED);
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       (ip->i_df.if_flags & XFS_IFEXTENTS));
>  
>  	/*
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index c42f90e16b4fa..00ffc46c0bf71 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -367,7 +367,7 @@ xfs_attr_inactive(
>  	 * removal below.
>  	 */
>  	if (xfs_inode_hasattr(dp) &&
> -	    dp->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    dp->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_attr3_root_inactive(&trans, dp);
>  		if (error)
>  			goto out_cancel;
> diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
> index 5ff1d929d3b5f..e380bd1a9bfc9 100644
> --- a/fs/xfs/xfs_attr_list.c
> +++ b/fs/xfs/xfs_attr_list.c
> @@ -512,9 +512,9 @@ xfs_attr_list_ilocked(
>  	 */
>  	if (!xfs_inode_hasattr(dp))
>  		return 0;
> -	else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return xfs_attr_shortform_list(context);
> -	else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
> +	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
>  		return xfs_attr_leaf_list(context);
>  	return xfs_attr_node_list(context);
>  }
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 4f277a6253b8d..5e32c3cf8e8c1 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -223,7 +223,7 @@ xfs_bmap_count_blocks(
>  	if (!ifp)
>  		return 0;
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_BTREE:
>  		if (!(ifp->if_flags & XFS_IFEXTENTS)) {
>  			error = xfs_iread_extents(tp, ip, whichfork);
> @@ -449,7 +449,7 @@ xfs_getbmap(
>  		break;
>  	}
>  
> -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
> +	switch (ifp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  	case XFS_DINODE_FMT_BTREE:
>  		break;
> @@ -1210,17 +1210,19 @@ xfs_swap_extents_check_format(
>  	struct xfs_inode	*ip,	/* target inode */
>  	struct xfs_inode	*tip)	/* tmp inode */
>  {
> +	struct xfs_ifork	*ifp = &ip->i_df;
> +	struct xfs_ifork	*tifp = &tip->i_df;
>  
>  	/* Should never get a local format */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
> -	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (ifp->if_format == XFS_DINODE_FMT_LOCAL ||
> +	    tifp->if_format == XFS_DINODE_FMT_LOCAL)
>  		return -EINVAL;
>  
>  	/*
>  	 * if the target inode has less extents that then temporary inode then
>  	 * why did userspace call us?
>  	 */
> -	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
> +	if (ifp->if_nextents < tifp->if_nextents)
>  		return -EINVAL;
>  
>  	/*
> @@ -1235,18 +1237,18 @@ xfs_swap_extents_check_format(
>  	 * form then we will end up with the target inode in the wrong format
>  	 * as we already know there are less extents in the temp inode.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_format == XFS_DINODE_FMT_BTREE)
>  		return -EINVAL;
>  
>  	/* Check temp in extent form to max in target */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +	if (tifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    tifp->if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/* Check target in extent form to max in temp */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> -	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +	if (ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
> +	    ifp->if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  		return -EINVAL;
>  
>  	/*
> @@ -1258,22 +1260,20 @@ xfs_swap_extents_check_format(
>  	 * (a common defrag case) which will occur when the temp inode is in
>  	 * extent format...
>  	 */
> -	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (tifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(ip) &&
> -		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
> +		    XFS_BMAP_BMDR_SPACE(tifp->if_broot) > XFS_IFORK_BOFF(ip))
>  			return -EINVAL;
> -		if (tip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> +		if (tifp->if_nextents <= XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
>  	/* Reciprocal target->temp btree format checks */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
> +	if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
>  		if (XFS_IFORK_Q(tip) &&
>  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
>  			return -EINVAL;
> -		if (ip->i_df.if_nextents <=
> -		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> +		if (ifp->if_nextents <= XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
>  			return -EINVAL;
>  	}
>  
> @@ -1426,14 +1426,14 @@ xfs_swap_extent_forks(
>  	 * Count the number of extended attribute blocks
>  	 */
>  	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> -	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
>  				&aforkblks);
>  		if (error)
>  			return error;
>  	}
>  	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> -	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> +	    tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
>  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
>  				&taforkblks);
>  		if (error)
> @@ -1448,9 +1448,9 @@ xfs_swap_extent_forks(
>  	 * bmbt scan as the last step.
>  	 */
>  	if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
> -		if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*target_log_flags) |= XFS_ILOG_DOWNER;
> -		if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
> +		if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
>  			(*src_log_flags) |= XFS_ILOG_DOWNER;
>  	}
>  
> @@ -1466,8 +1466,6 @@ xfs_swap_extent_forks(
>  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
>  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
>  
> -	swap(ip->i_d.di_format, tip->i_d.di_format);
> -
>  	/*
>  	 * The extents in the source inode could still contain speculative
>  	 * preallocation beyond EOF (e.g. the file is open but not modified
> @@ -1481,7 +1479,7 @@ xfs_swap_extent_forks(
>  	tip->i_delayed_blks = ip->i_delayed_blks;
>  	ip->i_delayed_blks = 0;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*src_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1492,7 +1490,7 @@ xfs_swap_extent_forks(
>  		break;
>  	}
>  
> -	switch (tip->i_d.di_format) {
> +	switch (tip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		(*target_log_flags) |= XFS_ILOG_DEXT;
>  		break;
> @@ -1714,8 +1712,10 @@ xfs_swap_extents(
>  
>  	/* Swap the cow forks. */
>  	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
> -		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> -		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!ip->i_cowfp ||
> +		       ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
> +		ASSERT(!tip->i_cowfp ||
> +		       tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
>  
>  		swap(ip->i_cowfp, tip->i_cowfp);
>  
> diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
> index 871ec22c9aee9..66deddd5e2969 100644
> --- a/fs/xfs/xfs_dir2_readdir.c
> +++ b/fs/xfs/xfs_dir2_readdir.c
> @@ -524,7 +524,7 @@ xfs_readdir(
>  	args.geo = dp->i_mount->m_dir_geo;
>  	args.trans = tp;
>  
> -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> +	if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
>  		rval = xfs_dir2_sf_getdents(&args, ctx);
>  	else if ((rval = xfs_dir2_isblock(&args, &v)))
>  		;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 791d5d5e318cf..c09b3e9eab1da 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -63,7 +63,6 @@ xfs_inode_alloc(
>  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
>  	ip->i_afp = NULL;
>  	ip->i_cowfp = NULL;
> -	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
>  	memset(&ip->i_df, 0, sizeof(ip->i_df));
>  	ip->i_flags = 0;
>  	ip->i_delayed_blks = 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 1677c4e7207ed..64f5f9a440aed 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -112,7 +112,7 @@ xfs_ilock_data_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_df.if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -125,7 +125,8 @@ xfs_ilock_attr_map_shared(
>  {
>  	uint			lock_mode = XFS_ILOCK_SHARED;
>  
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE &&
> +	if (ip->i_afp &&
> +	    ip->i_afp->if_format == XFS_DINODE_FMT_BTREE &&
>  	    (ip->i_afp->if_flags & XFS_IFEXTENTS) == 0)
>  		lock_mode = XFS_ILOCK_EXCL;
>  	xfs_ilock(ip, lock_mode);
> @@ -851,7 +852,7 @@ xfs_ialloc(
>  	case S_IFCHR:
>  	case S_IFBLK:
>  	case S_IFSOCK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_DEV;
> +		ip->i_df.if_format = XFS_DINODE_FMT_DEV;
>  		ip->i_df.if_flags = 0;
>  		flags |= XFS_ILOG_DEV;
>  		break;
> @@ -907,7 +908,7 @@ xfs_ialloc(
>  		}
>  		/* FALLTHROUGH */
>  	case S_IFLNK:
> -		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> +		ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  		ip->i_df.if_flags = XFS_IFEXTENTS;
>  		ip->i_df.if_bytes = 0;
>  		ip->i_df.if_u1.if_root = NULL;
> @@ -915,10 +916,6 @@ xfs_ialloc(
>  	default:
>  		ASSERT(0);
>  	}
> -	/*
> -	 * Attribute fork settings for new inode.
> -	 */
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
>  
>  	/*
>  	 * Log the new values stuffed into the inode.
> @@ -2749,7 +2746,7 @@ xfs_ifree(
>  	 * data fork to extents format.  Note that the attr fork data has
>  	 * already been freed by xfs_attr_inactive.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
>  		kmem_free(ip->i_df.if_u1.if_data);
>  		ip->i_df.if_u1.if_data = NULL;
>  		ip->i_df.if_bytes = 0;
> @@ -2760,8 +2757,7 @@ xfs_ifree(
>  	ip->i_d.di_flags2 = 0;
>  	ip->i_d.di_dmevmask = 0;
>  	ip->i_d.di_forkoff = 0;		/* mark the attr fork not in use */
> -	ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
> -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> +	ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
>  
>  	/* Don't attempt to replay owner changes for a deleted inode */
>  	ip->i_itemp->ili_fields &= ~(XFS_ILOG_AOWNER|XFS_ILOG_DOWNER);
> @@ -3624,7 +3620,7 @@ xfs_iflush(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  
>  	*bpp = NULL;
> @@ -3706,7 +3702,7 @@ xfs_iflush_int(
>  
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
>  	ASSERT(xfs_isiflocked(ip));
> -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> +	ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
>  	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
>  	ASSERT(iip != NULL && iip->ili_fields != 0);
>  
> @@ -3728,8 +3724,8 @@ xfs_iflush_int(
>  	}
>  	if (S_ISREG(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE,
>  		    mp, XFS_ERRTAG_IFLUSH_3)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad regular inode %Lu, ptr "PTR_FMT,
> @@ -3738,9 +3734,9 @@ xfs_iflush_int(
>  		}
>  	} else if (S_ISDIR(VFS_I(ip)->i_mode)) {
>  		if (XFS_TEST_ERROR(
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
> -		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
> +		    ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_BTREE &&
> +		    ip->i_df.if_format != XFS_DINODE_FMT_LOCAL,
>  		    mp, XFS_ERRTAG_IFLUSH_4)) {
>  			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
>  				"%s: Bad directory inode %Lu, ptr "PTR_FMT,
> @@ -3782,10 +3778,10 @@ xfs_iflush_int(
>  	 * If there are inline format data / attr forks attached to this inode,
>  	 * make sure they are not corrupt.
>  	 */
> -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_data(ip))
>  		goto flush_out;
> -	if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
> +	if (ip->i_afp && ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL &&
>  	    xfs_ifork_verify_local_attr(ip))
>  		goto flush_out;
>  
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 24dae63ba16c0..dadcf19458960 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -57,8 +57,6 @@ typedef struct xfs_inode {
>  
>  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
>  
> -	unsigned int		i_cformat;	/* format of cow fork */
> -
>  	/* VFS inode */
>  	struct inode		i_vnode;	/* embedded VFS inode */
>  
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index 401ba26aeed7b..ba47bf65b772b 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -36,7 +36,7 @@ xfs_inode_item_data_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
>  		    ip->i_df.if_nextents > 0 &&
> @@ -77,7 +77,7 @@ xfs_inode_item_attr_fork_size(
>  {
>  	struct xfs_inode	*ip = iip->ili_inode;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
>  		    ip->i_afp->if_nextents > 0 &&
> @@ -142,7 +142,7 @@ xfs_inode_item_format_data_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
> @@ -227,7 +227,7 @@ xfs_inode_item_format_attr_fork(
>  	struct xfs_inode	*ip = iip->ili_inode;
>  	size_t			data_bytes;
>  
> -	switch (ip->i_d.di_aformat) {
> +	switch (ip->i_afp->if_format) {
>  	case XFS_DINODE_FMT_EXTENTS:
>  		iip->ili_fields &=
>  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
> @@ -305,7 +305,7 @@ xfs_inode_to_log_dinode(
>  	struct inode		*inode = VFS_I(ip);
>  
>  	to->di_magic = XFS_DINODE_MAGIC;
> -	to->di_format = from->di_format;
> +	to->di_format = xfs_ifork_format(&ip->i_df);
>  	to->di_uid = i_uid_read(inode);
>  	to->di_gid = i_gid_read(inode);
>  	to->di_projid_lo = from->di_projid & 0xffff;
> @@ -329,7 +329,7 @@ xfs_inode_to_log_dinode(
>  	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
>  	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
>  	to->di_forkoff = from->di_forkoff;
> -	to->di_aformat = from->di_aformat;
> +	to->di_aformat = xfs_ifork_format(ip->i_afp);
>  	to->di_dmevmask = from->di_dmevmask;
>  	to->di_dmstate = from->di_dmstate;
>  	to->di_flags = from->di_flags;
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index b4fd918749e5f..6ae3a2457777a 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -856,7 +856,7 @@ xfs_buffered_write_iomap_begin(
>  
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
>  
> -	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, XFS_DATA_FORK)) ||
> +	if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(&ip->i_df)) ||
>  	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
>  		error = -EFSCORRUPTED;
>  		goto out_unlock;
> @@ -1263,7 +1263,7 @@ xfs_xattr_iomap_begin(
>  		goto out_unlock;
>  	}
>  
> -	ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
> +	ASSERT(ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL);
>  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
>  			       &nimaps, XFS_BMAPI_ATTRFORK);
>  out_unlock:
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 80da86c5703fb..16ca97a7ff00f 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -115,7 +115,7 @@ xfs_bulkstat_one_int(
>  			buf->bs_cowextsize_blks = dic->di_cowextsize;
>  	}
>  
> -	switch (dic->di_format) {
> +	switch (ip->i_df.if_format) {
>  	case XFS_DINODE_FMT_DEV:
>  		buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
>  		buf->bs_blksize = BLKDEV_IOSIZE;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 8cf2fcb509c12..8e88a7ca387ea 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -251,7 +251,7 @@ xfs_symlink(
>  		xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
>  
>  		ip->i_d.di_size = pathlen;
> -		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +		ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
>  		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
>  	} else {
>  		int	offset;
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index ba2ab69e1fc7d..460136628a795 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -1897,7 +1897,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
>  		__entry->dev = VFS_I(ip)->i_sb->s_dev;
>  		__entry->which = which;
>  		__entry->ino = ip->i_ino;
> -		__entry->format = ip->i_d.di_format;
> +		__entry->format = ip->i_df.if_format;
>  		__entry->nex = ip->i_df.if_nextents;
>  		__entry->broot_size = ip->i_df.if_broot_bytes;
>  		__entry->fork_off = XFS_IFORK_BOFF(ip);
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-14 21:25   ` Darrick J. Wong
@ 2020-05-16 13:58     ` Christoph Hellwig
  2020-05-16 17:01       ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-16 13:58 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

On Thu, May 14, 2020 at 02:25:41PM -0700, Darrick J. Wong wrote:

[~1000 lines of fullquote deleted until I hit the first comment, sigh..]

> > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > index 157f72efec5e9..dfa1533b4edfc 100644
> > --- a/fs/xfs/scrub/bmap.c
> > +++ b/fs/xfs/scrub/bmap.c
> > @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
> >  		size = 0;
> >  		break;
> >  	}
> > -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> > +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
> 
> ifp can be null here if bmapbt scrub is called on a file that has no
> xattrs; this crashed my test vm immediately...

What tests is that?  And xfstests auto run did not hit it, even if a
NULL check here seems sensible.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-16 13:58     ` Christoph Hellwig
@ 2020-05-16 17:01       ` Darrick J. Wong
  2020-05-16 18:01         ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 17:01 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sat, May 16, 2020 at 03:58:08PM +0200, Christoph Hellwig wrote:
> On Thu, May 14, 2020 at 02:25:41PM -0700, Darrick J. Wong wrote:
> 
> [~1000 lines of fullquote deleted until I hit the first comment, sigh..]
> 
> > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > index 157f72efec5e9..dfa1533b4edfc 100644
> > > --- a/fs/xfs/scrub/bmap.c
> > > +++ b/fs/xfs/scrub/bmap.c
> > > @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
> > >  		size = 0;
> > >  		break;
> > >  	}
> > > -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> > > +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
> > 
> > ifp can be null here if bmapbt scrub is called on a file that has no
> > xattrs; this crashed my test vm immediately...
> 
> What tests is that?  And xfstests auto run did not hit it, even if a
> NULL check here seems sensible.

In my case it was the xfs_scrub run after generic/001 that did it.

I think we're covered against null *ifp in most cases because they're
guarded by an if(XFS_IFORK_Q()); it's jut here where I went around
shortcutting.  Maybe I should just fix this function for you... :)

--D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-16 17:01       ` Darrick J. Wong
@ 2020-05-16 18:01         ` Darrick J. Wong
  2020-05-16 18:16           ` Christoph Hellwig
  0 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:01 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sat, May 16, 2020 at 10:01:43AM -0700, Darrick J. Wong wrote:
> On Sat, May 16, 2020 at 03:58:08PM +0200, Christoph Hellwig wrote:
> > On Thu, May 14, 2020 at 02:25:41PM -0700, Darrick J. Wong wrote:
> > 
> > [~1000 lines of fullquote deleted until I hit the first comment, sigh..]
> > 
> > > > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > > > index 157f72efec5e9..dfa1533b4edfc 100644
> > > > --- a/fs/xfs/scrub/bmap.c
> > > > +++ b/fs/xfs/scrub/bmap.c
> > > > @@ -598,7 +598,7 @@ xchk_bmap_check_rmaps(
> > > >  		size = 0;
> > > >  		break;
> > > >  	}
> > > > -	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> > > > +	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
> > > 
> > > ifp can be null here if bmapbt scrub is called on a file that has no
> > > xattrs; this crashed my test vm immediately...
> > 
> > What tests is that?  And xfstests auto run did not hit it, even if a
> > NULL check here seems sensible.
> 
> In my case it was the xfs_scrub run after generic/001 that did it.
> 
> I think we're covered against null *ifp in most cases because they're
> guarded by an if(XFS_IFORK_Q()); it's jut here where I went around
> shortcutting.  Maybe I should just fix this function for you... :)

Hmm, that sounded meaner than I intended it to be. :/

Also, it turns out that it's pretty easy to fix this as part of fixing
the contorted logic in patch 1 (aka xchk_bmap_check_rmaps) so I'll do
that there.

> --D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro
  2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
  2020-05-11 12:39   ` Chandan Babu R
  2020-05-12 15:31   ` Brian Foster
@ 2020-05-16 18:02   ` Darrick J. Wong
  2 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:02 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:00AM +0200, Christoph Hellwig wrote:
> Just checking di_forkoff directly is a little easier to follow.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

/me hates macros
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_format.h    | 5 ++---
>  fs/xfs/libxfs/xfs_inode_buf.c | 6 +++---
>  2 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 045556e78ee2c..3cc352000b8a1 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -964,13 +964,12 @@ enum xfs_dinode_fmt {
>  /*
>   * Inode data & attribute fork sizes, per inode.
>   */
> -#define XFS_DFORK_Q(dip)		((dip)->di_forkoff != 0)
>  #define XFS_DFORK_BOFF(dip)		((int)((dip)->di_forkoff << 3))
>  
>  #define XFS_DFORK_DSIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
> +	((dip)->di_forkoff ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
>  #define XFS_DFORK_ASIZE(dip,mp) \
> -	(XFS_DFORK_Q(dip) ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
> +	((dip)->di_forkoff ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
>  #define XFS_DFORK_SIZE(dip,mp,w) \
>  	((w) == XFS_DATA_FORK ? \
>  		XFS_DFORK_DSIZE(dip, mp) : \
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index 05f939adea944..5547bbb3cf945 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -265,7 +265,7 @@ xfs_inode_from_disk(
>  	error = xfs_iformat_data_fork(ip, from);
>  	if (error)
>  		return error;
> -	if (XFS_DFORK_Q(from)) {
> +	if (from->di_forkoff) {
>  		error = xfs_iformat_attr_fork(ip, from);
>  		if (error)
>  			goto out_destroy_data_fork;
> @@ -435,7 +435,7 @@ xfs_dinode_verify_forkoff(
>  	struct xfs_dinode	*dip,
>  	struct xfs_mount	*mp)
>  {
> -	if (!XFS_DFORK_Q(dip))
> +	if (!dip->di_forkoff)
>  		return NULL;
>  
>  	switch (dip->di_format)  {
> @@ -538,7 +538,7 @@ xfs_dinode_verify(
>  		return __this_address;
>  	}
>  
> -	if (XFS_DFORK_Q(dip)) {
> +	if (dip->di_forkoff) {
>  		fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
>  		if (fa)
>  			return fa;
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 3/6] xfs: remove xfs_ifree_local_data
  2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
  2020-05-11 16:32   ` Chandan Babu R
  2020-05-12 15:31   ` Brian Foster
@ 2020-05-16 18:07   ` Darrick J. Wong
  2022-07-24 12:14     ` Alex Lyakas
  2 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:07 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sun, May 10, 2020 at 09:24:01AM +0200, Christoph Hellwig wrote:
> xfs_ifree only need to free inline data in the data fork, as we've
> already taken care of the attr fork before (and in fact freed the
> fork structure).  Just open code the freeing of the inline data.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/xfs_inode.c | 30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 549ff468b7b60..7d3144dc99b72 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2711,24 +2711,6 @@ xfs_ifree_cluster(
>  	return 0;
>  }
>  
> -/*
> - * Free any local-format buffers sitting around before we reset to
> - * extents format.
> - */
> -static inline void
> -xfs_ifree_local_data(
> -	struct xfs_inode	*ip,
> -	int			whichfork)
> -{
> -	struct xfs_ifork	*ifp;
> -
> -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
> -		return;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
> -}
> -
>  /*
>   * This is called to return an inode to the inode free list.
>   * The inode should already be truncated to 0 length and have
> @@ -2765,8 +2747,16 @@ xfs_ifree(
>  	if (error)
>  		return error;
>  
> -	xfs_ifree_local_data(ip, XFS_DATA_FORK);
> -	xfs_ifree_local_data(ip, XFS_ATTR_FORK);
> +	/*
> +	 * Free any local-format data sitting around before we reset the
> +	 * data fork to extents format.  Note that the attr fork data has
> +	 * already been freed by xfs_attr_inactive.
> +	 */
> +	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> +		kmem_free(ip->i_df.if_u1.if_data);
> +		ip->i_df.if_u1.if_data = NULL;
> +		ip->i_df.if_bytes = 0;
> +	}
>  
>  	VFS_I(ip)->i_mode = 0;		/* mark incore inode as free */
>  	ip->i_d.di_flags = 0;
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork
  2020-05-12 16:10   ` Brian Foster
@ 2020-05-16 18:09     ` Darrick J. Wong
  2020-05-17  8:12     ` Christoph Hellwig
  1 sibling, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:09 UTC (permalink / raw)
  To: Brian Foster; +Cc: Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 12:10:53PM -0400, Brian Foster wrote:
> On Sun, May 10, 2020 at 09:24:02AM +0200, Christoph Hellwig wrote:
> > There are thee number of extents counters, one for each of the forks,
> > Two are in the legacy icdinode and one is directly in struct xfs_inode.
> > Switch to a single counter in the xfs_ifork structure where it uses up
> > padding at the end of the structure.  This simplifies various bits of
> > code that just wants the number of extents counter and can now directly
> > dereference it.
> > 
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  fs/xfs/libxfs/xfs_attr.c       |   4 +-
> >  fs/xfs/libxfs/xfs_attr_leaf.c  |   1 -
> >  fs/xfs/libxfs/xfs_bmap.c       | 126 ++++++++++++++-------------------
> >  fs/xfs/libxfs/xfs_dir2_block.c |   2 +-
> >  fs/xfs/libxfs/xfs_inode_buf.c  |   6 +-
> >  fs/xfs/libxfs/xfs_inode_buf.h  |   2 -
> >  fs/xfs/libxfs/xfs_inode_fork.c |  12 ++--
> >  fs/xfs/libxfs/xfs_inode_fork.h |  20 +++---
> >  fs/xfs/scrub/bmap.c            |   3 +-
> >  fs/xfs/scrub/parent.c          |   2 +-
> >  fs/xfs/xfs_bmap_util.c         |  28 ++++----
> >  fs/xfs/xfs_file.c              |   2 +-
> >  fs/xfs/xfs_icache.c            |   1 -
> >  fs/xfs/xfs_inode.c             |  19 +++--
> >  fs/xfs/xfs_inode.h             |   1 -
> >  fs/xfs/xfs_inode_item.c        |  14 ++--
> >  fs/xfs/xfs_ioctl.c             |  25 +++----
> >  fs/xfs/xfs_iomap.c             |   2 +-
> >  fs/xfs/xfs_iops.c              |   2 +-
> >  fs/xfs/xfs_itable.c            |   4 +-
> >  fs/xfs/xfs_qm_syscalls.c       |   2 +-
> >  fs/xfs/xfs_quotaops.c          |   2 +-
> >  fs/xfs/xfs_symlink.c           |   2 +-
> >  fs/xfs/xfs_trace.h             |   2 +-
> >  24 files changed, 122 insertions(+), 162 deletions(-)
> > 
> ...
> > diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> > index 863444e2dda7e..64b172180c42c 100644
> > --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> > +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> > @@ -723,7 +723,6 @@ xfs_attr_fork_remove(
> >  	ip->i_d.di_forkoff = 0;
> >  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> >  
> > -	ASSERT(ip->i_d.di_anextents == 0);
> 
> Perhaps we could create an analogous assert in xfs_idestroy_fork()?
> 
> >  	ASSERT(ip->i_afp == NULL);
> >  
> >  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> ...
> > diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> > index 2fe325e38fd88..195da3552c5b5 100644
> > --- a/fs/xfs/libxfs/xfs_inode_fork.c
> > +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> > @@ -188,12 +188,11 @@ xfs_iformat_btree(
> >  	 * or the number of extents is greater than the number of
> >  	 * blocks.
> >  	 */
> > -	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
> > -					XFS_IFORK_MAXEXT(ip, whichfork) ||
> > +	if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
> >  		     nrecs == 0 ||
> >  		     XFS_BMDR_SPACE_CALC(nrecs) >
> >  					XFS_DFORK_SIZE(dip, mp, whichfork) ||
> > -		     XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
> > +		     ifp->if_nextents > ip->i_d.di_nblocks) ||
> >  		     level == 0 || level > XFS_BTREE_MAXLEVELS) {
> >  		xfs_warn(mp, "corrupt inode %Lu (btree).",
> >  					(unsigned long long) ip->i_ino);
> > @@ -229,6 +228,8 @@ xfs_iformat_data_fork(
> >  	struct inode		*inode = VFS_I(ip);
> >  	int			error;
> >  
> > +	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
> > +
> 
> Could use a comment here that the format calls below might depend on
> this being set (i.e. xfs_iformat_btree() just above).
> 
> >  	switch (inode->i_mode & S_IFMT) {
> >  	case S_IFIFO:
> >  	case S_IFCHR:
> > @@ -282,6 +283,8 @@ xfs_iformat_attr_fork(
> >  	int			error = 0;
> >  
> >  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> > +	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
> > +
> 
> Same here. Otherwise LGTM:
> 

Looks fine to me, and I can add those things on merge...

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> Reviewed-by: Brian Foster <bfoster@redhat.com>
> 
> >  	switch (dip->di_aformat) {
> >  	case XFS_DINODE_FMT_LOCAL:
> >  		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
> > @@ -617,7 +620,7 @@ xfs_iflush_fork(
> >  		       !(iip->ili_fields & extflag[whichfork]));
> >  		if ((iip->ili_fields & extflag[whichfork]) &&
> >  		    (ifp->if_bytes > 0)) {
> > -			ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
> > +			ASSERT(ifp->if_nextents > 0);
> >  			(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
> >  				whichfork);
> >  		}
> > @@ -676,7 +679,6 @@ xfs_ifork_init_cow(
> >  				       KM_NOFS);
> >  	ip->i_cowfp->if_flags = XFS_IFEXTENTS;
> >  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> > -	ip->i_cnextents = 0;
> >  }
> >  
> >  /* Verify the inline contents of the data fork of an inode. */
> > diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> > index f46a8c1db5964..a69d425fe68df 100644
> > --- a/fs/xfs/libxfs/xfs_inode_fork.h
> > +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> > @@ -23,6 +23,7 @@ struct xfs_ifork {
> >  	} if_u1;
> >  	short			if_broot_bytes;	/* bytes allocated for root */
> >  	unsigned char		if_flags;	/* per-fork flags */
> > +	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
> >  };
> >  
> >  /*
> > @@ -67,18 +68,6 @@ struct xfs_ifork {
> >  		((w) == XFS_ATTR_FORK ? \
> >  			((ip)->i_d.di_aformat = (n)) : \
> >  			((ip)->i_cformat = (n))))
> > -#define XFS_IFORK_NEXTENTS(ip,w) \
> > -	((w) == XFS_DATA_FORK ? \
> > -		(ip)->i_d.di_nextents : \
> > -		((w) == XFS_ATTR_FORK ? \
> > -			(ip)->i_d.di_anextents : \
> > -			(ip)->i_cnextents))
> > -#define XFS_IFORK_NEXT_SET(ip,w,n) \
> > -	((w) == XFS_DATA_FORK ? \
> > -		((ip)->i_d.di_nextents = (n)) : \
> > -		((w) == XFS_ATTR_FORK ? \
> > -			((ip)->i_d.di_anextents = (n)) : \
> > -			((ip)->i_cnextents = (n))))
> >  #define XFS_IFORK_MAXEXT(ip, w) \
> >  	(XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
> >  
> > @@ -86,6 +75,13 @@ struct xfs_ifork {
> >  	(XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_EXTENTS || \
> >  	 XFS_IFORK_FORMAT((ip), (w)) == XFS_DINODE_FMT_BTREE)
> >  
> > +static inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
> > +{
> > +	if (!ifp)
> > +		return 0;
> > +	return ifp->if_nextents;
> > +}
> > +
> >  struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
> >  
> >  int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> > diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> > index 283424d6d2bb6..157f72efec5e9 100644
> > --- a/fs/xfs/scrub/bmap.c
> > +++ b/fs/xfs/scrub/bmap.c
> > @@ -566,6 +566,7 @@ xchk_bmap_check_rmaps(
> >  	struct xfs_scrub	*sc,
> >  	int			whichfork)
> >  {
> > +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
> >  	loff_t			size;
> >  	xfs_agnumber_t		agno;
> >  	int			error;
> > @@ -598,7 +599,7 @@ xchk_bmap_check_rmaps(
> >  		break;
> >  	}
> >  	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
> > -	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
> > +	    (size == 0 || ifp->if_nextents > 0))
> >  		return 0;
> >  
> >  	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
> > diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
> > index 5705adc43a75f..855aa8bcab64b 100644
> > --- a/fs/xfs/scrub/parent.c
> > +++ b/fs/xfs/scrub/parent.c
> > @@ -90,7 +90,7 @@ xchk_parent_count_parent_dentries(
> >  	 * if there is one.
> >  	 */
> >  	lock_mode = xfs_ilock_data_map_shared(parent);
> > -	if (parent->i_d.di_nextents > 0)
> > +	if (parent->i_df.if_nextents > 0)
> >  		error = xfs_dir3_data_readahead(parent, 0, 0);
> >  	xfs_iunlock(parent, lock_mode);
> >  	if (error)
> > diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> > index cc23a3e23e2d1..4f277a6253b8d 100644
> > --- a/fs/xfs/xfs_bmap_util.c
> > +++ b/fs/xfs/xfs_bmap_util.c
> > @@ -1220,7 +1220,7 @@ xfs_swap_extents_check_format(
> >  	 * if the target inode has less extents that then temporary inode then
> >  	 * why did userspace call us?
> >  	 */
> > -	if (ip->i_d.di_nextents < tip->i_d.di_nextents)
> > +	if (ip->i_df.if_nextents < tip->i_df.if_nextents)
> >  		return -EINVAL;
> >  
> >  	/*
> > @@ -1241,14 +1241,12 @@ xfs_swap_extents_check_format(
> >  
> >  	/* Check temp in extent form to max in target */
> >  	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> > -	    XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) >
> > -			XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> > +	    tip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> >  		return -EINVAL;
> >  
> >  	/* Check target in extent form to max in temp */
> >  	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
> > -	    XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) >
> > -			XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> > +	    ip->i_df.if_nextents > XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> >  		return -EINVAL;
> >  
> >  	/*
> > @@ -1264,7 +1262,7 @@ xfs_swap_extents_check_format(
> >  		if (XFS_IFORK_Q(ip) &&
> >  		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
> >  			return -EINVAL;
> > -		if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
> > +		if (tip->i_df.if_nextents <=
> >  		    XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
> >  			return -EINVAL;
> >  	}
> > @@ -1274,7 +1272,7 @@ xfs_swap_extents_check_format(
> >  		if (XFS_IFORK_Q(tip) &&
> >  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
> >  			return -EINVAL;
> > -		if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
> > +		if (ip->i_df.if_nextents <=
> >  		    XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
> >  			return -EINVAL;
> >  	}
> > @@ -1427,15 +1425,15 @@ xfs_swap_extent_forks(
> >  	/*
> >  	 * Count the number of extended attribute blocks
> >  	 */
> > -	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
> > -	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> > +	if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
> > +	    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> >  		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
> >  				&aforkblks);
> >  		if (error)
> >  			return error;
> >  	}
> > -	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
> > -	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
> > +	if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
> > +	    tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
> >  		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
> >  				&taforkblks);
> >  		if (error)
> > @@ -1468,7 +1466,6 @@ xfs_swap_extent_forks(
> >  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
> >  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
> >  
> > -	swap(ip->i_d.di_nextents, tip->i_d.di_nextents);
> >  	swap(ip->i_d.di_format, tip->i_d.di_format);
> >  
> >  	/*
> > @@ -1615,9 +1612,9 @@ xfs_swap_extents(
> >  	 * performed with log redo items!
> >  	 */
> >  	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
> > -		int		w	= XFS_DATA_FORK;
> > -		uint32_t	ipnext	= XFS_IFORK_NEXTENTS(ip, w);
> > -		uint32_t	tipnext	= XFS_IFORK_NEXTENTS(tip, w);
> > +		int		w = XFS_DATA_FORK;
> > +		uint32_t	ipnext = ip->i_df.if_nextents;
> > +		uint32_t	tipnext	= tip->i_df.if_nextents;
> >  
> >  		/*
> >  		 * Conceptually this shouldn't affect the shape of either bmbt,
> > @@ -1720,7 +1717,6 @@ xfs_swap_extents(
> >  		ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> >  		ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
> >  
> > -		swap(ip->i_cnextents, tip->i_cnextents);
> >  		swap(ip->i_cowfp, tip->i_cowfp);
> >  
> >  		if (ip->i_cowfp && ip->i_cowfp->if_bytes)
> > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> > index 4b8bdecc38635..403c90309a8ff 100644
> > --- a/fs/xfs/xfs_file.c
> > +++ b/fs/xfs/xfs_file.c
> > @@ -1102,7 +1102,7 @@ xfs_dir_open(
> >  	 * certain to have the next operation be a read there.
> >  	 */
> >  	mode = xfs_ilock_data_map_shared(ip);
> > -	if (ip->i_d.di_nextents > 0)
> > +	if (ip->i_df.if_nextents > 0)
> >  		error = xfs_dir3_data_readahead(ip, 0, 0);
> >  	xfs_iunlock(ip, mode);
> >  	return error;
> > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> > index 5a3a520b95288..791d5d5e318cf 100644
> > --- a/fs/xfs/xfs_icache.c
> > +++ b/fs/xfs/xfs_icache.c
> > @@ -63,7 +63,6 @@ xfs_inode_alloc(
> >  	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
> >  	ip->i_afp = NULL;
> >  	ip->i_cowfp = NULL;
> > -	ip->i_cnextents = 0;
> >  	ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
> >  	memset(&ip->i_df, 0, sizeof(ip->i_df));
> >  	ip->i_flags = 0;
> > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> > index 7d3144dc99b72..1677c4e7207ed 100644
> > --- a/fs/xfs/xfs_inode.c
> > +++ b/fs/xfs/xfs_inode.c
> > @@ -825,7 +825,7 @@ xfs_ialloc(
> >  		inode->i_mode &= ~S_ISGID;
> >  
> >  	ip->i_d.di_size = 0;
> > -	ip->i_d.di_nextents = 0;
> > +	ip->i_df.if_nextents = 0;
> >  	ASSERT(ip->i_d.di_nblocks == 0);
> >  
> >  	tv = current_time(inode);
> > @@ -919,7 +919,6 @@ xfs_ialloc(
> >  	 * Attribute fork settings for new inode.
> >  	 */
> >  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> > -	ip->i_d.di_anextents = 0;
> >  
> >  	/*
> >  	 * Log the new values stuffed into the inode.
> > @@ -1686,7 +1685,7 @@ xfs_inactive_truncate(
> >  	if (error)
> >  		goto error_trans_cancel;
> >  
> > -	ASSERT(ip->i_d.di_nextents == 0);
> > +	ASSERT(ip->i_df.if_nextents == 0);
> >  
> >  	error = xfs_trans_commit(tp);
> >  	if (error)
> > @@ -1836,7 +1835,7 @@ xfs_inactive(
> >  
> >  	if (S_ISREG(VFS_I(ip)->i_mode) &&
> >  	    (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
> > -	     ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
> > +	     ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
> >  		truncate = 1;
> >  
> >  	error = xfs_qm_dqattach(ip);
> > @@ -1862,7 +1861,6 @@ xfs_inactive(
> >  	}
> >  
> >  	ASSERT(!ip->i_afp);
> > -	ASSERT(ip->i_d.di_anextents == 0);
> >  	ASSERT(ip->i_d.di_forkoff == 0);
> >  
> >  	/*
> > @@ -2731,8 +2729,7 @@ xfs_ifree(
> >  
> >  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> >  	ASSERT(VFS_I(ip)->i_nlink == 0);
> > -	ASSERT(ip->i_d.di_nextents == 0);
> > -	ASSERT(ip->i_d.di_anextents == 0);
> > +	ASSERT(ip->i_df.if_nextents == 0);
> >  	ASSERT(ip->i_d.di_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
> >  	ASSERT(ip->i_d.di_nblocks == 0);
> >  
> > @@ -3628,7 +3625,7 @@ xfs_iflush(
> >  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> >  	ASSERT(xfs_isiflocked(ip));
> >  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> > -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> > +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> >  
> >  	*bpp = NULL;
> >  
> > @@ -3710,7 +3707,7 @@ xfs_iflush_int(
> >  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> >  	ASSERT(xfs_isiflocked(ip));
> >  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
> > -	       ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> > +	       ip->i_df.if_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
> >  	ASSERT(iip != NULL && iip->ili_fields != 0);
> >  
> >  	dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
> > @@ -3751,13 +3748,13 @@ xfs_iflush_int(
> >  			goto flush_out;
> >  		}
> >  	}
> > -	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
> > +	if (XFS_TEST_ERROR(ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp) >
> >  				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5)) {
> >  		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
> >  			"%s: detected corrupt incore inode %Lu, "
> >  			"total extents = %d, nblocks = %Ld, ptr "PTR_FMT,
> >  			__func__, ip->i_ino,
> > -			ip->i_d.di_nextents + ip->i_d.di_anextents,
> > +			ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp),
> >  			ip->i_d.di_nblocks, ip);
> >  		goto flush_out;
> >  	}
> > diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> > index ff846197941e4..24dae63ba16c0 100644
> > --- a/fs/xfs/xfs_inode.h
> > +++ b/fs/xfs/xfs_inode.h
> > @@ -57,7 +57,6 @@ typedef struct xfs_inode {
> >  
> >  	struct xfs_icdinode	i_d;		/* most of ondisk inode */
> >  
> > -	xfs_extnum_t		i_cnextents;	/* # of extents in cow fork */
> >  	unsigned int		i_cformat;	/* format of cow fork */
> >  
> >  	/* VFS inode */
> > diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> > index cefa2484f0dbf..401ba26aeed7b 100644
> > --- a/fs/xfs/xfs_inode_item.c
> > +++ b/fs/xfs/xfs_inode_item.c
> > @@ -39,7 +39,7 @@ xfs_inode_item_data_fork_size(
> >  	switch (ip->i_d.di_format) {
> >  	case XFS_DINODE_FMT_EXTENTS:
> >  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> > -		    ip->i_d.di_nextents > 0 &&
> > +		    ip->i_df.if_nextents > 0 &&
> >  		    ip->i_df.if_bytes > 0) {
> >  			/* worst case, doesn't subtract delalloc extents */
> >  			*nbytes += XFS_IFORK_DSIZE(ip);
> > @@ -80,7 +80,7 @@ xfs_inode_item_attr_fork_size(
> >  	switch (ip->i_d.di_aformat) {
> >  	case XFS_DINODE_FMT_EXTENTS:
> >  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> > -		    ip->i_d.di_anextents > 0 &&
> > +		    ip->i_afp->if_nextents > 0 &&
> >  		    ip->i_afp->if_bytes > 0) {
> >  			/* worst case, doesn't subtract unused space */
> >  			*nbytes += XFS_IFORK_ASIZE(ip);
> > @@ -148,7 +148,7 @@ xfs_inode_item_format_data_fork(
> >  			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
> >  
> >  		if ((iip->ili_fields & XFS_ILOG_DEXT) &&
> > -		    ip->i_d.di_nextents > 0 &&
> > +		    ip->i_df.if_nextents > 0 &&
> >  		    ip->i_df.if_bytes > 0) {
> >  			struct xfs_bmbt_rec *p;
> >  
> > @@ -233,12 +233,12 @@ xfs_inode_item_format_attr_fork(
> >  			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
> >  
> >  		if ((iip->ili_fields & XFS_ILOG_AEXT) &&
> > -		    ip->i_d.di_anextents > 0 &&
> > +		    ip->i_afp->if_nextents > 0 &&
> >  		    ip->i_afp->if_bytes > 0) {
> >  			struct xfs_bmbt_rec *p;
> >  
> >  			ASSERT(xfs_iext_count(ip->i_afp) ==
> > -				ip->i_d.di_anextents);
> > +				ip->i_afp->if_nextents);
> >  
> >  			p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT);
> >  			data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK);
> > @@ -326,8 +326,8 @@ xfs_inode_to_log_dinode(
> >  	to->di_size = from->di_size;
> >  	to->di_nblocks = from->di_nblocks;
> >  	to->di_extsize = from->di_extsize;
> > -	to->di_nextents = from->di_nextents;
> > -	to->di_anextents = from->di_anextents;
> > +	to->di_nextents = xfs_ifork_nextents(&ip->i_df);
> > +	to->di_anextents = xfs_ifork_nextents(ip->i_afp);
> >  	to->di_forkoff = from->di_forkoff;
> >  	to->di_aformat = from->di_aformat;
> >  	to->di_dmevmask = from->di_dmevmask;
> > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > index 4ee0d13232f3f..7a71c03e9022b 100644
> > --- a/fs/xfs/xfs_ioctl.c
> > +++ b/fs/xfs/xfs_ioctl.c
> > @@ -1104,26 +1104,17 @@ xfs_fill_fsxattr(
> >  	bool			attr,
> >  	struct fsxattr		*fa)
> >  {
> > +	struct xfs_ifork	*ifp = attr ? ip->i_afp : &ip->i_df;
> > +
> >  	simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
> >  	fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
> >  	fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
> >  			ip->i_mount->m_sb.sb_blocklog;
> >  	fa->fsx_projid = ip->i_d.di_projid;
> > -
> > -	if (attr) {
> > -		if (ip->i_afp) {
> > -			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
> > -				fa->fsx_nextents = xfs_iext_count(ip->i_afp);
> > -			else
> > -				fa->fsx_nextents = ip->i_d.di_anextents;
> > -		} else
> > -			fa->fsx_nextents = 0;
> > -	} else {
> > -		if (ip->i_df.if_flags & XFS_IFEXTENTS)
> > -			fa->fsx_nextents = xfs_iext_count(&ip->i_df);
> > -		else
> > -			fa->fsx_nextents = ip->i_d.di_nextents;
> > -	}
> > +	if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
> > +		fa->fsx_nextents = xfs_iext_count(ifp);
> > +	else
> > +		fa->fsx_nextents = xfs_ifork_nextents(ifp);
> >  }
> >  
> >  STATIC int
> > @@ -1211,7 +1202,7 @@ xfs_ioctl_setattr_xflags(
> >  	uint64_t		di_flags2;
> >  
> >  	/* Can't change realtime flag if any extents are allocated. */
> > -	if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
> > +	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
> >  	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
> >  		return -EINVAL;
> >  
> > @@ -1389,7 +1380,7 @@ xfs_ioctl_setattr_check_extsize(
> >  	xfs_extlen_t		size;
> >  	xfs_fsblock_t		extsize_fsb;
> >  
> > -	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
> > +	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
> >  	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
> >  		return -EINVAL;
> >  
> > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> > index bb590a267a7f9..b4fd918749e5f 100644
> > --- a/fs/xfs/xfs_iomap.c
> > +++ b/fs/xfs/xfs_iomap.c
> > @@ -1258,7 +1258,7 @@ xfs_xattr_iomap_begin(
> >  	lockmode = xfs_ilock_attr_map_shared(ip);
> >  
> >  	/* if there are no attribute fork or extents, return ENOENT */
> > -	if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
> > +	if (!XFS_IFORK_Q(ip) || !ip->i_afp->if_nextents) {
> >  		error = -ENOENT;
> >  		goto out_unlock;
> >  	}
> > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> > index 26a71237d70f6..d66528fa36570 100644
> > --- a/fs/xfs/xfs_iops.c
> > +++ b/fs/xfs/xfs_iops.c
> > @@ -872,7 +872,7 @@ xfs_setattr_size(
> >  	/*
> >  	 * Short circuit the truncate case for zero length files.
> >  	 */
> > -	if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
> > +	if (newsize == 0 && oldsize == 0 && ip->i_df.if_nextents == 0) {
> >  		if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
> >  			return 0;
> >  
> > diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> > index ff2da28fed90e..80da86c5703fb 100644
> > --- a/fs/xfs/xfs_itable.c
> > +++ b/fs/xfs/xfs_itable.c
> > @@ -104,9 +104,9 @@ xfs_bulkstat_one_int(
> >  
> >  	buf->bs_xflags = xfs_ip2xflags(ip);
> >  	buf->bs_extsize_blks = dic->di_extsize;
> > -	buf->bs_extents = dic->di_nextents;
> > +	buf->bs_extents = xfs_ifork_nextents(&ip->i_df);
> >  	xfs_bulkstat_health(ip, buf);
> > -	buf->bs_aextents = dic->di_anextents;
> > +	buf->bs_aextents = xfs_ifork_nextents(ip->i_afp);
> >  	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
> >  	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
> >  
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index 944486f2b2874..9edf761eec739 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -302,7 +302,7 @@ xfs_qm_scall_trunc_qfile(
> >  		goto out_unlock;
> >  	}
> >  
> > -	ASSERT(ip->i_d.di_nextents == 0);
> > +	ASSERT(ip->i_df.if_nextents == 0);
> >  
> >  	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
> >  	error = xfs_trans_commit(tp);
> > diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
> > index 38669e8272060..b5d10ecb54743 100644
> > --- a/fs/xfs/xfs_quotaops.c
> > +++ b/fs/xfs/xfs_quotaops.c
> > @@ -36,7 +36,7 @@ xfs_qm_fill_state(
> >  	}
> >  	tstate->flags |= QCI_SYSFILE;
> >  	tstate->blocks = ip->i_d.di_nblocks;
> > -	tstate->nextents = ip->i_d.di_nextents;
> > +	tstate->nextents = ip->i_df.if_nextents;
> >  	tstate->spc_timelimit = (u32)q->qi_btimelimit;
> >  	tstate->ino_timelimit = (u32)q->qi_itimelimit;
> >  	tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit;
> > diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> > index 973441992b084..8cf2fcb509c12 100644
> > --- a/fs/xfs/xfs_symlink.c
> > +++ b/fs/xfs/xfs_symlink.c
> > @@ -384,7 +384,7 @@ xfs_inactive_symlink_rmt(
> >  	 * either 1 or 2 extents and that we can
> >  	 * free them all in one bunmapi call.
> >  	 */
> > -	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
> > +	ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
> >  
> >  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
> >  	if (error)
> > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> > index a4323a63438d8..ba2ab69e1fc7d 100644
> > --- a/fs/xfs/xfs_trace.h
> > +++ b/fs/xfs/xfs_trace.h
> > @@ -1898,7 +1898,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
> >  		__entry->which = which;
> >  		__entry->ino = ip->i_ino;
> >  		__entry->format = ip->i_d.di_format;
> > -		__entry->nex = ip->i_d.di_nextents;
> > +		__entry->nex = ip->i_df.if_nextents;
> >  		__entry->broot_size = ip->i_df.if_broot_bytes;
> >  		__entry->fork_off = XFS_IFORK_BOFF(ip);
> >  	),
> > -- 
> > 2.26.2
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-12 18:54   ` Brian Foster
@ 2020-05-16 18:10     ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:10 UTC (permalink / raw)
  To: Brian Foster; +Cc: Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 02:54:35PM -0400, Brian Foster wrote:
> On Sun, May 10, 2020 at 09:24:04AM +0200, Christoph Hellwig wrote:
> > Move freeing the dynamically allocated attr and COW fork, as well
> > as zeroing the pointers where actually needed into the callers, and
> > just pass the xfs_ifork structure to xfs_idestroy_fork.  Simplify
> > the kmem_free calls by not checking for NULL first, and not zeroing
> > the pointers in structure that are about to be freed (either the
> > ifork or the containing inode in case of the data fork).
> > 
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
> >  fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
> >  fs/xfs/libxfs/xfs_inode_fork.c | 36 +++++++++-------------------------
> >  fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
> >  fs/xfs/xfs_attr_inactive.c     |  7 +++++--
> >  fs/xfs/xfs_icache.c            | 15 ++++++++------
> >  6 files changed, 28 insertions(+), 41 deletions(-)
> > 
> ...
> > diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> > index 6562f2bcd15cc..577cc20e03170 100644
> > --- a/fs/xfs/libxfs/xfs_inode_fork.c
> > +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> > @@ -495,38 +495,20 @@ xfs_idata_realloc(
> >  
> >  void
> >  xfs_idestroy_fork(
> > -	xfs_inode_t	*ip,
> > -	int		whichfork)
> > +	struct xfs_ifork	*ifp)
> >  {
> > -	struct xfs_ifork	*ifp;
> > -
> > -	ifp = XFS_IFORK_PTR(ip, whichfork);
> > -	if (ifp->if_broot != NULL) {
> > -		kmem_free(ifp->if_broot);
> > -		ifp->if_broot = NULL;
> > -	}
> > +	kmem_free(ifp->if_broot);
> 
> I think this function should still reset the pointers within the ifp
> that it frees (if_broot and if_data below), particularly as long as
> there are multiple callers that pass the data fork because it is not
> immediately/independently freed. IOW, it's not clear if something
> happens to reset i_mode between when xfs_inode_from_disk() might fail
> and destroy the data fork, and when the inode is ultimately freed and we
> look at i_mode to determine whether to destroy the data fork.

/me agrees, let's not leave a potential UAF landmine here.

--D

> Brian
> 
> >  
> >  	/*
> > -	 * If the format is local, then we can't have an extents
> > -	 * array so just look for an inline data array.  If we're
> > -	 * not local then we may or may not have an extents list,
> > -	 * so check and free it up if we do.
> > +	 * If the format is local, then we can't have an extents array so just
> > +	 * look for an inline data array.  If we're not local then we may or may
> > +	 * not have an extents list, so check and free it up if we do.
> >  	 */
> >  	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
> > -		if (ifp->if_u1.if_data != NULL) {
> > -			kmem_free(ifp->if_u1.if_data);
> > -			ifp->if_u1.if_data = NULL;
> > -		}
> > -	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
> > -		xfs_iext_destroy(ifp);
> > -	}
> > -
> > -	if (whichfork == XFS_ATTR_FORK) {
> > -		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> > -		ip->i_afp = NULL;
> > -	} else if (whichfork == XFS_COW_FORK) {
> > -		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> > -		ip->i_cowfp = NULL;
> > +		kmem_free(ifp->if_u1.if_data);
> > +	} else if (ifp->if_flags & XFS_IFEXTENTS) {
> > +		if (ifp->if_height)
> > +			xfs_iext_destroy(ifp);
> >  	}
> >  }
> >  
> > diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> > index d849cca103edd..a4953e95c4f3f 100644
> > --- a/fs/xfs/libxfs/xfs_inode_fork.h
> > +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> > @@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
> >  int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
> >  void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
> >  				struct xfs_inode_log_item *, int);
> > -void		xfs_idestroy_fork(struct xfs_inode *, int);
> > +void		xfs_idestroy_fork(struct xfs_ifork *ifp);
> >  void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
> >  				int whichfork);
> >  void		xfs_iroot_realloc(struct xfs_inode *, int, int);
> > diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> > index 00ffc46c0bf71..bfad669e6b2f8 100644
> > --- a/fs/xfs/xfs_attr_inactive.c
> > +++ b/fs/xfs/xfs_attr_inactive.c
> > @@ -388,8 +388,11 @@ xfs_attr_inactive(
> >  	xfs_trans_cancel(trans);
> >  out_destroy_fork:
> >  	/* kill the in-core attr fork before we drop the inode lock */
> > -	if (dp->i_afp)
> > -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
> > +	if (dp->i_afp) {
> > +		xfs_idestroy_fork(dp->i_afp);
> > +		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
> > +		dp->i_afp = NULL;
> > +	}
> >  	if (lock_mode)
> >  		xfs_iunlock(dp, lock_mode);
> >  	return error;
> > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> > index c09b3e9eab1da..d806d3bfa8936 100644
> > --- a/fs/xfs/xfs_icache.c
> > +++ b/fs/xfs/xfs_icache.c
> > @@ -87,15 +87,18 @@ xfs_inode_free_callback(
> >  	case S_IFREG:
> >  	case S_IFDIR:
> >  	case S_IFLNK:
> > -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
> > +		xfs_idestroy_fork(&ip->i_df);
> >  		break;
> >  	}
> >  
> > -	if (ip->i_afp)
> > -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> > -	if (ip->i_cowfp)
> > -		xfs_idestroy_fork(ip, XFS_COW_FORK);
> > -
> > +	if (ip->i_afp) {
> > +		xfs_idestroy_fork(ip->i_afp);
> > +		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> > +	}
> > +	if (ip->i_cowfp) {
> > +		xfs_idestroy_fork(ip->i_cowfp);
> > +		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> > +	}
> >  	if (ip->i_itemp) {
> >  		ASSERT(!test_bit(XFS_LI_IN_AIL,
> >  				 &ip->i_itemp->ili_item.li_flags));
> > -- 
> > 2.26.2
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-16 18:01         ` Darrick J. Wong
@ 2020-05-16 18:16           ` Christoph Hellwig
  2020-05-16 18:29             ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-16 18:16 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

On Sat, May 16, 2020 at 11:01:50AM -0700, Darrick J. Wong wrote:
> > In my case it was the xfs_scrub run after generic/001 that did it.
> > 
> > I think we're covered against null *ifp in most cases because they're
> > guarded by an if(XFS_IFORK_Q()); it's jut here where I went around
> > shortcutting.  Maybe I should just fix this function for you... :)
> 
> Hmm, that sounded meaner than I intended it to be. :/
> 
> Also, it turns out that it's pretty easy to fix this as part of fixing
> the contorted logic in patch 1 (aka xchk_bmap_check_rmaps) so I'll do
> that there.

How about you send a patch to just fix up that function for now,
and I'll rebase on top of that?

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 5/6] xfs: move the fork format fields into struct xfs_ifork
  2020-05-16 18:16           ` Christoph Hellwig
@ 2020-05-16 18:29             ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:29 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Sat, May 16, 2020 at 08:16:58PM +0200, Christoph Hellwig wrote:
> On Sat, May 16, 2020 at 11:01:50AM -0700, Darrick J. Wong wrote:
> > > In my case it was the xfs_scrub run after generic/001 that did it.
> > > 
> > > I think we're covered against null *ifp in most cases because they're
> > > guarded by an if(XFS_IFORK_Q()); it's jut here where I went around
> > > shortcutting.  Maybe I should just fix this function for you... :)
> > 
> > Hmm, that sounded meaner than I intended it to be. :/
> > 
> > Also, it turns out that it's pretty easy to fix this as part of fixing
> > the contorted logic in patch 1 (aka xchk_bmap_check_rmaps) so I'll do
> > that there.
> 
> How about you send a patch to just fix up that function for now,
> and I'll rebase on top of that?

Ok.

--D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q
  2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
  2020-05-11 11:40   ` Chandan Babu R
@ 2020-05-16 18:42   ` Darrick J. Wong
  2020-05-16 20:01     ` Christoph Hellwig
  1 sibling, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2020-05-16 18:42 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

XFS_IFORK_Q is supposed to be a predicate, not a function returning a
value.  Its usage is in xchk_bmap_check_rmaps is incorrect, but that
function only cares about whether or not the "size" of the data is zero
or not.  Convert that logic to use a proper boolean, and teach the
caller to skip the call entirely if the end result would be that we'd do
nothing anyway.  This avoids a crash later in this series.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/scrub/bmap.c |   26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index add8598eacd5..002f10944de7 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -566,8 +566,8 @@ xchk_bmap_check_rmaps(
 	struct xfs_scrub	*sc,
 	int			whichfork)
 {
-	loff_t			size;
 	xfs_agnumber_t		agno;
+	bool			zero_size;
 	int			error;
 
 	if (!xfs_sb_version_hasrmapbt(&sc->mp->m_sb) ||
@@ -579,6 +579,8 @@ xchk_bmap_check_rmaps(
 	if (XFS_IS_REALTIME_INODE(sc->ip) && whichfork == XFS_DATA_FORK)
 		return 0;
 
+	ASSERT(XFS_IFORK_PTR(sc->ip, whichfork) != NULL);
+
 	/*
 	 * Only do this for complex maps that are in btree format, or for
 	 * situations where we would seem to have a size but zero extents.
@@ -586,19 +588,13 @@ xchk_bmap_check_rmaps(
 	 * to flag this bmap as corrupt if there are rmaps that need to be
 	 * reattached.
 	 */
-	switch (whichfork) {
-	case XFS_DATA_FORK:
-		size = i_size_read(VFS_I(sc->ip));
-		break;
-	case XFS_ATTR_FORK:
-		size = XFS_IFORK_Q(sc->ip);
-		break;
-	default:
-		size = 0;
-		break;
-	}
+	if (whichfork == XFS_DATA_FORK)
+		zero_size = i_size_read(VFS_I(sc->ip)) == 0;
+	else
+		zero_size = false;
+
 	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
+	    (zero_size || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
 		return 0;
 
 	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
@@ -651,8 +647,9 @@ xchk_bmap(
 		}
 		break;
 	case XFS_ATTR_FORK:
+		/* No fork means no attr data at all. */
 		if (!ifp)
-			goto out_check_rmap;
+			goto out;
 		if (!xfs_sb_version_hasattr(&mp->m_sb) &&
 		    !xfs_sb_version_hasattr2(&mp->m_sb))
 			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
@@ -717,7 +714,6 @@ xchk_bmap(
 			goto out;
 	}
 
-out_check_rmap:
 	error = xchk_bmap_check_rmaps(sc, whichfork);
 	if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
 		goto out;

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q
  2020-05-16 18:42   ` [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q Darrick J. Wong
@ 2020-05-16 20:01     ` Christoph Hellwig
  2020-05-17  8:05       ` Christoph Hellwig
  0 siblings, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-16 20:01 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

>  	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
> @@ -651,8 +647,9 @@ xchk_bmap(
>  		}
>  		break;
>  	case XFS_ATTR_FORK:
> +		/* No fork means no attr data at all. */
>  		if (!ifp)
> -			goto out_check_rmap;
> +			goto out;

Maybe lift the !ifp to before the switch statement, or even to just after
assigning the value to ifp?  For the data fork it obviously won't be
true, but it still looks simple than duplicating it for the attr and
cow fork.

Otherwise looks fine:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q
  2020-05-16 20:01     ` Christoph Hellwig
@ 2020-05-17  8:05       ` Christoph Hellwig
  0 siblings, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-17  8:05 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

On Sat, May 16, 2020 at 10:01:06PM +0200, Christoph Hellwig wrote:
> >  	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
> > @@ -651,8 +647,9 @@ xchk_bmap(
> >  		}
> >  		break;
> >  	case XFS_ATTR_FORK:
> > +		/* No fork means no attr data at all. */
> >  		if (!ifp)
> > -			goto out_check_rmap;
> > +			goto out;
> 
> Maybe lift the !ifp to before the switch statement, or even to just after
> assigning the value to ifp?  For the data fork it obviously won't be
> true, but it still looks simple than duplicating it for the attr and
> cow fork.
> 
> Otherwise looks fine:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>

This is what I ended up with for my tree:

---
From a98ef6f4bbfe186a83d3384cbd0a0727c0e1ddee Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Sat, 16 May 2020 11:42:59 -0700
Subject: xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q

XFS_IFORK_Q is supposed to be a predicate, not a function returning a
value.  Its usage is in xchk_bmap_check_rmaps is incorrect, but that
function only cares about whether or not the "size" of the data is zero
or not.  Convert that logic to use a proper boolean, and teach the
caller to skip the call entirely if the end result would be that we'd do
nothing anyway.  This avoids a crash later in this series.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
[hch: generalized the NULL ifor check]
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/scrub/bmap.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index add8598eacd5d..93d5b8a9d7f74 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -566,8 +566,8 @@ xchk_bmap_check_rmaps(
 	struct xfs_scrub	*sc,
 	int			whichfork)
 {
-	loff_t			size;
 	xfs_agnumber_t		agno;
+	bool			zero_size;
 	int			error;
 
 	if (!xfs_sb_version_hasrmapbt(&sc->mp->m_sb) ||
@@ -579,6 +579,8 @@ xchk_bmap_check_rmaps(
 	if (XFS_IS_REALTIME_INODE(sc->ip) && whichfork == XFS_DATA_FORK)
 		return 0;
 
+	ASSERT(XFS_IFORK_PTR(sc->ip, whichfork) != NULL);
+
 	/*
 	 * Only do this for complex maps that are in btree format, or for
 	 * situations where we would seem to have a size but zero extents.
@@ -586,19 +588,13 @@ xchk_bmap_check_rmaps(
 	 * to flag this bmap as corrupt if there are rmaps that need to be
 	 * reattached.
 	 */
-	switch (whichfork) {
-	case XFS_DATA_FORK:
-		size = i_size_read(VFS_I(sc->ip));
-		break;
-	case XFS_ATTR_FORK:
-		size = XFS_IFORK_Q(sc->ip);
-		break;
-	default:
-		size = 0;
-		break;
-	}
+	if (whichfork == XFS_DATA_FORK)
+		zero_size = i_size_read(VFS_I(sc->ip)) == 0;
+	else
+		zero_size = false;
+
 	if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    (size == 0 || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
+	    (zero_size || XFS_IFORK_NEXTENTS(sc->ip, whichfork) > 0))
 		return 0;
 
 	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
@@ -627,12 +623,14 @@ xchk_bmap(
 	struct xchk_bmap_info	info = { NULL };
 	struct xfs_mount	*mp = sc->mp;
 	struct xfs_inode	*ip = sc->ip;
-	struct xfs_ifork	*ifp;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 	xfs_fileoff_t		endoff;
 	struct xfs_iext_cursor	icur;
 	int			error = 0;
 
-	ifp = XFS_IFORK_PTR(ip, whichfork);
+	/* Non-existent forks can be ignored. */
+	if (!ifp)
+		goto out;
 
 	info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip);
 	info.whichfork = whichfork;
@@ -641,9 +639,6 @@ xchk_bmap(
 
 	switch (whichfork) {
 	case XFS_COW_FORK:
-		/* Non-existent CoW forks are ignorable. */
-		if (!ifp)
-			goto out;
 		/* No CoW forks on non-reflink inodes/filesystems. */
 		if (!xfs_is_reflink_inode(ip)) {
 			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
@@ -651,8 +646,6 @@ xchk_bmap(
 		}
 		break;
 	case XFS_ATTR_FORK:
-		if (!ifp)
-			goto out_check_rmap;
 		if (!xfs_sb_version_hasattr(&mp->m_sb) &&
 		    !xfs_sb_version_hasattr2(&mp->m_sb))
 			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
@@ -717,7 +710,6 @@ xchk_bmap(
 			goto out;
 	}
 
-out_check_rmap:
 	error = xchk_bmap_check_rmaps(sc, whichfork);
 	if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
 		goto out;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork
  2020-05-12 16:10   ` Brian Foster
  2020-05-16 18:09     ` Darrick J. Wong
@ 2020-05-17  8:12     ` Christoph Hellwig
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-17  8:12 UTC (permalink / raw)
  To: Brian Foster; +Cc: Christoph Hellwig, linux-xfs

On Tue, May 12, 2020 at 12:10:53PM -0400, Brian Foster wrote:
> >  	ip->i_d.di_forkoff = 0;
> >  	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
> >  
> > -	ASSERT(ip->i_d.di_anextents == 0);
> 
> Perhaps we could create an analogous assert in xfs_idestroy_fork()?

Added for the next version.

> > @@ -229,6 +228,8 @@ xfs_iformat_data_fork(
> >  	struct inode		*inode = VFS_I(ip);
> >  	int			error;
> >  
> > +	ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
> > +
> 
> Could use a comment here that the format calls below might depend on
> this being set (i.e. xfs_iformat_btree() just above).

> >  	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
> > +	ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents);
> > +
> 
> Same here. Otherwise LGTM:

Sure.


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 3/6] xfs: remove xfs_ifree_local_data
  2020-05-16 18:07   ` Darrick J. Wong
@ 2022-07-24 12:14     ` Alex Lyakas
  0 siblings, 0 replies; 41+ messages in thread
From: Alex Lyakas @ 2022-07-24 12:14 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

Hi Christoph,

On Sat, May 16, 2020 at 9:07 PM Darrick J. Wong <darrick.wong@oracle.com> wrote:
>
> On Sun, May 10, 2020 at 09:24:01AM +0200, Christoph Hellwig wrote:
> > xfs_ifree only need to free inline data in the data fork, as we've
> > already taken care of the attr fork before (and in fact freed the
> > fork structure).  Just open code the freeing of the inline data.
> >
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Looks ok,
> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
>
> --D
>
> > ---
> >  fs/xfs/xfs_inode.c | 30 ++++++++++--------------------
> >  1 file changed, 10 insertions(+), 20 deletions(-)
> >
> > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> > index 549ff468b7b60..7d3144dc99b72 100644
> > --- a/fs/xfs/xfs_inode.c
> > +++ b/fs/xfs/xfs_inode.c
> > @@ -2711,24 +2711,6 @@ xfs_ifree_cluster(
> >       return 0;
> >  }
> >
> > -/*
> > - * Free any local-format buffers sitting around before we reset to
> > - * extents format.
> > - */
> > -static inline void
> > -xfs_ifree_local_data(
> > -     struct xfs_inode        *ip,
> > -     int                     whichfork)
> > -{
> > -     struct xfs_ifork        *ifp;
> > -
> > -     if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
> > -             return;
> > -
> > -     ifp = XFS_IFORK_PTR(ip, whichfork);
> > -     xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
> > -}
> > -
> >  /*
> >   * This is called to return an inode to the inode free list.
> >   * The inode should already be truncated to 0 length and have
> > @@ -2765,8 +2747,16 @@ xfs_ifree(
> >       if (error)
> >               return error;
> >
> > -     xfs_ifree_local_data(ip, XFS_DATA_FORK);
> > -     xfs_ifree_local_data(ip, XFS_ATTR_FORK);
> > +     /*
> > +      * Free any local-format data sitting around before we reset the
> > +      * data fork to extents format.  Note that the attr fork data has
> > +      * already been freed by xfs_attr_inactive.
> > +      */
> > +     if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
> > +             kmem_free(ip->i_df.if_u1.if_data);
> > +             ip->i_df.if_u1.if_data = NULL;
> > +             ip->i_df.if_bytes = 0;
> > +     }
> >
> >       VFS_I(ip)->i_mode = 0;          /* mark incore inode as free */
> >       ip->i_d.di_flags = 0;
> > --
> > 2.26.2
> >


I stumbled upon this patch, by analyzing a kernel panic we had [1].
Looking at the call trace, the panic happened in
xfs_ifree_local_data() being called with XFS_ATTR_FORK.
It looks like
ifp = XFS_IFORK_PTR(ip, whichfork);
returned NULL.

Based on your patch, do I understand correctly that it fixes the panic?

What happened seems to be that inode had an attribute fork and
xfs_attr_fork_remove() was called on it. This function set:
ip->i_afp = NULL
ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS.

As a result, xfs_ifree_local_data() [2] checked XFS_IFORK_FORMAT() and
got XFS_DINODE_FMT_EXTENTS. So it performed:
    ifp = XFS_IFORK_PTR(ip, whichfork);
    xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
which caused NULL pointer exception.

Is this analysis correct, that any time we have an inode with an
attribute fork, we will crash deleting it?

Thanks,
Alex.



[1]
BUG: unable to handle kernel NULL pointer dereference at           (null)
IP: xfs_ifree+0x12c/0x150 [xfs]
PGD 800000066eea0067 P4D 800000066eea0067 PUD 3066ce067 PMD 0
Oops: 0000 [#1] PREEMPT SMP PTI
Modules linked in: binfmt_misc xt_nat xfs(OE) sd_mod sg bonding xt_CHECKSUM i
 libiscsi_tcp(OE) sunrpc libiscsi(OE) scsi_transport_iscsi(OE) i6300esb ip_ta
CPU: 3 PID: 19176 Comm: swift-object-re Tainted: G        W  OE   4.14.99-zad
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 0
task: ffffa009b0d45640 task.stack: ffffb0a85dddc000
RIP: 0010:xfs_ifree+0x12c/0x150 [xfs]
RSP: 0018:ffffb0a85dddfdb8 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa00999610f00 RCX: 000000168215a803
RDX: 0000000000000000 RSI: ffffd0a83f9b3ed0 RDI: ffffa00999610f00
RBP: ffffa00edbe1af30 R08: 00003091b4833ed0 R09: ffffffffc0a39de4
R10: 0000000000000000 R11: 0000000000000040 R12: ffffb0a85dddfe10
R13: ffffb0a85dddfe08 R14: ffffa00d7f147780 R15: 0000000000000000
FS:  00007f012ffff700(0000) GS:ffffa0168b180000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000749f26006 CR4: 00000000003606e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 xfs_inactive_ifree+0xbb/0x220 [xfs]
 xfs_inactive+0x74/0x100 [xfs]
 xfs_fs_destroy_inode+0xb4/0x240 [xfs]
 do_unlinkat+0x1b3/0x310
 do_syscall_64+0x6e/0x120
 entry_SYSCALL_64_after_hwframe+0x3d/0xa2


[2]
static inline void
xfs_ifree_local_data(
    struct xfs_inode    *ip,
    int            whichfork)
{
    struct xfs_ifork    *ifp;

    if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
        return;

    ifp = XFS_IFORK_PTR(ip, whichfork);
    xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
}

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-18  7:33 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
@ 2020-05-18 13:28   ` Brian Foster
  0 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2020-05-18 13:28 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs, Chandan Babu R

On Mon, May 18, 2020 at 09:33:58AM +0200, Christoph Hellwig wrote:
> Move freeing the dynamically allocated attr and COW fork, as well
> as zeroing the pointers where actually needed into the callers, and
> just pass the xfs_ifork structure to xfs_idestroy_fork.  Also simplify
> the kmem_free calls by not checking for NULL first.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
>  fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
>  fs/xfs/libxfs/xfs_inode_fork.c | 32 +++++++++-----------------------
>  fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
>  fs/xfs/xfs_attr_inactive.c     |  7 +++++--
>  fs/xfs/xfs_icache.c            | 15 +++++++++------
>  6 files changed, 28 insertions(+), 37 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index b279200519777..394805abb4535 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -718,11 +718,10 @@ xfs_attr_fork_remove(
>  {
>  	ASSERT(ip->i_afp->if_nextents == 0);
>  
> -	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> +	xfs_idestroy_fork(ip->i_afp);
> +	kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> +	ip->i_afp = NULL;
>  	ip->i_d.di_forkoff = 0;
> -
> -	ASSERT(ip->i_afp == NULL);
> -
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index ab555671e1543..6f84ea85fdd83 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -271,7 +271,7 @@ xfs_inode_from_disk(
>  	return 0;
>  
>  out_destroy_data_fork:
> -	xfs_idestroy_fork(ip, XFS_DATA_FORK);
> +	xfs_idestroy_fork(&ip->i_df);
>  	return error;
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index ef43b4893766c..28b366275ae0e 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -503,38 +503,24 @@ xfs_idata_realloc(
>  
>  void
>  xfs_idestroy_fork(
> -	xfs_inode_t	*ip,
> -	int		whichfork)
> +	struct xfs_ifork	*ifp)
>  {
> -	struct xfs_ifork	*ifp;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
>  	if (ifp->if_broot != NULL) {
>  		kmem_free(ifp->if_broot);
>  		ifp->if_broot = NULL;
>  	}
>  
>  	/*
> -	 * If the format is local, then we can't have an extents
> -	 * array so just look for an inline data array.  If we're
> -	 * not local then we may or may not have an extents list,
> -	 * so check and free it up if we do.
> +	 * If the format is local, then we can't have an extents array so just
> +	 * look for an inline data array.  If we're not local then we may or may
> +	 * not have an extents list, so check and free it up if we do.
>  	 */
>  	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
> -		if (ifp->if_u1.if_data != NULL) {
> -			kmem_free(ifp->if_u1.if_data);
> -			ifp->if_u1.if_data = NULL;
> -		}
> -	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
> -		xfs_iext_destroy(ifp);
> -	}
> -
> -	if (whichfork == XFS_ATTR_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> -		ip->i_afp = NULL;
> -	} else if (whichfork == XFS_COW_FORK) {
> -		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> -		ip->i_cowfp = NULL;
> +		kmem_free(ifp->if_u1.if_data);
> +		ifp->if_u1.if_data = NULL;
> +	} else if (ifp->if_flags & XFS_IFEXTENTS) {
> +		if (ifp->if_height)
> +			xfs_iext_destroy(ifp);
>  	}
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
> index d849cca103edd..a4953e95c4f3f 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.h
> +++ b/fs/xfs/libxfs/xfs_inode_fork.h
> @@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
>  int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
>  void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
>  				struct xfs_inode_log_item *, int);
> -void		xfs_idestroy_fork(struct xfs_inode *, int);
> +void		xfs_idestroy_fork(struct xfs_ifork *ifp);
>  void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
>  				int whichfork);
>  void		xfs_iroot_realloc(struct xfs_inode *, int, int);
> diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
> index 00ffc46c0bf71..bfad669e6b2f8 100644
> --- a/fs/xfs/xfs_attr_inactive.c
> +++ b/fs/xfs/xfs_attr_inactive.c
> @@ -388,8 +388,11 @@ xfs_attr_inactive(
>  	xfs_trans_cancel(trans);
>  out_destroy_fork:
>  	/* kill the in-core attr fork before we drop the inode lock */
> -	if (dp->i_afp)
> -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
> +	if (dp->i_afp) {
> +		xfs_idestroy_fork(dp->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
> +		dp->i_afp = NULL;
> +	}
>  	if (lock_mode)
>  		xfs_iunlock(dp, lock_mode);
>  	return error;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index c09b3e9eab1da..d806d3bfa8936 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -87,15 +87,18 @@ xfs_inode_free_callback(
>  	case S_IFREG:
>  	case S_IFDIR:
>  	case S_IFLNK:
> -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
> +		xfs_idestroy_fork(&ip->i_df);
>  		break;
>  	}
>  
> -	if (ip->i_afp)
> -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
> -	if (ip->i_cowfp)
> -		xfs_idestroy_fork(ip, XFS_COW_FORK);
> -
> +	if (ip->i_afp) {
> +		xfs_idestroy_fork(ip->i_afp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
> +	}
> +	if (ip->i_cowfp) {
> +		xfs_idestroy_fork(ip->i_cowfp);
> +		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
> +	}
>  	if (ip->i_itemp) {
>  		ASSERT(!test_bit(XFS_LI_IN_AIL,
>  				 &ip->i_itemp->ili_item.li_flags));
> -- 
> 2.26.2
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 6/6] xfs: cleanup xfs_idestroy_fork
  2020-05-18  7:33 move the extent count and format into struct xfs_ifork v2 Christoph Hellwig
@ 2020-05-18  7:33 ` Christoph Hellwig
  2020-05-18 13:28   ` Brian Foster
  0 siblings, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2020-05-18  7:33 UTC (permalink / raw)
  To: linux-xfs; +Cc: Chandan Babu R

Move freeing the dynamically allocated attr and COW fork, as well
as zeroing the pointers where actually needed into the callers, and
just pass the xfs_ifork structure to xfs_idestroy_fork.  Also simplify
the kmem_free calls by not checking for NULL first.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
---
 fs/xfs/libxfs/xfs_attr_leaf.c  |  7 +++----
 fs/xfs/libxfs/xfs_inode_buf.c  |  2 +-
 fs/xfs/libxfs/xfs_inode_fork.c | 32 +++++++++-----------------------
 fs/xfs/libxfs/xfs_inode_fork.h |  2 +-
 fs/xfs/xfs_attr_inactive.c     |  7 +++++--
 fs/xfs/xfs_icache.c            | 15 +++++++++------
 6 files changed, 28 insertions(+), 37 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index b279200519777..394805abb4535 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -718,11 +718,10 @@ xfs_attr_fork_remove(
 {
 	ASSERT(ip->i_afp->if_nextents == 0);
 
-	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+	xfs_idestroy_fork(ip->i_afp);
+	kmem_cache_free(xfs_ifork_zone, ip->i_afp);
+	ip->i_afp = NULL;
 	ip->i_d.di_forkoff = 0;
-
-	ASSERT(ip->i_afp == NULL);
-
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index ab555671e1543..6f84ea85fdd83 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -271,7 +271,7 @@ xfs_inode_from_disk(
 	return 0;
 
 out_destroy_data_fork:
-	xfs_idestroy_fork(ip, XFS_DATA_FORK);
+	xfs_idestroy_fork(&ip->i_df);
 	return error;
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index ef43b4893766c..28b366275ae0e 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -503,38 +503,24 @@ xfs_idata_realloc(
 
 void
 xfs_idestroy_fork(
-	xfs_inode_t	*ip,
-	int		whichfork)
+	struct xfs_ifork	*ifp)
 {
-	struct xfs_ifork	*ifp;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
 	if (ifp->if_broot != NULL) {
 		kmem_free(ifp->if_broot);
 		ifp->if_broot = NULL;
 	}
 
 	/*
-	 * If the format is local, then we can't have an extents
-	 * array so just look for an inline data array.  If we're
-	 * not local then we may or may not have an extents list,
-	 * so check and free it up if we do.
+	 * If the format is local, then we can't have an extents array so just
+	 * look for an inline data array.  If we're not local then we may or may
+	 * not have an extents list, so check and free it up if we do.
 	 */
 	if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
-		if (ifp->if_u1.if_data != NULL) {
-			kmem_free(ifp->if_u1.if_data);
-			ifp->if_u1.if_data = NULL;
-		}
-	} else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
-		xfs_iext_destroy(ifp);
-	}
-
-	if (whichfork == XFS_ATTR_FORK) {
-		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
-		ip->i_afp = NULL;
-	} else if (whichfork == XFS_COW_FORK) {
-		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
-		ip->i_cowfp = NULL;
+		kmem_free(ifp->if_u1.if_data);
+		ifp->if_u1.if_data = NULL;
+	} else if (ifp->if_flags & XFS_IFEXTENTS) {
+		if (ifp->if_height)
+			xfs_iext_destroy(ifp);
 	}
 }
 
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index d849cca103edd..a4953e95c4f3f 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -86,7 +86,7 @@ int		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
 int		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
 void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
 				struct xfs_inode_log_item *, int);
-void		xfs_idestroy_fork(struct xfs_inode *, int);
+void		xfs_idestroy_fork(struct xfs_ifork *ifp);
 void		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
 				int whichfork);
 void		xfs_iroot_realloc(struct xfs_inode *, int, int);
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index 00ffc46c0bf71..bfad669e6b2f8 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -388,8 +388,11 @@ xfs_attr_inactive(
 	xfs_trans_cancel(trans);
 out_destroy_fork:
 	/* kill the in-core attr fork before we drop the inode lock */
-	if (dp->i_afp)
-		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
+	if (dp->i_afp) {
+		xfs_idestroy_fork(dp->i_afp);
+		kmem_cache_free(xfs_ifork_zone, dp->i_afp);
+		dp->i_afp = NULL;
+	}
 	if (lock_mode)
 		xfs_iunlock(dp, lock_mode);
 	return error;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index c09b3e9eab1da..d806d3bfa8936 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -87,15 +87,18 @@ xfs_inode_free_callback(
 	case S_IFREG:
 	case S_IFDIR:
 	case S_IFLNK:
-		xfs_idestroy_fork(ip, XFS_DATA_FORK);
+		xfs_idestroy_fork(&ip->i_df);
 		break;
 	}
 
-	if (ip->i_afp)
-		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-	if (ip->i_cowfp)
-		xfs_idestroy_fork(ip, XFS_COW_FORK);
-
+	if (ip->i_afp) {
+		xfs_idestroy_fork(ip->i_afp);
+		kmem_cache_free(xfs_ifork_zone, ip->i_afp);
+	}
+	if (ip->i_cowfp) {
+		xfs_idestroy_fork(ip->i_cowfp);
+		kmem_cache_free(xfs_ifork_zone, ip->i_cowfp);
+	}
 	if (ip->i_itemp) {
 		ASSERT(!test_bit(XFS_LI_IN_AIL,
 				 &ip->i_itemp->ili_item.li_flags));
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2022-07-24 12:14 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-10  7:23 move the extent count and format into struct xfs_ifork Christoph Hellwig
2020-05-10  7:23 ` [PATCH 1/6] xfs: use XFS_IFORK_BOFF xchk_bmap_check_rmaps Christoph Hellwig
2020-05-11 11:40   ` Chandan Babu R
2020-05-12 15:31     ` Brian Foster
2020-05-12 15:38       ` Darrick J. Wong
2020-05-12 16:14         ` Brian Foster
2020-05-12 19:16           ` Darrick J. Wong
2020-05-13 13:19             ` Brian Foster
2020-05-13 13:21               ` Christoph Hellwig
2020-05-16 18:42   ` [PATCH] xfs: clean up xchk_bmap_check_rmaps usage of XFS_IFORK_Q Darrick J. Wong
2020-05-16 20:01     ` Christoph Hellwig
2020-05-17  8:05       ` Christoph Hellwig
2020-05-10  7:24 ` [PATCH 2/6] xfs: remove the XFS_DFORK_Q macro Christoph Hellwig
2020-05-11 12:39   ` Chandan Babu R
2020-05-12 15:31   ` Brian Foster
2020-05-16 18:02   ` Darrick J. Wong
2020-05-10  7:24 ` [PATCH 3/6] xfs: remove xfs_ifree_local_data Christoph Hellwig
2020-05-11 16:32   ` Chandan Babu R
2020-05-12 15:31   ` Brian Foster
2020-05-16 18:07   ` Darrick J. Wong
2022-07-24 12:14     ` Alex Lyakas
2020-05-10  7:24 ` [PATCH 4/6] xfs: move the per-fork nextents fields into struct xfs_ifork Christoph Hellwig
2020-05-12  5:26   ` Chandan Babu R
2020-05-12 16:10   ` Brian Foster
2020-05-16 18:09     ` Darrick J. Wong
2020-05-17  8:12     ` Christoph Hellwig
2020-05-10  7:24 ` [PATCH 5/6] xfs: move the fork format " Christoph Hellwig
2020-05-12  9:37   ` Chandan Babu R
2020-05-12 18:53   ` Brian Foster
2020-05-14 21:25   ` Darrick J. Wong
2020-05-16 13:58     ` Christoph Hellwig
2020-05-16 17:01       ` Darrick J. Wong
2020-05-16 18:01         ` Darrick J. Wong
2020-05-16 18:16           ` Christoph Hellwig
2020-05-16 18:29             ` Darrick J. Wong
2020-05-10  7:24 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
2020-05-12  9:48   ` Chandan Babu R
2020-05-12 18:54   ` Brian Foster
2020-05-16 18:10     ` Darrick J. Wong
2020-05-18  7:33 move the extent count and format into struct xfs_ifork v2 Christoph Hellwig
2020-05-18  7:33 ` [PATCH 6/6] xfs: cleanup xfs_idestroy_fork Christoph Hellwig
2020-05-18 13:28   ` Brian Foster

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.