Commit bbe682c7 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Ensure devices are always correctly initialized

We can't mark device superblocks or allocate journal on a device that
isn't online.

That means we may need to do this on every mount, because we may have
formatted a new filesystem and then done the first mount
(bch2_fs_initialize()) in degraded mode.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent d0261559
...@@ -1825,16 +1825,16 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans, ...@@ -1825,16 +1825,16 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
bch2_data_types[type], bch2_data_types[type],
bch2_data_types[type]); bch2_data_types[type]);
ret = -EIO; ret = -EIO;
goto out; goto err;
} }
a->v.data_type = type; if (a->v.data_type != type ||
a->v.dirty_sectors = sectors; a->v.dirty_sectors != sectors) {
a->v.data_type = type;
ret = bch2_trans_update(trans, &iter, &a->k_i, 0); a->v.dirty_sectors = sectors;
if (ret) ret = bch2_trans_update(trans, &iter, &a->k_i, 0);
goto out; }
out: err:
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
return ret; return ret;
} }
...@@ -1929,6 +1929,22 @@ int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca) ...@@ -1929,6 +1929,22 @@ int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca)
return ret; return ret;
} }
int bch2_trans_mark_dev_sbs(struct bch_fs *c)
{
struct bch_dev *ca;
unsigned i;
for_each_online_member(ca, c, i) {
int ret = bch2_trans_mark_dev_sb(c, ca);
if (ret) {
percpu_ref_put(&ca->ref);
return ret;
}
}
return 0;
}
/* Disk reservations: */ /* Disk reservations: */
#define SECTORS_CACHE 1024 #define SECTORS_CACHE 1024
......
...@@ -345,6 +345,7 @@ int bch2_trans_fs_usage_apply(struct btree_trans *, struct replicas_delta_list * ...@@ -345,6 +345,7 @@ int bch2_trans_fs_usage_apply(struct btree_trans *, struct replicas_delta_list *
int bch2_trans_mark_metadata_bucket(struct btree_trans *, struct bch_dev *, int bch2_trans_mark_metadata_bucket(struct btree_trans *, struct bch_dev *,
size_t, enum bch_data_type, unsigned); size_t, enum bch_data_type, unsigned);
int bch2_trans_mark_dev_sb(struct bch_fs *, struct bch_dev *); int bch2_trans_mark_dev_sb(struct bch_fs *, struct bch_dev *);
int bch2_trans_mark_dev_sbs(struct bch_fs *);
static inline bool is_superblock_bucket(struct bch_dev *ca, u64 b) static inline bool is_superblock_bucket(struct bch_dev *ca, u64 b)
{ {
......
...@@ -1019,6 +1019,25 @@ int bch2_dev_journal_alloc(struct bch_dev *ca) ...@@ -1019,6 +1019,25 @@ int bch2_dev_journal_alloc(struct bch_dev *ca)
return ret; return ret;
} }
int bch2_fs_journal_alloc(struct bch_fs *c)
{
struct bch_dev *ca;
unsigned i;
for_each_online_member(ca, c, i) {
if (ca->journal.nr)
continue;
int ret = bch2_dev_journal_alloc(ca);
if (ret) {
percpu_ref_put(&ca->io_ref);
return ret;
}
}
return 0;
}
/* startup/shutdown: */ /* startup/shutdown: */
static bool bch2_journal_writing_to_device(struct journal *j, unsigned dev_idx) static bool bch2_journal_writing_to_device(struct journal *j, unsigned dev_idx)
......
...@@ -534,6 +534,7 @@ bool bch2_journal_seq_pins_to_text(struct printbuf *, struct journal *, u64 *); ...@@ -534,6 +534,7 @@ bool bch2_journal_seq_pins_to_text(struct printbuf *, struct journal *, u64 *);
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *, int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *,
unsigned nr); unsigned nr);
int bch2_dev_journal_alloc(struct bch_dev *); int bch2_dev_journal_alloc(struct bch_dev *);
int bch2_fs_journal_alloc(struct bch_fs *);
void bch2_dev_journal_stop(struct journal *, struct bch_dev *); void bch2_dev_journal_stop(struct journal *, struct bch_dev *);
......
...@@ -946,16 +946,12 @@ int bch2_fs_initialize(struct bch_fs *c) ...@@ -946,16 +946,12 @@ int bch2_fs_initialize(struct bch_fs *c)
for (i = 0; i < BTREE_ID_NR; i++) for (i = 0; i < BTREE_ID_NR; i++)
bch2_btree_root_alloc(c, i); bch2_btree_root_alloc(c, i);
for_each_online_member(ca, c, i) for_each_member_device(ca, c, i)
bch2_dev_usage_init(ca); bch2_dev_usage_init(ca);
for_each_online_member(ca, c, i) { ret = bch2_fs_journal_alloc(c);
ret = bch2_dev_journal_alloc(ca); if (ret)
if (ret) { goto err;
percpu_ref_put(&ca->io_ref);
goto err;
}
}
/* /*
* journal_res_get() will crash if called before this has * journal_res_get() will crash if called before this has
...@@ -973,15 +969,13 @@ int bch2_fs_initialize(struct bch_fs *c) ...@@ -973,15 +969,13 @@ int bch2_fs_initialize(struct bch_fs *c)
* btree updates * btree updates
*/ */
bch_verbose(c, "marking superblocks"); bch_verbose(c, "marking superblocks");
for_each_member_device(ca, c, i) { ret = bch2_trans_mark_dev_sbs(c);
ret = bch2_trans_mark_dev_sb(c, ca); bch_err_msg(c, ret, "marking superblocks");
if (ret) { if (ret)
percpu_ref_put(&ca->ref); goto err;
goto err;
}
for_each_online_member(ca, c, i)
ca->new_fs_bucket_idx = 0; ca->new_fs_bucket_idx = 0;
}
ret = bch2_fs_freespace_init(c); ret = bch2_fs_freespace_init(c);
if (ret) if (ret)
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
x(snapshots_read, PASS_ALWAYS) \ x(snapshots_read, PASS_ALWAYS) \
x(check_topology, 0) \ x(check_topology, 0) \
x(check_allocations, PASS_FSCK) \ x(check_allocations, PASS_FSCK) \
x(trans_mark_dev_sbs, PASS_ALWAYS|PASS_SILENT) \
x(fs_journal_alloc, PASS_ALWAYS|PASS_SILENT) \
x(set_may_go_rw, PASS_ALWAYS|PASS_SILENT) \ x(set_may_go_rw, PASS_ALWAYS|PASS_SILENT) \
x(journal_replay, PASS_ALWAYS) \ x(journal_replay, PASS_ALWAYS) \
x(check_alloc_info, PASS_FSCK) \ x(check_alloc_info, PASS_FSCK) \
......
...@@ -948,9 +948,6 @@ int bch2_fs_start(struct bch_fs *c) ...@@ -948,9 +948,6 @@ int bch2_fs_start(struct bch_fs *c)
goto err; goto err;
} }
for_each_online_member(ca, c, i)
bch2_sb_from_fs(c, ca);
for_each_online_member(ca, c, i) for_each_online_member(ca, c, i)
bch2_members_v2_get_mut(c->disk_sb.sb, i)->last_mount = cpu_to_le64(now); bch2_members_v2_get_mut(c->disk_sb.sb, i)->last_mount = cpu_to_le64(now);
...@@ -1683,13 +1680,13 @@ int bch2_dev_add(struct bch_fs *c, const char *path) ...@@ -1683,13 +1680,13 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
ret = bch2_trans_mark_dev_sb(c, ca); ret = bch2_trans_mark_dev_sb(c, ca);
if (ret) { if (ret) {
bch_err_msg(c, ret, "marking new superblock"); bch_err_msg(ca, ret, "marking new superblock");
goto err_late; goto err_late;
} }
ret = bch2_fs_freespace_init(c); ret = bch2_fs_freespace_init(c);
if (ret) { if (ret) {
bch_err_msg(c, ret, "initializing free space"); bch_err_msg(ca, ret, "initializing free space");
goto err_late; goto err_late;
} }
...@@ -1757,19 +1754,26 @@ int bch2_dev_online(struct bch_fs *c, const char *path) ...@@ -1757,19 +1754,26 @@ int bch2_dev_online(struct bch_fs *c, const char *path)
if (ca->mi.state == BCH_MEMBER_STATE_rw) if (ca->mi.state == BCH_MEMBER_STATE_rw)
__bch2_dev_read_write(c, ca); __bch2_dev_read_write(c, ca);
mutex_lock(&c->sb_lock); if (!ca->mi.freespace_initialized) {
struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx); ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets);
bch_err_msg(ca, ret, "initializing free space");
if (ret)
goto err;
}
m->last_mount = if (!ca->journal.nr) {
cpu_to_le64(ktime_get_real_seconds()); ret = bch2_dev_journal_alloc(ca);
bch_err_msg(ca, ret, "allocating journal");
if (ret)
goto err;
}
mutex_lock(&c->sb_lock);
bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount =
cpu_to_le64(ktime_get_real_seconds());
bch2_write_super(c); bch2_write_super(c);
mutex_unlock(&c->sb_lock); mutex_unlock(&c->sb_lock);
ret = bch2_fs_freespace_init(c);
if (ret)
bch_err_msg(c, ret, "initializing free space");
up_write(&c->state_lock); up_write(&c->state_lock);
return 0; return 0;
err: err:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment