From: "Darrick J. Wong" djwong@kernel.org
mainline inclusion from mainline-v5.19-rc5 commit e45d7cb2356e6b59fe64da28324025cc6fcd3fbd category: bugfix bugzilla: 187164, https://gitee.com/openeuler/kernel/issues/I4KIAO CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Modify xfs_ifork_ptr to return a NULL pointer if the caller asks for the attribute fork but i_forkoff is zero. This eliminates the ambiguity between i_forkoff and i_af.if_present, which should make it easier to understand the lifetime of attr forks.
While we're at it, remove the if_present checks around calls to xfs_idestroy_fork and xfs_ifork_zap_attr since they can both handle attr forks that have already been torn down.
Signed-off-by: Darrick J. Wong djwong@kernel.org Reviewed-by: Dave Chinner dchinner@redhat.com
conflicts: fs/xfs/libxfs/xfs_attr.h fs/xfs/libxfs/xfs_inode_fork.c fs/xfs/libxfs/xfs_inode_fork.h fs/xfs/xfs_icache.c fs/xfs/xfs_inode.c
Signed-off-by: Long Li leo.lilong@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- fs/xfs/libxfs/xfs_attr.c | 2 -- fs/xfs/libxfs/xfs_bmap.c | 1 - fs/xfs/libxfs/xfs_inode_buf.c | 1 - fs/xfs/libxfs/xfs_inode_fork.c | 7 +------ fs/xfs/libxfs/xfs_inode_fork.h | 1 - fs/xfs/xfs_attr_inactive.c | 11 ++++------- fs/xfs/xfs_attr_list.c | 1 - fs/xfs/xfs_icache.c | 8 +++----- fs/xfs/xfs_inode.c | 5 ++--- fs/xfs/xfs_inode.h | 2 +- 10 files changed, 11 insertions(+), 28 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 5dc6650f6513..cbb8bec5291f 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -65,8 +65,6 @@ xfs_inode_hasattr( { if (!XFS_IFORK_Q(ip)) return 0; - if (!ip->i_af.if_present) - return 0; if (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS && ip->i_af.if_nextents == 0) return 0; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index eaee170fc990..90f4b99291ed 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1089,7 +1089,6 @@ xfs_bmap_add_attrfork( error = xfs_bmap_set_attrforkoff(ip, size, &version); if (error) goto trans_cancel; - ASSERT(!ip->i_af.if_present);
xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); ip->i_af.if_flags = XFS_IFEXTENTS; diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index fd354f847954..012af77edf36 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -198,7 +198,6 @@ xfs_inode_from_disk( xfs_failaddr_t fa;
ASSERT(ip->i_cowfp == NULL); - ASSERT(!ip->i_af.if_present);
fa = xfs_dinode_verify(ip->i_mount, ip->i_ino, from); if (fa) { diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 1a2aa3f8308a..3460c3d8a959 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -287,9 +287,6 @@ xfs_ifork_init_attr( enum xfs_dinode_fmt format, xfs_extnum_t nextents) { - ASSERT(!ip->i_af.if_present); - - ip->i_af.if_present = 1; ip->i_af.if_format = format; ip->i_af.if_nextents = nextents; } @@ -298,7 +295,6 @@ void xfs_ifork_zap_attr( struct xfs_inode *ip) { - ASSERT(ip->i_af.if_present); ASSERT(ip->i_af.if_broot == NULL); ASSERT(ip->i_af.if_u1.if_data == NULL); ASSERT(ip->i_af.if_height == 0); @@ -697,7 +693,6 @@ xfs_ifork_init_cow(
ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_zone, GFP_NOFS | __GFP_NOFAIL); - ip->i_cowfp->if_present = 1; ip->i_cowfp->if_flags = XFS_IFEXTENTS; ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS; } @@ -737,7 +732,7 @@ xfs_ifork_verify_local_attr( struct xfs_ifork *ifp = &ip->i_af; xfs_failaddr_t fa;
- if (!ifp->if_present) + if (!XFS_IFORK_Q(ip)) fa = __this_address; else fa = xfs_attr_shortform_verify(ip); diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index 5c87ab4638fd..8466923d450e 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -25,7 +25,6 @@ struct xfs_ifork { 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 */ - int8_t if_present; /* 1 if present */ };
/* diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 72cdf9b58dbd..c882c734f7b5 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -360,12 +360,11 @@ xfs_attr_inactive(
/* * Invalidate and truncate the attribute fork extents. Make sure the - * fork actually has attributes as otherwise the invalidation has no + * fork actually has xattr blocks as otherwise the invalidation has no * blocks to read and returns an error. In this case, just do the fork * removal below. */ - if (xfs_inode_hasattr(dp) && - dp->i_af.if_format != XFS_DINODE_FMT_LOCAL) { + if (dp->i_af.if_nextents > 0) { error = xfs_attr3_root_inactive(&trans, dp); if (error) goto out_cancel; @@ -386,10 +385,8 @@ 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_af.if_present) { - xfs_idestroy_fork(&dp->i_af); - xfs_ifork_zap_attr(dp); - } + xfs_idestroy_fork(&dp->i_af); + xfs_ifork_zap_attr(dp); if (lock_mode) xfs_iunlock(dp, lock_mode); return error; diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 391d9d4558ba..b43e48fdf120 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -60,7 +60,6 @@ xfs_attr_shortform_list( int sbsize, nsbuf, count, i; int error = 0;
- ASSERT(dp->i_af.if_present); sf = (struct xfs_attr_shortform *)dp->i_af.if_u1.if_data; ASSERT(sf != NULL); if (!sf->hdr.count) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 94dc0eddc6e6..82708548f0c4 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -109,7 +109,6 @@ xfs_inode_alloc( memset(&ip->i_af, 0, sizeof(ip->i_af)); ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS; memset(&ip->i_df, 0, sizeof(ip->i_df)); - ip->i_df.if_present = 1; ip->i_flags = 0; ip->i_delayed_blks = 0; memset(&ip->i_d, 0, sizeof(ip->i_d)); @@ -137,10 +136,9 @@ xfs_inode_free_callback( break; }
- if (ip->i_af.if_present) { - xfs_idestroy_fork(&ip->i_af); - xfs_ifork_zap_attr(ip); - } + xfs_idestroy_fork(&ip->i_af); + xfs_ifork_zap_attr(ip); + if (ip->i_cowfp) { xfs_idestroy_fork(ip->i_cowfp); kmem_cache_free(xfs_ifork_zone, ip->i_cowfp); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index bac87fd204b7..28db32ed0de6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -124,7 +124,7 @@ xfs_ilock_attr_map_shared( { uint lock_mode = XFS_ILOCK_SHARED;
- if (ip->i_af.if_present && + if (XFS_IFORK_Q(ip) && ip->i_af.if_format == XFS_DINODE_FMT_BTREE && (ip->i_af.if_flags & XFS_IFEXTENTS) == 0) lock_mode = XFS_ILOCK_EXCL; @@ -1927,7 +1927,6 @@ xfs_inactive( goto out; }
- ASSERT(!ip->i_af.if_present); ASSERT(ip->i_d.di_forkoff == 0);
/* @@ -3644,7 +3643,7 @@ xfs_iflush( if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL && xfs_ifork_verify_local_data(ip)) goto flush_out; - if (ip->i_af.if_present && + if (XFS_IFORK_Q(ip) && ip->i_af.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 e4e5a8dda0f3..4f5b3764c4d9 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -76,7 +76,7 @@ xfs_ifork_ptr( case XFS_DATA_FORK: return &ip->i_df; case XFS_ATTR_FORK: - if (!ip->i_af.if_present) + if (!XFS_IFORK_Q(ip)) return NULL; return &ip->i_af; case XFS_COW_FORK: