From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Create a helper function to iterate all the dquots of a given type in the system, and refactor the dquot scrub to use it. This will get more use in the quota repair code. Note that the new function differs from xfs_qm_dqiterate in that _dqiterate iterates dquot buffers, not the in-core structures themselves. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- fs/xfs/scrub/quota.c | 46 +++++++++++++++++++++------------------------- fs/xfs/xfs_dquot.c | 41 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_dquot.h | 5 +++++ 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c index 6ba465e..363e318 100644 --- a/fs/xfs/scrub/quota.c +++ b/fs/xfs/scrub/quota.c @@ -77,14 +77,21 @@ xfs_scrub_setup_quota( /* Quotas. */ +struct xfs_scrub_quota_info { + struct xfs_scrub_context *sc; + xfs_dqid_t last_id; +}; + /* Scrub the fields in an individual quota item. */ -STATIC void +STATIC int xfs_scrub_quota_item( - struct xfs_scrub_context *sc, - uint dqtype, struct xfs_dquot *dq, - xfs_dqid_t id) + uint dqtype, + xfs_dqid_t id, + void *priv) { + struct xfs_scrub_quota_info *sqi = priv; + struct xfs_scrub_context *sc = sqi->sc; struct xfs_mount *mp = sc->mp; struct xfs_disk_dquot *d = &dq->q_core; struct xfs_quotainfo *qi = mp->m_quotainfo; @@ -100,6 +107,7 @@ xfs_scrub_quota_item( unsigned long long rcount; xfs_ino_t fs_icount; + sqi->last_id = id; offset = id / qi->qi_dqperchunk; /* @@ -183,6 +191,8 @@ xfs_scrub_quota_item( xfs_scrub_fblock_set_warning(sc, XFS_DATA_FORK, offset); if (id != 0 && rhard != 0 && rcount > rhard) xfs_scrub_fblock_set_warning(sc, XFS_DATA_FORK, offset); + + return 0; } /* Scrub all of a quota type's items. */ @@ -191,13 +201,12 @@ xfs_scrub_quota( struct xfs_scrub_context *sc) { struct xfs_bmbt_irec irec = { 0 }; + struct xfs_scrub_quota_info sqi; struct xfs_mount *mp = sc->mp; struct xfs_inode *ip; struct xfs_quotainfo *qi = mp->m_quotainfo; - struct xfs_dquot *dq; xfs_fileoff_t max_dqid_off; xfs_fileoff_t off = 0; - xfs_dqid_t id = 0; uint dqtype; int nimaps; int error = 0; @@ -264,25 +273,12 @@ xfs_scrub_quota( goto out; /* Check all the quota items. */ - while (id < ((xfs_dqid_t)-1ULL)) { - if (xfs_scrub_should_terminate(sc, &error)) - break; - - error = xfs_qm_dqget(mp, NULL, id, dqtype, XFS_QMOPT_DQNEXT, - &dq); - if (error == -ENOENT) - break; - if (!xfs_scrub_fblock_process_error(sc, XFS_DATA_FORK, - id * qi->qi_dqperchunk, &error)) - break; - - xfs_scrub_quota_item(sc, dqtype, dq, id); - - id = be32_to_cpu(dq->q_core.d_id) + 1; - xfs_qm_dqput(dq); - if (!id) - break; - } + sqi.sc = sc; + sqi.last_id = 0; + error = xfs_dquot_iterate(mp, dqtype, 0, xfs_scrub_quota_item, &sqi); + if (!xfs_scrub_fblock_process_error(sc, XFS_DATA_FORK, + sqi.last_id * qi->qi_dqperchunk, &error)) + goto out; out: /* We set sc->ip earlier, so make sure we clear it now. */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index ed2e37c..ec00402 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -1127,3 +1127,44 @@ xfs_qm_exit(void) kmem_zone_destroy(xfs_qm_dqtrxzone); kmem_zone_destroy(xfs_qm_dqzone); } + +/* + * Iterate every dquot of a particular type. The caller must ensure that the + * particular quota type is active. iter_fn can return negative error codes, + * or XFS_BTREE_QUERY_RANGE_ABORT to indicate that it wants to stop iterating. + * + * Note that xfs_qm_dqiterate iterates all the dquot bufs, not the dquots + * themselves. + */ +int +xfs_dquot_iterate( + struct xfs_mount *mp, + uint dqtype, + uint iter_flags, + xfs_dquot_iterate_fn iter_fn, + void *priv) +{ + struct xfs_dquot *dq; + xfs_dqid_t id = 0; + int error; + + while (id < ((xfs_dqid_t)-1ULL)) { + error = xfs_qm_dqget(mp, NULL, id, dqtype, + XFS_QMOPT_DQNEXT | iter_flags, &dq); + if (error == -ENOENT) { + error = 0; + break; + } + if (error) + break; + + id = be32_to_cpu(dq->q_core.d_id); + error = iter_fn(dq, dqtype, id, priv); + xfs_qm_dqput(dq); + id++; + if (error || id == 0) + break; + } + + return error; +} diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h index 2f536f3..db0511e 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h @@ -185,4 +185,9 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) return dqp; } +typedef int (*xfs_dquot_iterate_fn)(struct xfs_dquot *dq, uint dqtype, + xfs_dqid_t id, void *priv); +int xfs_dquot_iterate(struct xfs_mount *mp, uint dqtype, uint iter_flags, + xfs_dquot_iterate_fn iter_fn, void *priv); + #endif /* __XFS_DQUOT_H__ */ -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html