mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
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:
parent
09943313d7
commit
77170d0dd7
6 changed files with 19 additions and 106 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue