From: Greg Kroah-Hartman Date: Tue, 18 Apr 2023 09:53:53 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.14.313~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2db03bacd662caaec0ef53313d8bfb2bb2573d6f;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches 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 --- 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 index 00000000000..cf9cc803f0d --- /dev/null +++ b/queue-5.4/coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch @@ -0,0 +1,33 @@ +From bf84937e882009075f57fd213836256fc65d96bc Mon Sep 17 00:00:00 2001 +From: Steve Clevenger +Date: Mon, 27 Feb 2023 16:54:32 -0700 +Subject: coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug + +From: Steve Clevenger + +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 +Reviewed-by: James Clark +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/4a4ee61ce8ef402615a4528b21a051de3444fb7b.1677540079.git.scclevenger@os.amperecomputing.com +Signed-off-by: Greg Kroah-Hartman +--- + 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], diff --git a/queue-5.4/series b/queue-5.4/series index 903c7ba2d6e..b1213a206e9 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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 index 00000000000..ca773763ac4 --- /dev/null +++ b/queue-5.4/watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch @@ -0,0 +1,36 @@ +From 000987a38b53c172f435142a4026dd71378ca464 Mon Sep 17 00:00:00 2001 +From: George Cherian +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 + +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 +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20230209021117.1512097-1-george.cherian@marvell.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Tyler Hicks (Microsoft) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ba8021368d0 --- /dev/null +++ b/queue-5.4/xfs-add-a-new-xfs_sb_version_has_v3inode-helper.patch @@ -0,0 +1,175 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:19 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Brian Foster +Reviewed-by: Chandan Rajendra +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..feff22f838a --- /dev/null +++ b/queue-5.4/xfs-consider-shutdown-in-bmapbt-cursor-delete-assert.patch @@ -0,0 +1,90 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:22 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..55715d2b894 --- /dev/null +++ b/queue-5.4/xfs-don-t-reuse-busy-extents-on-extent-trim.patch @@ -0,0 +1,98 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:32 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Reviewed-by: Chandan Babu R +Reviewed-by: Christoph Hellwig +Signed-off-by: Amir Goldstein +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ec06b560e1c --- /dev/null +++ b/queue-5.4/xfs-ensure-that-the-inode-uid-gid-match-values-match-the-icdinode-ones.patch @@ -0,0 +1,97 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:27:52 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..77ee20d62c8 --- /dev/null +++ b/queue-5.4/xfs-fix-up-non-directory-creation-in-sgid-directories.patch @@ -0,0 +1,71 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:03 2023 +From: Chandan Babu R +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 + +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 +Signed-off-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Amir Goldstein +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7034c32c795 --- /dev/null +++ b/queue-5.4/xfs-force-log-and-push-ail-to-clear-pinned-inodes-when-aborting-mount.patch @@ -0,0 +1,160 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:46 2023 +From: Chandan Babu R +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" + +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Dave Chinner +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..13a9e94d96a --- /dev/null +++ b/queue-5.4/xfs-merge-the-projid-fields-in-struct-xfs_icdinode.patch @@ -0,0 +1,292 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:27:08 2023 +From: Chandan Babu R +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 + +commit de7a866fd41b227b0aa6e9cbeb0dae221c12f542 upstream. + +There is no point in splitting the fields like this in an purely +in-memory structure. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..32d824daeb7 --- /dev/null +++ b/queue-5.4/xfs-only-check-the-superblock-version-for-dinode-size-calculation.patch @@ -0,0 +1,227 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:32 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Brian Foster +Reviewed-by: Chandan Rajendra +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4de2c9ce4e6 --- /dev/null +++ b/queue-5.4/xfs-remove-the-di_version-field-from-struct-icdinode.patch @@ -0,0 +1,327 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:46 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Brian Foster +Reviewed-by: Chandan Rajendra +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c3d0ece968d --- /dev/null +++ b/queue-5.4/xfs-remove-the-icdinode-di_uid-di_gid-members.patch @@ -0,0 +1,367 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:27:59 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b3c57ee28d6 --- /dev/null +++ b/queue-5.4/xfs-remove-the-kuid-kgid-conversion-wrappers.patch @@ -0,0 +1,254 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:09 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..98f5588997f --- /dev/null +++ b/queue-5.4/xfs-report-corruption-only-as-a-regular-error.patch @@ -0,0 +1,56 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:08 2023 +From: Chandan Babu R +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" + +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9b7638bdeac --- /dev/null +++ b/queue-5.4/xfs-set-inode-size-after-creating-symlink.patch @@ -0,0 +1,46 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:01 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Reviewed-by: Brian Foster +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c83e3d1ffd2 --- /dev/null +++ b/queue-5.4/xfs-show-the-proper-user-quota-options.patch @@ -0,0 +1,48 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:26:51 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..bfb5b321c2c --- /dev/null +++ b/queue-5.4/xfs-shut-down-the-filesystem-if-we-screw-up-quota-reservation.patch @@ -0,0 +1,68 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:29:35 2023 +From: Chandan Babu R +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" + +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Brian Foster +Signed-off-by: Amir Goldstein +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..002aab2037f --- /dev/null +++ b/queue-5.4/xfs-simplify-a-check-in-xfs_ioctl_setattr_check_cowextsize.patch @@ -0,0 +1,40 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:38 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Brian Foster +Reviewed-by: Chandan Rajendra +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..9116ac38965 --- /dev/null +++ b/queue-5.4/xfs-simplify-di_flags2-inheritance-in-xfs_ialloc.patch @@ -0,0 +1,56 @@ +From stable-owner@vger.kernel.org Wed Apr 12 06:28:33 2023 +From: Chandan Babu R +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 + +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 +Reviewed-by: Brian Foster +Reviewed-by: Chandan Rajendra +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Chandan Babu R +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + 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: