summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/btree_gc.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-12-30 14:37:25 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:36 -0400
commite3e464ac6d09269b19cea3dc32b626db44d0e6ba (patch)
tree7aafd377933161ed88573a5e3dab7ee3d8e0e06a /fs/bcachefs/btree_gc.c
parent57b0b3db475de6b724e4db3b827c00484cdde642 (diff)
downloadlinux-stable-e3e464ac6d09269b19cea3dc32b626db44d0e6ba.tar.gz
linux-stable-e3e464ac6d09269b19cea3dc32b626db44d0e6ba.tar.bz2
linux-stable-e3e464ac6d09269b19cea3dc32b626db44d0e6ba.zip
bcachefs: Move extent overwrite handling out of core btree code
Ever since the btree code was first written, handling of overwriting existing extents - including partially overwriting and splittin existing extents - was handled as part of the core btree insert path. The modern transaction and iterator infrastructure didn't exist then, so that was the only way for it to be done. This patch moves that outside of the core btree code to a pass that runs at transaction commit time. This is a significant simplification to the btree code and overall reduction in code size, but more importantly it gets us much closer to the core btree code being completely independent of extents and is important prep work for snapshots. This introduces a new feature bit; the old and new extent update models are incompatible when the filesystem needs journal replay. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_gc.c')
-rw-r--r--fs/bcachefs/btree_gc.c57
1 files changed, 22 insertions, 35 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index a5fe3b316e06..f85fbc057fb3 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -186,8 +186,16 @@ fsck_err:
return ret;
}
-static int btree_gc_mark_node(struct bch_fs *c, struct btree *b,
- u8 *max_stale, bool initial)
+static bool pos_in_journal_keys(struct journal_keys *journal_keys,
+ enum btree_id id, struct bpos pos)
+{
+ struct journal_key *k = journal_key_search(journal_keys, id, pos);
+
+ return k && k->btree_id == id && !bkey_cmp(k->k->k.p, pos);
+}
+
+static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, u8 *max_stale,
+ struct journal_keys *journal_keys, bool initial)
{
struct btree_node_iter iter;
struct bkey unpacked;
@@ -201,6 +209,10 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b,
for_each_btree_node_key_unpack(b, k, &iter,
&unpacked) {
+ if (!b->c.level && journal_keys &&
+ pos_in_journal_keys(journal_keys, b->c.btree_id, k.k->p))
+ continue;
+
bch2_bkey_debugcheck(c, b, k);
ret = bch2_gc_mark_key(c, k, max_stale, initial);
@@ -212,6 +224,7 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b,
}
static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
+ struct journal_keys *journal_keys,
bool initial, bool metadata_only)
{
struct btree_trans trans;
@@ -239,7 +252,8 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
gc_pos_set(c, gc_pos_btree_node(b));
- ret = btree_gc_mark_node(c, b, &max_stale, initial);
+ ret = btree_gc_mark_node(c, b, &max_stale,
+ journal_keys, initial);
if (ret)
break;
@@ -281,36 +295,6 @@ static inline int btree_id_gc_phase_cmp(enum btree_id l, enum btree_id r)
(int) btree_id_to_gc_phase(r);
}
-static int mark_journal_key(struct bch_fs *c, enum btree_id id,
- struct bkey_i *insert)
-{
- struct btree_trans trans;
- struct btree_iter *iter;
- struct bkey_s_c k;
- u8 max_stale;
- int ret = 0;
-
- ret = bch2_gc_mark_key(c, bkey_i_to_s_c(insert), &max_stale, true);
- if (ret)
- return ret;
-
- bch2_trans_init(&trans, c, 0, 0);
-
- for_each_btree_key(&trans, iter, id, bkey_start_pos(&insert->k),
- BTREE_ITER_SLOTS, k, ret) {
- percpu_down_read(&c->mark_lock);
- ret = bch2_mark_overwrite(&trans, iter, k, insert, NULL,
- BTREE_TRIGGER_GC|
- BTREE_TRIGGER_NOATOMIC);
- percpu_up_read(&c->mark_lock);
-
- if (!ret)
- break;
- }
-
- return bch2_trans_exit(&trans) ?: ret;
-}
-
static int bch2_gc_btrees(struct bch_fs *c, struct journal_keys *journal_keys,
bool initial, bool metadata_only)
{
@@ -325,18 +309,21 @@ static int bch2_gc_btrees(struct bch_fs *c, struct journal_keys *journal_keys,
enum btree_id id = ids[i];
enum btree_node_type type = __btree_node_type(0, id);
- int ret = bch2_gc_btree(c, id, initial, metadata_only);
+ int ret = bch2_gc_btree(c, id, journal_keys,
+ initial, metadata_only);
if (ret)
return ret;
if (journal_keys && !metadata_only &&
btree_node_type_needs_gc(type)) {
struct journal_key *j;
+ u8 max_stale;
int ret;
for_each_journal_key(*journal_keys, j)
if (j->btree_id == id) {
- ret = mark_journal_key(c, id, j->k);
+ ret = bch2_gc_mark_key(c, bkey_i_to_s_c(j->k),
+ &max_stale, initial);
if (ret)
return ret;
}