fs/xfs/scrub/dqiterate.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/dqiterate.c
Extension
.c
Size
5853 bytes
Lines
212
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

if (fileoff > XFS_DQ_ID_MAX / qi->qi_dqperchunk) {
			/* The hole goes beyond the max dquot id, we're done */
			*next_ondisk_id = -1ULL;
			return 0;
		}

		error = xfs_bmapi_read(cursor->quota_ip, fileoff,
				XFS_MAX_FILEOFF - fileoff, &cursor->bmap,
				&nmaps, 0);
		if (error)
			return error;
		if (!nmaps) {
			/* Must have reached the end of the mappings. */
			*next_ondisk_id = -1ULL;
			return 0;
		}
		if (cursor->bmap.br_startoff > fileoff) {
			ASSERT(cursor->bmap.br_startoff == fileoff);
			return -EFSCORRUPTED;
		}
	} while (!xfs_bmap_is_real_extent(&cursor->bmap));

	next_id = cursor->bmap.br_startoff * qi->qi_dqperchunk;
	if (next_id > XFS_DQ_ID_MAX) {
		/* The hole goes beyond the max dquot id, we're done */
		*next_ondisk_id = -1ULL;
		return 0;
	}

	/* Propose jumping forward to the dquot in the next allocated block. */
	*next_ondisk_id = next_id;
	cursor->if_seq = ifp->if_seq;
	trace_xchk_dquot_iter_advance_bmap(cursor, *next_ondisk_id);
	return 0;
}

/*
 * Find the id of the next highest incore dquot.  Normally this will correspond
 * exactly with the quota file block mappings, but repair might have erased a
 * mapping because it was crosslinked; in that case, we need to re-allocate the
 * space so that we can reset q_blkno.
 */
STATIC void
xchk_dquot_iter_advance_incore(
	struct xchk_dqiter	*cursor,
	uint64_t		*next_incore_id)
{
	struct xfs_quotainfo	*qi = cursor->sc->mp->m_quotainfo;
	struct radix_tree_root	*tree = xfs_dquot_tree(qi, cursor->dqtype);
	struct xfs_dquot	*dq;
	unsigned int		nr_found;

	*next_incore_id = -1ULL;

	mutex_lock(&qi->qi_tree_lock);
	nr_found = radix_tree_gang_lookup(tree, (void **)&dq, cursor->id, 1);
	if (nr_found)
		*next_incore_id = dq->q_id;
	mutex_unlock(&qi->qi_tree_lock);

	trace_xchk_dquot_iter_advance_incore(cursor, *next_incore_id);
}

/*
 * Walk all incore dquots of this filesystem.  Caller must set *@cursorp to
 * zero before the first call, and must not hold the quota file ILOCK.
 * Returns 1 and a valid *@dqpp; 0 and *@dqpp == NULL when there are no more
 * dquots to iterate; or a negative errno.
 */
int
xchk_dquot_iter(
	struct xchk_dqiter	*cursor,
	struct xfs_dquot	**dqpp)
{
	struct xfs_mount	*mp = cursor->sc->mp;
	struct xfs_dquot	*dq = NULL;
	uint64_t		next_ondisk, next_incore = -1ULL;
	unsigned int		lock_mode;
	int			error = 0;

	if (cursor->id > XFS_DQ_ID_MAX)
		return 0;
	next_ondisk = cursor->id;

	/* Revalidate and/or advance the cursor. */
	lock_mode = xfs_ilock_data_map_shared(cursor->quota_ip);
	error = xchk_dquot_iter_revalidate_bmap(cursor);
	if (!error && !xfs_bmap_is_real_extent(&cursor->bmap))
		error = xchk_dquot_iter_advance_bmap(cursor, &next_ondisk);
	xfs_iunlock(cursor->quota_ip, lock_mode);

Annotation

Implementation Notes