Commit 259ba1d3 authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: try to attach dquots to files before repairing them

Inode resource usage is tracked in the quota metadata.  Repairing a file
might change the resources used by that file, which means that we need
to attach dquots to the file that we're examining before accessing
anything in the file protected by the ILOCK.

However, there's a twist: a dquot cache miss requires the dquot to be
read in from the quota file, during which we drop the ILOCK on the file
being examined.  This means that we *must* try to attach the dquots
before taking the ILOCK.

Therefore, dquots must be attached to files in the scrub setup function.
If doing so yields corruption errors (or unknown dquot errors), we
instead clear the quotachecked status, which will cause a quotacheck on
next mount.  A future series will make this trigger live quotacheck.

While we're here, change the xrep_ino_dqattach function to use the
unlocked dqattach functions so that we avoid cycling the ILOCK if the
inode already has dquots attached.  This makes the naming and locking
requirements consistent with the rest of the filesystem.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent d5aa62de
......@@ -78,6 +78,10 @@ xchk_setup_inode_bmap(
if (error)
goto out;
error = xchk_ino_dqattach(sc);
if (error)
goto out;
xchk_ilock(sc, XFS_ILOCK_EXCL);
out:
/* scrub teardown will unlock and release the inode */
......
......@@ -819,6 +819,26 @@ xchk_iget_agi(
return 0;
}
#ifdef CONFIG_XFS_QUOTA
/*
* Try to attach dquots to this inode if we think we might want to repair it.
* Callers must not hold any ILOCKs. If the dquots are broken and cannot be
* attached, a quotacheck will be scheduled.
*/
int
xchk_ino_dqattach(
struct xfs_scrub *sc)
{
ASSERT(sc->tp != NULL);
ASSERT(sc->ip != NULL);
if (!xchk_could_repair(sc))
return 0;
return xrep_ino_dqattach(sc);
}
#endif
/* Install an inode that we opened by handle for scrubbing. */
int
xchk_install_handle_inode(
......@@ -1030,6 +1050,11 @@ xchk_setup_inode_contents(
error = xchk_trans_alloc(sc, resblks);
if (error)
goto out;
error = xchk_ino_dqattach(sc);
if (error)
goto out;
xchk_ilock(sc, XFS_ILOCK_EXCL);
out:
/* scrub teardown will unlock and release the inode for us */
......
......@@ -103,9 +103,15 @@ xchk_setup_rtsummary(struct xfs_scrub *sc)
}
#endif
#ifdef CONFIG_XFS_QUOTA
int xchk_ino_dqattach(struct xfs_scrub *sc);
int xchk_setup_quota(struct xfs_scrub *sc);
#else
static inline int
xchk_ino_dqattach(struct xfs_scrub *sc)
{
return 0;
}
static inline int
xchk_setup_quota(struct xfs_scrub *sc)
{
return -ENOENT;
......
......@@ -39,6 +39,10 @@ xchk_prepare_iscrub(
if (error)
return error;
error = xchk_ino_dqattach(sc);
if (error)
return error;
xchk_ilock(sc, XFS_ILOCK_EXCL);
return 0;
}
......
......@@ -700,10 +700,10 @@ xrep_force_quotacheck(
*
* This function ensures that the appropriate dquots are attached to an inode.
* We cannot allow the dquot code to allocate an on-disk dquot block here
* because we're already in transaction context with the inode locked. The
* on-disk dquot should already exist anyway. If the quota code signals
* corruption or missing quota information, schedule quotacheck, which will
* repair corruptions in the quota metadata.
* because we're already in transaction context. The on-disk dquot should
* already exist anyway. If the quota code signals corruption or missing quota
* information, schedule quotacheck, which will repair corruptions in the quota
* metadata.
*/
int
xrep_ino_dqattach(
......@@ -711,7 +711,10 @@ xrep_ino_dqattach(
{
int error;
error = xfs_qm_dqattach_locked(sc->ip, false);
ASSERT(sc->tp != NULL);
ASSERT(sc->ip != NULL);
error = xfs_qm_dqattach(sc->ip);
switch (error) {
case -EFSBADCRC:
case -EFSCORRUPTED:
......
......@@ -32,6 +32,10 @@ xchk_setup_rtbitmap(
if (error)
return error;
error = xchk_ino_dqattach(sc);
if (error)
return error;
xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
return 0;
}
......
......@@ -63,6 +63,10 @@ xchk_setup_rtsummary(
if (error)
return error;
error = xchk_ino_dqattach(sc);
if (error)
return error;
/*
* Locking order requires us to take the rtbitmap first. We must be
* careful to unlock it ourselves when we are done with the rtbitmap
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment