summaryrefslogtreecommitdiff
path: root/fs/bcachefs/snapshot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/snapshot.c')
-rw-r--r--fs/bcachefs/snapshot.c155
1 files changed, 71 insertions, 84 deletions
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c
index 7a801513b134..1b7b21494479 100644
--- a/fs/bcachefs/snapshot.c
+++ b/fs/bcachefs/snapshot.c
@@ -11,6 +11,7 @@
#include "errcode.h"
#include "error.h"
#include "fs.h"
+#include "progress.h"
#include "recovery_passes.h"
#include "snapshot.h"
@@ -73,7 +74,7 @@ __bch2_snapshot_tree_create(struct btree_trans *trans)
s_t = bch2_bkey_alloc(trans, &iter, 0, snapshot_tree);
ret = PTR_ERR_OR_ZERO(s_t);
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret ? ERR_PTR(ret) : s_t;
}
@@ -142,7 +143,7 @@ bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor)
guard(rcu)();
struct snapshot_table *t = rcu_dereference(c->snapshots);
- if (unlikely(c->recovery.pass_done < BCH_RECOVERY_PASS_check_snapshots))
+ if (unlikely(recovery_pass_will_run(c, BCH_RECOVERY_PASS_check_snapshots)))
return __bch2_snapshot_is_ancestor_early(t, id, ancestor);
if (likely(ancestor >= IS_ANCESTOR_BITMAP))
@@ -364,31 +365,32 @@ int bch2_snapshot_lookup(struct btree_trans *trans, u32 id,
/* fsck: */
-static u32 bch2_snapshot_child(struct bch_fs *c, u32 id, unsigned child)
+static u32 bch2_snapshot_child(struct snapshot_table *t,
+ u32 id, unsigned child)
{
- return snapshot_t(c, id)->children[child];
+ return __snapshot_t(t, id)->children[child];
}
-static u32 bch2_snapshot_left_child(struct bch_fs *c, u32 id)
+static u32 bch2_snapshot_left_child(struct snapshot_table *t, u32 id)
{
- return bch2_snapshot_child(c, id, 0);
+ return bch2_snapshot_child(t, id, 0);
}
-static u32 bch2_snapshot_right_child(struct bch_fs *c, u32 id)
+static u32 bch2_snapshot_right_child(struct snapshot_table *t, u32 id)
{
- return bch2_snapshot_child(c, id, 1);
+ return bch2_snapshot_child(t, id, 1);
}
-static u32 bch2_snapshot_tree_next(struct bch_fs *c, u32 id)
+static u32 bch2_snapshot_tree_next(struct snapshot_table *t, u32 id)
{
u32 n, parent;
- n = bch2_snapshot_left_child(c, id);
+ n = bch2_snapshot_left_child(t, id);
if (n)
return n;
- while ((parent = bch2_snapshot_parent(c, id))) {
- n = bch2_snapshot_right_child(c, parent);
+ while ((parent = __bch2_snapshot_parent(t, id))) {
+ n = bch2_snapshot_right_child(t, parent);
if (n && n != id)
return n;
id = parent;
@@ -401,17 +403,18 @@ u32 bch2_snapshot_oldest_subvol(struct bch_fs *c, u32 snapshot_root,
snapshot_id_list *skip)
{
guard(rcu)();
+ struct snapshot_table *t = rcu_dereference(c->snapshots);
u32 id, subvol = 0, s;
retry:
id = snapshot_root;
- while (id && bch2_snapshot_exists(c, id)) {
+ while (id && __bch2_snapshot_exists(t, id)) {
if (!(skip && snapshot_list_has_id(skip, id))) {
- s = snapshot_t(c, id)->subvol;
+ s = __snapshot_t(t, id)->subvol;
if (s && (!subvol || s < subvol))
subvol = s;
}
- id = bch2_snapshot_tree_next(c, id);
+ id = bch2_snapshot_tree_next(t, id);
if (id == snapshot_root)
break;
}
@@ -447,7 +450,7 @@ static int bch2_snapshot_tree_master_subvol(struct btree_trans *trans,
break;
}
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (!ret && !found) {
struct bkey_i_subvolume *u;
@@ -560,7 +563,7 @@ static int check_snapshot_tree(struct btree_trans *trans,
out:
err:
fsck_err:
- bch2_trans_iter_exit(trans, &snapshot_iter);
+ bch2_trans_iter_exit(&snapshot_iter);
return ret;
}
@@ -682,7 +685,7 @@ static int snapshot_tree_ptr_repair(struct btree_trans *trans,
*s = u->v;
}
err:
- bch2_trans_iter_exit(trans, &root_iter);
+ bch2_trans_iter_exit(&root_iter);
return ret;
}
@@ -865,7 +868,7 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id)
break;
}
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (ret)
return ret;
@@ -895,7 +898,7 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id)
break;
}
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return bch2_snapshot_table_make_room(c, id) ?:
bch2_btree_insert_trans(trans, BTREE_ID_snapshots, &snapshot->k_i, 0);
@@ -973,12 +976,16 @@ int bch2_reconstruct_snapshots(struct bch_fs *c)
struct snapshot_tree_reconstruct r = {};
int ret = 0;
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, btree_has_snapshots_mask);
+
for (unsigned btree = 0; btree < BTREE_ID_NR; btree++) {
if (btree_type_has_snapshots(btree)) {
r.btree = btree;
ret = for_each_btree_key(trans, iter, btree, POS_MIN,
BTREE_ITER_all_snapshots|BTREE_ITER_prefetch, k, ({
+ progress_update_iter(trans, &progress, &iter);
get_snapshot_trees(c, &r, k.k->p);
}));
if (ret)
@@ -1093,7 +1100,7 @@ int __bch2_get_snapshot_overwrites(struct btree_trans *trans,
if (ret)
break;
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (ret)
darray_exit(s);
@@ -1125,7 +1132,7 @@ int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id)
SET_BCH_SNAPSHOT_SUBVOL(&s->v, false);
s->v.subvol = 0;
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -1250,10 +1257,10 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id)
set_bkey_val_u64s(&s->k, 0);
}
err:
- bch2_trans_iter_exit(trans, &tree_iter);
- bch2_trans_iter_exit(trans, &p_iter);
- bch2_trans_iter_exit(trans, &c_iter);
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&tree_iter);
+ bch2_trans_iter_exit(&p_iter);
+ bch2_trans_iter_exit(&c_iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -1263,35 +1270,30 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree,
unsigned nr_snapids)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter;
struct bkey_i_snapshot *n;
- struct bkey_s_c k;
- unsigned i, j;
u32 depth = bch2_snapshot_depth(c, parent);
- int ret;
- bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots,
- POS_MIN, BTREE_ITER_intent);
- k = bch2_btree_iter_peek(trans, &iter);
- ret = bkey_err(k);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_snapshots,
+ POS_MIN, BTREE_ITER_intent);
+ struct bkey_s_c k = bch2_btree_iter_peek(&iter);
+ int ret = bkey_err(k);
if (ret)
- goto err;
+ return ret;
- for (i = 0; i < nr_snapids; i++) {
- k = bch2_btree_iter_prev_slot(trans, &iter);
+ for (unsigned i = 0; i < nr_snapids; i++) {
+ k = bch2_btree_iter_prev_slot(&iter);
ret = bkey_err(k);
if (ret)
- goto err;
+ return ret;
if (!k.k || !k.k->p.offset) {
- ret = bch_err_throw(c, ENOSPC_snapshot_create);
- goto err;
+ return bch_err_throw(c, ENOSPC_snapshot_create);
}
n = bch2_bkey_alloc(trans, &iter, 0, snapshot);
ret = PTR_ERR_OR_ZERO(n);
if (ret)
- goto err;
+ return ret;
n->v.flags = 0;
n->v.parent = cpu_to_le32(parent);
@@ -1301,7 +1303,7 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree,
n->v.btime.lo = cpu_to_le64(bch2_current_time(c));
n->v.btime.hi = 0;
- for (j = 0; j < ARRAY_SIZE(n->v.skip); j++)
+ for (unsigned j = 0; j < ARRAY_SIZE(n->v.skip); j++)
n->v.skip[j] = cpu_to_le32(bch2_snapshot_skiplist_get(c, parent));
bubble_sort(n->v.skip, ARRAY_SIZE(n->v.skip), cmp_le32);
@@ -1310,13 +1312,12 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree,
ret = __bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
if (ret)
- goto err;
+ return ret;
new_snapids[i] = iter.pos.offset;
}
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+
+ return 0;
}
/*
@@ -1357,7 +1358,7 @@ static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 par
n_parent->v.subvol = 0;
SET_BCH_SNAPSHOT_SUBVOL(&n_parent->v, false);
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -1424,38 +1425,22 @@ static inline u32 interior_delete_has_id(interior_delete_list *l, u32 id)
return i ? i->live_child : 0;
}
-static unsigned __live_child(struct snapshot_table *t, u32 id,
- snapshot_id_list *delete_leaves,
- interior_delete_list *delete_interior)
-{
- struct snapshot_t *s = __snapshot_t(t, id);
- if (!s)
- return 0;
-
- for (unsigned i = 0; i < ARRAY_SIZE(s->children); i++)
- if (s->children[i] &&
- !snapshot_list_has_id(delete_leaves, s->children[i]) &&
- !interior_delete_has_id(delete_interior, s->children[i]))
- return s->children[i];
-
- for (unsigned i = 0; i < ARRAY_SIZE(s->children); i++) {
- u32 live_child = s->children[i]
- ? __live_child(t, s->children[i], delete_leaves, delete_interior)
- : 0;
- if (live_child)
- return live_child;
- }
-
- return 0;
-}
-
-static unsigned live_child(struct bch_fs *c, u32 id)
+static unsigned live_child(struct bch_fs *c, u32 start)
{
struct snapshot_delete *d = &c->snapshot_delete;
guard(rcu)();
- return __live_child(rcu_dereference(c->snapshots), id,
- &d->delete_leaves, &d->delete_interior);
+ struct snapshot_table *t = rcu_dereference(c->snapshots);
+
+ for (u32 id = bch2_snapshot_tree_next(t, start);
+ id && id != start;
+ id = bch2_snapshot_tree_next(t, id))
+ if (bch2_snapshot_is_leaf(c, id) &&
+ !snapshot_list_has_id(&d->delete_leaves, id) &&
+ !interior_delete_has_id(&d->delete_interior, id))
+ return id;
+
+ return 0;
}
static bool snapshot_id_dying(struct snapshot_delete *d, unsigned id)
@@ -1498,7 +1483,7 @@ static int delete_dead_snapshots_process_key(struct btree_trans *trans,
: 0) ?:
bch2_btree_delete_at(trans, iter,
BTREE_UPDATE_internal_snapshot_node);
- bch2_trans_iter_exit(trans, &dst_iter);
+ bch2_trans_iter_exit(&dst_iter);
return ret;
}
@@ -1526,7 +1511,7 @@ static bool skip_unrelated_snapshot_tree(struct btree_trans *trans, struct btree
pos.snapshot = 0;
if (iter->btree_id != BTREE_ID_inodes)
pos.offset = U64_MAX;
- bch2_btree_iter_set_pos(trans, iter, bpos_nosnap_successor(pos));
+ bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(pos));
}
return ret;
@@ -1604,7 +1589,7 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans)
while (1) {
struct bkey_s_c k;
ret = lockrestart_do(trans,
- bkey_err(k = bch2_btree_iter_peek(trans, &iter)));
+ bkey_err(k = bch2_btree_iter_peek(&iter)));
if (ret)
break;
@@ -1627,12 +1612,12 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans)
if (ret)
break;
- bch2_btree_iter_set_pos(trans, &iter, POS(0, k.k->p.offset + 1));
+ bch2_btree_iter_set_pos(&iter, POS(0, k.k->p.offset + 1));
} else {
- bch2_btree_iter_advance(trans, &iter);
+ bch2_btree_iter_advance(&iter);
}
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (ret)
goto err;
@@ -1712,12 +1697,14 @@ static inline u32 bch2_snapshot_nth_parent_skip(struct bch_fs *c, u32 id, u32 n,
interior_delete_list *skip)
{
guard(rcu)();
+ struct snapshot_table *t = rcu_dereference(c->snapshots);
+
while (interior_delete_has_id(skip, id))
- id = __bch2_snapshot_parent(c, id);
+ id = __bch2_snapshot_parent(t, id);
while (n--) {
do {
- id = __bch2_snapshot_parent(c, id);
+ id = __bch2_snapshot_parent(t, id);
} while (interior_delete_has_id(skip, id));
}
@@ -1960,7 +1947,7 @@ int __bch2_key_has_snapshot_overwrites(struct btree_trans *trans,
break;
}
}
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}