@@ -148,6 +148,7 @@
#define xfs_log_sb libxfs_log_sb
#define xfs_mode_to_ftype libxfs_mode_to_ftype
#define xfs_perag_get libxfs_perag_get
+#define xfs_perag_hold libxfs_perag_hold
#define xfs_perag_put libxfs_perag_put
#define xfs_prealloc_blocks libxfs_prealloc_blocks
@@ -77,13 +77,17 @@ reserve_agblocks(
uint32_t nr_blocks)
{
struct extent_tree_node *ext_ptr;
+ struct xfs_perag *pag;
uint32_t blocks_allocated = 0;
uint32_t len;
int error;
+ pag = libxfs_perag_get(mp, agno);
+ if (!pag)
+ do_error(_("could not open perag structure for agno 0x%x\n"),
+ agno);
+
while (blocks_allocated < nr_blocks) {
- xfs_fsblock_t fsbno;
-
/*
* Grab the smallest extent and use it up, then get the
* next smallest. This mimics the init_*_cursor code.
@@ -94,8 +98,8 @@ reserve_agblocks(
/* Use up the extent we've got. */
len = min(ext_ptr->ex_blockcount, nr_blocks - blocks_allocated);
- fsbno = XFS_AGB_TO_FSB(mp, agno, ext_ptr->ex_startblock);
- error = bulkload_add_blocks(&btr->newbt, fsbno, len);
+ error = bulkload_add_extent(&btr->newbt, pag,
+ ext_ptr->ex_startblock, len);
if (error)
do_error(_("could not set up btree reservation: %s\n"),
strerror(-error));
@@ -113,6 +117,7 @@ reserve_agblocks(
fprintf(stderr, "blocks_allocated = %d\n",
blocks_allocated);
#endif
+ libxfs_perag_put(pag);
return blocks_allocated == nr_blocks;
}
@@ -155,18 +160,21 @@ finish_rebuild(
int error;
for_each_bulkload_reservation(&btr->newbt, resv, n) {
+ xfs_fsblock_t fsbno;
+
if (resv->used == resv->len)
continue;
- error = bitmap_set(lost_blocks, resv->fsbno + resv->used,
- resv->len - resv->used);
+ fsbno = XFS_AGB_TO_FSB(mp, resv->pag->pag_agno,
+ resv->agbno + resv->used);
+ error = bitmap_set(lost_blocks, fsbno, resv->len - resv->used);
if (error)
do_error(
_("Insufficient memory saving lost blocks, err=%d.\n"), error);
resv->used = resv->len;
}
- bulkload_destroy(&btr->newbt, 0);
+ bulkload_commit(&btr->newbt);
}
/*
@@ -23,39 +23,64 @@ bulkload_init_ag(
}
/* Designate specific blocks to be used to build our new btree. */
-int
+static int
bulkload_add_blocks(
- struct bulkload *bkl,
- xfs_fsblock_t fsbno,
- xfs_extlen_t len)
+ struct bulkload *bkl,
+ struct xfs_perag *pag,
+ const struct xfs_alloc_arg *args)
{
- struct bulkload_resv *resv;
+ struct xfs_mount *mp = bkl->sc->mp;
+ struct bulkload_resv *resv;
- resv = kmem_alloc(sizeof(struct bulkload_resv), KM_MAYFAIL);
+ resv = kmalloc(sizeof(struct bulkload_resv), GFP_KERNEL);
if (!resv)
return ENOMEM;
INIT_LIST_HEAD(&resv->list);
- resv->fsbno = fsbno;
- resv->len = len;
+ resv->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
+ resv->len = args->len;
resv->used = 0;
+ resv->pag = libxfs_perag_hold(pag);
+
list_add_tail(&resv->list, &bkl->resv_list);
- bkl->nr_reserved += len;
-
+ bkl->nr_reserved += args->len;
return 0;
}
+/*
+ * Add an extent to the new btree reservation pool. Callers are required to
+ * reap this reservation manually if the repair is cancelled. @pag must be a
+ * passive reference.
+ */
+int
+bulkload_add_extent(
+ struct bulkload *bkl,
+ struct xfs_perag *pag,
+ xfs_agblock_t agbno,
+ xfs_extlen_t len)
+{
+ struct xfs_mount *mp = bkl->sc->mp;
+ struct xfs_alloc_arg args = {
+ .tp = NULL, /* no autoreap */
+ .oinfo = bkl->oinfo,
+ .fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, agbno),
+ .len = len,
+ .resv = XFS_AG_RESV_NONE,
+ };
+
+ return bulkload_add_blocks(bkl, pag, &args);
+}
+
/* Free all the accounting info and disk space we reserved for a new btree. */
void
-bulkload_destroy(
- struct bulkload *bkl,
- int error)
+bulkload_commit(
+ struct bulkload *bkl)
{
struct bulkload_resv *resv, *n;
list_for_each_entry_safe(resv, n, &bkl->resv_list, list) {
list_del(&resv->list);
- kmem_free(resv);
+ kfree(resv);
}
}
@@ -67,7 +92,8 @@ bulkload_claim_block(
union xfs_btree_ptr *ptr)
{
struct bulkload_resv *resv;
- xfs_fsblock_t fsb;
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agblock_t agbno;
/*
* The first item in the list should always have a free block unless
@@ -84,7 +110,7 @@ bulkload_claim_block(
* decreasing order, which hopefully results in leaf blocks ending up
* together.
*/
- fsb = resv->fsbno + resv->used;
+ agbno = resv->agbno + resv->used;
resv->used++;
/* If we used all the blocks in this reservation, move it to the end. */
@@ -92,9 +118,10 @@ bulkload_claim_block(
list_move_tail(&resv->list, &bkl->resv_list);
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
- ptr->l = cpu_to_be64(fsb);
+ ptr->l = cpu_to_be64(XFS_AGB_TO_FSB(mp, resv->pag->pag_agno,
+ agbno));
else
- ptr->s = cpu_to_be32(XFS_FSB_TO_AGBNO(cur->bc_mp, fsb));
+ ptr->s = cpu_to_be32(agbno);
return 0;
}
@@ -17,8 +17,10 @@ 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;
+ struct xfs_perag *pag;
+
+ /* AG block of the block we reserved. */
+ xfs_agblock_t agbno;
/* Length of the reservation. */
xfs_extlen_t len;
@@ -51,11 +53,11 @@ struct bulkload {
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);
+int bulkload_add_extent(struct bulkload *bkl, struct xfs_perag *pag,
+ xfs_agblock_t agbno, xfs_extlen_t len);
+void bulkload_commit(struct bulkload *bkl);
void bulkload_estimate_ag_slack(struct repair_ctx *sc,
struct xfs_btree_bload *bload, unsigned int free);
@@ -194,7 +194,7 @@ fill_agfl(
for_each_bulkload_reservation(&btr->newbt, resv, n) {
xfs_agblock_t bno;
- bno = XFS_FSB_TO_AGBNO(mp, resv->fsbno + resv->used);
+ bno = resv->agbno + resv->used;
while (resv->used < resv->len &&
*agfl_idx < libxfs_agfl_size(mp)) {
agfl_bnos[(*agfl_idx)++] = cpu_to_be32(bno++);