diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-01-16 10:12:15 -0800 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-04-15 17:02:48 -0700 |
commit | e5684884987e79af29b31c670ea693461abeb1d6 (patch) | |
tree | b8b81e154c379ba513a9a56acea3ebb05cd93607 /fs/xfs/xfs_dquot.c | |
parent | be8ac34e89c0cb3c9a5959dd6f8b393d22cfac73 (diff) |
xfs: implement live quotacheck as part of quota repairrepair-part-two_2019-04-15
Use the fs freezing mechanism we developed for the rmapbt repair to
freeze the fs, this time to scan the fs for a live quotacheck. We add a
new dqget variant to use the existing scrub transaction to allocate an
on-disk dquot block if it is missing.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_dquot.c')
-rw-r--r-- | fs/xfs/xfs_dquot.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 14e2b732213e..978ce0c2e0aa 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -517,6 +517,7 @@ xfs_dquot_from_disk( static int xfs_qm_dqread_alloc( struct xfs_mount *mp, + struct xfs_trans **tpp, struct xfs_dquot *dqp, struct xfs_buf **bpp) { @@ -524,6 +525,18 @@ xfs_qm_dqread_alloc( struct xfs_buf *bp; int error; + /* + * The caller passed in a transaction which we don't control, so + * release the hold before passing back the buffer. + */ + if (tpp) { + error = xfs_dquot_disk_alloc(tpp, dqp, &bp); + if (error) + return error; + xfs_trans_bhold_release(*tpp, bp); + return 0; + } + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc, XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp); if (error) @@ -559,6 +572,7 @@ err: static int xfs_qm_dqread( struct xfs_mount *mp, + struct xfs_trans **tpp, xfs_dqid_t id, uint type, bool can_alloc, @@ -574,7 +588,7 @@ xfs_qm_dqread( /* Try to read the buffer, allocating if necessary. */ error = xfs_dquot_disk_read(mp, dqp, &bp); if (error == -ENOENT && can_alloc) - error = xfs_qm_dqread_alloc(mp, dqp, &bp); + error = xfs_qm_dqread_alloc(mp, tpp, dqp, &bp); if (error) goto err; @@ -758,9 +772,10 @@ xfs_qm_dqget_checks( * Given the file system, id, and type (UDQUOT/GDQUOT), return a a locked * dquot, doing an allocation (if requested) as needed. */ -int -xfs_qm_dqget( +static int +__xfs_qm_dqget( struct xfs_mount *mp, + struct xfs_trans **tpp, xfs_dqid_t id, uint type, bool can_alloc, @@ -782,7 +797,7 @@ restart: return 0; } - error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp); + error = xfs_qm_dqread(mp, NULL, id, type, can_alloc, &dqp); if (error) return error; @@ -821,7 +836,39 @@ xfs_qm_dqget_uncached( if (error) return error; - return xfs_qm_dqread(mp, id, type, 0, dqpp); + return xfs_qm_dqread(mp, NULL, id, type, 0, dqpp); +} + +/* + * Given the file system, id, and type (UDQUOT/GDQUOT), return a a locked + * dquot, doing an allocation (if requested) as needed. + */ +int +xfs_qm_dqget( + struct xfs_mount *mp, + xfs_dqid_t id, + uint type, + bool can_alloc, + struct xfs_dquot **O_dqpp) +{ + return __xfs_qm_dqget(mp, NULL, id, type, can_alloc, O_dqpp); +} + +/* + * Given the file system, id, and type (UDQUOT/GDQUOT) and a hole in the quota + * data where the on-disk dquot is supposed to live, return a locked dquot + * having allocated blocks with the transaction. This is a corner case + * required by online repair, which already has a transaction and has to pass + * that into dquot_setup. + */ +int +xfs_qm_dqget_alloc( + struct xfs_trans **tpp, + xfs_dqid_t id, + uint type, + struct xfs_dquot **dqpp) +{ + return __xfs_qm_dqget((*tpp)->t_mountp, tpp, id, type, true, dqpp); } /* Return the quota id for a given inode and type. */ @@ -885,7 +932,7 @@ restart: * we re-acquire the lock. */ xfs_iunlock(ip, XFS_ILOCK_EXCL); - error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp); + error = xfs_qm_dqread(mp, NULL, id, type, can_alloc, &dqp); xfs_ilock(ip, XFS_ILOCK_EXCL); if (error) return error; |