]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2023 09:53:53 +0000 (11:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2023 09:53:53 +0000 (11:53 +0200)
added patches:
coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch
watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch
xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch
xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch
xfs-don-t-reuse-busy-extents-on-extent-trim.patch
xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch
xfs-fix-up-non-directory-creation-in-sgid-directories.patch
xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch
xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch
xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch
xfs-remove-the-di_version-field-from-struct-icdinode.patch
xfs-remove-the-icdinode-di_uid-di_gid-members.patch
xfs-remove-the-kuid-kgid-conversion-wrappers.patch
xfs-report-corruption-only-as-a-regular-error.patch
xfs-set-inode-size-after-creating-symlink.patch
xfs-show-the-proper-user-quota-options.patch
xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch
xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch
xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch

20 files changed:
queue-5.4/coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch [new file with mode: 0644]
queue-5.4/xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch [new file with mode: 0644]
queue-5.4/xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch [new file with mode: 0644]
queue-5.4/xfs-don-t-reuse-busy-extents-on-extent-trim.patch [new file with mode: 0644]
queue-5.4/xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch [new file with mode: 0644]
queue-5.4/xfs-fix-up-non-directory-creation-in-sgid-directories.patch [new file with mode: 0644]
queue-5.4/xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch [new file with mode: 0644]
queue-5.4/xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch [new file with mode: 0644]
queue-5.4/xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch [new file with mode: 0644]
queue-5.4/xfs-remove-the-di_version-field-from-struct-icdinode.patch [new file with mode: 0644]
queue-5.4/xfs-remove-the-icdinode-di_uid-di_gid-members.patch [new file with mode: 0644]
queue-5.4/xfs-remove-the-kuid-kgid-conversion-wrappers.patch [new file with mode: 0644]
queue-5.4/xfs-report-corruption-only-as-a-regular-error.patch [new file with mode: 0644]
queue-5.4/xfs-set-inode-size-after-creating-symlink.patch [new file with mode: 0644]
queue-5.4/xfs-show-the-proper-user-quota-options.patch [new file with mode: 0644]
queue-5.4/xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch [new file with mode: 0644]
queue-5.4/xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch [new file with mode: 0644]
queue-5.4/xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch [new file with mode: 0644]

diff --git a/queue-5.4/coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch b/queue-5.4/coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch
new file mode 100644 (file)
index 0000000..cf9cc80
--- /dev/null
@@ -0,0 +1,33 @@
+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],
index 903c7ba2d6efd8a176ab71e4f466bade7640c1b9..b1213a206e9cdf0074a7633a404066c9fe5f7a3a 100644 (file)
@@ -71,3 +71,22 @@ ubi-fix-failure-attaching-when-vid_hdr-offset-equals-to-sub-page-size.patch
 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
diff --git a/queue-5.4/watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch b/queue-5.4/watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch
new file mode 100644 (file)
index 0000000..ca77376
--- /dev/null
@@ -0,0 +1,36 @@
+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,
diff --git a/queue-5.4/xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch b/queue-5.4/xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch
new file mode 100644 (file)
index 0000000..ba80213
--- /dev/null
@@ -0,0 +1,175 @@
+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
diff --git a/queue-5.4/xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch b/queue-5.4/xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch
new file mode 100644 (file)
index 0000000..feff22f
--- /dev/null
@@ -0,0 +1,90 @@
+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);
+ }
diff --git a/queue-5.4/xfs-don-t-reuse-busy-extents-on-extent-trim.patch b/queue-5.4/xfs-don-t-reuse-busy-extents-on-extent-trim.patch
new file mode 100644 (file)
index 0000000..55715d2
--- /dev/null
@@ -0,0 +1,98 @@
+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 */
diff --git a/queue-5.4/xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch b/queue-5.4/xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch
new file mode 100644 (file)
index 0000000..ec06b56
--- /dev/null
@@ -0,0 +1,97 @@
+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);
diff --git a/queue-5.4/xfs-fix-up-non-directory-creation-in-sgid-directories.patch b/queue-5.4/xfs-fix-up-non-directory-creation-in-sgid-directories.patch
new file mode 100644 (file)
index 0000000..77ee20d
--- /dev/null
@@ -0,0 +1,71 @@
+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);
+       }
+       /*
diff --git a/queue-5.4/xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch b/queue-5.4/xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch
new file mode 100644 (file)
index 0000000..7034c32
--- /dev/null
@@ -0,0 +1,160 @@
+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);
diff --git a/queue-5.4/xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch b/queue-5.4/xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch
new file mode 100644 (file)
index 0000000..13a9e94
--- /dev/null
@@ -0,0 +1,292 @@
+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);
+       }
diff --git a/queue-5.4/xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch b/queue-5.4/xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch
new file mode 100644 (file)
index 0000000..32d824d
--- /dev/null
@@ -0,0 +1,227 @@
+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);
diff --git a/queue-5.4/xfs-remove-the-di_version-field-from-struct-icdinode.patch b/queue-5.4/xfs-remove-the-di_version-field-from-struct-icdinode.patch
new file mode 100644 (file)
index 0000000..4de2c9c
--- /dev/null
@@ -0,0 +1,327 @@
+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)
diff --git a/queue-5.4/xfs-remove-the-icdinode-di_uid-di_gid-members.patch b/queue-5.4/xfs-remove-the-icdinode-di_uid-di_gid-members.patch
new file mode 100644 (file)
index 0000000..c3d0ece
--- /dev/null
@@ -0,0 +1,367 @@
+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)
diff --git a/queue-5.4/xfs-remove-the-kuid-kgid-conversion-wrappers.patch b/queue-5.4/xfs-remove-the-kuid-kgid-conversion-wrappers.patch
new file mode 100644 (file)
index 0000000..b3c57ee
--- /dev/null
@@ -0,0 +1,254 @@
+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);
diff --git a/queue-5.4/xfs-report-corruption-only-as-a-regular-error.patch b/queue-5.4/xfs-report-corruption-only-as-a-regular-error.patch
new file mode 100644 (file)
index 0000000..98f5588
--- /dev/null
@@ -0,0 +1,56 @@
+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
diff --git a/queue-5.4/xfs-set-inode-size-after-creating-symlink.patch b/queue-5.4/xfs-set-inode-size-after-creating-symlink.patch
new file mode 100644 (file)
index 0000000..9b7638b
--- /dev/null
@@ -0,0 +1,46 @@
+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.
diff --git a/queue-5.4/xfs-show-the-proper-user-quota-options.patch b/queue-5.4/xfs-show-the-proper-user-quota-options.patch
new file mode 100644 (file)
index 0000000..c83e3d1
--- /dev/null
@@ -0,0 +1,48 @@
+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)
diff --git a/queue-5.4/xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch b/queue-5.4/xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch
new file mode 100644 (file)
index 0000000..bfb5b32
--- /dev/null
@@ -0,0 +1,68 @@
+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;
+ }
diff --git a/queue-5.4/xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch b/queue-5.4/xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch
new file mode 100644 (file)
index 0000000..002aab2
--- /dev/null
@@ -0,0 +1,40 @@
+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)
diff --git a/queue-5.4/xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch b/queue-5.4/xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch
new file mode 100644 (file)
index 0000000..9116ac3
--- /dev/null
@@ -0,0 +1,56 @@
+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: