mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
bcachefs: Walk leaf to root in btree_gc
Next change will move gc_alloc_start initialization into the alloc trigger, so we have to mark those first. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -635,13 +635,27 @@ fsck_err:
|
||||
static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree, bool initial)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
int level = 0, target_depth = btree_node_type_needs_gc(__btree_node_type(0, btree)) ? 0 : 1;
|
||||
unsigned target_depth = btree_node_type_needs_gc(__btree_node_type(0, btree)) ? 0 : 1;
|
||||
int ret = 0;
|
||||
|
||||
/* We need to make sure every leaf node is readable before going RW */
|
||||
if (initial)
|
||||
target_depth = 0;
|
||||
|
||||
for (unsigned level = target_depth; level < BTREE_MAX_DEPTH; level++) {
|
||||
struct btree *prev = NULL;
|
||||
struct btree_iter iter;
|
||||
bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN, 0, level,
|
||||
BTREE_ITER_prefetch);
|
||||
|
||||
ret = for_each_btree_key_continue(trans, iter, 0, k, ({
|
||||
gc_pos_set(c, gc_pos_btree(btree, level, k.k->p));
|
||||
bch2_gc_mark_key(trans, btree, level, &prev, &iter, k, initial);
|
||||
}));
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* root */
|
||||
do {
|
||||
retry_root:
|
||||
@@ -663,28 +677,11 @@ retry_root:
|
||||
gc_pos_set(c, gc_pos_btree(btree, b->c.level + 1, SPOS_MAX));
|
||||
struct bkey_s_c k = bkey_i_to_s_c(&b->key);
|
||||
ret = bch2_gc_mark_key(trans, btree, b->c.level + 1, NULL, NULL, k, initial);
|
||||
level = b->c.level;
|
||||
err_root:
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
} while (bch2_err_matches(ret, BCH_ERR_transaction_restart));
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (; level >= target_depth; --level) {
|
||||
struct btree *prev = NULL;
|
||||
struct btree_iter iter;
|
||||
bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN, 0, level,
|
||||
BTREE_ITER_prefetch);
|
||||
|
||||
ret = for_each_btree_key_continue(trans, iter, 0, k, ({
|
||||
gc_pos_set(c, gc_pos_btree(btree, level, k.k->p));
|
||||
bch2_gc_mark_key(trans, btree, level, &prev, &iter, k, initial);
|
||||
}));
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ static inline struct gc_pos gc_pos_btree_node(struct btree *b)
|
||||
|
||||
static inline int gc_btree_order(enum btree_id btree)
|
||||
{
|
||||
if (btree == BTREE_ID_alloc)
|
||||
return -2;
|
||||
if (btree == BTREE_ID_stripes)
|
||||
return -1;
|
||||
return btree;
|
||||
@@ -65,11 +67,11 @@ static inline int gc_btree_order(enum btree_id btree)
|
||||
|
||||
static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
|
||||
{
|
||||
return cmp_int(l.phase, r.phase) ?:
|
||||
cmp_int(gc_btree_order(l.btree),
|
||||
gc_btree_order(r.btree)) ?:
|
||||
-cmp_int(l.level, r.level) ?:
|
||||
bpos_cmp(l.pos, r.pos);
|
||||
return cmp_int(l.phase, r.phase) ?:
|
||||
cmp_int(gc_btree_order(l.btree),
|
||||
gc_btree_order(r.btree)) ?:
|
||||
cmp_int(l.level, r.level) ?:
|
||||
bpos_cmp(l.pos, r.pos);
|
||||
}
|
||||
|
||||
static inline bool gc_visited(struct bch_fs *c, struct gc_pos pos)
|
||||
|
||||
Reference in New Issue
Block a user