diff options
-rw-r--r-- | fs/xfs/scrub/bmap.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/common.c | 36 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 2 | ||||
-rw-r--r-- | fs/xfs/scrub/rtbitmap.c | 9 | ||||
-rw-r--r-- | fs/xfs/scrub/rtsummary.c | 26 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.h | 8 |
7 files changed, 59 insertions, 29 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 0eb0040e40d4..21422becd960 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -259,8 +259,12 @@ xchk_bmap_rt_iextent_xref( struct xchk_bmap_info *info, struct xfs_bmbt_irec *irec) { + xchk_rt_init(info->sc, &info->sc->sr); + xchk_xref_is_used_rt_space(info->sc, irec->br_startblock, irec->br_blockcount); + + xchk_rt_unlock(info->sc, &info->sc->sr); } /* Cross-reference a single datadev extent record. */ diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index c8ec7abbb74e..952dfb234bf2 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -596,6 +596,42 @@ xchk_perag_get( sa->pag = xfs_perag_get(mp, sa->agno); } +/* + * For scrubbing a realtime file, grab all the in-core resources we'll need to + * check the realtime metadata, which means taking the ILOCK of the realtime + * metadata inodes. Callers must not join these inodes to the transaction + * with non-zero lockflags or concurrency problems will result. + */ +void +xchk_rt_init( + struct xfs_scrub *sc, + struct xchk_rt *sr) +{ + struct xfs_mount *mp = sc->mp; + + memset(sr, 0, sizeof(*sr)); + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP); + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM); + sr->locked = true; +} + +/* + * Unlock the realtime metadata inodes. This must be done /after/ committing + * (or cancelling) the scrub transaction. + */ +void +xchk_rt_unlock( + struct xfs_scrub *sc, + struct xchk_rt *sr) +{ + if (!sr->locked) + return; + + xfs_iunlock(sc->mp->m_rsumip, XFS_ILOCK_EXCL); + xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_EXCL); + sr->locked = false; +} + /* Per-scrubber setup functions */ /* diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index a9f03e7eda3c..874b3704f36f 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -132,6 +132,8 @@ int xchk_setup_fscounters(struct xfs_scrub *sc, struct xfs_inode *ip); void xchk_ag_free(struct xfs_scrub *sc, struct xchk_ag *sa); int xchk_ag_init(struct xfs_scrub *sc, xfs_agnumber_t agno, struct xchk_ag *sa); +void xchk_rt_init(struct xfs_scrub *sc, struct xchk_rt *sr); +void xchk_rt_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); void xchk_perag_get(struct xfs_mount *mp, struct xchk_ag *sa); int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno, struct xfs_buf **agi, struct xfs_buf **agf, diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index 47260724645b..c99f1636613a 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -29,10 +29,8 @@ xchk_setup_rtbitmap( if (error) return error; - sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP; + xchk_rt_init(sc, &sc->sr); sc->ip = sc->mp->m_rbmip; - xfs_ilock(sc->ip, sc->ilock_flags); - return 0; } @@ -146,13 +144,10 @@ xchk_xref_is_used_rt_space( do_div(startext, sc->mp->m_sb.sb_rextsize); do_div(endext, sc->mp->m_sb.sb_rextsize); extcount = endext - startext + 1; - xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount, &is_free); if (!xchk_should_check_xref(sc, &error, NULL)) - goto out_unlock; + return; if (is_free) xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino); -out_unlock: - xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); } diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c index 149616f2d392..dd7c83926f13 100644 --- a/fs/xfs/scrub/rtsummary.c +++ b/fs/xfs/scrub/rtsummary.c @@ -96,18 +96,8 @@ xchk_setup_rtsummary( if (!sc->buf) return -ENOMEM; - /* - * Locking order requires us to take the rtbitmap first. We must be - * careful to unlock it ourselves when we are done with the rtbitmap - * file since the scrub infrastructure won't do that for us. - */ - xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); - - /* ...and then we can lock the rtsummary inode. */ - sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM; + xchk_rt_init(sc, &sc->sr); sc->ip = sc->mp->m_rsumip; - xfs_ilock(sc->ip, sc->ilock_flags); - return 0; } @@ -316,7 +306,7 @@ xchk_rtsummary( /* Invoke the fork scrubber. */ error = xchk_metadata_inode_forks(sc); if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) - goto out_rbm; + return error; /* Construct the new summary file from the rtbitmap. */ error = xchk_rtsum_compute(sc); @@ -326,17 +316,11 @@ xchk_rtsummary( * error since we're checking the summary file. */ xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino); - error = 0; - goto out_rbm; + return 0; } if (error) - goto out_rbm; + return error; /* Does the computed summary file match the actual rtsummary file? */ - error = xchk_rtsum_compare(sc); - -out_rbm: - /* Unlock the rtbitmap since we're done with it. */ - xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); - return error; + return xchk_rtsum_compare(sc); } diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 482cc13d709c..6dd5d9c319f7 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -155,7 +155,7 @@ xchk_teardown( struct xfs_inode *ip_in, int error) { - int err2; + int err2; xchk_ag_free(sc, &sc->sa); if (sc->tp) { @@ -165,6 +165,7 @@ xchk_teardown( xfs_trans_cancel(sc->tp); sc->tp = NULL; } + xchk_rt_unlock(sc, &sc->sr); if (sc->ip) { if (sc->ilock_flags) xfs_iunlock(sc->ip, sc->ilock_flags); diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 596cb16580f0..cae4a2c7e631 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -61,6 +61,11 @@ struct xchk_ag { struct xfs_btree_cur *refc_cur; }; +/* Btree cursors for the RT volume. */ +struct xchk_rt { + bool locked:1; +}; + struct xfs_scrub { /* General scrub state. */ struct xfs_mount *mp; @@ -100,6 +105,9 @@ struct xfs_scrub { /* State tracking for single-AG operations. */ struct xchk_ag sa; + + /* State tracking for realtime operations. */ + struct xchk_rt sr; }; /* XCHK state flags grow up from zero, XREP state flags grown down from 2^31 */ |