FAILED: patch "[PATCH] xfs: reattach dquots after changing inode ids" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 2f528e4a8f89daa6d0cc64b044f6f94c018fe9ae
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026110407-plot-stainable-802b@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2f528e4a8f89daa6d0cc64b044f6f94c018fe9ae Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <[email protected]>
Date: Mon, 12 Oct 2026 08:21:22 -0700
Subject: [PATCH] xfs: reattach dquots after changing inode ids
LOLLM noticed that xrep_inode_ids can change the user, group, or project id of any given file. When this happens, we need to detach any existing incore dquot and attach the correct ones.
fs/xfs/scrub/inode_repair.c +132 -1
@@ -41,6 +41,8 @@#include "xfs_rtgroup.h" #include "xfs_rtrmap_btree.h" #include "xfs_rtrefcount_btree.h" +#include "xfs_dquot_item.h" +#include "xfs_dquot.h" #include "scrub/xfs_scrub.h" #include "scrub/scrub.h" #include "scrub/common.h"
@@ -1757,6 +1759,20 @@ xrep_inode_ids(trace_xrep_inode_ids (sc); +/* +* We changed one of the file IDs, so we must detach the dquots to +* prevent further changes from being accounted to them, and try to +* attach the dquot for the new id to absorb any other block usage +* changes. We can't do that right now because the existing dquots +* might be attached to the scrub transaction and we're in the middle +* of fixing the inode, so we'll switch the incore dquot pointers +* later. +* +* Schedule a quotacheck so the accounting discrepancies will get fixed +* eventually. We'll have to repeat this later when we do the actual +* switch. +*/ +if (!uid_valid (VFS_I (sc->ip)->i_uid)) {i_uid_write (VFS_I (sc->ip),0 ); dirty = true;
@@ -2066,6 +2082,113 @@ xrep_inode_unlinked(return 0 ; } +#ifdef CONFIG_XFS_QUOTA +static inline bool +xrep_inode_need_reset_dquots ( +struct xfs_scrub *sc) +{ +struct xfs_mount *mp = sc->mp; +struct xfs_inode *ip = sc->ip; + +if (!XFS_IS_QUOTA_ON (mp)) +return false; +if (xfs_is_quota_inode (&mp->m_sb,I_INO (ip))) +return false; +if (xfs_is_metadir_inode (ip)) +return false; + +if (XFS_IS_UQUOTA_ON (sc->mp) && + (!ip->i_udquot || ip->i_udquot->q_id !=i_uid_read (VFS_I (ip)))) +return true; +if (XFS_IS_GQUOTA_ON (sc->mp) && + (!ip->i_gdquot || ip->i_gdquot->q_id !=i_gid_read (VFS_I (ip)))) +return true; +if (XFS_IS_PQUOTA_ON (sc->mp) && + (!ip->i_pdquot || ip->i_pdquot->q_id != ip->i_projid)) +return true; + +return false; +} + +/* Switch dquot, return dqtype if we need quotacheck */ +static xfs_dqtype_t +xrep_inode_switch_dquot ( +struct xfs_scrub *sc, +xfs_dqtype_t type, +struct xfs_dquot **dqp) +{ +xfs_dqtype_t ret =0 ; +xfs_dqid_t id =xfs_qm_id_for_quotatype (sc->ip, type); + +if (*dqp !=NULL && (*dqp)->q_id != id) { +xfs_qm_dqrele (*dqp); + *dqp =NULL ; + } + +if (!*dqp) { +xfs_qm_dqget_inode (sc->ip, type, true, dqp); + ret = type; + } +return ret; +} + +static int +xrep_inode_reset_dquots ( +struct xfs_scrub *sc) +{ +xfs_dqtype_t need =0 ; +int error; + +/* +* If we changed the file IDs, then we need to drop the transaction so +* that we can detach the dquots and attach new ones. +* +* Commit the scrub transaction so that there are no dangling +* references to any dquots that might get detached, and retain the +* ILOCK, as required by the dqattach code. +* +* Note that dqattach can cycle the ILOCK when creating a new dquot, so +* this must be the very last thing that the repair function does. +*/ + error =xrep_trans_commit (sc); +if (error) +return error; + +if (XFS_IS_UQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_USER , + &sc->ip->i_udquot); +if (XFS_IS_GQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_GROUP , + &sc->ip->i_gdquot); +if (XFS_IS_PQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_PROJ , + &sc->ip->i_pdquot); + +xchk_iunlock (sc,XFS_ILOCK_EXCL ); + +/* +* Now that we've updated the dquots, force quotacheck once again. +* In theory we could be racing against a concurrent quotacheck. +* Note that we can't hold the ILOCK when allocating a transaction. +*/ + error =xchk_trans_alloc (sc,0 ); +if (error) +return error; + +if (need &XFS_DQTYPE_USER ) +xrep_force_quotacheck (sc,XFS_DQTYPE_USER ); +if (need &XFS_DQTYPE_GROUP ) +xrep_force_quotacheck (sc,XFS_DQTYPE_GROUP ); +if (need &XFS_DQTYPE_PROJ ) +xrep_force_quotacheck (sc,XFS_DQTYPE_PROJ ); + +return 0 ; +} +#else +# define xrep_inode_need_reset_dquots (sc) (false) +# define xrep_inode_reset_dquots (sc) (0) +#endif +/* Repair an inode's fields. */ int xrep_inode(
@@ -2120,5 +2243,13 @@ xrep_inode(if (error)return error; -return xrep_defer_finish (sc); + error =xrep_defer_finish (sc); +if (error) +return error; + +/* Must come last */ +if (xrep_inode_need_reset_dquots (sc)) +return xrep_inode_reset_dquots (sc); + +return 0 ; }
Sasha Levin
maintainerPATCH 1/1 xfs: reattach dquots after changing inode ids
From: "Darrick J. Wong" <[email protected]>
[ Upstream commit 2f528e4a8f89daa6d0cc64b044f6f94c018fe9ae ]
LOLLM noticed that xrep_inode_ids can change the user, group, or project id of any given file. When this happens, we need to detach any existing incore dquot and attach the correct ones.
--- fs/xfs/scrub/inode_repair.c | 132 +++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-)
fs/xfs/scrub/inode_repair.c +131 -1
@@ -38,6 +38,8 @@#include "xfs_log_priv.h" #include "xfs_health.h" #include "xfs_symlink_remote.h" +#include "xfs_dquot_item.h" +#include "xfs_dquot.h" #include "scrub/xfs_scrub.h" #include "scrub/scrub.h" #include "scrub/common.h"
@@ -1570,6 +1572,20 @@ xrep_inode_ids(trace_xrep_inode_ids (sc); +/* +* We changed one of the file IDs, so we must detach the dquots to +* prevent further changes from being accounted to them, and try to +* attach the dquot for the new id to absorb any other block usage +* changes. We can't do that right now because the existing dquots +* might be attached to the scrub transaction and we're in the middle +* of fixing the inode, so we'll switch the incore dquot pointers +* later. +* +* Schedule a quotacheck so the accounting discrepancies will get fixed +* eventually. We'll have to repeat this later when we do the actual +* switch. +*/ +if (!uid_valid (VFS_I (sc->ip)->i_uid)) {i_uid_write (VFS_I (sc->ip),0 ); dirty = true;
@@ -1876,6 +1892,112 @@ xrep_inode_unlinked(return 0 ; } +#ifdef CONFIG_XFS_QUOTA +static inline bool +xrep_inode_need_reset_dquots ( +struct xfs_scrub *sc) +{ +struct xfs_mount *mp = sc->mp; +struct xfs_inode *ip = sc->ip; + +if (!XFS_IS_QUOTA_ON (mp)) +return false; +if (xfs_is_quota_inode (&mp->m_sb,I_INO (ip))) +return false; + +if (XFS_IS_UQUOTA_ON (sc->mp) && + (!ip->i_udquot || ip->i_udquot->q_id !=i_uid_read (VFS_I (ip)))) +return true; +if (XFS_IS_GQUOTA_ON (sc->mp) && + (!ip->i_gdquot || ip->i_gdquot->q_id !=i_gid_read (VFS_I (ip)))) +return true; +if (XFS_IS_PQUOTA_ON (sc->mp) && + (!ip->i_pdquot || ip->i_pdquot->q_id != ip->i_projid)) +return true; + +return false; +} + +/* Switch dquot, return dqtype if we need quotacheck */ +static xfs_dqtype_t +xrep_inode_switch_dquot ( +struct xfs_scrub *sc, +xfs_dqtype_t type, +struct xfs_dquot **dqp) +{ +xfs_dqtype_t ret =0 ; +xfs_dqid_t id =xfs_qm_id_for_quotatype (sc->ip, type); + +if (*dqp !=NULL && (*dqp)->q_id != id) { +xfs_qm_dqrele (*dqp); + *dqp =NULL ; + } + +if (!*dqp) { +if (!xfs_qm_dqget_inode (sc->ip, type, true, dqp)) +xfs_dqunlock (*dqp); + ret = type; + } +return ret; +} + +static int +xrep_inode_reset_dquots ( +struct xfs_scrub *sc) +{ +xfs_dqtype_t need =0 ; +int error; + +/* +* If we changed the file IDs, then we need to drop the transaction so +* that we can detach the dquots and attach new ones. +* +* Commit the scrub transaction so that there are no dangling +* references to any dquots that might get detached, and retain the +* ILOCK, as required by the dqattach code. +* +* Note that dqattach can cycle the ILOCK when creating a new dquot, so +* this must be the very last thing that the repair function does. +*/ + error =xrep_trans_commit (sc); +if (error) +return error; + +if (XFS_IS_UQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_USER , + &sc->ip->i_udquot); +if (XFS_IS_GQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_GROUP , + &sc->ip->i_gdquot); +if (XFS_IS_PQUOTA_ON (sc->mp)) + need |=xrep_inode_switch_dquot (sc,XFS_DQTYPE_PROJ , + &sc->ip->i_pdquot); + +xchk_iunlock (sc,XFS_ILOCK_EXCL ); + +/* +* Now that we've updated the dquots, force quotacheck once again. +* In theory we could be racing against a concurrent quotacheck. +* Note that we can't hold the ILOCK when allocating a transaction. +*/ + error =xchk_trans_alloc (sc,0 ); +if (error) +return error; + +if (need &XFS_DQTYPE_USER ) +xrep_force_quotacheck (sc,XFS_DQTYPE_USER ); +if (need &XFS_DQTYPE_GROUP ) +xrep_force_quotacheck (sc,XFS_DQTYPE_GROUP ); +if (need &XFS_DQTYPE_PROJ ) +xrep_force_quotacheck (sc,XFS_DQTYPE_PROJ ); + +return 0 ; +} +#else +# define xrep_inode_need_reset_dquots (sc) (false) +# define xrep_inode_reset_dquots (sc) (0) +#endif +/* Repair an inode's fields. */ int xrep_inode(
@@ -1930,5 +2052,13 @@ xrep_inode(if (error)return error; -return xrep_defer_finish (sc); + error =xrep_defer_finish (sc); +if (error) +return error; + +/* Must come last */ +if (xrep_inode_need_reset_dquots (sc)) +return xrep_inode_reset_dquots (sc); + +return 0 ; }
Signature · 1 line
2.53.0