/* * Ensure that the cached data fork mapping for the dqiter cursor is fresh and * covers the dquot pointed to by the scan cursor.
*/ STATICint
xchk_dquot_iter_revalidate_bmap( struct xchk_dqiter *cursor)
{ struct xfs_quotainfo *qi = cursor->sc->mp->m_quotainfo; struct xfs_ifork *ifp = xfs_ifork_ptr(cursor->quota_ip,
XFS_DATA_FORK);
xfs_fileoff_t fileoff;
xfs_dqid_t this_id = cursor->id; int nmaps = 1; int error;
fileoff = this_id / qi->qi_dqperchunk;
/* * If we have a mapping for cursor->id and it's still fresh, there's * no need to reread the bmbt.
*/ if (cursor->bmap.br_startoff != NULLFILEOFF &&
cursor->if_seq == ifp->if_seq &&
cursor->bmap.br_startoff + cursor->bmap.br_blockcount > fileoff) return 0;
/* Look up the data fork mapping for the dquot id of interest. */
error = xfs_bmapi_read(cursor->quota_ip, fileoff,
XFS_MAX_FILEOFF - fileoff, &cursor->bmap, &nmaps, 0); if (error) return error; if (!nmaps) {
ASSERT(nmaps > 0); return -EFSCORRUPTED;
} if (cursor->bmap.br_startoff > fileoff) {
ASSERT(cursor->bmap.br_startoff == fileoff); return -EFSCORRUPTED;
}
/* Advance the dqiter cursor to the next non-sparse region of the quota file. */ STATICint
xchk_dquot_iter_advance_bmap( struct xchk_dqiter *cursor,
uint64_t *next_ondisk_id)
{ struct xfs_quotainfo *qi = cursor->sc->mp->m_quotainfo; struct xfs_ifork *ifp = xfs_ifork_ptr(cursor->quota_ip,
XFS_DATA_FORK);
xfs_fileoff_t fileoff;
uint64_t next_id; int nmaps = 1; int error;
/* Find the dquot id for the next non-hole mapping. */ do {
fileoff = cursor->bmap.br_startoff + cursor->bmap.br_blockcount; 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.
*/ STATICvoid
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; unsignedint nr_found;
/* * 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; unsignedint 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); if (error) return error;
if (next_ondisk > cursor->id)
xchk_dquot_iter_advance_incore(cursor, &next_incore);
/* Pick the next dquot in the sequence and return it. */
cursor->id = min(next_ondisk, next_incore); if (cursor->id > XFS_DQ_ID_MAX) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.