bcachefs: bch2_bucket_alloc_new_fs() no longer depends on bucket marks

Now that bch2_bucket_alloc_new_fs() isn't looking at bucket marks to
decide what buckets are eligible to allocate, we can clean up the
filesystem initialization and device add paths. Previously, we had to
use ancient code to mark superblock/journal buckets in the in memory
bucket marks as we allocated them, and then zero that out and re-do that
marking using the newer transational bucket mark paths. Now, we can
simply delete the in-memory bucket marking.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
Kent Overstreet 2021-12-24 04:27:01 -05:00 committed by Kent Overstreet
parent 09943313d7
commit 77170d0dd7
6 changed files with 19 additions and 106 deletions

View file

@ -1056,23 +1056,13 @@ static void mark_metadata_sectors(struct bch_fs *c, struct bch_dev *ca,
} while (start < end);
}
void bch2_mark_dev_superblock(struct bch_fs *c, struct bch_dev *ca,
unsigned flags)
static void bch2_mark_dev_superblock(struct bch_fs *c, struct bch_dev *ca,
unsigned flags)
{
struct bch_sb_layout *layout = &ca->disk_sb.sb->layout;
unsigned i;
u64 b;
/*
* This conditional is kind of gross, but we may be called from the
* device add path, before the new device has actually been added to the
* running filesystem:
*/
if (c) {
lockdep_assert_held(&c->sb_lock);
percpu_down_read(&c->mark_lock);
}
for (i = 0; i < layout->nr_superblocks; i++) {
u64 offset = le64_to_cpu(layout->sb_offset[i]);
@ -1091,9 +1081,6 @@ void bch2_mark_dev_superblock(struct bch_fs *c, struct bch_dev *ca,
ca->mi.bucket_size,
gc_phase(GC_PHASE_SB), flags);
}
if (c)
percpu_up_read(&c->mark_lock);
}
static void bch2_mark_superblocks(struct bch_fs *c)

View file

