mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
bcachefs: metadata version bucket_stripe_sectors
New on disk format version for bch_alloc->stripe_sectors and BCH_DATA_unstriped - accounting for unstriped data in stripe buckets. Upgrade/downgrade requires regenerating alloc info - but only if erasure coding is in use. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
2612e29142
commit
7773df19c3
@ -592,6 +592,7 @@ struct bch_dev {
|
|||||||
#define BCH_FS_FLAGS() \
|
#define BCH_FS_FLAGS() \
|
||||||
x(new_fs) \
|
x(new_fs) \
|
||||||
x(started) \
|
x(started) \
|
||||||
|
x(btree_running) \
|
||||||
x(may_go_rw) \
|
x(may_go_rw) \
|
||||||
x(rw) \
|
x(rw) \
|
||||||
x(was_rw) \
|
x(was_rw) \
|
||||||
|
@ -723,7 +723,8 @@ struct bch_sb_field_ext {
|
|||||||
x(member_seq, BCH_VERSION(1, 4)) \
|
x(member_seq, BCH_VERSION(1, 4)) \
|
||||||
x(subvolume_fs_parent, BCH_VERSION(1, 5)) \
|
x(subvolume_fs_parent, BCH_VERSION(1, 5)) \
|
||||||
x(btree_subvolume_children, BCH_VERSION(1, 6)) \
|
x(btree_subvolume_children, BCH_VERSION(1, 6)) \
|
||||||
x(mi_btree_bitmap, BCH_VERSION(1, 7))
|
x(mi_btree_bitmap, BCH_VERSION(1, 7)) \
|
||||||
|
x(bucket_stripe_sectors, BCH_VERSION(1, 8))
|
||||||
|
|
||||||
enum bcachefs_metadata_version {
|
enum bcachefs_metadata_version {
|
||||||
bcachefs_metadata_version_min = 9,
|
bcachefs_metadata_version_min = 9,
|
||||||
|
@ -866,6 +866,14 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
|
|||||||
_p; \
|
_p; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define bch2_trans_run(_c, _do) \
|
||||||
|
({ \
|
||||||
|
struct btree_trans *trans = bch2_trans_get(_c); \
|
||||||
|
int _ret = (_do); \
|
||||||
|
bch2_trans_put(trans); \
|
||||||
|
_ret; \
|
||||||
|
})
|
||||||
|
|
||||||
void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);
|
void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);
|
||||||
void bch2_btree_path_to_text(struct printbuf *, struct btree_trans *, btree_path_idx_t);
|
void bch2_btree_path_to_text(struct printbuf *, struct btree_trans *, btree_path_idx_t);
|
||||||
void bch2_trans_paths_to_text(struct printbuf *, struct btree_trans *);
|
void bch2_trans_paths_to_text(struct printbuf *, struct btree_trans *);
|
||||||
|
@ -178,14 +178,6 @@ static inline int bch2_trans_commit(struct btree_trans *trans,
|
|||||||
nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\
|
nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\
|
||||||
(_journal_seq), (_flags)))
|
(_journal_seq), (_flags)))
|
||||||
|
|
||||||
#define bch2_trans_run(_c, _do) \
|
|
||||||
({ \
|
|
||||||
struct btree_trans *trans = bch2_trans_get(_c); \
|
|
||||||
int _ret = (_do); \
|
|
||||||
bch2_trans_put(trans); \
|
|
||||||
_ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \
|
#define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \
|
||||||
bch2_trans_run(_c, commit_do(trans, _disk_res, _journal_seq, _flags, _do))
|
bch2_trans_run(_c, commit_do(trans, _disk_res, _journal_seq, _flags, _do))
|
||||||
|
|
||||||
|
@ -810,6 +810,10 @@ use_clean:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
set_bit(BCH_FS_btree_running, &c->flags);
|
||||||
|
|
||||||
|
ret = bch2_sb_set_upgrade_extra(c);
|
||||||
|
|
||||||
ret = bch2_run_recovery_passes(c);
|
ret = bch2_run_recovery_passes(c);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@ -969,6 +973,7 @@ int bch2_fs_initialize(struct bch_fs *c)
|
|||||||
mutex_unlock(&c->sb_lock);
|
mutex_unlock(&c->sb_lock);
|
||||||
|
|
||||||
c->curr_recovery_pass = BCH_RECOVERY_PASS_NR;
|
c->curr_recovery_pass = BCH_RECOVERY_PASS_NR;
|
||||||
|
set_bit(BCH_FS_btree_running, &c->flags);
|
||||||
set_bit(BCH_FS_may_go_rw, &c->flags);
|
set_bit(BCH_FS_may_go_rw, &c->flags);
|
||||||
|
|
||||||
for (unsigned i = 0; i < BTREE_ID_NR; i++)
|
for (unsigned i = 0; i < BTREE_ID_NR; i++)
|
||||||
|
@ -56,7 +56,9 @@
|
|||||||
BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \
|
BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \
|
||||||
BCH_FSCK_ERR_btree_bitmap_not_marked)
|
BCH_FSCK_ERR_btree_bitmap_not_marked)
|
||||||
|
|
||||||
#define DOWNGRADE_TABLE()
|
#define DOWNGRADE_TABLE() \
|
||||||
|
x(bucket_stripe_sectors, \
|
||||||
|
0)
|
||||||
|
|
||||||
struct upgrade_downgrade_entry {
|
struct upgrade_downgrade_entry {
|
||||||
u64 recovery_passes;
|
u64 recovery_passes;
|
||||||
@ -80,6 +82,37 @@ UPGRADE_TABLE()
|
|||||||
#undef x
|
#undef x
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int have_stripes(struct bch_fs *c)
|
||||||
|
{
|
||||||
|
return !btree_node_fake(c->btree_roots_known[BTREE_ID_stripes].b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bch2_sb_set_upgrade_extra(struct bch_fs *c)
|
||||||
|
{
|
||||||
|
unsigned old_version = c->sb.version_upgrade_complete ?: c->sb.version;
|
||||||
|
unsigned new_version = c->sb.version;
|
||||||
|
bool write_sb = false;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&c->sb_lock);
|
||||||
|
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
|
||||||
|
|
||||||
|
if (old_version < bcachefs_metadata_version_bucket_stripe_sectors &&
|
||||||
|
new_version >= bcachefs_metadata_version_bucket_stripe_sectors &&
|
||||||
|
(ret = have_stripes(c) > 0)) {
|
||||||
|
__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_allocations, ext->recovery_passes_required);
|
||||||
|
__set_bit_le64(BCH_FSCK_ERR_alloc_key_dirty_sectors_wrong, ext->errors_silent);
|
||||||
|
__set_bit_le64(BCH_FSCK_ERR_alloc_key_stripe_sectors_wrong, ext->errors_silent);
|
||||||
|
write_sb = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_sb)
|
||||||
|
bch2_write_super(c);
|
||||||
|
mutex_unlock(&c->sb_lock);
|
||||||
|
|
||||||
|
return ret < 0 ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void bch2_sb_set_upgrade(struct bch_fs *c,
|
void bch2_sb_set_upgrade(struct bch_fs *c,
|
||||||
unsigned old_version,
|
unsigned old_version,
|
||||||
unsigned new_version)
|
unsigned new_version)
|
||||||
@ -101,16 +134,12 @@ void bch2_sb_set_upgrade(struct bch_fs *c,
|
|||||||
ext->recovery_passes_required[0] |=
|
ext->recovery_passes_required[0] |=
|
||||||
cpu_to_le64(bch2_recovery_passes_to_stable(passes));
|
cpu_to_le64(bch2_recovery_passes_to_stable(passes));
|
||||||
|
|
||||||
for (const u16 *e = i->errors;
|
for (const u16 *e = i->errors; e < i->errors + i->nr_errors; e++)
|
||||||
e < i->errors + i->nr_errors;
|
__set_bit_le64(*e, ext->errors_silent);
|
||||||
e++) {
|
|
||||||
__set_bit(*e, c->sb.errors_silent);
|
|
||||||
ext->errors_silent[*e / 64] |= cpu_to_le64(BIT_ULL(*e % 64));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define x(ver, passes, ...) static const u16 downgrade_ver_##errors[] = { __VA_ARGS__ };
|
#define x(ver, passes, ...) static const u16 downgrade_##ver##_errors[] = { __VA_ARGS__ };
|
||||||
DOWNGRADE_TABLE()
|
DOWNGRADE_TABLE()
|
||||||
#undef x
|
#undef x
|
||||||
|
|
||||||
@ -125,6 +154,37 @@ DOWNGRADE_TABLE()
|
|||||||
#undef x
|
#undef x
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int downgrade_table_extra(struct bch_fs *c, darray_char *table)
|
||||||
|
{
|
||||||
|
struct bch_sb_field_downgrade_entry *dst = (void *) &darray_top(*table);
|
||||||
|
unsigned bytes = sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
unsigned nr_errors = le16_to_cpu(dst->nr_errors);
|
||||||
|
|
||||||
|
switch (le16_to_cpu(dst->version)) {
|
||||||
|
case bcachefs_metadata_version_bucket_stripe_sectors:
|
||||||
|
if (have_stripes(c)) {
|
||||||
|
bytes += sizeof(dst->errors[0]) * 2;
|
||||||
|
|
||||||
|
ret = darray_make_room(table, bytes);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* open coded __set_bit_le64, as dst is packed and
|
||||||
|
* dst->recovery_passes is misaligned */
|
||||||
|
unsigned b = BCH_RECOVERY_PASS_STABLE_check_allocations;
|
||||||
|
dst->recovery_passes[b / 64] |= cpu_to_le64(BIT_ULL(b % 64));
|
||||||
|
|
||||||
|
dst->errors[nr_errors++] = cpu_to_le16(BCH_FSCK_ERR_alloc_key_dirty_sectors_wrong);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->nr_errors = cpu_to_le16(nr_errors);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline const struct bch_sb_field_downgrade_entry *
|
static inline const struct bch_sb_field_downgrade_entry *
|
||||||
downgrade_entry_next_c(const struct bch_sb_field_downgrade_entry *e)
|
downgrade_entry_next_c(const struct bch_sb_field_downgrade_entry *e)
|
||||||
{
|
{
|
||||||
@ -210,6 +270,9 @@ const struct bch_sb_field_ops bch_sb_field_ops_downgrade = {
|
|||||||
|
|
||||||
int bch2_sb_downgrade_update(struct bch_fs *c)
|
int bch2_sb_downgrade_update(struct bch_fs *c)
|
||||||
{
|
{
|
||||||
|
if (!test_bit(BCH_FS_btree_running, &c->flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
darray_char table = {};
|
darray_char table = {};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -234,7 +297,14 @@ int bch2_sb_downgrade_update(struct bch_fs *c)
|
|||||||
for (unsigned i = 0; i < src->nr_errors; i++)
|
for (unsigned i = 0; i < src->nr_errors; i++)
|
||||||
dst->errors[i] = cpu_to_le16(src->errors[i]);
|
dst->errors[i] = cpu_to_le16(src->errors[i]);
|
||||||
|
|
||||||
table.nr += bytes;
|
downgrade_table_extra(c, &table);
|
||||||
|
|
||||||
|
if (!dst->recovery_passes[0] &&
|
||||||
|
!dst->recovery_passes[1] &&
|
||||||
|
!dst->nr_errors)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
table.nr += sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bch_sb_field_downgrade *d = bch2_sb_field_get(c->disk_sb.sb, downgrade);
|
struct bch_sb_field_downgrade *d = bch2_sb_field_get(c->disk_sb.sb, downgrade);
|
||||||
|
@ -6,6 +6,7 @@ extern const struct bch_sb_field_ops bch_sb_field_ops_downgrade;
|
|||||||
|
|
||||||
int bch2_sb_downgrade_update(struct bch_fs *);
|
int bch2_sb_downgrade_update(struct bch_fs *);
|
||||||
void bch2_sb_set_upgrade(struct bch_fs *, unsigned, unsigned);
|
void bch2_sb_set_upgrade(struct bch_fs *, unsigned, unsigned);
|
||||||
|
int bch2_sb_set_upgrade_extra(struct bch_fs *);
|
||||||
void bch2_sb_set_downgrade(struct bch_fs *, unsigned, unsigned);
|
void bch2_sb_set_downgrade(struct bch_fs *, unsigned, unsigned);
|
||||||
|
|
||||||
#endif /* _BCACHEFS_SB_DOWNGRADE_H */
|
#endif /* _BCACHEFS_SB_DOWNGRADE_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user