fs/xfs/scrub/quotacheck.c

Source file repositories/reference/linux-study-clean/fs/xfs/scrub/quotacheck.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/quotacheck.c
Extension
.c
Size
22500 bytes
Lines
861
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct xqcheck_dqtrx {
	xfs_dqtype_t		q_type;
	xfs_dqid_t		q_id;

	int64_t			icount_delta;

	int64_t			bcount_delta;
	int64_t			delbcnt_delta;

	int64_t			rtbcount_delta;
	int64_t			delrtb_delta;
};

#define XQCHECK_MAX_NR_DQTRXS	(XFS_QM_TRANS_DQTYPES * XFS_QM_TRANS_MAXDQS)

/*
 * Track the quota deltas for all dquots attached to a transaction if the
 * quota deltas are being applied to an inode that we already scanned.
 */
struct xqcheck_dqacct {
	struct rhash_head	hash;
	uintptr_t		tx_id;
	struct xqcheck_dqtrx	dqtrx[XQCHECK_MAX_NR_DQTRXS];
	unsigned int		refcount;
};

/* Free a shadow dquot accounting structure. */
static void
xqcheck_dqacct_free(
	void			*ptr,
	void			*arg)
{
	struct xqcheck_dqacct	*dqa = ptr;

	kfree(dqa);
}

/* Set us up to scrub quota counters. */
int
xchk_setup_quotacheck(
	struct xfs_scrub	*sc)
{
	if (!XFS_IS_QUOTA_ON(sc->mp))
		return -ENOENT;

	xchk_fsgates_enable(sc, XCHK_FSGATES_QUOTA);

	sc->buf = kzalloc_obj(struct xqcheck, XCHK_GFP_FLAGS);
	if (!sc->buf)
		return -ENOMEM;

	return xchk_setup_fs(sc);
}

/*
 * Part 1: Collecting dquot resource usage counts.  For each xfs_dquot attached
 * to each inode, we create a shadow dquot, and compute the inode count and add
 * the data/rt block usage from what we see.
 *
 * To avoid false corruption reports in part 2, any failure in this part must
 * set the INCOMPLETE flag even when a negative errno is returned.  This care
 * must be taken with certain errno values (i.e. EFSBADCRC, EFSCORRUPTED,
 * ECANCELED) that are absorbed into a scrub state flag update by
 * xchk_*_process_error.  Scrub and repair share the same incore data
 * structures, so the INCOMPLETE flag is critical to prevent a repair based on
 * insufficient information.
 *
 * Because we are scanning a live filesystem, it's possible that another thread
 * will try to update the quota counters for an inode that we've already
 * scanned.  This will cause our counts to be incorrect.  Therefore, we hook
 * the live transaction code in two places: (1) when the callers update the
 * per-transaction dqtrx structure to log quota counter updates; and (2) when
 * transaction commit actually logs those updates to the incore dquot.  By
 * shadowing transaction updates in this manner, live quotacheck can ensure
 * by locking the dquot and the shadow structure that its own copies are not
 * out of date.  Because the hook code runs in a different process context from
 * the scrub code and the scrub state flags are not accessed atomically,
 * failures in the hook code must abort the iscan and the scrubber must notice
 * the aborted scan and set the incomplete flag.
 *
 * Note that we use srcu notifier hooks to minimize the overhead when live
 * quotacheck is /not/ running.
 */

/* Update an incore dquot counter information from a live update. */
static int
xqcheck_update_incore_counts(
	struct xqcheck		*xqc,
	struct xfarray		*counts,
	xfs_dqid_t		id,

Annotation

Implementation Notes