From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: sandeen@sandeen.net, darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com
Subject: [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors
Date: Sat, 09 May 2020 09:31:59 -0700 [thread overview]
Message-ID: <158904191982.984305.12997847094211521747.stgit@magnolia> (raw)
In-Reply-To: <158904190079.984305.707785748675261111.stgit@magnolia>
From: Darrick J. Wong <darrick.wong@oracle.com>
Create some new support structures and functions to assist phase5 in
using the btree bulk loader to reconstruct metadata btrees. This is the
first step in removing the open-coded rebuilding code.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
repair/phase5.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 219 insertions(+), 21 deletions(-)
diff --git a/repair/phase5.c b/repair/phase5.c
index f3be15de..7eb24519 100644
--- a/repair/phase5.c
+++ b/repair/phase5.c
@@ -18,6 +18,7 @@
#include "progress.h"
#include "slab.h"
#include "rmap.h"
+#include "bload.h"
/*
* we maintain the current slice (path from root to leaf)
@@ -65,6 +66,23 @@ typedef struct bt_status {
uint64_t owner; /* owner */
} bt_status_t;
+/* Context for rebuilding a per-AG btree. */
+struct bt_rebuild {
+ /* Fake root for staging and space preallocations. */
+ struct xrep_newbt newbt;
+
+ /* Geometry of the new btree. */
+ struct xfs_btree_bload bload;
+
+ /* Staging btree cursor for the new tree. */
+ struct xfs_btree_cur *cur;
+
+ /* Tree-specific data. */
+ union {
+ struct xfs_slab_cursor *slab_cursor;
+ };
+};
+
/*
* extra metadata for the agi
*/
@@ -306,6 +324,157 @@ _("error - not enough free space in filesystem\n"));
#endif
}
+/*
+ * Estimate proper slack values for a btree that's being reloaded.
+ *
+ * Under most circumstances, we'll take whatever default loading value the
+ * btree bulk loading code calculates for us. However, there are some
+ * exceptions to this rule:
+ *
+ * (1) If someone turned one of the debug knobs.
+ * (2) The AG has less than ~9% space free.
+ *
+ * Note that we actually use 3/32 for the comparison to avoid division.
+ */
+static void
+estimate_ag_bload_slack(
+ struct repair_ctx *sc,
+ struct xfs_btree_bload *bload,
+ unsigned int free)
+{
+ /*
+ * The global values are set to -1 (i.e. take the bload defaults)
+ * unless someone has set them otherwise, so we just pull the values
+ * here.
+ */
+ bload->leaf_slack = bload_leaf_slack;
+ bload->node_slack = bload_node_slack;
+
+ /* No further changes if there's more than 3/32ths space left. */
+ if (free >= ((sc->mp->m_sb.sb_agblocks * 3) >> 5))
+ return;
+
+ /* We're low on space; load the btrees as tightly as possible. */
+ if (bload->leaf_slack < 0)
+ bload->leaf_slack = 0;
+ if (bload->node_slack < 0)
+ bload->node_slack = 0;
+}
+
+/* Initialize a btree rebuild context. */
+static void
+init_rebuild(
+ struct repair_ctx *sc,
+ const struct xfs_owner_info *oinfo,
+ xfs_agblock_t free_space,
+ struct bt_rebuild *btr)
+{
+ memset(btr, 0, sizeof(struct bt_rebuild));
+
+ xrep_newbt_init_bare(&btr->newbt, sc);
+ btr->newbt.oinfo = *oinfo; /* struct copy */
+ estimate_ag_bload_slack(sc, &btr->bload, free_space);
+}
+
+/* Reserve blocks for the new btree. */
+static void
+setup_rebuild(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ struct bt_rebuild *btr,
+ uint32_t nr_blocks)
+{
+ struct extent_tree_node *ext_ptr;
+ struct extent_tree_node *bno_ext_ptr;
+ uint32_t blocks_allocated = 0;
+ int error;
+
+ /*
+ * grab the smallest extent and use it up, then get the
+ * next smallest. This mimics the init_*_cursor code.
+ */
+ ext_ptr = findfirst_bcnt_extent(agno);
+
+ /*
+ * set up the free block array
+ */
+ while (blocks_allocated < nr_blocks) {
+ uint64_t len;
+ xfs_agblock_t new_start;
+ xfs_extlen_t new_len;
+
+ if (!ext_ptr)
+ do_error(
+_("error - not enough free space in filesystem\n"));
+
+ /* Use up the extent we've got. */
+ len = min(ext_ptr->ex_blockcount,
+ btr->bload.nr_blocks - blocks_allocated);
+ error = xrep_newbt_add_reservation(&btr->newbt,
+ XFS_AGB_TO_FSB(mp, agno,
+ ext_ptr->ex_startblock),
+ len, NULL);
+ if (error)
+ do_error(_("could not set up btree reservation: %s\n"),
+ strerror(-error));
+ blocks_allocated += len;
+
+ error = rmap_add_ag_rec(mp, agno, ext_ptr->ex_startblock, len,
+ btr->newbt.oinfo.oi_owner);
+ if (error)
+ do_error(_("could not set up btree rmaps: %s\n"),
+ strerror(-error));
+
+ /* Figure out if we're putting anything back. */
+ new_start = ext_ptr->ex_startblock + len;
+ new_len = ext_ptr->ex_blockcount - len;
+
+ /* Delete the used-up extent from both extent trees. */
+#ifdef XR_BLD_FREE_TRACE
+ fprintf(stderr, "releasing extent: %u [%u %u]\n",
+ agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount);
+#endif
+ bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock);
+ ASSERT(bno_ext_ptr != NULL);
+ get_bno_extent(agno, bno_ext_ptr);
+ release_extent_tree_node(bno_ext_ptr);
+
+ ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock,
+ ext_ptr->ex_blockcount);
+ ASSERT(ext_ptr != NULL);
+ release_extent_tree_node(ext_ptr);
+
+ /*
+ * If we only used part of this last extent, then we need only
+ * to reinsert the extent in the extent trees and we're done.
+ */
+ if (new_len > 0) {
+ add_bno_extent(agno, new_start, new_len);
+ add_bcnt_extent(agno, new_start, new_len);
+ break;
+ }
+
+ /* Otherwise, find the next biggest extent. */
+ ext_ptr = findfirst_bcnt_extent(agno);
+ }
+#ifdef XR_BLD_FREE_TRACE
+ fprintf(stderr, "blocks_allocated = %d\n",
+ blocks_allocated);
+#endif
+}
+
+/* Feed one of the new btree blocks to the bulk loader. */
+static int
+rebuild_alloc_block(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *ptr,
+ void *priv)
+{
+ struct bt_rebuild *btr = priv;
+
+ return xrep_newbt_claim_block(cur, &btr->newbt, ptr);
+}
+
static void
write_cursor(bt_status_t *curs)
{
@@ -336,6 +505,34 @@ finish_cursor(bt_status_t *curs)
free(curs->btree_blocks);
}
+static void
+finish_rebuild(
+ struct xfs_mount *mp,
+ struct bt_rebuild *btr)
+{
+ struct xrep_newbt_resv *resv, *n;
+
+ for_each_xrep_newbt_reservation(&btr->newbt, resv, n) {
+ xfs_agnumber_t agno;
+ xfs_agblock_t bno;
+ xfs_extlen_t len;
+
+ if (resv->used >= resv->len)
+ continue;
+
+ /* XXX: Shouldn't this go on the AGFL? */
+ /* Put back everything we didn't use. */
+ bno = XFS_FSB_TO_AGBNO(mp, resv->fsbno + resv->used);
+ agno = XFS_FSB_TO_AGNO(mp, resv->fsbno + resv->used);
+ len = resv->len - resv->used;
+
+ add_bno_extent(agno, bno, len);
+ add_bcnt_extent(agno, bno, len);
+ }
+
+ xrep_newbt_destroy(&btr->newbt, 0);
+}
+
/*
* We need to leave some free records in the tree for the corner case of
* setting up the AGFL. This may require allocation of blocks, and as
@@ -2290,28 +2487,29 @@ keep_fsinos(xfs_mount_t *mp)
static void
phase5_func(
- xfs_mount_t *mp,
- xfs_agnumber_t agno,
- struct xfs_slab *lost_fsb)
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ struct xfs_slab *lost_fsb)
{
- uint64_t num_inos;
- uint64_t num_free_inos;
- uint64_t finobt_num_inos;
- uint64_t finobt_num_free_inos;
- bt_status_t bno_btree_curs;
- bt_status_t bcnt_btree_curs;
- bt_status_t ino_btree_curs;
- bt_status_t fino_btree_curs;
- bt_status_t rmap_btree_curs;
- bt_status_t refcnt_btree_curs;
- int extra_blocks = 0;
- uint num_freeblocks;
- xfs_extlen_t freeblks1;
+ struct repair_ctx sc = { .mp = mp, };
+ struct agi_stat agi_stat = {0,};
+ uint64_t num_inos;
+ uint64_t num_free_inos;
+ uint64_t finobt_num_inos;
+ uint64_t finobt_num_free_inos;
+ bt_status_t bno_btree_curs;
+ bt_status_t bcnt_btree_curs;
+ bt_status_t ino_btree_curs;
+ bt_status_t fino_btree_curs;
+ bt_status_t rmap_btree_curs;
+ bt_status_t refcnt_btree_curs;
+ int extra_blocks = 0;
+ uint num_freeblocks;
+ xfs_extlen_t freeblks1;
#ifdef DEBUG
- xfs_extlen_t freeblks2;
+ xfs_extlen_t freeblks2;
#endif
- xfs_agblock_t num_extents;
- struct agi_stat agi_stat = {0,};
+ xfs_agblock_t num_extents;
if (verbose)
do_log(_(" - agno = %d\n"), agno);
@@ -2533,8 +2731,8 @@ inject_lost_blocks(
if (error)
goto out_cancel;
- error = -libxfs_free_extent(tp, *fsb, 1, &XFS_RMAP_OINFO_AG,
- XFS_AG_RESV_NONE);
+ error = -libxfs_free_extent(tp, *fsb, 1,
+ &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE);
if (error)
goto out_cancel;
next prev parent reply other threads:[~2020-05-09 16:32 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-09 16:31 [PATCH v4 0/9] xfs_repair: use btree bulk loading Darrick J. Wong
2020-05-09 16:31 ` [PATCH 1/9] xfs_repair: port the online repair newbt structure Darrick J. Wong
2020-05-14 15:09 ` Brian Foster
2020-05-14 19:20 ` Darrick J. Wong
2020-05-15 11:41 ` Brian Foster
2020-05-15 18:52 ` Darrick J. Wong
2020-05-15 19:43 ` Brian Foster
2020-05-09 16:31 ` [PATCH 2/9] xfs_repair: unindent phase 5 function Darrick J. Wong
2020-05-14 15:09 ` Brian Foster
2020-05-14 19:23 ` Darrick J. Wong
2020-05-09 16:31 ` Darrick J. Wong [this message]
2020-05-14 15:11 ` [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors Brian Foster
2020-05-14 19:47 ` Darrick J. Wong
2020-05-09 16:32 ` [PATCH 4/9] xfs_repair: rebuild free space btrees with bulk loader Darrick J. Wong
2020-05-14 15:12 ` Brian Foster
2020-05-14 19:53 ` Darrick J. Wong
2020-05-15 11:42 ` Brian Foster
2020-05-09 16:32 ` [PATCH 5/9] xfs_repair: rebuild inode " Darrick J. Wong
2020-05-09 16:32 ` [PATCH 6/9] xfs_repair: rebuild reverse mapping " Darrick J. Wong
2020-05-09 16:32 ` [PATCH 7/9] xfs_repair: rebuild refcount " Darrick J. Wong
2020-05-09 16:32 ` [PATCH 8/9] xfs_repair: remove old btree rebuild support code Darrick J. Wong
2020-05-09 16:32 ` [PATCH 9/9] xfs_repair: track blocks lost during btree construction via extents Darrick J. Wong
-- strict thread matches above, loose matches on Subject: below --
2020-05-20 1:50 [PATCH v5 0/9] xfs_repair: use btree bulk loading Darrick J. Wong
2020-05-20 1:51 ` [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors Darrick J. Wong
2020-05-27 12:18 ` Brian Foster
2020-05-27 22:07 ` Darrick J. Wong
2020-05-28 15:09 ` Brian Foster
2020-05-29 21:08 ` Darrick J. Wong
2020-03-04 3:29 [PATCH v3 0/9] xfs_repair: use btree bulk loading Darrick J. Wong
2020-03-04 3:29 ` [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors Darrick J. Wong
2020-01-01 1:21 [PATCH v2 0/9] xfs_repair: use btree bulk loading Darrick J. Wong
2020-01-01 1:21 ` [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors Darrick J. Wong
2019-10-29 23:45 [PATCH RFC 0/9] xfs_repair: use btree bulk loading Darrick J. Wong
2019-10-29 23:45 ` [PATCH 3/9] xfs_repair: create a new class of btree rebuild cursors Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=158904191982.984305.12997847094211521747.stgit@magnolia \
--to=darrick.wong@oracle.com \
--cc=bfoster@redhat.com \
--cc=linux-xfs@vger.kernel.org \
--cc=sandeen@sandeen.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).