@ -8,7 +8,6 @@ int bch2_gc(struct bch_fs *, bool, bool);
int bch2_gc_gens(struct bch_fs *);
void bch2_gc_thread_stop(struct bch_fs *);
int bch2_gc_thread_start(struct bch_fs *);
void bch2_mark_dev_superblock(struct bch_fs *, struct bch_dev *, unsigned);
/*
* For concurrent mark and sweep (with other index updates), we define a total

View file

@ -369,13 +369,6 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
struct bch_fs_usage *fs_usage;
struct bch_dev_usage *u;
/*
* Hack for bch2_fs_initialize path, where we're first marking sb and
* journal non-transactionally:
*/
if (!journal_seq && !test_bit(BCH_FS_INITIALIZED, &c->flags))
journal_seq = 1;
preempt_disable();
fs_usage = fs_usage_ptr(c, journal_seq, gc);
u = dev_usage_ptr(ca, journal_seq, gc);
@ -536,19 +529,6 @@ static inline void update_cached_sectors_list(struct btree_trans *trans,
update_replicas_list(trans, &r.e, sectors);
}
#define do_mark_fn(fn, c, pos, flags, ...) \
({ \
int gc, ret = 0; \
\
percpu_rwsem_assert_held(&c->mark_lock); \
\
for (gc = 0; gc < 2 && !ret; gc++) \
if (!gc == !(flags & BTREE_TRIGGER_GC) || \
(gc && gc_visited(c, pos))) \
ret = fn(c, __VA_ARGS__, gc); \
ret; \
})
void bch2_mark_alloc_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, bool owned_by_allocator)
{
@ -659,17 +639,27 @@ static int bch2_mark_alloc(struct btree_trans *trans,
overflow; \
})
static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, enum bch_data_type data_type,
unsigned sectors, bool gc)
void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, enum bch_data_type data_type,
unsigned sectors, struct gc_pos pos,
unsigned flags)
{
struct bucket *g = __bucket(ca, b, gc);
struct bucket *g;
struct bucket_mark old, new;
bool overflow;
BUG_ON(!(flags & BTREE_TRIGGER_GC));
BUG_ON(data_type != BCH_DATA_sb &&
data_type != BCH_DATA_journal);
/*
* Backup superblock might be past the end of our normal usable space:
*/
if (b >= ca->mi.nbuckets)
return;
percpu_down_read(&c->mark_lock);
g = __bucket(ca, b, true);
old = bucket_cmpxchg(g, new, ({
new.data_type = data_type;
overflow = checked_add(new.dirty_sectors, sectors);
@ -687,32 +677,8 @@ static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
bch2_data_types[old.data_type ?: data_type],
old.dirty_sectors, sectors);
if (c)
bch2_dev_usage_update(c, ca, old, new, 0, gc);
return 0;
}
void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, enum bch_data_type type,
unsigned sectors, struct gc_pos pos,
unsigned flags)
{
BUG_ON(type != BCH_DATA_sb &&
type != BCH_DATA_journal);
/*
* Backup superblock might be past the end of our normal usable space:
*/
if (b >= ca->mi.nbuckets)
return;
if (likely(c)) {
do_mark_fn(__bch2_mark_metadata_bucket, c, pos, flags,
ca, b, type, sectors);
} else {
__bch2_mark_metadata_bucket(c, ca, b, type, sectors, 0);
}
bch2_dev_usage_update(c, ca, old, new, 0, true);
percpu_up_read(&c->mark_lock);
}
static s64 ptr_disk_sectors(s64 sectors, struct extent_ptr_decoded p)

View file

@ -769,11 +769,8 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
long b;
if (new_fs) {
if (c)
percpu_down_read(&c->mark_lock);
b = bch2_bucket_alloc_new_fs(ca);
if (b < 0) {
percpu_up_read(&c->mark_lock);
ret = -ENOSPC;
goto err;
}
@ -821,14 +818,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
if (c)
spin_unlock(&c->journal.lock);
if (new_fs) {
bch2_mark_metadata_bucket(c, ca, b, BCH_DATA_journal,
ca->mi.bucket_size,
gc_phase(GC_PHASE_SB),
0);
if (c)
percpu_up_read(&c->mark_lock);
} else {
if (!new_fs) {
ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_NOFAIL,
bch2_trans_mark_metadata_bucket(&trans, ca,
b, BCH_DATA_journal,

View file

@ -1383,9 +1383,6 @@ int bch2_fs_initialize(struct bch_fs *c)
c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_SB_FEATURES_ALL);
bch2_write_super(c);
}
for_each_online_member(ca, c, i)
bch2_mark_dev_superblock(c, ca, 0);
mutex_unlock(&c->sb_lock);
set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);

View file

@ -1606,8 +1606,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
struct bch_dev *ca = NULL;
struct bch_sb_field_members *mi;
struct bch_member dev_mi;
struct bucket_array *buckets;
struct bucket *g;
unsigned dev_idx, nr_devices, u64s;
int ret;
@ -1637,20 +1635,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
return ret;
}
/*
* We want to allocate journal on the new device before adding the new
* device to the filesystem because allocating after we attach requires
* spinning up the allocator thread, and the allocator thread requires
* doing btree writes, which if the existing devices are RO isn't going
* to work
*
* So we have to mark where the superblocks are, but marking allocated
* data normally updates the filesystem usage too, so we have to mark,
* allocate the journal, reset all the marks, then remark after we
* attach...
*/
bch2_mark_dev_superblock(NULL, ca, 0);
err = "journal alloc failed";
ret = bch2_dev_journal_alloc(ca);
if (ret)
@ -1711,16 +1695,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
bch2_dev_usage_journal_reserve(c);
/*
* Clear marks before marking transactionally in the btree, so that
* per-device accounting gets done correctly:
*/
down_read(&ca->bucket_lock);
buckets = bucket_array(ca);
for_each_bucket(g, buckets)
atomic64_set(&g->_mark.v, 0);
up_read(&ca->bucket_lock);
err = "error marking superblock";
ret = bch2_trans_mark_dev_sb(c, ca);
if (ret)