--- /dev/null
+From bf84937e882009075f57fd213836256fc65d96bc Mon Sep 17 00:00:00 2001
+From: Steve Clevenger <scclevenger@os.amperecomputing.com>
+Date: Mon, 27 Feb 2023 16:54:32 -0700
+Subject: coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug
+
+From: Steve Clevenger <scclevenger@os.amperecomputing.com>
+
+commit bf84937e882009075f57fd213836256fc65d96bc upstream.
+
+In etm4_enable_hw, fix for() loop range to represent address comparator pairs.
+
+Fixes: 2e1cdfe184b5 ("coresight-etm4x: Adding CoreSight ETM4x driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Steve Clevenger <scclevenger@os.amperecomputing.com>
+Reviewed-by: James Clark <james.clark@arm.com>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/4a4ee61ce8ef402615a4528b21a051de3444fb7b.1677540079.git.scclevenger@os.amperecomputing.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hwtracing/coresight/coresight-etm4x.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x.c
+@@ -156,7 +156,7 @@ static int etm4_enable_hw(struct etmv4_d
+ writel_relaxed(config->ss_pe_cmp[i],
+ drvdata->base + TRCSSPCICRn(i));
+ }
+- for (i = 0; i < drvdata->nr_addr_cmp; i++) {
++ for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
+ writeq_relaxed(config->addr_val[i],
+ drvdata->base + TRCACVRn(i));
+ writeq_relaxed(config->addr_acc[i],
mtd-ubi-wl-fix-a-couple-of-kernel-doc-issues.patch
ubi-fix-deadlock-caused-by-recursively-holding-work_.patch
i2c-ocores-generate-stop-condition-after-timeout-in-.patch
+watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch
+coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch
+xfs-show-the-proper-user-quota-options.patch
+xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch
+xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch
+xfs-remove-the-icdinode-di_uid-di_gid-members.patch
+xfs-remove-the-kuid-kgid-conversion-wrappers.patch
+xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch
+xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch
+xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch
+xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch
+xfs-remove-the-di_version-field-from-struct-icdinode.patch
+xfs-fix-up-non-directory-creation-in-sgid-directories.patch
+xfs-set-inode-size-after-creating-symlink.patch
+xfs-report-corruption-only-as-a-regular-error.patch
+xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch
+xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch
+xfs-don-t-reuse-busy-extents-on-extent-trim.patch
+xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch
--- /dev/null
+From 000987a38b53c172f435142a4026dd71378ca464 Mon Sep 17 00:00:00 2001
+From: George Cherian <george.cherian@marvell.com>
+Date: Thu, 9 Feb 2023 02:11:17 +0000
+Subject: watchdog: sbsa_wdog: Make sure the timeout programming is within the limits
+
+From: George Cherian <george.cherian@marvell.com>
+
+commit 000987a38b53c172f435142a4026dd71378ca464 upstream.
+
+Make sure to honour the max_hw_heartbeat_ms while programming the timeout
+value to WOR. Clamp the timeout passed to sbsa_gwdt_set_timeout() to
+make sure the programmed value is within the permissible range.
+
+Fixes: abd3ac7902fb ("watchdog: sbsa: Support architecture version 1")
+
+Signed-off-by: George Cherian <george.cherian@marvell.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230209021117.1512097-1-george.cherian@marvell.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Tyler Hicks (Microsoft) <code@tyhicks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sbsa_gwdt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/watchdog/sbsa_gwdt.c
++++ b/drivers/watchdog/sbsa_gwdt.c
+@@ -121,6 +121,7 @@ static int sbsa_gwdt_set_timeout(struct
+ struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
+
+ wdd->timeout = timeout;
++ timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000);
+
+ if (action)
+ writel(gwdt->clk * timeout,
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:19 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:13 +0530
+Subject: xfs: add a new xfs_sb_version_has_v3inode helper
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-7-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit b81b79f4eda2ea98ae5695c0b6eb384c8d90b74d upstream.
+
+Add a new wrapper to check if a file system supports the v3 inode format
+with a larger dinode core. Previously we used xfs_sb_version_hascrc for
+that, which is technically correct but a little confusing to read.
+
+Also move xfs_dinode_good_version next to xfs_sb_version_has_v3inode
+so that we have one place that documents the superblock version to
+inode version relationship.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_format.h | 17 +++++++++++++++++
+ fs/xfs/libxfs/xfs_ialloc.c | 4 ++--
+ fs/xfs/libxfs/xfs_inode_buf.c | 17 +++--------------
+ fs/xfs/libxfs/xfs_inode_buf.h | 2 --
+ fs/xfs/libxfs/xfs_trans_resv.c | 2 +-
+ fs/xfs/xfs_buf_item.c | 2 +-
+ fs/xfs/xfs_log_recover.c | 2 +-
+ 7 files changed, 25 insertions(+), 21 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_format.h
++++ b/fs/xfs/libxfs/xfs_format.h
+@@ -497,6 +497,23 @@ static inline bool xfs_sb_version_hascrc
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
+ }
+
++/*
++ * v5 file systems support V3 inodes only, earlier file systems support
++ * v2 and v1 inodes.
++ */
++static inline bool xfs_sb_version_has_v3inode(struct xfs_sb *sbp)
++{
++ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
++}
++
++static inline bool xfs_dinode_good_version(struct xfs_sb *sbp,
++ uint8_t version)
++{
++ if (xfs_sb_version_has_v3inode(sbp))
++ return version == 3;
++ return version == 1 || version == 2;
++}
++
+ static inline bool xfs_sb_version_has_pquotino(struct xfs_sb *sbp)
+ {
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
+--- a/fs/xfs/libxfs/xfs_ialloc.c
++++ b/fs/xfs/libxfs/xfs_ialloc.c
+@@ -303,7 +303,7 @@ xfs_ialloc_inode_init(
+ * That means for v3 inode we log the entire buffer rather than just the
+ * inode cores.
+ */
+- if (xfs_sb_version_hascrc(&mp->m_sb)) {
++ if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ version = 3;
+ ino = XFS_AGINO_TO_INO(mp, agno, XFS_AGB_TO_AGINO(mp, agbno));
+
+@@ -2818,7 +2818,7 @@ xfs_ialloc_setup_geometry(
+ * cannot change the behavior.
+ */
+ igeo->inode_cluster_size_raw = XFS_INODE_BIG_CLUSTER_SIZE;
+- if (xfs_sb_version_hascrc(&mp->m_sb)) {
++ if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ int new_size = igeo->inode_cluster_size_raw;
+
+ new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE;
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -44,17 +44,6 @@ xfs_inobp_check(
+ }
+ #endif
+
+-bool
+-xfs_dinode_good_version(
+- struct xfs_mount *mp,
+- __u8 version)
+-{
+- if (xfs_sb_version_hascrc(&mp->m_sb))
+- return version == 3;
+-
+- return version == 1 || version == 2;
+-}
+-
+ /*
+ * If we are doing readahead on an inode buffer, we might be in log recovery
+ * reading an inode allocation buffer that hasn't yet been replayed, and hence
+@@ -93,7 +82,7 @@ xfs_inode_buf_verify(
+ dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
+ unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
+ di_ok = xfs_verify_magic16(bp, dip->di_magic) &&
+- xfs_dinode_good_version(mp, dip->di_version) &&
++ xfs_dinode_good_version(&mp->m_sb, dip->di_version) &&
+ xfs_verify_agino_or_null(mp, agno, unlinked_ino);
+ if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
+ XFS_ERRTAG_ITOBP_INOTOBP))) {
+@@ -454,7 +443,7 @@ xfs_dinode_verify(
+
+ /* Verify v3 integrity information first */
+ if (dip->di_version >= 3) {
+- if (!xfs_sb_version_hascrc(&mp->m_sb))
++ if (!xfs_sb_version_has_v3inode(&mp->m_sb))
+ return __this_address;
+ if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
+ XFS_DINODE_CRC_OFF))
+@@ -629,7 +618,7 @@ xfs_iread(
+
+ /* shortcut IO on inode allocation if possible */
+ if ((iget_flags & XFS_IGET_CREATE) &&
+- xfs_sb_version_hascrc(&mp->m_sb) &&
++ xfs_sb_version_has_v3inode(&mp->m_sb) &&
+ !(mp->m_flags & XFS_MOUNT_IKEEP)) {
+ /* initialise the on-disk inode core */
+ memset(&ip->i_d, 0, sizeof(ip->i_d));
+--- a/fs/xfs/libxfs/xfs_inode_buf.h
++++ b/fs/xfs/libxfs/xfs_inode_buf.h
+@@ -59,8 +59,6 @@ void xfs_inode_from_disk(struct xfs_inod
+ void xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
+ struct xfs_dinode *to);
+
+-bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);
+-
+ #if defined(DEBUG)
+ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
+ #else
+--- a/fs/xfs/libxfs/xfs_trans_resv.c
++++ b/fs/xfs/libxfs/xfs_trans_resv.c
+@@ -187,7 +187,7 @@ xfs_calc_inode_chunk_res(
+ XFS_FSB_TO_B(mp, 1));
+ if (alloc) {
+ /* icreate tx uses ordered buffers */
+- if (xfs_sb_version_hascrc(&mp->m_sb))
++ if (xfs_sb_version_has_v3inode(&mp->m_sb))
+ return res;
+ size = XFS_FSB_TO_B(mp, 1);
+ }
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -328,7 +328,7 @@ xfs_buf_item_format(
+ * occurs during recovery.
+ */
+ if (bip->bli_flags & XFS_BLI_INODE_BUF) {
+- if (xfs_sb_version_hascrc(&lip->li_mountp->m_sb) ||
++ if (xfs_sb_version_has_v3inode(&lip->li_mountp->m_sb) ||
+ !((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
+ xfs_log_item_in_current_chkpt(lip)))
+ bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF;
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -3018,7 +3018,7 @@ xlog_recover_inode_pass2(
+ * superblock flag to determine whether we need to look at di_flushiter
+ * to skip replay when the on disk inode is newer than the log one
+ */
+- if (!xfs_sb_version_hascrc(&mp->m_sb) &&
++ if (!xfs_sb_version_has_v3inode(&mp->m_sb) &&
+ ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
+ /*
+ * Deal with the wrap case, DI_MAX_FLUSH is less
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:22 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:22 +0530
+Subject: xfs: consider shutdown in bmapbt cursor delete assert
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-16-chandan.babu@oracle.com>
+
+From: Brian Foster <bfoster@redhat.com>
+
+commit 1cd738b13ae9b29e03d6149f0246c61f76e81fcf upstream.
+
+[ Slightly modify fs/xfs/libxfs/xfs_btree.c to resolve merge conflicts ]
+
+The assert in xfs_btree_del_cursor() checks that the bmapbt block
+allocation field has been handled correctly before the cursor is
+freed. This field is used for accurate calculation of indirect block
+reservation requirements (for delayed allocations), for example.
+generic/019 reproduces a scenario where this assert fails because
+the filesystem has shutdown while in the middle of a bmbt record
+insertion. This occurs after a bmbt block has been allocated via the
+cursor but before the higher level bmap function (i.e.
+xfs_bmap_add_extent_hole_real()) completes and resets the field.
+
+Update the assert to accommodate the transient state if the
+filesystem has shutdown. While here, clean up the indentation and
+comments in the function.
+
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_btree.c | 30 +++++++++++-------------------
+ 1 file changed, 11 insertions(+), 19 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_btree.c
++++ b/fs/xfs/libxfs/xfs_btree.c
+@@ -354,20 +354,17 @@ xfs_btree_free_block(
+ */
+ void
+ xfs_btree_del_cursor(
+- xfs_btree_cur_t *cur, /* btree cursor */
+- int error) /* del because of error */
++ struct xfs_btree_cur *cur, /* btree cursor */
++ int error) /* del because of error */
+ {
+- int i; /* btree level */
++ int i; /* btree level */
+
+ /*
+- * Clear the buffer pointers, and release the buffers.
+- * If we're doing this in the face of an error, we
+- * need to make sure to inspect all of the entries
+- * in the bc_bufs array for buffers to be unlocked.
+- * This is because some of the btree code works from
+- * level n down to 0, and if we get an error along
+- * the way we won't have initialized all the entries
+- * down to 0.
++ * Clear the buffer pointers and release the buffers. If we're doing
++ * this because of an error, inspect all of the entries in the bc_bufs
++ * array for buffers to be unlocked. This is because some of the btree
++ * code works from level n down to 0, and if we get an error along the
++ * way we won't have initialized all the entries down to 0.
+ */
+ for (i = 0; i < cur->bc_nlevels; i++) {
+ if (cur->bc_bufs[i])
+@@ -375,15 +372,10 @@ xfs_btree_del_cursor(
+ else if (!error)
+ break;
+ }
+- /*
+- * Can't free a bmap cursor without having dealt with the
+- * allocated indirect blocks' accounting.
+- */
++
+ ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
+- cur->bc_private.b.allocated == 0);
+- /*
+- * Free the cursor.
+- */
++ cur->bc_private.b.allocated == 0 ||
++ XFS_FORCED_SHUTDOWN(cur->bc_mp));
+ kmem_zone_free(xfs_btree_cur_zone, cur);
+ }
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:32 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:23 +0530
+Subject: xfs: don't reuse busy extents on extent trim
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-17-chandan.babu@oracle.com>
+
+From: Brian Foster <bfoster@redhat.com>
+
+commit 06058bc40534530e617e5623775c53bb24f032cb upstream.
+
+Freed extents are marked busy from the point the freeing transaction
+commits until the associated CIL context is checkpointed to the log.
+This prevents reuse and overwrite of recently freed blocks before
+the changes are committed to disk, which can lead to corruption
+after a crash. The exception to this rule is that metadata
+allocation is allowed to reuse busy extents because metadata changes
+are also logged.
+
+As of commit 97d3ac75e5e0 ("xfs: exact busy extent tracking"), XFS
+has allowed modification or complete invalidation of outstanding
+busy extents for metadata allocations. This implementation assumes
+that use of the associated extent is imminent, which is not always
+the case. For example, the trimmed extent might not satisfy the
+minimum length of the allocation request, or the allocation
+algorithm might be involved in a search for the optimal result based
+on locality.
+
+generic/019 reproduces a corruption caused by this scenario. First,
+a metadata block (usually a bmbt or symlink block) is freed from an
+inode. A subsequent bmbt split on an unrelated inode attempts a near
+mode allocation request that invalidates the busy block during the
+search, but does not ultimately allocate it. Due to the busy state
+invalidation, the block is no longer considered busy to subsequent
+allocation. A direct I/O write request immediately allocates the
+block and writes to it. Finally, the filesystem crashes while in a
+state where the initial metadata block free had not committed to the
+on-disk log. After recovery, the original metadata block is in its
+original location as expected, but has been corrupted by the
+aforementioned dio.
+
+This demonstrates that it is fundamentally unsafe to modify busy
+extent state for extents that are not guaranteed to be allocated.
+This applies to pretty much all of the code paths that currently
+trim busy extents for one reason or another. Therefore to address
+this problem, drop the reuse mechanism from the busy extent trim
+path. This code already knows how to return partial non-busy ranges
+of the targeted free extent and higher level code tracks the busy
+state of the allocation attempt. If a block allocation fails where
+one or more candidate extents is busy, we force the log and retry
+the allocation.
+
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_extent_busy.c | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+--- a/fs/xfs/xfs_extent_busy.c
++++ b/fs/xfs/xfs_extent_busy.c
+@@ -344,7 +344,6 @@ xfs_extent_busy_trim(
+ ASSERT(*len > 0);
+
+ spin_lock(&args->pag->pagb_lock);
+-restart:
+ fbno = *bno;
+ flen = *len;
+ rbp = args->pag->pagb_tree.rb_node;
+@@ -363,19 +362,6 @@ restart:
+ continue;
+ }
+
+- /*
+- * If this is a metadata allocation, try to reuse the busy
+- * extent instead of trimming the allocation.
+- */
+- if (!xfs_alloc_is_userdata(args->datatype) &&
+- !(busyp->flags & XFS_EXTENT_BUSY_DISCARDED)) {
+- if (!xfs_extent_busy_update_extent(args->mp, args->pag,
+- busyp, fbno, flen,
+- false))
+- goto restart;
+- continue;
+- }
+-
+ if (bbno <= fbno) {
+ /* start overlap */
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:27:52 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:10 +0530
+Subject: xfs: ensure that the inode uid/gid match values match the icdinode ones
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-4-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 3d8f2821502d0b60bac2789d0bea951fda61de0c upstream.
+
+Instead of only synchronizing the uid/gid values in xfs_setup_inode,
+ensure that they always match to prepare for removing the icdinode
+fields.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 2 ++
+ fs/xfs/xfs_icache.c | 4 ++++
+ fs/xfs/xfs_inode.c | 8 ++++++--
+ fs/xfs/xfs_iops.c | 3 ---
+ 4 files changed, 12 insertions(+), 5 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -223,7 +223,9 @@ xfs_inode_from_disk(
+
+ to->di_format = from->di_format;
+ to->di_uid = be32_to_cpu(from->di_uid);
++ inode->i_uid = xfs_uid_to_kuid(to->di_uid);
+ to->di_gid = be32_to_cpu(from->di_gid);
++ inode->i_gid = xfs_gid_to_kgid(to->di_gid);
+ to->di_flushiter = be16_to_cpu(from->di_flushiter);
+
+ /*
+--- a/fs/xfs/xfs_icache.c
++++ b/fs/xfs/xfs_icache.c
+@@ -289,6 +289,8 @@ xfs_reinit_inode(
+ uint64_t version = inode_peek_iversion(inode);
+ umode_t mode = inode->i_mode;
+ dev_t dev = inode->i_rdev;
++ kuid_t uid = inode->i_uid;
++ kgid_t gid = inode->i_gid;
+
+ error = inode_init_always(mp->m_super, inode);
+
+@@ -297,6 +299,8 @@ xfs_reinit_inode(
+ inode_set_iversion_queried(inode, version);
+ inode->i_mode = mode;
+ inode->i_rdev = dev;
++ inode->i_uid = uid;
++ inode->i_gid = gid;
+ return error;
+ }
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -806,15 +806,19 @@ xfs_ialloc(
+
+ inode->i_mode = mode;
+ set_nlink(inode, nlink);
+- ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid());
+- ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid());
++ inode->i_uid = current_fsuid();
++ ip->i_d.di_uid = xfs_kuid_to_uid(inode->i_uid);
+ inode->i_rdev = rdev;
+ ip->i_d.di_projid = prid;
+
+ if (pip && XFS_INHERIT_GID(pip)) {
++ inode->i_gid = VFS_I(pip)->i_gid;
+ ip->i_d.di_gid = pip->i_d.di_gid;
+ if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
++ } else {
++ inode->i_gid = current_fsgid();
++ ip->i_d.di_gid = xfs_kgid_to_gid(inode->i_gid);
+ }
+
+ /*
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -1288,9 +1288,6 @@ xfs_setup_inode(
+ /* make the inode look hashed for the writeback code */
+ inode_fake_hash(inode);
+
+- inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid);
+- inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid);
+-
+ i_size_write(inode, ip->i_d.di_size);
+ xfs_diflags_to_iflags(inode, ip);
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:03 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:18 +0530
+Subject: xfs: fix up non-directory creation in SGID directories
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-12-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 01ea173e103edd5ec41acec65b9261b87e123fc2 upstream.
+
+XFS always inherits the SGID bit if it is set on the parent inode, while
+the generic inode_init_owner does not do this in a few cases where it can
+create a possible security problem, see commit 0fa3ecd87848
+("Fix up non-directory creation in SGID directories") for details.
+
+Switch XFS to use the generic helper for the normal path to fix this,
+just keeping the simple field inheritance open coded for the case of the
+non-sgid case with the bsdgrpid mount option.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_inode.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -750,6 +750,7 @@ xfs_ialloc(
+ xfs_buf_t **ialloc_context,
+ xfs_inode_t **ipp)
+ {
++ struct inode *dir = pip ? VFS_I(pip) : NULL;
+ struct xfs_mount *mp = tp->t_mountp;
+ xfs_ino_t ino;
+ xfs_inode_t *ip;
+@@ -795,18 +796,17 @@ xfs_ialloc(
+ return error;
+ ASSERT(ip != NULL);
+ inode = VFS_I(ip);
+- inode->i_mode = mode;
+ set_nlink(inode, nlink);
+- inode->i_uid = current_fsuid();
+ inode->i_rdev = rdev;
+ ip->i_d.di_projid = prid;
+
+- if (pip && XFS_INHERIT_GID(pip)) {
+- inode->i_gid = VFS_I(pip)->i_gid;
+- if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode))
+- inode->i_mode |= S_ISGID;
++ if (dir && !(dir->i_mode & S_ISGID) &&
++ (mp->m_flags & XFS_MOUNT_GRPID)) {
++ inode->i_uid = current_fsuid();
++ inode->i_gid = dir->i_gid;
++ inode->i_mode = mode;
+ } else {
+- inode->i_gid = current_fsgid();
++ inode_init_owner(inode, dir, mode);
+ }
+
+ /*
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:46 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:24 +0530
+Subject: xfs: force log and push AIL to clear pinned inodes when aborting mount
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-18-chandan.babu@oracle.com>
+
+From: "Darrick J. Wong" <djwong@kernel.org>
+
+commit d336f7ebc65007f5831e2297e6f3383ae8dbf8ed upstream.
+
+[ Slightly modify fs/xfs/xfs_mount.c to resolve merge conflicts ]
+
+If we allocate quota inodes in the process of mounting a filesystem but
+then decide to abort the mount, it's possible that the quota inodes are
+sitting around pinned by the log. Now that inode reclaim relies on the
+AIL to flush inodes, we have to force the log and push the AIL in
+between releasing the quota inodes and kicking off reclaim to tear down
+all the incore inodes. Do this by extracting the bits we need from the
+unmount path and reusing them. As an added bonus, failed writes during
+a failed mount will not retry forever now.
+
+This was originally found during a fuzz test of metadata directories
+(xfs/1546), but the actual symptom was that reclaim hung up on the quota
+inodes.
+
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_mount.c | 90 +++++++++++++++++++++++++----------------------------
+ 1 file changed, 44 insertions(+), 46 deletions(-)
+
+--- a/fs/xfs/xfs_mount.c
++++ b/fs/xfs/xfs_mount.c
+@@ -675,6 +675,47 @@ xfs_check_summary_counts(
+ }
+
+ /*
++ * Flush and reclaim dirty inodes in preparation for unmount. Inodes and
++ * internal inode structures can be sitting in the CIL and AIL at this point,
++ * so we need to unpin them, write them back and/or reclaim them before unmount
++ * can proceed.
++ *
++ * An inode cluster that has been freed can have its buffer still pinned in
++ * memory because the transaction is still sitting in a iclog. The stale inodes
++ * on that buffer will be pinned to the buffer until the transaction hits the
++ * disk and the callbacks run. Pushing the AIL will skip the stale inodes and
++ * may never see the pinned buffer, so nothing will push out the iclog and
++ * unpin the buffer.
++ *
++ * Hence we need to force the log to unpin everything first. However, log
++ * forces don't wait for the discards they issue to complete, so we have to
++ * explicitly wait for them to complete here as well.
++ *
++ * Then we can tell the world we are unmounting so that error handling knows
++ * that the filesystem is going away and we should error out anything that we
++ * have been retrying in the background. This will prevent never-ending
++ * retries in AIL pushing from hanging the unmount.
++ *
++ * Finally, we can push the AIL to clean all the remaining dirty objects, then
++ * reclaim the remaining inodes that are still in memory at this point in time.
++ */
++static void
++xfs_unmount_flush_inodes(
++ struct xfs_mount *mp)
++{
++ xfs_log_force(mp, XFS_LOG_SYNC);
++ xfs_extent_busy_wait_all(mp);
++ flush_workqueue(xfs_discard_wq);
++
++ mp->m_flags |= XFS_MOUNT_UNMOUNTING;
++
++ xfs_ail_push_all_sync(mp->m_ail);
++ cancel_delayed_work_sync(&mp->m_reclaim_work);
++ xfs_reclaim_inodes(mp, SYNC_WAIT);
++ xfs_health_unmount(mp);
++}
++
++/*
+ * This function does the following on an initial mount of a file system:
+ * - reads the superblock from disk and init the mount struct
+ * - if we're a 32-bit kernel, do a size check on the superblock
+@@ -1047,7 +1088,7 @@ xfs_mountfs(
+ /* Clean out dquots that might be in memory after quotacheck. */
+ xfs_qm_unmount(mp);
+ /*
+- * Cancel all delayed reclaim work and reclaim the inodes directly.
++ * Flush all inode reclamation work and flush the log.
+ * We have to do this /after/ rtunmount and qm_unmount because those
+ * two will have scheduled delayed reclaim for the rt/quota inodes.
+ *
+@@ -1057,11 +1098,8 @@ xfs_mountfs(
+ * qm_unmount_quotas and therefore rely on qm_unmount to release the
+ * quota inodes.
+ */
+- cancel_delayed_work_sync(&mp->m_reclaim_work);
+- xfs_reclaim_inodes(mp, SYNC_WAIT);
+- xfs_health_unmount(mp);
++ xfs_unmount_flush_inodes(mp);
+ out_log_dealloc:
+- mp->m_flags |= XFS_MOUNT_UNMOUNTING;
+ xfs_log_mount_cancel(mp);
+ out_fail_wait:
+ if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
+@@ -1102,47 +1140,7 @@ xfs_unmountfs(
+ xfs_rtunmount_inodes(mp);
+ xfs_irele(mp->m_rootip);
+
+- /*
+- * We can potentially deadlock here if we have an inode cluster
+- * that has been freed has its buffer still pinned in memory because
+- * the transaction is still sitting in a iclog. The stale inodes
+- * on that buffer will have their flush locks held until the
+- * transaction hits the disk and the callbacks run. the inode
+- * flush takes the flush lock unconditionally and with nothing to
+- * push out the iclog we will never get that unlocked. hence we
+- * need to force the log first.
+- */
+- xfs_log_force(mp, XFS_LOG_SYNC);
+-
+- /*
+- * Wait for all busy extents to be freed, including completion of
+- * any discard operation.
+- */
+- xfs_extent_busy_wait_all(mp);
+- flush_workqueue(xfs_discard_wq);
+-
+- /*
+- * We now need to tell the world we are unmounting. This will allow
+- * us to detect that the filesystem is going away and we should error
+- * out anything that we have been retrying in the background. This will
+- * prevent neverending retries in AIL pushing from hanging the unmount.
+- */
+- mp->m_flags |= XFS_MOUNT_UNMOUNTING;
+-
+- /*
+- * Flush all pending changes from the AIL.
+- */
+- xfs_ail_push_all_sync(mp->m_ail);
+-
+- /*
+- * And reclaim all inodes. At this point there should be no dirty
+- * inodes and none should be pinned or locked, but use synchronous
+- * reclaim just to be sure. We can stop background inode reclaim
+- * here as well if it is still running.
+- */
+- cancel_delayed_work_sync(&mp->m_reclaim_work);
+- xfs_reclaim_inodes(mp, SYNC_WAIT);
+- xfs_health_unmount(mp);
++ xfs_unmount_flush_inodes(mp);
+
+ xfs_qm_unmount(mp);
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:27:08 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:09 +0530
+Subject: xfs: merge the projid fields in struct xfs_icdinode
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-3-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit de7a866fd41b227b0aa6e9cbeb0dae221c12f542 upstream.
+
+There is no point in splitting the fields like this in an purely
+in-memory structure.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 11 +++++------
+ fs/xfs/libxfs/xfs_inode_buf.h | 3 +--
+ fs/xfs/xfs_dquot.c | 2 +-
+ fs/xfs/xfs_icache.c | 4 ++--
+ fs/xfs/xfs_inode.c | 6 +++---
+ fs/xfs/xfs_inode.h | 21 +--------------------
+ fs/xfs/xfs_inode_item.c | 4 ++--
+ fs/xfs/xfs_ioctl.c | 8 ++++----
+ fs/xfs/xfs_iops.c | 2 +-
+ fs/xfs/xfs_itable.c | 2 +-
+ fs/xfs/xfs_qm.c | 8 ++++----
+ fs/xfs/xfs_qm_bhv.c | 2 +-
+ 12 files changed, 26 insertions(+), 47 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -213,13 +213,12 @@ xfs_inode_from_disk(
+ to->di_version = from->di_version;
+ if (to->di_version == 1) {
+ set_nlink(inode, be16_to_cpu(from->di_onlink));
+- to->di_projid_lo = 0;
+- to->di_projid_hi = 0;
++ to->di_projid = 0;
+ to->di_version = 2;
+ } else {
+ set_nlink(inode, be32_to_cpu(from->di_nlink));
+- to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
+- to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
++ to->di_projid = (prid_t)be16_to_cpu(from->di_projid_hi) << 16 |
++ be16_to_cpu(from->di_projid_lo);
+ }
+
+ to->di_format = from->di_format;
+@@ -279,8 +278,8 @@ xfs_inode_to_disk(
+ to->di_format = from->di_format;
+ to->di_uid = cpu_to_be32(from->di_uid);
+ to->di_gid = cpu_to_be32(from->di_gid);
+- to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
+- to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
++ to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
++ to->di_projid_hi = cpu_to_be16(from->di_projid >> 16);
+
+ memset(to->di_pad, 0, sizeof(to->di_pad));
+ to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec);
+--- a/fs/xfs/libxfs/xfs_inode_buf.h
++++ b/fs/xfs/libxfs/xfs_inode_buf.h
+@@ -21,8 +21,7 @@ struct xfs_icdinode {
+ uint16_t di_flushiter; /* incremented on flush */
+ uint32_t di_uid; /* owner's user id */
+ uint32_t di_gid; /* owner's group id */
+- uint16_t di_projid_lo; /* lower part of owner's project id */
+- uint16_t di_projid_hi; /* higher part of owner's project id */
++ 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 */
+--- a/fs/xfs/xfs_dquot.c
++++ b/fs/xfs/xfs_dquot.c
+@@ -863,7 +863,7 @@ xfs_qm_id_for_quotatype(
+ case XFS_DQ_GROUP:
+ return ip->i_d.di_gid;
+ case XFS_DQ_PROJ:
+- return xfs_get_projid(ip);
++ return ip->i_d.di_projid;
+ }
+ ASSERT(0);
+ return 0;
+--- a/fs/xfs/xfs_icache.c
++++ b/fs/xfs/xfs_icache.c
+@@ -1430,7 +1430,7 @@ xfs_inode_match_id(
+ return 0;
+
+ if ((eofb->eof_flags & XFS_EOF_FLAGS_PRID) &&
+- xfs_get_projid(ip) != eofb->eof_prid)
++ ip->i_d.di_projid != eofb->eof_prid)
+ return 0;
+
+ return 1;
+@@ -1454,7 +1454,7 @@ xfs_inode_match_id_union(
+ return 1;
+
+ if ((eofb->eof_flags & XFS_EOF_FLAGS_PRID) &&
+- xfs_get_projid(ip) == eofb->eof_prid)
++ ip->i_d.di_projid == eofb->eof_prid)
+ return 1;
+
+ return 0;
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -809,7 +809,7 @@ xfs_ialloc(
+ ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid());
+ ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid());
+ inode->i_rdev = rdev;
+- xfs_set_projid(ip, prid);
++ ip->i_d.di_projid = prid;
+
+ if (pip && XFS_INHERIT_GID(pip)) {
+ ip->i_d.di_gid = pip->i_d.di_gid;
+@@ -1418,7 +1418,7 @@ xfs_link(
+ * the tree quota mechanism could be circumvented.
+ */
+ if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+- (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
++ tdp->i_d.di_projid != sip->i_d.di_projid)) {
+ error = -EXDEV;
+ goto error_return;
+ }
+@@ -3299,7 +3299,7 @@ xfs_rename(
+ * tree quota mechanism would be circumvented.
+ */
+ if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+- (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
++ target_dp->i_d.di_projid != src_ip->i_d.di_projid)) {
+ error = -EXDEV;
+ goto out_trans_cancel;
+ }
+--- a/fs/xfs/xfs_inode.h
++++ b/fs/xfs/xfs_inode.h
+@@ -177,30 +177,11 @@ xfs_iflags_test_and_set(xfs_inode_t *ip,
+ return ret;
+ }
+
+-/*
+- * Project quota id helpers (previously projid was 16bit only
+- * and using two 16bit values to hold new 32bit projid was chosen
+- * to retain compatibility with "old" filesystems).
+- */
+-static inline prid_t
+-xfs_get_projid(struct xfs_inode *ip)
+-{
+- return (prid_t)ip->i_d.di_projid_hi << 16 | ip->i_d.di_projid_lo;
+-}
+-
+-static inline void
+-xfs_set_projid(struct xfs_inode *ip,
+- prid_t projid)
+-{
+- ip->i_d.di_projid_hi = (uint16_t) (projid >> 16);
+- ip->i_d.di_projid_lo = (uint16_t) (projid & 0xffff);
+-}
+-
+ static inline prid_t
+ xfs_get_initial_prid(struct xfs_inode *dp)
+ {
+ if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+- return xfs_get_projid(dp);
++ return dp->i_d.di_projid;
+
+ return XFS_PROJID_DEFAULT;
+ }
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -310,8 +310,8 @@ xfs_inode_to_log_dinode(
+ to->di_format = from->di_format;
+ to->di_uid = from->di_uid;
+ to->di_gid = from->di_gid;
+- to->di_projid_lo = from->di_projid_lo;
+- to->di_projid_hi = from->di_projid_hi;
++ to->di_projid_lo = from->di_projid & 0xffff;
++ to->di_projid_hi = from->di_projid >> 16;
+
+ memset(to->di_pad, 0, sizeof(to->di_pad));
+ memset(to->di_pad3, 0, sizeof(to->di_pad3));
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1144,7 +1144,7 @@ xfs_fill_fsxattr(
+ 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 = xfs_get_projid(ip);
++ fa->fsx_projid = ip->i_d.di_projid;
+
+ if (attr) {
+ if (ip->i_afp) {
+@@ -1597,7 +1597,7 @@ xfs_ioctl_setattr(
+ }
+
+ if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
+- xfs_get_projid(ip) != fa->fsx_projid) {
++ ip->i_d.di_projid != fa->fsx_projid) {
+ code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
+ capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0);
+ if (code) /* out of quota */
+@@ -1634,13 +1634,13 @@ xfs_ioctl_setattr(
+ VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
+
+ /* Change the ownerships and register project quota modifications */
+- if (xfs_get_projid(ip) != fa->fsx_projid) {
++ if (ip->i_d.di_projid != fa->fsx_projid) {
+ if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
+ olddquot = xfs_qm_vop_chown(tp, ip,
+ &ip->i_pdquot, pdqp);
+ }
+ ASSERT(ip->i_d.di_version > 1);
+- xfs_set_projid(ip, fa->fsx_projid);
++ ip->i_d.di_projid = fa->fsx_projid;
+ }
+
+ /*
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -668,7 +668,7 @@ xfs_setattr_nonsize(
+ ASSERT(gdqp == NULL);
+ error = xfs_qm_vop_dqalloc(ip, xfs_kuid_to_uid(uid),
+ xfs_kgid_to_gid(gid),
+- xfs_get_projid(ip),
++ ip->i_d.di_projid,
+ qflags, &udqp, &gdqp, NULL);
+ if (error)
+ return error;
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -84,7 +84,7 @@ xfs_bulkstat_one_int(
+ /* xfs_iget returns the following without needing
+ * further change.
+ */
+- buf->bs_projectid = xfs_get_projid(ip);
++ buf->bs_projectid = ip->i_d.di_projid;
+ buf->bs_ino = ino;
+ buf->bs_uid = dic->di_uid;
+ buf->bs_gid = dic->di_gid;
+--- a/fs/xfs/xfs_qm.c
++++ b/fs/xfs/xfs_qm.c
+@@ -347,7 +347,7 @@ xfs_qm_dqattach_locked(
+ }
+
+ if (XFS_IS_PQUOTA_ON(mp) && !ip->i_pdquot) {
+- error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
++ error = xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
+ doalloc, &ip->i_pdquot);
+ if (error)
+ goto done;
+@@ -1715,7 +1715,7 @@ xfs_qm_vop_dqalloc(
+ }
+ }
+ if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
+- if (xfs_get_projid(ip) != prid) {
++ if (ip->i_d.di_projid != prid) {
+ xfs_iunlock(ip, lockflags);
+ error = xfs_qm_dqget(mp, (xfs_dqid_t)prid, XFS_DQ_PROJ,
+ true, &pq);
+@@ -1849,7 +1849,7 @@ xfs_qm_vop_chown_reserve(
+ }
+
+ if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
+- xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) {
++ ip->i_d.di_projid != be32_to_cpu(pdqp->q_core.d_id)) {
+ prjflags = XFS_QMOPT_ENOSPC;
+ pdq_delblks = pdqp;
+ if (delblks) {
+@@ -1950,7 +1950,7 @@ xfs_qm_vop_create_dqattach(
+ }
+ if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
+ ASSERT(ip->i_pdquot == NULL);
+- ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
++ ASSERT(ip->i_d.di_projid == be32_to_cpu(pdqp->q_core.d_id));
+
+ ip->i_pdquot = xfs_qm_dqhold(pdqp);
+ xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);
+--- a/fs/xfs/xfs_qm_bhv.c
++++ b/fs/xfs/xfs_qm_bhv.c
+@@ -60,7 +60,7 @@ xfs_qm_statvfs(
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_dquot *dqp;
+
+- if (!xfs_qm_dqget(mp, xfs_get_projid(ip), XFS_DQ_PROJ, false, &dqp)) {
++ if (!xfs_qm_dqget(mp, ip->i_d.di_projid, XFS_DQ_PROJ, false, &dqp)) {
+ xfs_fill_statvfs_from_dquot(statp, dqp);
+ xfs_qm_dqput(dqp);
+ }
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:32 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:14 +0530
+Subject: xfs: only check the superblock version for dinode size calculation
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-8-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit e9e2eae89ddb658ea332295153fdca78c12c1e0d upstream.
+
+The size of the dinode structure is only dependent on the file system
+version, so instead of checking the individual inode version just use
+the newly added xfs_sb_version_has_large_dinode helper, and simplify
+various calling conventions.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_attr_leaf.c | 5 ++---
+ fs/xfs/libxfs/xfs_bmap.c | 10 ++++------
+ fs/xfs/libxfs/xfs_format.h | 16 ++++++++--------
+ fs/xfs/libxfs/xfs_ialloc.c | 2 +-
+ fs/xfs/libxfs/xfs_inode_buf.c | 2 +-
+ fs/xfs/libxfs/xfs_inode_fork.c | 2 +-
+ fs/xfs/libxfs/xfs_inode_fork.h | 9 ++-------
+ fs/xfs/libxfs/xfs_log_format.h | 10 ++++------
+ fs/xfs/xfs_inode_item.c | 4 ++--
+ fs/xfs/xfs_log_recover.c | 2 +-
+ fs/xfs/xfs_symlink.c | 2 +-
+ 11 files changed, 27 insertions(+), 37 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_attr_leaf.c
++++ b/fs/xfs/libxfs/xfs_attr_leaf.c
+@@ -456,7 +456,7 @@ xfs_attr_shortform_bytesfit(
+ int offset;
+
+ /* rounded down */
+- offset = (XFS_LITINO(mp, dp->i_d.di_version) - bytes) >> 3;
++ offset = (XFS_LITINO(mp) - bytes) >> 3;
+
+ if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) {
+ minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+@@ -523,8 +523,7 @@ xfs_attr_shortform_bytesfit(
+ minforkoff = roundup(minforkoff, 8) >> 3;
+
+ /* attr fork btree root can have at least this many key/ptr pairs */
+- maxforkoff = XFS_LITINO(mp, dp->i_d.di_version) -
+- XFS_BMDR_SPACE_CALC(MINABTPTRS);
++ maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ maxforkoff = maxforkoff >> 3; /* rounded down */
+
+ if (offset >= maxforkoff)
+--- a/fs/xfs/libxfs/xfs_bmap.c
++++ b/fs/xfs/libxfs/xfs_bmap.c
+@@ -192,14 +192,12 @@ xfs_default_attroffset(
+ struct xfs_mount *mp = ip->i_mount;
+ uint offset;
+
+- if (mp->m_sb.sb_inodesize == 256) {
+- offset = XFS_LITINO(mp, ip->i_d.di_version) -
+- XFS_BMDR_SPACE_CALC(MINABTPTRS);
+- } else {
++ if (mp->m_sb.sb_inodesize == 256)
++ offset = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
++ else
+ offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
+- }
+
+- ASSERT(offset < XFS_LITINO(mp, ip->i_d.di_version));
++ ASSERT(offset < XFS_LITINO(mp));
+ return offset;
+ }
+
+--- a/fs/xfs/libxfs/xfs_format.h
++++ b/fs/xfs/libxfs/xfs_format.h
+@@ -963,8 +963,12 @@ typedef enum xfs_dinode_fmt {
+ /*
+ * Inode size for given fs.
+ */
+-#define XFS_LITINO(mp, version) \
+- ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))
++#define XFS_DINODE_SIZE(sbp) \
++ (xfs_sb_version_has_v3inode(sbp) ? \
++ sizeof(struct xfs_dinode) : \
++ offsetof(struct xfs_dinode, di_crc))
++#define XFS_LITINO(mp) \
++ ((mp)->m_sb.sb_inodesize - XFS_DINODE_SIZE(&(mp)->m_sb))
+
+ /*
+ * Inode data & attribute fork sizes, per inode.
+@@ -973,13 +977,9 @@ typedef enum xfs_dinode_fmt {
+ #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_version))
++ (XFS_DFORK_Q(dip) ? XFS_DFORK_BOFF(dip) : XFS_LITINO(mp))
+ #define XFS_DFORK_ASIZE(dip,mp) \
+- (XFS_DFORK_Q(dip) ? \
+- XFS_LITINO(mp, (dip)->di_version) - XFS_DFORK_BOFF(dip) : \
+- 0)
++ (XFS_DFORK_Q(dip) ? XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : 0)
+ #define XFS_DFORK_SIZE(dip,mp,w) \
+ ((w) == XFS_DATA_FORK ? \
+ XFS_DFORK_DSIZE(dip, mp) : \
+--- a/fs/xfs/libxfs/xfs_ialloc.c
++++ b/fs/xfs/libxfs/xfs_ialloc.c
+@@ -339,7 +339,7 @@ xfs_ialloc_inode_init(
+ xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length));
+ for (i = 0; i < M_IGEO(mp)->inodes_per_cluster; i++) {
+ int ioffset = i << mp->m_sb.sb_inodelog;
+- uint isize = xfs_dinode_size(version);
++ uint isize = XFS_DINODE_SIZE(&mp->m_sb);
+
+ free = xfs_make_iptr(mp, fbuf, i);
+ free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -417,7 +417,7 @@ xfs_dinode_verify_forkoff(
+ case XFS_DINODE_FMT_LOCAL: /* fall through ... */
+ case XFS_DINODE_FMT_EXTENTS: /* fall through ... */
+ case XFS_DINODE_FMT_BTREE:
+- if (dip->di_forkoff >= (XFS_LITINO(mp, dip->di_version) >> 3))
++ if (dip->di_forkoff >= (XFS_LITINO(mp) >> 3))
+ return __this_address;
+ break;
+ default:
+--- a/fs/xfs/libxfs/xfs_inode_fork.c
++++ b/fs/xfs/libxfs/xfs_inode_fork.c
+@@ -183,7 +183,7 @@ xfs_iformat_local(
+ */
+ if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
+ xfs_warn(ip->i_mount,
+- "corrupt inode %Lu (bad size %d for local fork, size = %d).",
++ "corrupt inode %Lu (bad size %d for local fork, size = %zd).",
+ (unsigned long long) ip->i_ino, size,
+ XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
+ xfs_inode_verifier_error(ip, -EFSCORRUPTED,
+--- a/fs/xfs/libxfs/xfs_inode_fork.h
++++ b/fs/xfs/libxfs/xfs_inode_fork.h
+@@ -46,14 +46,9 @@ struct xfs_ifork {
+ (ip)->i_afp : \
+ (ip)->i_cowfp))
+ #define XFS_IFORK_DSIZE(ip) \
+- (XFS_IFORK_Q(ip) ? \
+- XFS_IFORK_BOFF(ip) : \
+- XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version))
++ (XFS_IFORK_Q(ip) ? XFS_IFORK_BOFF(ip) : XFS_LITINO((ip)->i_mount))
+ #define XFS_IFORK_ASIZE(ip) \
+- (XFS_IFORK_Q(ip) ? \
+- XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version) - \
+- XFS_IFORK_BOFF(ip) : \
+- 0)
++ (XFS_IFORK_Q(ip) ? XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : 0)
+ #define XFS_IFORK_SIZE(ip,w) \
+ ((w) == XFS_DATA_FORK ? \
+ XFS_IFORK_DSIZE(ip) : \
+--- a/fs/xfs/libxfs/xfs_log_format.h
++++ b/fs/xfs/libxfs/xfs_log_format.h
+@@ -424,12 +424,10 @@ struct xfs_log_dinode {
+ /* structure must be padded to 64 bit alignment */
+ };
+
+-static inline uint xfs_log_dinode_size(int version)
+-{
+- if (version == 3)
+- return sizeof(struct xfs_log_dinode);
+- return offsetof(struct xfs_log_dinode, di_next_unlinked);
+-}
++#define xfs_log_dinode_size(mp) \
++ (xfs_sb_version_has_v3inode(&(mp)->m_sb) ? \
++ sizeof(struct xfs_log_dinode) : \
++ offsetof(struct xfs_log_dinode, di_next_unlinked))
+
+ /*
+ * Buffer Log Format defintions
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -125,7 +125,7 @@ xfs_inode_item_size(
+
+ *nvecs += 2;
+ *nbytes += sizeof(struct xfs_inode_log_format) +
+- xfs_log_dinode_size(ip->i_d.di_version);
++ xfs_log_dinode_size(ip->i_mount);
+
+ xfs_inode_item_data_fork_size(iip, nvecs, nbytes);
+ if (XFS_IFORK_Q(ip))
+@@ -370,7 +370,7 @@ xfs_inode_item_format_core(
+
+ dic = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_ICORE);
+ xfs_inode_to_log_dinode(ip, dic, ip->i_itemp->ili_item.li_lsn);
+- xlog_finish_iovec(lv, *vecp, xfs_log_dinode_size(ip->i_d.di_version));
++ xlog_finish_iovec(lv, *vecp, xfs_log_dinode_size(ip->i_mount));
+ }
+
+ /*
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -3089,7 +3089,7 @@ xlog_recover_inode_pass2(
+ error = -EFSCORRUPTED;
+ goto out_release;
+ }
+- isize = xfs_log_dinode_size(ldip->di_version);
++ isize = xfs_log_dinode_size(mp);
+ if (unlikely(item->ri_buf[1].i_len > isize)) {
+ XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
+ XFS_ERRLEVEL_LOW, mp, ldip,
+--- a/fs/xfs/xfs_symlink.c
++++ b/fs/xfs/xfs_symlink.c
+@@ -201,7 +201,7 @@ xfs_symlink(
+ * The symlink will fit into the inode data fork?
+ * There can't be any attributes so we get the whole variable part.
+ */
+- if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
++ if (pathlen <= XFS_LITINO(mp))
+ fs_blocks = 0;
+ else
+ fs_blocks = xfs_symlink_blocks(mp, pathlen);
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:46 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:17 +0530
+Subject: xfs: remove the di_version field from struct icdinode
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-11-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 6471e9c5e7a109a952be8e3e80b8d9e262af239d upstream.
+
+We know the version is 3 if on a v5 file system. For earlier file
+systems formats we always upgrade the remaining v1 inodes to v2 and
+thus only use v2 inodes. Use the xfs_sb_version_has_large_dinode
+helper to check if we deal with small or large dinodes, and thus
+remove the need for the di_version field in struct icdinode.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 16 ++++++----------
+ fs/xfs/libxfs/xfs_inode_buf.h | 1 -
+ fs/xfs/xfs_bmap_util.c | 16 ++++++++--------
+ fs/xfs/xfs_inode.c | 16 ++--------------
+ fs/xfs/xfs_inode_item.c | 8 +++-----
+ fs/xfs/xfs_ioctl.c | 5 ++---
+ fs/xfs/xfs_iops.c | 2 +-
+ fs/xfs/xfs_itable.c | 2 +-
+ fs/xfs/xfs_log_recover.c | 2 +-
+ 9 files changed, 24 insertions(+), 44 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -194,16 +194,14 @@ xfs_inode_from_disk(
+ struct xfs_icdinode *to = &ip->i_d;
+ struct inode *inode = VFS_I(ip);
+
+-
+ /*
+ * Convert v1 inodes immediately to v2 inode format as this is the
+ * minimum inode version format we support in the rest of the code.
++ * They will also be unconditionally written back to disk as v2 inodes.
+ */
+- to->di_version = from->di_version;
+- if (to->di_version == 1) {
++ if (unlikely(from->di_version == 1)) {
+ set_nlink(inode, be16_to_cpu(from->di_onlink));
+ to->di_projid = 0;
+- to->di_version = 2;
+ } else {
+ set_nlink(inode, be32_to_cpu(from->di_nlink));
+ to->di_projid = (prid_t)be16_to_cpu(from->di_projid_hi) << 16 |
+@@ -241,7 +239,7 @@ xfs_inode_from_disk(
+ to->di_dmstate = be16_to_cpu(from->di_dmstate);
+ to->di_flags = be16_to_cpu(from->di_flags);
+
+- if (to->di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
+ inode_set_iversion_queried(inode,
+ be64_to_cpu(from->di_changecount));
+ to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
+@@ -263,7 +261,6 @@ xfs_inode_to_disk(
+ to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
+ to->di_onlink = 0;
+
+- to->di_version = from->di_version;
+ to->di_format = from->di_format;
+ to->di_uid = cpu_to_be32(i_uid_read(inode));
+ to->di_gid = cpu_to_be32(i_gid_read(inode));
+@@ -292,7 +289,8 @@ xfs_inode_to_disk(
+ to->di_dmstate = cpu_to_be16(from->di_dmstate);
+ to->di_flags = cpu_to_be16(from->di_flags);
+
+- if (from->di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
++ to->di_version = 3;
+ to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
+ to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
+ to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
+@@ -304,6 +302,7 @@ xfs_inode_to_disk(
+ uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
+ to->di_flushiter = 0;
+ } else {
++ to->di_version = 2;
+ to->di_flushiter = cpu_to_be16(from->di_flushiter);
+ }
+ }
+@@ -623,7 +622,6 @@ xfs_iread(
+ /* initialise the on-disk inode core */
+ memset(&ip->i_d, 0, sizeof(ip->i_d));
+ VFS_I(ip)->i_generation = prandom_u32();
+- ip->i_d.di_version = 3;
+ return 0;
+ }
+
+@@ -665,7 +663,6 @@ xfs_iread(
+ * Partial initialisation of the in-core inode. Just the bits
+ * that xfs_ialloc won't overwrite or relies on being correct.
+ */
+- ip->i_d.di_version = dip->di_version;
+ VFS_I(ip)->i_generation = be32_to_cpu(dip->di_gen);
+ ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter);
+
+@@ -679,7 +676,6 @@ xfs_iread(
+ VFS_I(ip)->i_mode = 0;
+ }
+
+- ASSERT(ip->i_d.di_version >= 2);
+ ip->i_delayed_blks = 0;
+
+ /*
+--- a/fs/xfs/libxfs/xfs_inode_buf.h
++++ b/fs/xfs/libxfs/xfs_inode_buf.h
+@@ -16,7 +16,6 @@ struct xfs_dinode;
+ * format specific structures at the appropriate time.
+ */
+ struct xfs_icdinode {
+- int8_t di_version; /* inode version */
+ int8_t di_format; /* format of di_c data */
+ uint16_t di_flushiter; /* incremented on flush */
+ uint32_t di_projid; /* owner's project id */
+--- a/fs/xfs/xfs_bmap_util.c
++++ b/fs/xfs/xfs_bmap_util.c
+@@ -1624,12 +1624,12 @@ xfs_swap_extent_forks(
+ * event of a crash. Set the owner change log flags now and leave the
+ * bmbt scan as the last step.
+ */
+- if (ip->i_d.di_version == 3 &&
+- ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+- (*target_log_flags) |= XFS_ILOG_DOWNER;
+- if (tip->i_d.di_version == 3 &&
+- tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+- (*src_log_flags) |= XFS_ILOG_DOWNER;
++ if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
++ if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
++ (*target_log_flags) |= XFS_ILOG_DOWNER;
++ if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
++ (*src_log_flags) |= XFS_ILOG_DOWNER;
++ }
+
+ /*
+ * Swap the data forks of the inodes
+@@ -1664,7 +1664,7 @@ xfs_swap_extent_forks(
+ (*src_log_flags) |= XFS_ILOG_DEXT;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+- ASSERT(ip->i_d.di_version < 3 ||
++ ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
+ (*src_log_flags & XFS_ILOG_DOWNER));
+ (*src_log_flags) |= XFS_ILOG_DBROOT;
+ break;
+@@ -1676,7 +1676,7 @@ xfs_swap_extent_forks(
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ (*target_log_flags) |= XFS_ILOG_DBROOT;
+- ASSERT(tip->i_d.di_version < 3 ||
++ ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
+ (*target_log_flags & XFS_ILOG_DOWNER));
+ break;
+ }
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -795,15 +795,6 @@ xfs_ialloc(
+ return error;
+ ASSERT(ip != NULL);
+ inode = VFS_I(ip);
+-
+- /*
+- * We always convert v1 inodes to v2 now - we only support filesystems
+- * with >= v2 inode capability, so there is no reason for ever leaving
+- * an inode in v1 format.
+- */
+- if (ip->i_d.di_version == 1)
+- ip->i_d.di_version = 2;
+-
+ inode->i_mode = mode;
+ set_nlink(inode, nlink);
+ inode->i_uid = current_fsuid();
+@@ -841,7 +832,7 @@ xfs_ialloc(
+ ip->i_d.di_dmstate = 0;
+ ip->i_d.di_flags = 0;
+
+- if (ip->i_d.di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ inode_set_iversion(inode, 1);
+ ip->i_d.di_flags2 = 0;
+ ip->i_d.di_cowextsize = 0;
+@@ -849,7 +840,6 @@ xfs_ialloc(
+ ip->i_d.di_crtime.t_nsec = (int32_t)tv.tv_nsec;
+ }
+
+-
+ flags = XFS_ILOG_CORE;
+ switch (mode & S_IFMT) {
+ case S_IFIFO:
+@@ -1110,7 +1100,6 @@ xfs_bumplink(
+ {
+ xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
+
+- ASSERT(ip->i_d.di_version > 1);
+ inc_nlink(VFS_I(ip));
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ }
+@@ -3822,7 +3811,6 @@ xfs_iflush_int(
+ ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+ ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
+ ASSERT(iip != NULL && iip->ili_fields != 0);
+- ASSERT(ip->i_d.di_version > 1);
+
+ /* set *dip = inode's place in the buffer */
+ dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
+@@ -3883,7 +3871,7 @@ xfs_iflush_int(
+ * backwards compatibility with old kernels that predate logging all
+ * inode changes.
+ */
+- if (ip->i_d.di_version < 3)
++ if (!xfs_sb_version_has_v3inode(&mp->m_sb))
+ ip->i_d.di_flushiter++;
+
+ /* Check the inline fork data before we write out. */
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -305,8 +305,6 @@ xfs_inode_to_log_dinode(
+ struct inode *inode = VFS_I(ip);
+
+ to->di_magic = XFS_DINODE_MAGIC;
+-
+- to->di_version = from->di_version;
+ to->di_format = from->di_format;
+ to->di_uid = i_uid_read(inode);
+ to->di_gid = i_gid_read(inode);
+@@ -339,7 +337,8 @@ xfs_inode_to_log_dinode(
+ /* log a dummy value to ensure log structure is fully initialised */
+ to->di_next_unlinked = NULLAGINO;
+
+- if (from->di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
++ to->di_version = 3;
+ to->di_changecount = inode_peek_iversion(inode);
+ to->di_crtime.t_sec = from->di_crtime.t_sec;
+ to->di_crtime.t_nsec = from->di_crtime.t_nsec;
+@@ -351,6 +350,7 @@ xfs_inode_to_log_dinode(
+ uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
+ to->di_flushiter = 0;
+ } else {
++ to->di_version = 2;
+ to->di_flushiter = from->di_flushiter;
+ }
+ }
+@@ -395,8 +395,6 @@ xfs_inode_item_format(
+ struct xfs_log_iovec *vecp = NULL;
+ struct xfs_inode_log_format *ilf;
+
+- ASSERT(ip->i_d.di_version > 1);
+-
+ ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT);
+ ilf->ilf_type = XFS_LI_INODE;
+ ilf->ilf_ino = ip->i_ino;
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1299,7 +1299,7 @@ xfs_ioctl_setattr_xflags(
+
+ /* diflags2 only valid for v3 inodes. */
+ di_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
+- if (di_flags2 && ip->i_d.di_version < 3)
++ if (di_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
+ return -EINVAL;
+
+ ip->i_d.di_flags = xfs_flags2diflags(ip, fa->fsx_xflags);
+@@ -1638,7 +1638,6 @@ xfs_ioctl_setattr(
+ olddquot = xfs_qm_vop_chown(tp, ip,
+ &ip->i_pdquot, pdqp);
+ }
+- ASSERT(ip->i_d.di_version > 1);
+ ip->i_d.di_projid = fa->fsx_projid;
+ }
+
+@@ -1651,7 +1650,7 @@ xfs_ioctl_setattr(
+ ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
+ else
+ ip->i_d.di_extsize = 0;
+- if (ip->i_d.di_version == 3 &&
++ if (xfs_sb_version_has_v3inode(&mp->m_sb) &&
+ (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
+ ip->i_d.di_cowextsize = fa->fsx_cowextsize >>
+ mp->m_sb.sb_blocklog;
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -517,7 +517,7 @@ xfs_vn_getattr(
+ stat->blocks =
+ XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
+
+- if (ip->i_d.di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (request_mask & STATX_BTIME) {
+ stat->result_mask |= STATX_BTIME;
+ stat->btime.tv_sec = ip->i_d.di_crtime.t_sec;
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -110,7 +110,7 @@ xfs_bulkstat_one_int(
+ buf->bs_forkoff = XFS_IFORK_BOFF(ip);
+ buf->bs_version = XFS_BULKSTAT_VERSION_V5;
+
+- if (dic->di_version == 3) {
++ if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE)
+ buf->bs_cowextsize_blks = dic->di_cowextsize;
+ }
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -2879,8 +2879,8 @@ xfs_recover_inode_owner_change(
+ return -ENOMEM;
+
+ /* instantiate the inode */
++ ASSERT(dip->di_version >= 3);
+ xfs_inode_from_disk(ip, dip);
+- ASSERT(ip->i_d.di_version >= 3);
+
+ error = xfs_iformat_fork(ip, dip);
+ if (error)
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:27:59 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:11 +0530
+Subject: xfs: remove the icdinode di_uid/di_gid members
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-5-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 542951592c99ff7b15c050954c051dd6dd6c0f97 upstream.
+
+Use the Linux inode i_uid/i_gid members everywhere and just convert
+from/to the scalar value when reading or writing the on-disk inode.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 10 ++++------
+ fs/xfs/libxfs/xfs_inode_buf.h | 2 --
+ fs/xfs/xfs_dquot.c | 4 ++--
+ fs/xfs/xfs_inode.c | 14 ++++----------
+ fs/xfs/xfs_inode_item.c | 4 ++--
+ fs/xfs/xfs_ioctl.c | 6 +++---
+ fs/xfs/xfs_iops.c | 6 +-----
+ fs/xfs/xfs_itable.c | 4 ++--
+ fs/xfs/xfs_qm.c | 40 +++++++++++++++++++++++++---------------
+ fs/xfs/xfs_quota.h | 4 ++--
+ fs/xfs/xfs_symlink.c | 4 +---
+ 11 files changed, 46 insertions(+), 52 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -222,10 +222,8 @@ xfs_inode_from_disk(
+ }
+
+ to->di_format = from->di_format;
+- to->di_uid = be32_to_cpu(from->di_uid);
+- inode->i_uid = xfs_uid_to_kuid(to->di_uid);
+- to->di_gid = be32_to_cpu(from->di_gid);
+- inode->i_gid = xfs_gid_to_kgid(to->di_gid);
++ inode->i_uid = xfs_uid_to_kuid(be32_to_cpu(from->di_uid));
++ inode->i_gid = xfs_gid_to_kgid(be32_to_cpu(from->di_gid));
+ to->di_flushiter = be16_to_cpu(from->di_flushiter);
+
+ /*
+@@ -278,8 +276,8 @@ xfs_inode_to_disk(
+
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+- to->di_uid = cpu_to_be32(from->di_uid);
+- to->di_gid = cpu_to_be32(from->di_gid);
++ to->di_uid = cpu_to_be32(xfs_kuid_to_uid(inode->i_uid));
++ to->di_gid = cpu_to_be32(xfs_kgid_to_gid(inode->i_gid));
+ to->di_projid_lo = cpu_to_be16(from->di_projid & 0xffff);
+ to->di_projid_hi = cpu_to_be16(from->di_projid >> 16);
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.h
++++ b/fs/xfs/libxfs/xfs_inode_buf.h
+@@ -19,8 +19,6 @@ struct xfs_icdinode {
+ int8_t di_version; /* inode version */
+ int8_t di_format; /* format of di_c data */
+ uint16_t di_flushiter; /* incremented on flush */
+- uint32_t di_uid; /* owner's user id */
+- uint32_t di_gid; /* owner's group id */
+ 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 */
+--- a/fs/xfs/xfs_dquot.c
++++ b/fs/xfs/xfs_dquot.c
+@@ -859,9 +859,9 @@ xfs_qm_id_for_quotatype(
+ {
+ switch (type) {
+ case XFS_DQ_USER:
+- return ip->i_d.di_uid;
++ return xfs_kuid_to_uid(VFS_I(ip)->i_uid);
+ case XFS_DQ_GROUP:
+- return ip->i_d.di_gid;
++ return xfs_kgid_to_gid(VFS_I(ip)->i_gid);
+ case XFS_DQ_PROJ:
+ return ip->i_d.di_projid;
+ }
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -807,18 +807,15 @@ xfs_ialloc(
+ inode->i_mode = mode;
+ set_nlink(inode, nlink);
+ inode->i_uid = current_fsuid();
+- ip->i_d.di_uid = xfs_kuid_to_uid(inode->i_uid);
+ inode->i_rdev = rdev;
+ ip->i_d.di_projid = prid;
+
+ if (pip && XFS_INHERIT_GID(pip)) {
+ inode->i_gid = VFS_I(pip)->i_gid;
+- ip->i_d.di_gid = pip->i_d.di_gid;
+ if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
+ } else {
+ inode->i_gid = current_fsgid();
+- ip->i_d.di_gid = xfs_kgid_to_gid(inode->i_gid);
+ }
+
+ /*
+@@ -826,9 +823,8 @@ xfs_ialloc(
+ * ID or one of the supplementary group IDs, the S_ISGID bit is cleared
+ * (and only if the irix_sgid_inherit compatibility variable is set).
+ */
+- if ((irix_sgid_inherit) &&
+- (inode->i_mode & S_ISGID) &&
+- (!in_group_p(xfs_gid_to_kgid(ip->i_d.di_gid))))
++ if (irix_sgid_inherit &&
++ (inode->i_mode & S_ISGID) && !in_group_p(inode->i_gid))
+ inode->i_mode &= ~S_ISGID;
+
+ ip->i_d.di_size = 0;
+@@ -1157,8 +1153,7 @@ xfs_create(
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()),
+- xfs_kgid_to_gid(current_fsgid()), prid,
++ error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
+ &udqp, &gdqp, &pdqp);
+ if (error)
+@@ -1308,8 +1303,7 @@ xfs_create_tmpfile(
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()),
+- xfs_kgid_to_gid(current_fsgid()), prid,
++ error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
+ &udqp, &gdqp, &pdqp);
+ if (error)
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -308,8 +308,8 @@ xfs_inode_to_log_dinode(
+
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+- to->di_uid = from->di_uid;
+- to->di_gid = from->di_gid;
++ to->di_uid = xfs_kuid_to_uid(inode->i_uid);
++ to->di_gid = xfs_kgid_to_gid(inode->i_gid);
+ to->di_projid_lo = from->di_projid & 0xffff;
+ to->di_projid_hi = from->di_projid >> 16;
+
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1572,9 +1572,9 @@ xfs_ioctl_setattr(
+ * because the i_*dquot fields will get updated anyway.
+ */
+ if (XFS_IS_QUOTA_ON(mp)) {
+- code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
+- ip->i_d.di_gid, fa->fsx_projid,
+- XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
++ code = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,
++ VFS_I(ip)->i_gid, fa->fsx_projid,
++ XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
+ if (code)
+ return code;
+ }
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -666,9 +666,7 @@ xfs_setattr_nonsize(
+ */
+ ASSERT(udqp == NULL);
+ ASSERT(gdqp == NULL);
+- error = xfs_qm_vop_dqalloc(ip, xfs_kuid_to_uid(uid),
+- xfs_kgid_to_gid(gid),
+- ip->i_d.di_projid,
++ error = xfs_qm_vop_dqalloc(ip, uid, gid, ip->i_d.di_projid,
+ qflags, &udqp, &gdqp, NULL);
+ if (error)
+ return error;
+@@ -737,7 +735,6 @@ xfs_setattr_nonsize(
+ olddquot1 = xfs_qm_vop_chown(tp, ip,
+ &ip->i_udquot, udqp);
+ }
+- ip->i_d.di_uid = xfs_kuid_to_uid(uid);
+ inode->i_uid = uid;
+ }
+ if (!gid_eq(igid, gid)) {
+@@ -749,7 +746,6 @@ xfs_setattr_nonsize(
+ olddquot2 = xfs_qm_vop_chown(tp, ip,
+ &ip->i_gdquot, gdqp);
+ }
+- ip->i_d.di_gid = xfs_kgid_to_gid(gid);
+ inode->i_gid = gid;
+ }
+ }
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -86,8 +86,8 @@ xfs_bulkstat_one_int(
+ */
+ buf->bs_projectid = ip->i_d.di_projid;
+ buf->bs_ino = ino;
+- buf->bs_uid = dic->di_uid;
+- buf->bs_gid = dic->di_gid;
++ buf->bs_uid = xfs_kuid_to_uid(inode->i_uid);
++ buf->bs_gid = xfs_kgid_to_gid(inode->i_gid);
+ buf->bs_size = dic->di_size;
+
+ buf->bs_nlink = inode->i_nlink;
+--- a/fs/xfs/xfs_qm.c
++++ b/fs/xfs/xfs_qm.c
+@@ -331,16 +331,18 @@ xfs_qm_dqattach_locked(
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) {
+- error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER,
+- doalloc, &ip->i_udquot);
++ error = xfs_qm_dqattach_one(ip,
++ xfs_kuid_to_uid(VFS_I(ip)->i_uid),
++ XFS_DQ_USER, doalloc, &ip->i_udquot);
+ if (error)
+ goto done;
+ ASSERT(ip->i_udquot);
+ }
+
+ if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) {
+- error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+- doalloc, &ip->i_gdquot);
++ error = xfs_qm_dqattach_one(ip,
++ xfs_kgid_to_gid(VFS_I(ip)->i_gid),
++ XFS_DQ_GROUP, doalloc, &ip->i_gdquot);
+ if (error)
+ goto done;
+ ASSERT(ip->i_gdquot);
+@@ -1630,8 +1632,8 @@ xfs_qm_dqfree_one(
+ int
+ xfs_qm_vop_dqalloc(
+ struct xfs_inode *ip,
+- xfs_dqid_t uid,
+- xfs_dqid_t gid,
++ kuid_t uid,
++ kgid_t gid,
+ prid_t prid,
+ uint flags,
+ struct xfs_dquot **O_udqpp,
+@@ -1639,6 +1641,7 @@ xfs_qm_vop_dqalloc(
+ struct xfs_dquot **O_pdqpp)
+ {
+ struct xfs_mount *mp = ip->i_mount;
++ struct inode *inode = VFS_I(ip);
+ struct xfs_dquot *uq = NULL;
+ struct xfs_dquot *gq = NULL;
+ struct xfs_dquot *pq = NULL;
+@@ -1652,7 +1655,7 @@ xfs_qm_vop_dqalloc(
+ xfs_ilock(ip, lockflags);
+
+ if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
+- gid = ip->i_d.di_gid;
++ gid = inode->i_gid;
+
+ /*
+ * Attach the dquot(s) to this inode, doing a dquot allocation
+@@ -1667,7 +1670,7 @@ xfs_qm_vop_dqalloc(
+ }
+
+ if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
+- if (ip->i_d.di_uid != uid) {
++ if (!uid_eq(inode->i_uid, uid)) {
+ /*
+ * What we need is the dquot that has this uid, and
+ * if we send the inode to dqget, the uid of the inode
+@@ -1678,7 +1681,8 @@ xfs_qm_vop_dqalloc(
+ * holding ilock.
+ */
+ xfs_iunlock(ip, lockflags);
+- error = xfs_qm_dqget(mp, uid, XFS_DQ_USER, true, &uq);
++ error = xfs_qm_dqget(mp, xfs_kuid_to_uid(uid),
++ XFS_DQ_USER, true, &uq);
+ if (error) {
+ ASSERT(error != -ENOENT);
+ return error;
+@@ -1699,9 +1703,10 @@ xfs_qm_vop_dqalloc(
+ }
+ }
+ if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
+- if (ip->i_d.di_gid != gid) {
++ if (!gid_eq(inode->i_gid, gid)) {
+ xfs_iunlock(ip, lockflags);
+- error = xfs_qm_dqget(mp, gid, XFS_DQ_GROUP, true, &gq);
++ error = xfs_qm_dqget(mp, xfs_kgid_to_gid(gid),
++ XFS_DQ_GROUP, true, &gq);
+ if (error) {
+ ASSERT(error != -ENOENT);
+ goto error_rele;
+@@ -1827,7 +1832,8 @@ xfs_qm_vop_chown_reserve(
+ XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
+
+ if (XFS_IS_UQUOTA_ON(mp) && udqp &&
+- ip->i_d.di_uid != be32_to_cpu(udqp->q_core.d_id)) {
++ xfs_kuid_to_uid(VFS_I(ip)->i_uid) !=
++ be32_to_cpu(udqp->q_core.d_id)) {
+ udq_delblks = udqp;
+ /*
+ * If there are delayed allocation blocks, then we have to
+@@ -1840,7 +1846,8 @@ xfs_qm_vop_chown_reserve(
+ }
+ }
+ if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
+- ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) {
++ xfs_kgid_to_gid(VFS_I(ip)->i_gid) !=
++ be32_to_cpu(gdqp->q_core.d_id)) {
+ gdq_delblks = gdqp;
+ if (delblks) {
+ ASSERT(ip->i_gdquot);
+@@ -1937,14 +1944,17 @@ xfs_qm_vop_create_dqattach(
+
+ if (udqp && XFS_IS_UQUOTA_ON(mp)) {
+ ASSERT(ip->i_udquot == NULL);
+- ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
++ ASSERT(xfs_kuid_to_uid(VFS_I(ip)->i_uid) ==
++ be32_to_cpu(udqp->q_core.d_id));
+
+ ip->i_udquot = xfs_qm_dqhold(udqp);
+ xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
+ }
+ if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
+ ASSERT(ip->i_gdquot == NULL);
+- ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
++ ASSERT(xfs_kgid_to_gid(VFS_I(ip)->i_gid) ==
++ be32_to_cpu(gdqp->q_core.d_id));
++
+ ip->i_gdquot = xfs_qm_dqhold(gdqp);
+ xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
+ }
+--- a/fs/xfs/xfs_quota.h
++++ b/fs/xfs/xfs_quota.h
+@@ -86,7 +86,7 @@ extern int xfs_trans_reserve_quota_bydqu
+ struct xfs_mount *, struct xfs_dquot *,
+ struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
+
+-extern int xfs_qm_vop_dqalloc(struct xfs_inode *, xfs_dqid_t, xfs_dqid_t,
++extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t,
+ prid_t, uint, struct xfs_dquot **, struct xfs_dquot **,
+ struct xfs_dquot **);
+ extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
+@@ -109,7 +109,7 @@ extern void xfs_qm_unmount_quotas(struct
+
+ #else
+ static inline int
+-xfs_qm_vop_dqalloc(struct xfs_inode *ip, xfs_dqid_t uid, xfs_dqid_t gid,
++xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
+ prid_t prid, uint flags, struct xfs_dquot **udqp,
+ struct xfs_dquot **gdqp, struct xfs_dquot **pdqp)
+ {
+--- a/fs/xfs/xfs_symlink.c
++++ b/fs/xfs/xfs_symlink.c
+@@ -191,9 +191,7 @@ xfs_symlink(
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = xfs_qm_vop_dqalloc(dp,
+- xfs_kuid_to_uid(current_fsuid()),
+- xfs_kgid_to_gid(current_fsgid()), prid,
++ error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
+ &udqp, &gdqp, &pdqp);
+ if (error)
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:09 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:12 +0530
+Subject: xfs: remove the kuid/kgid conversion wrappers
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-6-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit ba8adad5d036733d240fa8a8f4d055f3d4490562 upstream.
+
+Remove the XFS wrappers for converting from and to the kuid/kgid types.
+Mostly this means switching to VFS i_{u,g}id_{read,write} helpers, but
+in a few spots the calls to the conversion functions is open coded.
+To match the use of sb->s_user_ns in the helpers and other file systems,
+sb->s_user_ns is also used in the quota code. The ACL code already does
+the conversion in a grotty layering violation in the VFS xattr code,
+so it keeps using init_user_ns for the identity mapping.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 8 ++++----
+ fs/xfs/xfs_acl.c | 12 ++++++++----
+ fs/xfs/xfs_dquot.c | 4 ++--
+ fs/xfs/xfs_inode_item.c | 4 ++--
+ fs/xfs/xfs_itable.c | 4 ++--
+ fs/xfs/xfs_linux.h | 26 --------------------------
+ fs/xfs/xfs_qm.c | 23 +++++++++--------------
+ 7 files changed, 27 insertions(+), 54 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -222,8 +222,8 @@ xfs_inode_from_disk(
+ }
+
+ to->di_format = from->di_format;
+- inode->i_uid = xfs_uid_to_kuid(be32_to_cpu(from->di_uid));
+- inode->i_gid = xfs_gid_to_kgid(be32_to_cpu(from->di_gid));
++ i_uid_write(inode, be32_to_cpu(from->di_uid));
++ i_gid_write(inode, be32_to_cpu(from->di_gid));
+ to->di_flushiter = be16_to_cpu(from->di_flushiter);
+
+ /*
+@@ -276,8 +276,8 @@ xfs_inode_to_disk(
+
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+- to->di_uid = cpu_to_be32(xfs_kuid_to_uid(inode->i_uid));
+- to->di_gid = cpu_to_be32(xfs_kgid_to_gid(inode->i_gid));
++ 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);
+ to->di_projid_hi = cpu_to_be16(from->di_projid >> 16);
+
+--- a/fs/xfs/xfs_acl.c
++++ b/fs/xfs/xfs_acl.c
+@@ -66,10 +66,12 @@ xfs_acl_from_disk(
+
+ switch (acl_e->e_tag) {
+ case ACL_USER:
+- acl_e->e_uid = xfs_uid_to_kuid(be32_to_cpu(ace->ae_id));
++ acl_e->e_uid = make_kuid(&init_user_ns,
++ be32_to_cpu(ace->ae_id));
+ break;
+ case ACL_GROUP:
+- acl_e->e_gid = xfs_gid_to_kgid(be32_to_cpu(ace->ae_id));
++ acl_e->e_gid = make_kgid(&init_user_ns,
++ be32_to_cpu(ace->ae_id));
+ break;
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+@@ -102,10 +104,12 @@ xfs_acl_to_disk(struct xfs_acl *aclp, co
+ ace->ae_tag = cpu_to_be32(acl_e->e_tag);
+ switch (acl_e->e_tag) {
+ case ACL_USER:
+- ace->ae_id = cpu_to_be32(xfs_kuid_to_uid(acl_e->e_uid));
++ ace->ae_id = cpu_to_be32(
++ from_kuid(&init_user_ns, acl_e->e_uid));
+ break;
+ case ACL_GROUP:
+- ace->ae_id = cpu_to_be32(xfs_kgid_to_gid(acl_e->e_gid));
++ ace->ae_id = cpu_to_be32(
++ from_kgid(&init_user_ns, acl_e->e_gid));
+ break;
+ default:
+ ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID);
+--- a/fs/xfs/xfs_dquot.c
++++ b/fs/xfs/xfs_dquot.c
+@@ -859,9 +859,9 @@ xfs_qm_id_for_quotatype(
+ {
+ switch (type) {
+ case XFS_DQ_USER:
+- return xfs_kuid_to_uid(VFS_I(ip)->i_uid);
++ return i_uid_read(VFS_I(ip));
+ case XFS_DQ_GROUP:
+- return xfs_kgid_to_gid(VFS_I(ip)->i_gid);
++ return i_gid_read(VFS_I(ip));
+ case XFS_DQ_PROJ:
+ return ip->i_d.di_projid;
+ }
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -308,8 +308,8 @@ xfs_inode_to_log_dinode(
+
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+- to->di_uid = xfs_kuid_to_uid(inode->i_uid);
+- to->di_gid = xfs_kgid_to_gid(inode->i_gid);
++ to->di_uid = i_uid_read(inode);
++ to->di_gid = i_gid_read(inode);
+ to->di_projid_lo = from->di_projid & 0xffff;
+ to->di_projid_hi = from->di_projid >> 16;
+
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -86,8 +86,8 @@ xfs_bulkstat_one_int(
+ */
+ buf->bs_projectid = ip->i_d.di_projid;
+ buf->bs_ino = ino;
+- buf->bs_uid = xfs_kuid_to_uid(inode->i_uid);
+- buf->bs_gid = xfs_kgid_to_gid(inode->i_gid);
++ buf->bs_uid = i_uid_read(inode);
++ buf->bs_gid = i_gid_read(inode);
+ buf->bs_size = dic->di_size;
+
+ buf->bs_nlink = inode->i_nlink;
+--- a/fs/xfs/xfs_linux.h
++++ b/fs/xfs/xfs_linux.h
+@@ -163,32 +163,6 @@ struct xstats {
+
+ extern struct xstats xfsstats;
+
+-/* Kernel uid/gid conversion. These are used to convert to/from the on disk
+- * uid_t/gid_t types to the kuid_t/kgid_t types that the kernel uses internally.
+- * The conversion here is type only, the value will remain the same since we
+- * are converting to the init_user_ns. The uid is later mapped to a particular
+- * user namespace value when crossing the kernel/user boundary.
+- */
+-static inline uint32_t xfs_kuid_to_uid(kuid_t uid)
+-{
+- return from_kuid(&init_user_ns, uid);
+-}
+-
+-static inline kuid_t xfs_uid_to_kuid(uint32_t uid)
+-{
+- return make_kuid(&init_user_ns, uid);
+-}
+-
+-static inline uint32_t xfs_kgid_to_gid(kgid_t gid)
+-{
+- return from_kgid(&init_user_ns, gid);
+-}
+-
+-static inline kgid_t xfs_gid_to_kgid(uint32_t gid)
+-{
+- return make_kgid(&init_user_ns, gid);
+-}
+-
+ static inline dev_t xfs_to_linux_dev_t(xfs_dev_t dev)
+ {
+ return MKDEV(sysv_major(dev) & 0x1ff, sysv_minor(dev));
+--- a/fs/xfs/xfs_qm.c
++++ b/fs/xfs/xfs_qm.c
+@@ -331,8 +331,7 @@ xfs_qm_dqattach_locked(
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) {
+- error = xfs_qm_dqattach_one(ip,
+- xfs_kuid_to_uid(VFS_I(ip)->i_uid),
++ error = xfs_qm_dqattach_one(ip, i_uid_read(VFS_I(ip)),
+ XFS_DQ_USER, doalloc, &ip->i_udquot);
+ if (error)
+ goto done;
+@@ -340,8 +339,7 @@ xfs_qm_dqattach_locked(
+ }
+
+ if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) {
+- error = xfs_qm_dqattach_one(ip,
+- xfs_kgid_to_gid(VFS_I(ip)->i_gid),
++ error = xfs_qm_dqattach_one(ip, i_gid_read(VFS_I(ip)),
+ XFS_DQ_GROUP, doalloc, &ip->i_gdquot);
+ if (error)
+ goto done;
+@@ -1642,6 +1640,7 @@ xfs_qm_vop_dqalloc(
+ {
+ struct xfs_mount *mp = ip->i_mount;
+ struct inode *inode = VFS_I(ip);
++ struct user_namespace *user_ns = inode->i_sb->s_user_ns;
+ struct xfs_dquot *uq = NULL;
+ struct xfs_dquot *gq = NULL;
+ struct xfs_dquot *pq = NULL;
+@@ -1681,7 +1680,7 @@ xfs_qm_vop_dqalloc(
+ * holding ilock.
+ */
+ xfs_iunlock(ip, lockflags);
+- error = xfs_qm_dqget(mp, xfs_kuid_to_uid(uid),
++ error = xfs_qm_dqget(mp, from_kuid(user_ns, uid),
+ XFS_DQ_USER, true, &uq);
+ if (error) {
+ ASSERT(error != -ENOENT);
+@@ -1705,7 +1704,7 @@ xfs_qm_vop_dqalloc(
+ if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
+ if (!gid_eq(inode->i_gid, gid)) {
+ xfs_iunlock(ip, lockflags);
+- error = xfs_qm_dqget(mp, xfs_kgid_to_gid(gid),
++ error = xfs_qm_dqget(mp, from_kgid(user_ns, gid),
+ XFS_DQ_GROUP, true, &gq);
+ if (error) {
+ ASSERT(error != -ENOENT);
+@@ -1832,8 +1831,7 @@ xfs_qm_vop_chown_reserve(
+ XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
+
+ if (XFS_IS_UQUOTA_ON(mp) && udqp &&
+- xfs_kuid_to_uid(VFS_I(ip)->i_uid) !=
+- be32_to_cpu(udqp->q_core.d_id)) {
++ i_uid_read(VFS_I(ip)) != be32_to_cpu(udqp->q_core.d_id)) {
+ udq_delblks = udqp;
+ /*
+ * If there are delayed allocation blocks, then we have to
+@@ -1846,8 +1844,7 @@ xfs_qm_vop_chown_reserve(
+ }
+ }
+ if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
+- xfs_kgid_to_gid(VFS_I(ip)->i_gid) !=
+- be32_to_cpu(gdqp->q_core.d_id)) {
++ i_gid_read(VFS_I(ip)) != be32_to_cpu(gdqp->q_core.d_id)) {
+ gdq_delblks = gdqp;
+ if (delblks) {
+ ASSERT(ip->i_gdquot);
+@@ -1944,16 +1941,14 @@ xfs_qm_vop_create_dqattach(
+
+ if (udqp && XFS_IS_UQUOTA_ON(mp)) {
+ ASSERT(ip->i_udquot == NULL);
+- ASSERT(xfs_kuid_to_uid(VFS_I(ip)->i_uid) ==
+- be32_to_cpu(udqp->q_core.d_id));
++ ASSERT(i_uid_read(VFS_I(ip)) == be32_to_cpu(udqp->q_core.d_id));
+
+ ip->i_udquot = xfs_qm_dqhold(udqp);
+ xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
+ }
+ if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
+ ASSERT(ip->i_gdquot == NULL);
+- ASSERT(xfs_kgid_to_gid(VFS_I(ip)->i_gid) ==
+- be32_to_cpu(gdqp->q_core.d_id));
++ ASSERT(i_gid_read(VFS_I(ip)) == be32_to_cpu(gdqp->q_core.d_id));
+
+ ip->i_gdquot = xfs_qm_dqhold(gdqp);
+ xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:08 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:20 +0530
+Subject: xfs: report corruption only as a regular error
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-14-chandan.babu@oracle.com>
+
+From: "Darrick J. Wong" <darrick.wong@oracle.com>
+
+commit 6519f708cc355c4834edbe1885c8542c0e7ef907 uptream.
+
+[ Slightly modify fs/xfs/xfs_linux.h to resolve merge conflicts ]
+
+Redefine XFS_IS_CORRUPT so that it reports corruptions only via
+xfs_corruption_report. Since these are on-disk contents (and not checks
+of internal state), we don't ever want to panic the kernel. This also
+amends the corruption report to recommend unmounting and running
+xfs_repair.
+
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_error.c | 2 +-
+ fs/xfs/xfs_linux.h | 6 ++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_error.c
++++ b/fs/xfs/xfs_error.c
+@@ -335,7 +335,7 @@ xfs_corruption_error(
+ int linenum,
+ xfs_failaddr_t failaddr)
+ {
+- if (level <= xfs_error_level)
++ if (buf && level <= xfs_error_level)
+ xfs_hex_dump(buf, bufsize);
+ xfs_error_report(tag, level, mp, filename, linenum, failaddr);
+ xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
+--- a/fs/xfs/xfs_linux.h
++++ b/fs/xfs/xfs_linux.h
+@@ -217,6 +217,12 @@ int xfs_rw_bdev(struct block_device *bde
+ #endif /* XFS_WARN */
+ #endif /* DEBUG */
+
++#define XFS_IS_CORRUPT(mp, expr) \
++ (unlikely(expr) ? xfs_corruption_error(#expr, XFS_ERRLEVEL_LOW, (mp), \
++ NULL, 0, __FILE__, __LINE__, \
++ __this_address), \
++ true : false)
++
+ #define STATIC static noinline
+
+ #ifdef CONFIG_XFS_RT
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:01 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:19 +0530
+Subject: xfs: set inode size after creating symlink
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-13-chandan.babu@oracle.com>
+
+From: Jeffrey Mitchell <jeffrey.mitchell@starlab.io>
+
+commit 8aa921a95335d0a8c8e2be35a44467e7c91ec3e4 upstream.
+
+When XFS creates a new symlink, it writes its size to disk but not to the
+VFS inode. This causes i_size_read() to return 0 for that symlink until
+it is re-read from disk, for example when the system is rebooted.
+
+I found this inconsistency while protecting directories with eCryptFS.
+The command "stat path/to/symlink/in/ecryptfs" will report "Size: 0" if
+the symlink was created after the last reboot on an XFS root.
+
+Call i_size_write() in xfs_symlink()
+
+Signed-off-by: Jeffrey Mitchell <jeffrey.mitchell@starlab.io>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_symlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/xfs/xfs_symlink.c
++++ b/fs/xfs/xfs_symlink.c
+@@ -314,6 +314,7 @@ xfs_symlink(
+ }
+ ASSERT(pathlen == 0);
+ }
++ i_size_write(VFS_I(ip), ip->i_d.di_size);
+
+ /*
+ * Create the directory entry for the symlink.
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:26:51 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:08 +0530
+Subject: xfs: show the proper user quota options
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-2-chandan.babu@oracle.com>
+
+From: Kaixu Xia <kaixuxia@tencent.com>
+
+commit 237d7887ae723af7d978e8b9a385fdff416f357b upstream.
+
+The quota option 'usrquota' should be shown if both the XFS_UQUOTA_ACCT
+and XFS_UQUOTA_ENFD flags are set. The option 'uqnoenforce' should be
+shown when only the XFS_UQUOTA_ACCT flag is set. The current code logic
+seems wrong, Fix it and show proper options.
+
+Signed-off-by: Kaixu Xia <kaixuxia@tencent.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_super.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -490,10 +490,12 @@ xfs_showargs(
+ seq_printf(m, ",swidth=%d",
+ (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
+
+- if (mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD))
+- seq_puts(m, ",usrquota");
+- else if (mp->m_qflags & XFS_UQUOTA_ACCT)
+- seq_puts(m, ",uqnoenforce");
++ if (mp->m_qflags & XFS_UQUOTA_ACCT) {
++ if (mp->m_qflags & XFS_UQUOTA_ENFD)
++ seq_puts(m, ",usrquota");
++ else
++ seq_puts(m, ",uqnoenforce");
++ }
+
+ if (mp->m_qflags & XFS_PQUOTA_ACCT) {
+ if (mp->m_qflags & XFS_PQUOTA_ENFD)
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:29:35 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:21 +0530
+Subject: xfs: shut down the filesystem if we screw up quota reservation
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-15-chandan.babu@oracle.com>
+
+From: "Darrick J. Wong" <djwong@kernel.org>
+
+commit 2a4bdfa8558ca2904dc17b83497dc82aa7fc05e9 upstream.
+
+If we ever screw up the quota reservations enough to trip the
+assertions, something's wrong with the quota code. Shut down the
+filesystem when this happens, because this is corruption.
+
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_trans_dquot.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/fs/xfs/xfs_trans_dquot.c
++++ b/fs/xfs/xfs_trans_dquot.c
+@@ -15,6 +15,7 @@
+ #include "xfs_trans_priv.h"
+ #include "xfs_quota.h"
+ #include "xfs_qm.h"
++#include "xfs_error.h"
+
+ STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *);
+
+@@ -700,9 +701,14 @@ xfs_trans_dqresv(
+ XFS_TRANS_DQ_RES_INOS,
+ ninos);
+ }
+- ASSERT(dqp->q_res_bcount >= be64_to_cpu(dqp->q_core.d_bcount));
+- ASSERT(dqp->q_res_rtbcount >= be64_to_cpu(dqp->q_core.d_rtbcount));
+- ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount));
++
++ if (XFS_IS_CORRUPT(mp,
++ dqp->q_res_bcount < be64_to_cpu(dqp->q_core.d_bcount)) ||
++ XFS_IS_CORRUPT(mp,
++ dqp->q_res_rtbcount < be64_to_cpu(dqp->q_core.d_rtbcount)) ||
++ XFS_IS_CORRUPT(mp,
++ dqp->q_res_icount < be64_to_cpu(dqp->q_core.d_icount)))
++ goto error_corrupt;
+
+ xfs_dqunlock(dqp);
+ return 0;
+@@ -712,6 +718,10 @@ error_return:
+ if (flags & XFS_QMOPT_ENOSPC)
+ return -ENOSPC;
+ return -EDQUOT;
++error_corrupt:
++ xfs_dqunlock(dqp);
++ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
++ return -EFSCORRUPTED;
+ }
+
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:38 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:16 +0530
+Subject: xfs: simplify a check in xfs_ioctl_setattr_check_cowextsize
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-10-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 5e28aafe708ba3e388f92a7148093319d3521c2f upstream.
+
+Only v5 file systems can have the reflink feature, and those will
+always use the large dinode format. Remove the extra check for the
+inode version.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_ioctl.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1510,8 +1510,7 @@ xfs_ioctl_setattr_check_cowextsize(
+ if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE))
+ return 0;
+
+- if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb) ||
+- ip->i_d.di_version != 3)
++ if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
+ return -EINVAL;
+
+ if (fa->fsx_cowextsize == 0)
--- /dev/null
+From stable-owner@vger.kernel.org Wed Apr 12 06:28:33 2023
+From: Chandan Babu R <chandan.babu@oracle.com>
+Date: Wed, 12 Apr 2023 09:56:15 +0530
+Subject: xfs: simplify di_flags2 inheritance in xfs_ialloc
+To: gregkh@linuxfoundation.org
+Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org, stable@vger.kernel.org, djwong@kernel.org, chandan.babu@oracle.com, amir73il@gmail.com, leah.rumancik@gmail.com
+Message-ID: <20230412042624.600511-9-chandan.babu@oracle.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit b3d1d37544d8c98be610df0ed66c884ff18748d5 upstream.
+
+di_flags2 is initialized to zero for v4 and earlier file systems. This
+means di_flags2 can only be non-zero for a v5 file systems, in which
+case both the parent and child inodes can store the field. Remove the
+extra di_version check, and also remove the rather pointless local
+di_flags2 variable while at it.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_inode.c | 13 +++----------
+ 1 file changed, 3 insertions(+), 10 deletions(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -902,20 +902,13 @@ xfs_ialloc(
+
+ ip->i_d.di_flags |= di_flags;
+ }
+- if (pip &&
+- (pip->i_d.di_flags2 & XFS_DIFLAG2_ANY) &&
+- pip->i_d.di_version == 3 &&
+- ip->i_d.di_version == 3) {
+- uint64_t di_flags2 = 0;
+-
++ if (pip && (pip->i_d.di_flags2 & XFS_DIFLAG2_ANY)) {
+ if (pip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) {
+- di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
++ ip->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
+ ip->i_d.di_cowextsize = pip->i_d.di_cowextsize;
+ }
+ if (pip->i_d.di_flags2 & XFS_DIFLAG2_DAX)
+- di_flags2 |= XFS_DIFLAG2_DAX;
+-
+- ip->i_d.di_flags2 |= di_flags2;
++ ip->i_d.di_flags2 |= XFS_DIFLAG2_DAX;
+ }
+ /* FALLTHROUGH */
+ case S_IFLNK: