summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/alloc_background.c5
-rw-r--r--fs/bcachefs/btree_trans_commit.c10
-rw-r--r--fs/bcachefs/btree_types.h12
-rw-r--r--fs/bcachefs/journal.c3
-rw-r--r--fs/bcachefs/journal.h2
-rw-r--r--fs/bcachefs/snapshot.c39
-rw-r--r--fs/bcachefs/snapshot.h30
7 files changed, 63 insertions, 38 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index afc0ab75abf6..55c21e9b4c52 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -1554,6 +1554,9 @@ int bch2_check_alloc_info(struct bch_fs *c)
struct bkey_s_c k;
int ret = 0;
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_alloc));
+
CLASS(btree_trans, trans)(c);
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_prefetch);
@@ -1577,6 +1580,8 @@ int bch2_check_alloc_info(struct bch_fs *c)
if (!k.k)
break;
+ progress_update_iter(trans, &progress, &iter);
+
if (k.k->type) {
next = bpos_nosnap_successor(k.k->p);
diff --git a/fs/bcachefs/btree_trans_commit.c b/fs/bcachefs/btree_trans_commit.c
index 58590ccc26bd..8b94a8156fbf 100644
--- a/fs/bcachefs/btree_trans_commit.c
+++ b/fs/bcachefs/btree_trans_commit.c
@@ -969,7 +969,7 @@ do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans,
BUG_ON(current != c->recovery_task);
struct bkey_i *accounting;
-
+retry:
percpu_down_read(&c->mark_lock);
for (accounting = btree_trans_subbuf_base(trans, &trans->accounting);
accounting != btree_trans_subbuf_top(trans, &trans->accounting);
@@ -1025,13 +1025,17 @@ fatal_err:
bch2_fs_fatal_error(c, "fatal error in transaction commit: %s", bch2_err_str(ret));
percpu_down_read(&c->mark_lock);
revert_fs_usage:
- BUG();
- /* error path not handled by __bch2_trans_commit() */
for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
i != accounting;
i = bkey_next(i))
bch2_accounting_trans_commit_revert(trans, bkey_i_to_accounting(i), flags);
percpu_up_read(&c->mark_lock);
+
+ if (bch2_err_matches(ret, BCH_ERR_btree_insert_need_mark_replicas)) {
+ ret = drop_locks_do(trans, bch2_accounting_update_sb(trans));
+ if (!ret)
+ goto retry;
+ }
return ret;
}
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 76adf75617aa..e6177b747216 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -854,15 +854,15 @@ static inline bool btree_node_type_is_extents(enum btree_node_type type)
return type != BKEY_TYPE_btree && btree_id_is_extents(type - 1);
}
-static inline bool btree_type_has_snapshots(enum btree_id btree)
-{
- const u64 mask = 0
+static const u64 btree_has_snapshots_mask = 0
#define x(name, nr, flags, ...) |((!!((flags) & BTREE_IS_snapshots)) << nr)
- BCH_BTREE_IDS()
+BCH_BTREE_IDS()
#undef x
- ;
+;
- return BIT_ULL(btree) & mask;
+static inline bool btree_type_has_snapshots(enum btree_id btree)
+{
+ return BIT_ULL(btree) & btree_has_snapshots_mask;
}
static inline bool btree_type_has_snapshot_field(enum btree_id btree)
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index f9e2e1a4e415..a4f43c550ad7 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1060,14 +1060,13 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou
if (open && !*blocked) {
__bch2_journal_block(j);
+ s.v = atomic64_read_acquire(&j->reservations.counter);
*blocked = true;
}
ret = journal_state_count(s, idx & JOURNAL_STATE_BUF_MASK) > open
? ERR_PTR(-EAGAIN)
: buf;
- if (!IS_ERR(ret))
- smp_mb();
break;
}
}
diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h
index c05aa94237f8..b46b9718d841 100644
--- a/fs/bcachefs/journal.h
+++ b/fs/bcachefs/journal.h
@@ -267,7 +267,7 @@ static inline union journal_res_state journal_state_buf_put(struct journal *j, u
{
union journal_res_state s;
- s.v = atomic64_sub_return_release(((union journal_res_state) {
+ s.v = atomic64_sub_return(((union journal_res_state) {
.buf0_count = idx == 0,
.buf1_count = idx == 1,
.buf2_count = idx == 2,
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c
index af3fae33b5ba..8c24e2a93041 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"
@@ -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;
}
@@ -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)
@@ -1712,12 +1719,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));
}
diff --git a/fs/bcachefs/snapshot.h b/fs/bcachefs/snapshot.h
index 6dcb118b0fbd..fef32a0118c4 100644
--- a/fs/bcachefs/snapshot.h
+++ b/fs/bcachefs/snapshot.h
@@ -63,19 +63,19 @@ static inline u32 bch2_snapshot_parent_early(struct bch_fs *c, u32 id)
return __bch2_snapshot_parent_early(c, id);
}
-static inline u32 __bch2_snapshot_parent(struct bch_fs *c, u32 id)
+static inline u32 __bch2_snapshot_parent(struct snapshot_table *t, u32 id)
{
- const struct snapshot_t *s = snapshot_t(c, id);
+ const struct snapshot_t *s = __snapshot_t(t, id);
if (!s)
return 0;
u32 parent = s->parent;
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG) &&
parent &&
- s->depth != snapshot_t(c, parent)->depth + 1)
+ s->depth != __snapshot_t(t, parent)->depth + 1)
panic("id %u depth=%u parent %u depth=%u\n",
- id, snapshot_t(c, id)->depth,
- parent, snapshot_t(c, parent)->depth);
+ id, __snapshot_t(t, id)->depth,
+ parent, __snapshot_t(t, parent)->depth);
return parent;
}
@@ -83,14 +83,16 @@ static inline u32 __bch2_snapshot_parent(struct bch_fs *c, u32 id)
static inline u32 bch2_snapshot_parent(struct bch_fs *c, u32 id)
{
guard(rcu)();
- return __bch2_snapshot_parent(c, id);
+ return __bch2_snapshot_parent(rcu_dereference(c->snapshots), id);
}
static inline u32 bch2_snapshot_nth_parent(struct bch_fs *c, u32 id, u32 n)
{
guard(rcu)();
+ struct snapshot_table *t = rcu_dereference(c->snapshots);
+
while (n--)
- id = __bch2_snapshot_parent(c, id);
+ id = __bch2_snapshot_parent(t, id);
return id;
}
@@ -100,23 +102,29 @@ u32 bch2_snapshot_skiplist_get(struct bch_fs *, u32);
static inline u32 bch2_snapshot_root(struct bch_fs *c, u32 id)
{
guard(rcu)();
+ struct snapshot_table *t = rcu_dereference(c->snapshots);
u32 parent;
- while ((parent = __bch2_snapshot_parent(c, id)))
+ while ((parent = __bch2_snapshot_parent(t, id)))
id = parent;
return id;
}
-static inline enum snapshot_id_state __bch2_snapshot_id_state(struct bch_fs *c, u32 id)
+static inline enum snapshot_id_state __bch2_snapshot_id_state(struct snapshot_table *t, u32 id)
{
- const struct snapshot_t *s = snapshot_t(c, id);
+ const struct snapshot_t *s = __snapshot_t(t, id);
return s ? s->state : SNAPSHOT_ID_empty;
}
static inline enum snapshot_id_state bch2_snapshot_id_state(struct bch_fs *c, u32 id)
{
guard(rcu)();
- return __bch2_snapshot_id_state(c, id);
+ return __bch2_snapshot_id_state(rcu_dereference(c->snapshots), id);
+}
+
+static inline bool __bch2_snapshot_exists(struct snapshot_table *t, u32 id)
+{
+ return __bch2_snapshot_id_state(t, id) == SNAPSHOT_ID_live;
}
static inline bool bch2_snapshot_exists(struct bch_fs *c, u32 id)