#include "libfrog/platform.h"
#include "rcbag.h"
#include "rt.h"
+#include "prefetch.h"
#undef RMAP_DEBUG
for (i = 0; i < mp->m_sb.sb_rgcount; i++)
rmaps_init_rt(mp, i, &rg_rmaps[i]);
-
- discover_rtgroup_inodes(mp);
}
/*
}
}
+/* Add this realtime group's fixed metadata to the incore data. */
+void
+rmap_add_fixed_rtgroup_rec(
+ struct xfs_mount *mp,
+ xfs_rgnumber_t rgno)
+{
+ struct xfs_rmap_irec rmap = {
+ .rm_startblock = 0,
+ .rm_blockcount = mp->m_sb.sb_rextsize,
+ .rm_owner = XFS_RMAP_OWN_FS,
+ .rm_offset = 0,
+ .rm_flags = 0,
+ };
+
+ if (!rmap_needs_work(mp))
+ return;
+
+ if (xfs_has_rtsb(mp) && rgno == 0)
+ rmap_add_mem_rec(mp, true, rgno, &rmap);
+}
+
/*
* Copy the per-AG btree reverse-mapping data into the rmapbt.
*
#undef NEXTP
#undef NEXTL
-/*
- * Compare the observed reverse mappings against what's in the ag btree.
- */
-void
-rmaps_verify_btree(
- struct xfs_mount *mp,
- xfs_agnumber_t agno)
+static int
+rmap_compare_records(
+ struct xfs_btree_cur *rm_cur,
+ struct xfs_btree_cur *bt_cur,
+ unsigned int group)
{
- struct xfs_btree_cur *rm_cur;
struct xfs_rmap_irec rm_rec;
struct xfs_rmap_irec tmp;
- struct xfs_btree_cur *bt_cur = NULL;
- struct xfs_buf *agbp = NULL;
- struct xfs_perag *pag = NULL;
int have;
int error;
- if (!xfs_has_rmapbt(mp))
- return;
- if (rmapbt_suspect) {
- if (no_modify && agno == 0)
- do_warn(_("would rebuild corrupt rmap btrees.\n"));
- return;
- }
-
- /* Create cursors to rmap structures */
- error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur);
- if (error) {
- do_warn(_("Not enough memory to check reverse mappings.\n"));
- return;
- }
-
- pag = libxfs_perag_get(mp, agno);
- error = -libxfs_alloc_read_agf(pag, NULL, 0, &agbp);
- if (error) {
- do_warn(_("Could not read AGF %u to check rmap btree.\n"),
- agno);
- goto err_pag;
- }
-
- /* Leave the per-ag data "uninitialized" since we rewrite it later */
- clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
-
- bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, pag);
- if (!bt_cur) {
- do_warn(_("Not enough memory to check reverse mappings.\n"));
- goto err_agf;
- }
-
while ((error = rmap_get_mem_rec(rm_cur, &rm_rec)) == 1) {
error = rmap_lookup(bt_cur, &rm_rec, &tmp, &have);
if (error) {
do_warn(
_("Could not read reverse-mapping record for (%u/%u).\n"),
- agno, rm_rec.rm_startblock);
- goto err_cur;
+ group,
+ rm_rec.rm_startblock);
+ return error;
}
/*
if (error) {
do_warn(
_("Could not read reverse-mapping record for (%u/%u).\n"),
- agno, rm_rec.rm_startblock);
- goto err_cur;
+ group, rm_rec.rm_startblock);
+ return error;
}
}
if (!have) {
do_warn(
_("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \
%s%soff %"PRIu64"\n"),
- agno, rm_rec.rm_startblock,
+ group, rm_rec.rm_startblock,
(rm_rec.rm_flags & XFS_RMAP_UNWRITTEN) ?
_("unwritten ") : "",
rm_rec.rm_blockcount,
continue;
}
- /* Compare each refcount observation against the btree's */
+ /* Compare each rmap observation against the btree's */
if (!rmap_is_good(&rm_rec, &tmp)) {
do_warn(
_("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \
%"PRIu64"; should be (%u/%u) %slen %u owner %"PRId64" %s%soff %"PRIu64"\n"),
- agno, tmp.rm_startblock,
+ group, tmp.rm_startblock,
(tmp.rm_flags & XFS_RMAP_UNWRITTEN) ?
_("unwritten ") : "",
tmp.rm_blockcount,
(tmp.rm_flags & XFS_RMAP_BMBT_BLOCK) ?
_("bmbt ") : "",
tmp.rm_offset,
- agno, rm_rec.rm_startblock,
+ group, rm_rec.rm_startblock,
(rm_rec.rm_flags & XFS_RMAP_UNWRITTEN) ?
_("unwritten ") : "",
rm_rec.rm_blockcount,
}
}
+ return error;
+}
+
+/*
+ * Compare the observed reverse mappings against what's in the ag btree.
+ */
+void
+rmaps_verify_btree(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno)
+{
+ struct xfs_btree_cur *rm_cur;
+ struct xfs_btree_cur *bt_cur = NULL;
+ struct xfs_buf *agbp = NULL;
+ struct xfs_perag *pag = NULL;
+ int error;
+
+ if (!xfs_has_rmapbt(mp))
+ return;
+ if (rmapbt_suspect) {
+ if (no_modify && agno == 0)
+ do_warn(_("would rebuild corrupt rmap btrees.\n"));
+ return;
+ }
+
+ /* Create cursors to rmap structures */
+ error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur);
+ if (error) {
+ do_warn(_("Not enough memory to check reverse mappings.\n"));
+ return;
+ }
+
+ pag = libxfs_perag_get(mp, agno);
+ error = -libxfs_alloc_read_agf(pag, NULL, 0, &agbp);
+ if (error) {
+ do_warn(_("Could not read AGF %u to check rmap btree.\n"),
+ agno);
+ goto err_pag;
+ }
+
+ /* Leave the per-ag data "uninitialized" since we rewrite it later */
+ clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
+
+ bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, pag);
+ if (!bt_cur) {
+ do_warn(_("Not enough memory to check reverse mappings.\n"));
+ goto err_agf;
+ }
+
+ error = rmap_compare_records(rm_cur, bt_cur, agno);
+ if (error)
+ goto err_cur;
+
err_cur:
- libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
+ libxfs_btree_del_cursor(bt_cur, error);
err_agf:
libxfs_buf_relse(agbp);
err_pag:
libxfs_btree_del_cursor(rm_cur, error);
}
+/*
+ * Compare the observed reverse mappings against what's in the rtgroup btree.
+ */
+void
+rtrmaps_verify_btree(
+ struct xfs_mount *mp,
+ xfs_rgnumber_t rgno)
+{
+ struct xfs_btree_cur *rm_cur;
+ struct xfs_btree_cur *bt_cur = NULL;
+ struct xfs_rtgroup *rtg = NULL;
+ struct xfs_inode *ip = NULL;
+ int error;
+
+ if (!xfs_has_rmapbt(mp))
+ return;
+ if (rmapbt_suspect) {
+ if (no_modify && rgno == 0)
+ do_warn(_("would rebuild corrupt rmap btrees.\n"));
+ return;
+ }
+
+ /* Create cursors to rmap structures */
+ error = rmap_init_mem_cursor(mp, NULL, true, rgno, &rm_cur);
+ if (error) {
+ do_warn(_("Not enough memory to check reverse mappings.\n"));
+ return;
+ }
+
+ rtg = libxfs_rtgroup_get(mp, rgno);
+ if (!rtg) {
+ do_warn(_("Could not load rtgroup %u.\n"), rgno);
+ goto err_rcur;
+ }
+
+ ip = rtg->rtg_inodes[XFS_RTGI_RMAP];
+ if (!ip) {
+ do_warn(_("Could not find rtgroup %u rmap inode.\n"), rgno);
+ goto err_rtg;
+ }
+
+ if (ip->i_df.if_format != XFS_DINODE_FMT_RMAP) {
+ do_warn(
+_("rtgroup %u rmap inode has wrong format 0x%x, expected 0x%x\n"),
+ rgno, ip->i_df.if_format,
+ XFS_DINODE_FMT_RMAP);
+ goto err_rtg;
+ }
+
+ if (xfs_inode_has_attr_fork(ip) &&
+ !(xfs_has_metadir(mp) && xfs_has_parent(mp))) {
+ do_warn(
+_("rtgroup %u rmap inode should not have extended attributes\n"), rgno);
+ goto err_rtg;
+ }
+
+ bt_cur = libxfs_rtrmapbt_init_cursor(NULL, rtg);
+ if (!bt_cur) {
+ do_warn(_("Not enough memory to check reverse mappings.\n"));
+ goto err_rtg;
+ }
+
+ error = rmap_compare_records(rm_cur, bt_cur, rgno);
+ if (error)
+ goto err_cur;
+
+err_cur:
+ libxfs_btree_del_cursor(bt_cur, error);
+err_rtg:
+ libxfs_rtgroup_put(rtg);
+err_rcur:
+ libxfs_btree_del_cursor(rm_cur, error);
+}
+
/*
* Compare the key fields of two rmap records -- positive if key1 > key2,
* negative if key1 < key2, and zero if equal.