]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: make container for btree bulkload root and block reservation
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 10 Jul 2020 19:35:45 +0000 (15:35 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 10 Jul 2020 19:35:45 +0000 (15:35 -0400)
Create appropriate data structures to manage the fake btree root and
block reservation lists needed to stage a btree bulkload operation.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/libxfs.h
libxfs/libxfs_api_defs.h
repair/Makefile
repair/bulkload.c [new file with mode: 0644]
repair/bulkload.h [new file with mode: 0644]
repair/xfs_repair.c

index 12447835ef0017d9ff4e45342e3a10608552cc37..b9370139becc40590d0e582bf7f9b58bbea9daac 100644 (file)
@@ -76,6 +76,7 @@ struct iomap;
 #include "xfs_rmap.h"
 #include "xfs_refcount_btree.h"
 #include "xfs_refcount.h"
+#include "xfs_btree_staging.h"
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
index be06c763aed57a86ba3e17b20b7e392d02076143..61047f8f46cdaf5c9bde6901ae6540304a152424 100644 (file)
 #define xfs_alloc_fix_freelist         libxfs_alloc_fix_freelist
 #define xfs_alloc_min_freelist         libxfs_alloc_min_freelist
 #define xfs_alloc_read_agf             libxfs_alloc_read_agf
+#define xfs_alloc_vextent              libxfs_alloc_vextent
 
 #define xfs_attr_get                   libxfs_attr_get
 #define xfs_attr_leaf_newentsize       libxfs_attr_leaf_newentsize
 #define xfs_attr_namecheck             libxfs_attr_namecheck
 #define xfs_attr_set                   libxfs_attr_set
 
+#define __xfs_bmap_add_free            __libxfs_bmap_add_free
 #define xfs_bmapi_read                 libxfs_bmapi_read
 #define xfs_bmapi_write                        libxfs_bmapi_write
 #define xfs_bmap_last_offset           libxfs_bmap_last_offset
index 0964499a009607d46ba7e170f86e86c9218fd069..62d84bbf799d8822ea91a714e1ee61c5aaf51adf 100644 (file)
@@ -9,11 +9,11 @@ LSRCFILES = README
 
 LTCOMMAND = xfs_repair
 
-HFILES = agheader.h attr_repair.h avl.h bmap.h btree.h \
+HFILES = agheader.h attr_repair.h avl.h bulkload.h bmap.h btree.h \
        da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \
        rt.h progress.h scan.h versions.h prefetch.h rmap.h slab.h threads.h
 
-CFILES = agheader.c attr_repair.c avl.c bmap.c btree.c \
+CFILES = agheader.c attr_repair.c avl.c bulkload.c bmap.c btree.c \
        da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \
        incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \
        phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \
diff --git a/repair/bulkload.c b/repair/bulkload.c
new file mode 100644 (file)
index 0000000..4c69fe0
--- /dev/null
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include <libxfs.h>
+#include "bulkload.h"
+
+int bload_leaf_slack = -1;
+int bload_node_slack = -1;
+
+/* Initialize accounting resources for staging a new AG btree. */
+void
+bulkload_init_ag(
+       struct bulkload                 *bkl,
+       struct repair_ctx               *sc,
+       const struct xfs_owner_info     *oinfo)
+{
+       memset(bkl, 0, sizeof(struct bulkload));
+       bkl->sc = sc;
+       bkl->oinfo = *oinfo; /* structure copy */
+       INIT_LIST_HEAD(&bkl->resv_list);
+}
+
+/* Designate specific blocks to be used to build our new btree. */
+int
+bulkload_add_blocks(
+       struct bulkload         *bkl,
+       xfs_fsblock_t           fsbno,
+       xfs_extlen_t            len)
+{
+       struct bulkload_resv    *resv;
+
+       resv = kmem_alloc(sizeof(struct bulkload_resv), KM_MAYFAIL);
+       if (!resv)
+               return ENOMEM;
+
+       INIT_LIST_HEAD(&resv->list);
+       resv->fsbno = fsbno;
+       resv->len = len;
+       resv->used = 0;
+       list_add_tail(&resv->list, &bkl->resv_list);
+       return 0;
+}
+
+/* Free all the accounting info and disk space we reserved for a new btree. */
+void
+bulkload_destroy(
+       struct bulkload         *bkl,
+       int                     error)
+{
+       struct bulkload_resv    *resv, *n;
+
+       list_for_each_entry_safe(resv, n, &bkl->resv_list, list) {
+               list_del(&resv->list);
+               kmem_free(resv);
+       }
+}
+
+/* Feed one of the reserved btree blocks to the bulk loader. */
+int
+bulkload_claim_block(
+       struct xfs_btree_cur    *cur,
+       struct bulkload         *bkl,
+       union xfs_btree_ptr     *ptr)
+{
+       struct bulkload_resv    *resv;
+       xfs_fsblock_t           fsb;
+
+       /*
+        * The first item in the list should always have a free block unless
+        * we're completely out.
+        */
+       resv = list_first_entry(&bkl->resv_list, struct bulkload_resv, list);
+       if (resv->used == resv->len)
+               return ENOSPC;
+
+       /*
+        * Peel off a block from the start of the reservation.  We allocate
+        * blocks in order to place blocks on disk in increasing record or key
+        * order.  The block reservations tend to end up on the list in
+        * decreasing order, which hopefully results in leaf blocks ending up
+        * together.
+        */
+       fsb = resv->fsbno + resv->used;
+       resv->used++;
+
+       /* If we used all the blocks in this reservation, move it to the end. */
+       if (resv->used == resv->len)
+               list_move_tail(&resv->list, &bkl->resv_list);
+
+       if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+               ptr->l = cpu_to_be64(fsb);
+       else
+               ptr->s = cpu_to_be32(XFS_FSB_TO_AGBNO(cur->bc_mp, fsb));
+       return 0;
+}
diff --git a/repair/bulkload.h b/repair/bulkload.h
new file mode 100644 (file)
index 0000000..79f81cb
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#ifndef __XFS_REPAIR_BULKLOAD_H__
+#define __XFS_REPAIR_BULKLOAD_H__
+
+extern int bload_leaf_slack;
+extern int bload_node_slack;
+
+struct repair_ctx {
+       struct xfs_mount        *mp;
+};
+
+struct bulkload_resv {
+       /* Link to list of extents that we've reserved. */
+       struct list_head        list;
+
+       /* FSB of the block we reserved. */
+       xfs_fsblock_t           fsbno;
+
+       /* Length of the reservation. */
+       xfs_extlen_t            len;
+
+       /* How much of this reservation we've used. */
+       xfs_extlen_t            used;
+};
+
+struct bulkload {
+       struct repair_ctx       *sc;
+
+       /* List of extents that we've reserved. */
+       struct list_head        resv_list;
+
+       /* Fake root for new btree. */
+       struct xbtree_afakeroot afake;
+
+       /* rmap owner of these blocks */
+       struct xfs_owner_info   oinfo;
+
+       /* The last reservation we allocated from. */
+       struct bulkload_resv    *last_resv;
+};
+
+#define for_each_bulkload_reservation(bkl, resv, n)    \
+       list_for_each_entry_safe((resv), (n), &(bkl)->resv_list, list)
+
+void bulkload_init_ag(struct bulkload *bkl, struct repair_ctx *sc,
+               const struct xfs_owner_info *oinfo);
+int bulkload_add_blocks(struct bulkload *bkl, xfs_fsblock_t fsbno,
+               xfs_extlen_t len);
+void bulkload_destroy(struct bulkload *bkl, int error);
+int bulkload_claim_block(struct xfs_btree_cur *cur, struct bulkload *bkl,
+               union xfs_btree_ptr *ptr);
+
+#endif /* __XFS_REPAIR_BULKLOAD_H__ */
index 9d72fa8e8810031a8b3c0e1cecd392f53c2ad22c..3bfc83115ecd2ee9d7f33fa4c0d1e0a1c76ad868 100644 (file)
@@ -24,6 +24,7 @@
 #include "rmap.h"
 #include "libfrog/fsgeom.h"
 #include "libfrog/platform.h"
+#include "bulkload.h"
 
 /*
  * option tables for getsubopt calls
@@ -39,6 +40,8 @@ enum o_opt_nums {
        AG_STRIDE,
        FORCE_GEO,
        PHASE2_THREADS,
+       BLOAD_LEAF_SLACK,
+       BLOAD_NODE_SLACK,
        O_MAX_OPTS,
 };
 
@@ -49,6 +52,8 @@ static char *o_opts[] = {
        [AG_STRIDE]             = "ag_stride",
        [FORCE_GEO]             = "force_geometry",
        [PHASE2_THREADS]        = "phase2_threads",
+       [BLOAD_LEAF_SLACK]      = "debug_bload_leaf_slack",
+       [BLOAD_NODE_SLACK]      = "debug_bload_node_slack",
        [O_MAX_OPTS]            = NULL,
 };
 
@@ -260,6 +265,18 @@ process_args(int argc, char **argv)
                _("-o phase2_threads requires a parameter\n"));
                                        phase2_threads = (int)strtol(val, NULL, 0);
                                        break;
+                               case BLOAD_LEAF_SLACK:
+                                       if (!val)
+                                               do_abort(
+               _("-o debug_bload_leaf_slack requires a parameter\n"));
+                                       bload_leaf_slack = (int)strtol(val, NULL, 0);
+                                       break;
+                               case BLOAD_NODE_SLACK:
+                                       if (!val)
+                                               do_abort(
+               _("-o debug_bload_node_slack requires a parameter\n"));
+                                       bload_node_slack = (int)strtol(val, NULL, 0);
+                                       break;
                                default:
                                        unknown('o', val);
                                        break;