diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 9807c8c5..5c522820 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -2449,7 +2449,7 @@ int scoutfs_btree_free_blocks(struct super_block *sb, struct scoutfs_alloc *alloc, struct scoutfs_block_writer *wri, struct scoutfs_key *key, - struct scoutfs_btree_root *root, int alloc_low) + struct scoutfs_btree_root *root, int free_budget) { u64 blknos[SCOUTFS_BTREE_MAX_HEIGHT]; struct scoutfs_block *bl = NULL; @@ -2459,11 +2459,15 @@ int scoutfs_btree_free_blocks(struct super_block *sb, struct scoutfs_avl_node *node; struct scoutfs_avl_node *next; struct scoutfs_key par_next; + int nr_freed = 0; int nr_par; int level; int ret; int i; + if (WARN_ON_ONCE(free_budget <= 0)) + return -EINVAL; + if (WARN_ON_ONCE(root->height > ARRAY_SIZE(blknos))) return -EIO; /* XXX corruption */ @@ -2538,8 +2542,7 @@ int scoutfs_btree_free_blocks(struct super_block *sb, while (node) { /* make sure we can always free parents after leaves */ - if (scoutfs_alloc_meta_low(sb, alloc, - alloc_low + nr_par + 1)) { + if ((nr_freed + 1 + nr_par) > free_budget) { ret = 0; goto out; } @@ -2553,6 +2556,7 @@ int scoutfs_btree_free_blocks(struct super_block *sb, le64_to_cpu(ref.blkno)); if (ret < 0) goto out; + nr_freed++; node = scoutfs_avl_next(&bt->item_root, node); if (node) { @@ -2568,6 +2572,7 @@ int scoutfs_btree_free_blocks(struct super_block *sb, blknos[i]); ret = scoutfs_free_meta(sb, alloc, wri, blknos[i]); BUG_ON(ret); /* checked meta low, freed should fit */ + nr_freed++; } /* restart walk past the subtree we just freed */ diff --git a/kmod/src/btree.h b/kmod/src/btree.h index 057aa779..0ff5599c 100644 --- a/kmod/src/btree.h +++ b/kmod/src/btree.h @@ -125,7 +125,7 @@ int scoutfs_btree_free_blocks(struct super_block *sb, struct scoutfs_alloc *alloc, struct scoutfs_block_writer *wri, struct scoutfs_key *key, - struct scoutfs_btree_root *root, int alloc_low); + struct scoutfs_btree_root *root, int free_budget); void scoutfs_btree_put_iref(struct scoutfs_btree_item_ref *iref); diff --git a/kmod/src/server.c b/kmod/src/server.c index ae1614ce..465abda0 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -2305,7 +2305,7 @@ static void server_log_merge_free_work(struct work_struct *work) ret = scoutfs_btree_free_blocks(sb, &server->alloc, &server->wri, &fr.key, - &fr.root, 10); + &fr.root, COMMIT_HOLD_ALLOC_BUDGET / 2); if (ret < 0) { err_str = "freeing log btree"; break;