summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/scrub/bmap.c4
-rw-r--r--fs/xfs/scrub/common.c36
-rw-r--r--fs/xfs/scrub/common.h2
-rw-r--r--fs/xfs/scrub/rtbitmap.c9
-rw-r--r--fs/xfs/scrub/rtsummary.c26
-rw-r--r--fs/xfs/scrub/scrub.c3
-rw-r--r--fs/xfs/scrub/scrub.h8
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 */