Skip to content

Commit fb23d57

Browse files
author
Kent Overstreet
committed
bcachefs: Convert gc to new accounting
Rewrite fsck/gc for the new accounting scheme. This adds a second set of in-memory accounting counters for gc to use; like with other parts of gc we run all trigger in TRIGGER_GC mode, then compare what we calculated to existing in-memory accounting at the end. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 4c4a7d4 commit fb23d57

17 files changed

+343
-576
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ static inline int bch2_dev_data_type_accounting_mod(struct btree_trans *trans, s
774774
};
775775
s64 d[3] = { delta_buckets, delta_sectors, delta_fragmented };
776776

777-
return bch2_disk_accounting_mod(trans, &acc, d, 3);
777+
return bch2_disk_accounting_mod(trans, &acc, d, 3, flags & BTREE_TRIGGER_gc);
778778
}
779779

780780
int bch2_alloc_key_to_dev_counters(struct btree_trans *trans, struct bch_dev *ca,
@@ -894,7 +894,8 @@ int bch2_trigger_alloc(struct btree_trans *trans,
894894
if ((flags & BTREE_TRIGGER_bucket_invalidate) &&
895895
old_a->cached_sectors) {
896896
ret = bch2_mod_dev_cached_sectors(trans, ca->dev_idx,
897-
-((s64) old_a->cached_sectors));
897+
-((s64) old_a->cached_sectors),
898+
flags & BTREE_TRIGGER_gc);
898899
if (ret)
899900
goto err;
900901
}
@@ -973,35 +974,6 @@ int bch2_trigger_alloc(struct btree_trans *trans,
973974
if (statechange(a->data_type == BCH_DATA_need_gc_gens))
974975
bch2_gc_gens_async(c);
975976
}
976-
977-
if ((flags & BTREE_TRIGGER_gc) &&
978-
(flags & BTREE_TRIGGER_bucket_invalidate)) {
979-
struct bch_alloc_v4 new_a_convert;
980-
const struct bch_alloc_v4 *new_a = bch2_alloc_to_v4(new.s_c, &new_a_convert);
981-
982-
percpu_down_read(&c->mark_lock);
983-
struct bucket *g = gc_bucket(ca, new.k->p.offset);
984-
if (unlikely(!g)) {
985-
percpu_up_read(&c->mark_lock);
986-
goto invalid_bucket;
987-
}
988-
g->gen_valid = 1;
989-
990-
bucket_lock(g);
991-
992-
g->gen_valid = 1;
993-
g->gen = new_a->gen;
994-
g->data_type = new_a->data_type;
995-
g->stripe = new_a->stripe;
996-
g->stripe_redundancy = new_a->stripe_redundancy;
997-
g->dirty_sectors = new_a->dirty_sectors;
998-
g->cached_sectors = new_a->cached_sectors;
999-
1000-
bucket_unlock(g);
1001-
percpu_up_read(&c->mark_lock);
1002-
1003-
bch2_dev_usage_update(c, ca, old_a, new_a);
1004-
}
1005977
err:
1006978
printbuf_exit(&buf);
1007979
bch2_dev_put(ca);

fs/bcachefs/alloc_foreground.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,15 +1708,13 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
17081708

17091709
prt_printf(out, "capacity\t%llu\n", c->capacity);
17101710
prt_printf(out, "reserved\t%llu\n", c->reserved);
1711-
percpu_down_read(&c->mark_lock);
1712-
prt_printf(out, "hidden\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.hidden));
1713-
prt_printf(out, "btree\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.btree));
1714-
prt_printf(out, "data\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.data));
1715-
prt_printf(out, "cached\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.cached));
1716-
prt_printf(out, "reserved\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.reserved));
1717-
prt_printf(out, "online_reserved\t%llu\n", percpu_u64_get(c->online_reserved));
1718-
prt_printf(out, "nr_inodes\t%llu\n", bch2_fs_usage_read_one(c, &c->usage_base->b.nr_inodes));
1719-
percpu_up_read(&c->mark_lock);
1711+
prt_printf(out, "hidden\t%llu\n", percpu_u64_get(&c->usage->hidden));
1712+
prt_printf(out, "btree\t%llu\n", percpu_u64_get(&c->usage->btree));
1713+
prt_printf(out, "data\t%llu\n", percpu_u64_get(&c->usage->data));
1714+
prt_printf(out, "cached\t%llu\n", percpu_u64_get(&c->usage->cached));
1715+
prt_printf(out, "reserved\t%llu\n", percpu_u64_get(&c->usage->reserved));
1716+
prt_printf(out, "online_reserved\t%llu\n", percpu_u64_get(c->online_reserved));
1717+
prt_printf(out, "nr_inodes\t%llu\n", percpu_u64_get(&c->usage->nr_inodes));
17201718

17211719
prt_newline(out);
17221720
prt_printf(out, "freelist_wait\t%s\n", c->freelist_wait.list.first ? "waiting" : "empty");

fs/bcachefs/bcachefs.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,6 @@ struct bch_dev {
546546
struct rw_semaphore bucket_lock;
547547

548548
struct bch_dev_usage __percpu *usage;
549-
struct bch_dev_usage __percpu *usage_gc;
550549

551550
/* Allocator: */
552551
u64 new_fs_bucket_idx;
@@ -741,7 +740,7 @@ struct bch_fs {
741740

742741
struct bch_dev __rcu *devs[BCH_SB_MEMBERS_MAX];
743742

744-
struct bch_accounting_mem accounting;
743+
struct bch_accounting_mem accounting[2];
745744

746745
struct bch_replicas_cpu replicas;
747746
struct bch_replicas_cpu replicas_gc;
@@ -890,7 +889,6 @@ struct bch_fs {
890889

891890
seqcount_t usage_lock;
892891
struct bch_fs_usage_base __percpu *usage;
893-
struct bch_fs_usage __percpu *usage_gc;
894892
u64 __percpu *online_reserved;
895893

896894
struct io_clock io_clock[2];

fs/bcachefs/btree_gc.c

Lines changed: 16 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "buckets.h"
2121
#include "clock.h"
2222
#include "debug.h"
23+
#include "disk_accounting.h"
2324
#include "ec.h"
2425
#include "error.h"
2526
#include "extents.h"
@@ -735,132 +736,25 @@ static int bch2_mark_superblocks(struct bch_fs *c)
735736

736737
static void bch2_gc_free(struct bch_fs *c)
737738
{
739+
bch2_accounting_free(&c->accounting[1]);
740+
738741
genradix_free(&c->reflink_gc_table);
739742
genradix_free(&c->gc_stripes);
740743

741744
for_each_member_device(c, ca) {
742745
kvfree(rcu_dereference_protected(ca->buckets_gc, 1));
743746
ca->buckets_gc = NULL;
744-
745-
free_percpu(ca->usage_gc);
746-
ca->usage_gc = NULL;
747-
}
748-
749-
free_percpu(c->usage_gc);
750-
c->usage_gc = NULL;
751-
}
752-
753-
static int bch2_gc_done(struct bch_fs *c)
754-
{
755-
struct bch_dev *ca = NULL;
756-
struct printbuf buf = PRINTBUF;
757-
unsigned i;
758-
int ret = 0;
759-
760-
percpu_down_write(&c->mark_lock);
761-
762-
#define copy_field(_err, _f, _msg, ...) \
763-
if (fsck_err_on(dst->_f != src->_f, c, _err, \
764-
_msg ": got %llu, should be %llu" , ##__VA_ARGS__, \
765-
dst->_f, src->_f)) \
766-
dst->_f = src->_f
767-
#define copy_dev_field(_err, _f, _msg, ...) \
768-
copy_field(_err, _f, "dev %u has wrong " _msg, ca->dev_idx, ##__VA_ARGS__)
769-
#define copy_fs_field(_err, _f, _msg, ...) \
770-
copy_field(_err, _f, "fs has wrong " _msg, ##__VA_ARGS__)
771-
772-
__for_each_member_device(c, ca) {
773-
/* XXX */
774-
struct bch_dev_usage *dst = this_cpu_ptr(ca->usage);
775-
struct bch_dev_usage *src = (void *)
776-
bch2_acc_percpu_u64s((u64 __percpu *) ca->usage_gc,
777-
dev_usage_u64s());
778-
779-
for (i = 0; i < BCH_DATA_NR; i++) {
780-
copy_dev_field(dev_usage_buckets_wrong,
781-
d[i].buckets, "%s buckets", bch2_data_type_str(i));
782-
copy_dev_field(dev_usage_sectors_wrong,
783-
d[i].sectors, "%s sectors", bch2_data_type_str(i));
784-
copy_dev_field(dev_usage_fragmented_wrong,
785-
d[i].fragmented, "%s fragmented", bch2_data_type_str(i));
786-
}
787747
}
788-
789-
{
790-
#if 0
791-
unsigned nr = fs_usage_u64s(c);
792-
/* XX: */
793-
struct bch_fs_usage *dst = this_cpu_ptr(c->usage);
794-
struct bch_fs_usage *src = (void *)
795-
bch2_acc_percpu_u64s((u64 __percpu *) c->usage_gc, nr);
796-
797-
copy_fs_field(fs_usage_hidden_wrong,
798-
b.hidden, "hidden");
799-
copy_fs_field(fs_usage_btree_wrong,
800-
b.btree, "btree");
801-
802-
copy_fs_field(fs_usage_data_wrong,
803-
b.data, "data");
804-
copy_fs_field(fs_usage_cached_wrong,
805-
b.cached, "cached");
806-
copy_fs_field(fs_usage_reserved_wrong,
807-
b.reserved, "reserved");
808-
copy_fs_field(fs_usage_nr_inodes_wrong,
809-
b.nr_inodes,"nr_inodes");
810-
811-
for (i = 0; i < BCH_REPLICAS_MAX; i++)
812-
copy_fs_field(fs_usage_persistent_reserved_wrong,
813-
persistent_reserved[i],
814-
"persistent_reserved[%i]", i);
815-
816-
for (i = 0; i < c->replicas.nr; i++) {
817-
struct bch_replicas_entry_v1 *e =
818-
cpu_replicas_entry(&c->replicas, i);
819-
820-
printbuf_reset(&buf);
821-
bch2_replicas_entry_to_text(&buf, e);
822-
823-
copy_fs_field(fs_usage_replicas_wrong,
824-
replicas[i], "%s", buf.buf);
825-
}
826-
#endif
827-
}
828-
829-
#undef copy_fs_field
830-
#undef copy_dev_field
831-
#undef copy_stripe_field
832-
#undef copy_field
833-
fsck_err:
834-
bch2_dev_put(ca);
835-
bch_err_fn(c, ret);
836-
percpu_up_write(&c->mark_lock);
837-
printbuf_exit(&buf);
838-
return ret;
839748
}
840749

841750
static int bch2_gc_start(struct bch_fs *c)
842751
{
843-
BUG_ON(c->usage_gc);
844-
845-
c->usage_gc = __alloc_percpu_gfp(fs_usage_u64s(c) * sizeof(u64),
846-
sizeof(u64), GFP_KERNEL);
847-
if (!c->usage_gc) {
848-
bch_err(c, "error allocating c->usage_gc");
849-
return -BCH_ERR_ENOMEM_gc_start;
850-
}
851-
852752
for_each_member_device(c, ca) {
853-
BUG_ON(ca->usage_gc);
854-
855-
ca->usage_gc = alloc_percpu(struct bch_dev_usage);
856-
if (!ca->usage_gc) {
857-
bch_err(c, "error allocating ca->usage_gc");
753+
int ret = bch2_dev_usage_init(ca, true);
754+
if (ret) {
858755
bch2_dev_put(ca);
859-
return -BCH_ERR_ENOMEM_gc_start;
756+
return ret;
860757
}
861-
862-
this_cpu_write(ca->usage_gc->d[BCH_DATA_free].buckets,
863-
ca->mi.nbuckets - ca->mi.first_bucket);
864758
}
865759

866760
return 0;
@@ -908,6 +802,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
908802
gc.data_type = old->data_type;
909803
gc.dirty_sectors = old->dirty_sectors;
910804
}
805+
percpu_up_read(&c->mark_lock);
911806

912807
/*
913808
* gc.data_type doesn't yet include need_discard & need_gc_gen states -
@@ -916,9 +811,11 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
916811
alloc_data_type_set(&gc, gc.data_type);
917812

918813
if (gc.data_type != old_gc.data_type ||
919-
gc.dirty_sectors != old_gc.dirty_sectors)
920-
bch2_dev_usage_update(c, ca, &old_gc, &gc);
921-
percpu_up_read(&c->mark_lock);
814+
gc.dirty_sectors != old_gc.dirty_sectors) {
815+
ret = bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc);
816+
if (ret)
817+
return ret;
818+
}
922819

923820
gc.fragmentation_lru = alloc_lru_idx_fragmentation(gc, ca);
924821

@@ -1235,7 +1132,9 @@ int bch2_check_allocations(struct bch_fs *c)
12351132
gc_pos_set(c, gc_phase(GC_PHASE_start));
12361133

12371134
ret = bch2_mark_superblocks(c);
1238-
BUG_ON(ret);
1135+
bch_err_msg(c, ret, "marking superblocks");
1136+
if (ret)
1137+
goto out;
12391138

12401139
ret = bch2_gc_btrees(c);
12411140
if (ret)
@@ -1246,7 +1145,7 @@ int bch2_check_allocations(struct bch_fs *c)
12461145
bch2_journal_block(&c->journal);
12471146
out:
12481147
ret = bch2_gc_alloc_done(c) ?:
1249-
bch2_gc_done(c) ?:
1148+
bch2_accounting_gc_done(c) ?:
12501149
bch2_gc_stripes_done(c) ?:
12511150
bch2_gc_reflink_done(c);
12521151

fs/bcachefs/btree_trans_commit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
724724
a->k.version = journal_pos_to_bversion(&trans->journal_res,
725725
(u64 *) entry - (u64 *) trans->journal_entries);
726726
BUG_ON(bversion_zero(a->k.version));
727-
ret = bch2_accounting_mem_mod(trans, accounting_i_to_s_c(a));
727+
ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), false);
728728
if (ret)
729729
goto revert_fs_usage;
730730
}
@@ -812,7 +812,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
812812
struct bkey_s_accounting a = bkey_i_to_s_accounting(entry2->start);
813813

814814
bch2_accounting_neg(a);
815-
bch2_accounting_mem_mod(trans, a.c);
815+
bch2_accounting_mem_mod_locked(trans, a.c, false);
816816
bch2_accounting_neg(a);
817817
}
818818
percpu_up_read(&c->mark_lock);

0 commit comments

Comments
 (0)