@@ -1097,3 +1097,33 @@ xfs_verify_rtbno(
{
return rtbno < mp->m_sb.sb_rblocks;
}
+
+/* Is the given extent all free? */
+int
+xfs_rtalloc_extent_is_free(
+ struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ xfs_rtblock_t start,
+ xfs_rtblock_t len,
+ bool *is_free)
+{
+ xfs_rtblock_t end;
+ xfs_extlen_t clen;
+ int matches;
+ int error;
+
+ *is_free = false;
+ while (len) {
+ clen = len > ~0U ? ~0U : len;
+ error = xfs_rtcheck_range(mp, tp, start, clen, 1, &end,
+ &matches);
+ if (error || !matches || end < start + clen)
+ return error;
+
+ len -= end - start;
+ start = end + 1;
+ }
+
+ *is_free = true;
+ return error;
+}
@@ -276,6 +276,8 @@ xfs_scrub_bmap_rt_extent_xref(
struct xfs_btree_cur *cur,
struct xfs_bmbt_irec *irec)
{
+ xfs_scrub_xref_not_rtfree(info->sc, irec->br_startblock,
+ irec->br_blockcount);
}
/* Cross-reference a single datadev extent record. */
@@ -98,3 +98,23 @@ xfs_scrub_rtsummary(
/* XXX: implement this some day */
return -ENOENT;
}
+
+
+/* xref check that the extent is not free in the rtbitmap */
+void
+xfs_scrub_xref_not_rtfree(
+ struct xfs_scrub_context *sc,
+ xfs_fsblock_t fsbno,
+ xfs_fsblock_t len)
+{
+ bool is_free;
+ int error;
+
+ xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+ error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, fsbno, len,
+ &is_free);
+ if (xfs_scrub_should_xref(sc, &error, NULL) && is_free)
+ xfs_scrub_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino,
+ NULL);
+ xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+}
@@ -148,5 +148,11 @@ void xfs_scrub_xref_has_cow_staging(struct xfs_scrub_context *sc,
void xfs_scrub_xref_not_shared(struct xfs_scrub_context *sc,
struct xfs_btree_cur **pcur, xfs_agblock_t bno,
xfs_extlen_t len);
+#ifdef CONFIG_XFS_RT
+void xfs_scrub_xref_not_rtfree(struct xfs_scrub_context *sc,
+ xfs_fsblock_t fsbno, xfs_fsblock_t len);
+#else
+# define xfs_scrub_xref_not_rtfree(sc, fsbno, len) do { } while (0)
+#endif
#endif /* __XFS_SCRUB_SCRUB_H__ */
@@ -139,6 +139,9 @@ int xfs_rtalloc_query_all(struct xfs_trans *tp,
xfs_rtalloc_query_range_fn fn,
void *priv);
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
+int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp,
+ xfs_rtblock_t start, xfs_rtblock_t len,
+ bool *is_free);
#else
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS)
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
@@ -148,6 +151,7 @@ bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
# define xfs_rtalloc_query_all(t,f,p) (ENOSYS)
# define xfs_rtbuf_get(m,t,b,i,p) (ENOSYS)
# define xfs_verify_rtbno(m, r) (false)
+# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (ENOSYS)
static inline int /* error */
xfs_rtmount_init(
xfs_mount_t *mp) /* file system mount structure */