diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-12-19 23:03:15 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-05 18:15:37 -0500 |
commit | a5b170883f114d0620bb90040a16dfab6d6e18bb (patch) | |
tree | 6b124d28c68da1b4c8eb900e0624dbe7edbe7127 | |
parent | d541281b4eb68094e3a7dabf79b1718be9416a77 (diff) |
bcachefs: Use btree write buffer for backpointers
When average write size is small backpointers won't fit in alloc keys
and we'll have to spill over to the backpointers btree - which can
suffer from lock contention on multithreaded workloads, since unlock the
alloc btree it doesn't use the key cache.
This switches to using the write buffer for the backpointers btree,
which solves the lock contention problems and helps performance even on
non multithreaded workloads by aggregating the backpointers btree
updates and doing them in sorted order.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/backpointers.c | 107 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/btree_write_buffer.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/btree_write_buffer_types.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/ec.c | 8 |
5 files changed, 35 insertions, 100 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 7d4367f93b5c..8b83992f3963 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -208,8 +208,7 @@ int bch2_bucket_backpointer_del(struct btree_trans *trans, struct bch_fs *c = trans->c; struct bch_backpointer *bps = alloc_v4_backpointers(&a->v); unsigned i, nr = BCH_ALLOC_V4_NR_BACKPOINTERS(&a->v); - struct btree_iter bp_iter; - struct bkey_s_c k; + struct bkey_i *delete; int ret; for (i = 0; i < nr; i++) { @@ -228,52 +227,15 @@ found: set_alloc_v4_u64s(a); return 0; btree: - bch2_trans_iter_init(trans, &bp_iter, BTREE_ID_backpointers, - bucket_pos_to_bp(c, a->k.p, bp.bucket_offset), - BTREE_ITER_INTENT| - BTREE_ITER_SLOTS| - BTREE_ITER_WITH_UPDATES); - k = bch2_btree_iter_peek_slot(&bp_iter); - ret = bkey_err(k); + delete = bch2_trans_kmalloc_nomemzero(trans, sizeof(*delete)); + ret = PTR_ERR_OR_ZERO(delete); if (ret) - goto err; - - if (k.k->type != KEY_TYPE_backpointer || - memcmp(bkey_s_c_to_backpointer(k).v, &bp, sizeof(bp))) { - struct printbuf buf = PRINTBUF; - - prt_printf(&buf, "backpointer not found when deleting"); - prt_newline(&buf); - printbuf_indent_add(&buf, 2); - - prt_printf(&buf, "searching for "); - bch2_backpointer_to_text(&buf, &bp); - prt_newline(&buf); - - prt_printf(&buf, "got "); - bch2_bkey_val_to_text(&buf, c, k); - prt_newline(&buf); - - prt_str(&buf, "alloc "); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&a->k_i)); - prt_newline(&buf); + return ret; - prt_printf(&buf, "for "); - bch2_bkey_val_to_text(&buf, c, orig_k); + bkey_init(&delete->k); + delete->k.p = bucket_pos_to_bp(c, a->k.p, bp.bucket_offset); - bch_err(c, "%s", buf.buf); - if (test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) { - bch2_inconsistent_error(c); - ret = -EIO; - } - printbuf_exit(&buf); - goto err; - } - - ret = bch2_btree_delete_at(trans, &bp_iter, 0); -err: - bch2_trans_iter_exit(trans, &bp_iter); - return ret; + return bch2_trans_update_buffered(trans, BTREE_ID_backpointers, delete); } int bch2_bucket_backpointer_add(struct btree_trans *trans, @@ -282,13 +244,11 @@ int bch2_bucket_backpointer_add(struct btree_trans *trans, struct bkey_s_c orig_k) { struct bch_fs *c = trans->c; - struct bch_backpointer *bps = alloc_v4_backpointers(&a->v); - unsigned i, nr = BCH_ALLOC_V4_NR_BACKPOINTERS(&a->v); struct bkey_i_backpointer *bp_k; - struct btree_iter bp_iter; - struct bkey_s_c k; int ret; - +#if 0 + struct bch_backpointer *bps = alloc_v4_backpointers(&a->v); + unsigned i, nr = BCH_ALLOC_V4_NR_BACKPOINTERS(&a->v); /* Check for duplicates: */ for (i = 0; i < nr; i++) { int cmp = backpointer_cmp(bps[i], bp); @@ -331,52 +291,17 @@ int bch2_bucket_backpointer_add(struct btree_trans *trans, } /* Overflow: use backpointer btree */ - - bch2_trans_iter_init(trans, &bp_iter, BTREE_ID_backpointers, - bucket_pos_to_bp(c, a->k.p, bp.bucket_offset), - BTREE_ITER_INTENT| - BTREE_ITER_SLOTS| - BTREE_ITER_WITH_UPDATES); - k = bch2_btree_iter_peek_slot(&bp_iter); - ret = bkey_err(k); - if (ret) - goto err; - - if (k.k->type) { - struct printbuf buf = PRINTBUF; - - prt_printf(&buf, "existing btree backpointer key found when inserting "); - bch2_backpointer_to_text(&buf, &bp); - prt_newline(&buf); - printbuf_indent_add(&buf, 2); - - prt_printf(&buf, "found "); - bch2_bkey_val_to_text(&buf, c, k); - prt_newline(&buf); - - prt_printf(&buf, "for "); - bch2_bkey_val_to_text(&buf, c, orig_k); - - bch_err(c, "%s", buf.buf); - printbuf_exit(&buf); - if (test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) { - bch2_inconsistent_error(c); - ret = -EIO; - goto err; - } - } - - bp_k = bch2_bkey_alloc(trans, &bp_iter, backpointer); +#endif + bp_k = bch2_trans_kmalloc_nomemzero(trans, sizeof(struct bkey_i_backpointer)); ret = PTR_ERR_OR_ZERO(bp_k); if (ret) - goto err; + return ret; + bkey_backpointer_init(&bp_k->k_i); + bp_k->k.p = bucket_pos_to_bp(c, a->k.p, bp.bucket_offset); bp_k->v = bp; - ret = bch2_trans_update(trans, &bp_iter, &bp_k->k_i, 0); -err: - bch2_trans_iter_exit(trans, &bp_iter); - return ret; + return bch2_trans_update_buffered(trans, BTREE_ID_backpointers, &bp_k->k_i); } /* diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 07a18b623475..475a26a3736e 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -1658,7 +1658,8 @@ int __must_check bch2_trans_update_buffered(struct btree_trans *trans, { int ret; - BUG_ON(trans->nr_wb_updates > trans->wb_updates_size); + EBUG_ON(trans->nr_wb_updates > trans->wb_updates_size); + EBUG_ON(k->k.u64s > BTREE_WRITE_BUFERED_U64s_MAX); if (!trans->wb_updates || trans->nr_wb_updates == trans->wb_updates_size) { @@ -1686,11 +1687,13 @@ int __must_check bch2_trans_update_buffered(struct btree_trans *trans, trans->wb_updates = u; } - trans->wb_updates[trans->nr_wb_updates++] = (struct btree_write_buffered_key) { + trans->wb_updates[trans->nr_wb_updates] = (struct btree_write_buffered_key) { .btree = btree, - .k = *k, }; + bkey_copy(&trans->wb_updates[trans->nr_wb_updates].k, k); + trans->nr_wb_updates++; + return 0; } diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index b5a419e1960a..c9208596628c 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c @@ -172,7 +172,7 @@ int bch2_btree_insert_keys_write_buffer(struct btree_trans *trans) struct btree_write_buffered_key *i; unsigned u64s = 0; - BUG_ON(trans->flags & BTREE_INSERT_JOURNAL_REPLAY); + EBUG_ON(trans->flags & BTREE_INSERT_JOURNAL_REPLAY); mutex_lock(&wb->lock); if (wb->nr + trans->nr_wb_updates > wb->size) { @@ -181,7 +181,7 @@ int bch2_btree_insert_keys_write_buffer(struct btree_trans *trans) } trans_for_each_wb_update(trans, i) { - BUG_ON(i->k.k.u64s != BKEY_U64s); + EBUG_ON(i->k.k.u64s > BTREE_WRITE_BUFERED_U64s_MAX); i->journal_seq = trans->journal_res.seq; i->journal_offset = trans->journal_res.offset; @@ -195,7 +195,7 @@ int bch2_btree_insert_keys_write_buffer(struct btree_trans *trans) wb->nr += trans->nr_wb_updates; if (likely(!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))) { - BUG_ON(u64s > trans->journal_preres.u64s); + EBUG_ON(u64s > trans->journal_preres.u64s); trans->journal_preres.u64s -= u64s; wb->res.u64s += u64s; diff --git a/fs/bcachefs/btree_write_buffer_types.h b/fs/bcachefs/btree_write_buffer_types.h index a6a9489afce9..a5bcb196e40f 100644 --- a/fs/bcachefs/btree_write_buffer_types.h +++ b/fs/bcachefs/btree_write_buffer_types.h @@ -4,11 +4,14 @@ #include "journal_types.h" +#define BTREE_WRITE_BUFERED_VAL_U64s_MAX 4 +#define BTREE_WRITE_BUFERED_U64s_MAX (BKEY_U64s + BTREE_WRITE_BUFERED_VAL_U64s_MAX) + struct btree_write_buffered_key { u64 journal_seq; unsigned journal_offset; enum btree_id btree; - struct bkey_i k; + __BKEY_PADDED(k, BTREE_WRITE_BUFERED_VAL_U64s_MAX); }; struct btree_write_buffer { diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 9da79651e967..7fed06326701 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -9,6 +9,7 @@ #include "bset.h" #include "btree_gc.h" #include "btree_update.h" +#include "btree_write_buffer.h" #include "buckets.h" #include "disk_groups.h" #include "ec.h" @@ -913,13 +914,16 @@ static int ec_stripe_update_extents(struct bch_fs *c, struct ec_stripe_buf *s) bch2_trans_init(&trans, c, 0, 0); + ret = bch2_btree_write_buffer_flush(&trans); + if (ret) + goto err; + for (i = 0; i < nr_data; i++) { ret = ec_stripe_update_bucket(&trans, s, i); if (ret) break; } - - +err: bch2_trans_exit(&trans); return ret; |