Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e85bc6c authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: add helpers to attach quotas to inodes



Add a helper routine to attach quota information to inodes that are
about to undergo repair.  If that fails, we need to schedule a
quotacheck for the next mount but allow the corrupted metadata repair to
continue.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 04a2b7b2
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "xfs_extent_busy.h"
#include "xfs_ag_resv.h"
#include "xfs_trans_space.h"
#include "xfs_quota.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -1026,3 +1027,63 @@ xfs_repair_find_ag_btree_roots(

	return error;
}

/* Force a quotacheck the next time we mount. */
void
xfs_repair_force_quotacheck(
	struct xfs_scrub_context	*sc,
	uint				dqtype)
{
	uint				flag;

	flag = xfs_quota_chkd_flag(dqtype);
	if (!(flag & sc->mp->m_qflags))
		return;

	sc->mp->m_qflags &= ~flag;
	spin_lock(&sc->mp->m_sb_lock);
	sc->mp->m_sb.sb_qflags &= ~flag;
	spin_unlock(&sc->mp->m_sb_lock);
	xfs_log_sb(sc->tp);
}

/*
 * Attach dquots to this inode, or schedule quotacheck to fix them.
 *
 * 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.
 */
int
xfs_repair_ino_dqattach(
	struct xfs_scrub_context	*sc)
{
	int				error;

	error = xfs_qm_dqattach_locked(sc->ip, false);
	switch (error) {
	case -EFSBADCRC:
	case -EFSCORRUPTED:
	case -ENOENT:
		xfs_err_ratelimited(sc->mp,
"inode %llu repair encountered quota error %d, quotacheck forced.",
				(unsigned long long)sc->ip->i_ino, error);
		if (XFS_IS_UQUOTA_ON(sc->mp) && !sc->ip->i_udquot)
			xfs_repair_force_quotacheck(sc, XFS_DQ_USER);
		if (XFS_IS_GQUOTA_ON(sc->mp) && !sc->ip->i_gdquot)
			xfs_repair_force_quotacheck(sc, XFS_DQ_GROUP);
		if (XFS_IS_PQUOTA_ON(sc->mp) && !sc->ip->i_pdquot)
			xfs_repair_force_quotacheck(sc, XFS_DQ_PROJ);
		/* fall through */
	case -ESRCH:
		error = 0;
		break;
	default:
		break;
	}

	return error;
}
+2 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ int xfs_repair_find_ag_btree_roots(struct xfs_scrub_context *sc,
		struct xfs_buf *agf_bp,
		struct xfs_repair_find_ag_btree *btree_info,
		struct xfs_buf *agfl_bp);
void xfs_repair_force_quotacheck(struct xfs_scrub_context *sc, uint dqtype);
int xfs_repair_ino_dqattach(struct xfs_scrub_context *sc);

/* Metadata repairers */

+16 −0
Original line number Diff line number Diff line
@@ -48,6 +48,22 @@ struct xfs_trans;
	 (XFS_IS_PQUOTA_ON(mp) && \
		(mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0))

static inline uint
xfs_quota_chkd_flag(
	uint		dqtype)
{
	switch (dqtype) {
	case XFS_DQ_USER:
		return XFS_UQUOTA_CHKD;
	case XFS_DQ_GROUP:
		return XFS_GQUOTA_CHKD;
	case XFS_DQ_PROJ:
		return XFS_PQUOTA_CHKD;
	default:
		return 0;
	}
}

/*
 * The structure kept inside the xfs_trans_t keep track of dquot changes
 * within a transaction and apply them later.