bcachefs: Upgrades now specify errors to fix, like downgrades
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
d641d4cae7
commit
15eaaa4c31
|
@ -1672,71 +1672,41 @@ struct bch_sb_field_downgrade {
|
|||
#define BCH_VERSION_MINOR(_v) ((__u16) ((_v) & ~(~0U << 10)))
|
||||
#define BCH_VERSION(_major, _minor) (((_major) << 10)|(_minor) << 0)
|
||||
|
||||
#define RECOVERY_PASS_ALL_FSCK (1ULL << 63)
|
||||
|
||||
/*
|
||||
* field 1: version name
|
||||
* field 2: BCH_VERSION(major, minor)
|
||||
* field 3: recovery passess required on upgrade
|
||||
*/
|
||||
#define BCH_METADATA_VERSIONS() \
|
||||
x(bkey_renumber, BCH_VERSION(0, 10), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(inode_btree_change, BCH_VERSION(0, 11), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(snapshot, BCH_VERSION(0, 12), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(inode_backpointers, BCH_VERSION(0, 13), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(btree_ptr_sectors_written, BCH_VERSION(0, 14), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(snapshot_2, BCH_VERSION(0, 15), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_fs_upgrade_for_subvolumes)| \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_initialize_subvolumes)| \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(reflink_p_fix, BCH_VERSION(0, 16), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_fix_reflink_p)) \
|
||||
x(subvol_dirent, BCH_VERSION(0, 17), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(inode_v2, BCH_VERSION(0, 18), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(freespace, BCH_VERSION(0, 19), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(alloc_v4, BCH_VERSION(0, 20), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(new_data_types, BCH_VERSION(0, 21), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(backpointers, BCH_VERSION(0, 22), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(inode_v3, BCH_VERSION(0, 23), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(unwritten_extents, BCH_VERSION(0, 24), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(bucket_gens, BCH_VERSION(0, 25), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_bucket_gens_init)| \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(lru_v2, BCH_VERSION(0, 26), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(fragmentation_lru, BCH_VERSION(0, 27), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(no_bps_in_alloc_keys, BCH_VERSION(0, 28), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(snapshot_trees, BCH_VERSION(0, 29), \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(major_minor, BCH_VERSION(1, 0), \
|
||||
0) \
|
||||
x(snapshot_skiplists, BCH_VERSION(1, 1), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_check_snapshots)) \
|
||||
x(deleted_inodes, BCH_VERSION(1, 2), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_check_inodes)) \
|
||||
x(rebalance_work, BCH_VERSION(1, 3), \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_set_fs_needs_rebalance)) \
|
||||
x(member_seq, BCH_VERSION(1, 4), \
|
||||
0)
|
||||
x(bkey_renumber, BCH_VERSION(0, 10)) \
|
||||
x(inode_btree_change, BCH_VERSION(0, 11)) \
|
||||
x(snapshot, BCH_VERSION(0, 12)) \
|
||||
x(inode_backpointers, BCH_VERSION(0, 13)) \
|
||||
x(btree_ptr_sectors_written, BCH_VERSION(0, 14)) \
|
||||
x(snapshot_2, BCH_VERSION(0, 15)) \
|
||||
x(reflink_p_fix, BCH_VERSION(0, 16)) \
|
||||
x(subvol_dirent, BCH_VERSION(0, 17)) \
|
||||
x(inode_v2, BCH_VERSION(0, 18)) \
|
||||
x(freespace, BCH_VERSION(0, 19)) \
|
||||
x(alloc_v4, BCH_VERSION(0, 20)) \
|
||||
x(new_data_types, BCH_VERSION(0, 21)) \
|
||||
x(backpointers, BCH_VERSION(0, 22)) \
|
||||
x(inode_v3, BCH_VERSION(0, 23)) \
|
||||
x(unwritten_extents, BCH_VERSION(0, 24)) \
|
||||
x(bucket_gens, BCH_VERSION(0, 25)) \
|
||||
x(lru_v2, BCH_VERSION(0, 26)) \
|
||||
x(fragmentation_lru, BCH_VERSION(0, 27)) \
|
||||
x(no_bps_in_alloc_keys, BCH_VERSION(0, 28)) \
|
||||
x(snapshot_trees, BCH_VERSION(0, 29)) \
|
||||
x(major_minor, BCH_VERSION(1, 0)) \
|
||||
x(snapshot_skiplists, BCH_VERSION(1, 1)) \
|
||||
x(deleted_inodes, BCH_VERSION(1, 2)) \
|
||||
x(rebalance_work, BCH_VERSION(1, 3)) \
|
||||
x(member_seq, BCH_VERSION(1, 4))
|
||||
|
||||
enum bcachefs_metadata_version {
|
||||
bcachefs_metadata_version_min = 9,
|
||||
#define x(t, n, upgrade_passes) bcachefs_metadata_version_##t = n,
|
||||
#define x(t, n) bcachefs_metadata_version_##t = n,
|
||||
BCH_METADATA_VERSIONS()
|
||||
#undef x
|
||||
bcachefs_metadata_version_max
|
||||
|
|
|
@ -575,7 +575,7 @@ u64 bch2_recovery_passes_from_stable(u64 v)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u64 check_version_upgrade(struct bch_fs *c)
|
||||
static bool check_version_upgrade(struct bch_fs *c)
|
||||
{
|
||||
unsigned latest_compatible = bch2_latest_compatible_version(c->sb.version);
|
||||
unsigned latest_version = bcachefs_metadata_version_current;
|
||||
|
@ -624,15 +624,15 @@ static u64 check_version_upgrade(struct bch_fs *c)
|
|||
bch2_version_to_text(&buf, new_version);
|
||||
prt_newline(&buf);
|
||||
|
||||
u64 recovery_passes = bch2_upgrade_recovery_passes(c, old_version, new_version);
|
||||
if (recovery_passes) {
|
||||
prt_str(&buf, " running recovery passes: ");
|
||||
prt_bitflags(&buf, bch2_recovery_passes, recovery_passes);
|
||||
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
|
||||
__le64 passes = ext->recovery_passes_required[0];
|
||||
bch2_sb_set_upgrade(c, old_version, new_version);
|
||||
passes = ext->recovery_passes_required[0] & ~passes;
|
||||
|
||||
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
|
||||
ext->recovery_passes_required[0] |=
|
||||
cpu_to_le64(bch2_recovery_passes_to_stable(recovery_passes));
|
||||
c->opts.fix_errors = FSCK_FIX_yes;
|
||||
if (passes) {
|
||||
prt_str(&buf, " running recovery passes: ");
|
||||
prt_bitflags(&buf, bch2_recovery_passes,
|
||||
bch2_recovery_passes_from_stable(le64_to_cpu(passes)));
|
||||
}
|
||||
|
||||
bch_info(c, "%s", buf.buf);
|
||||
|
|
|
@ -12,33 +12,103 @@
|
|||
#include "sb-errors.h"
|
||||
#include "super-io.h"
|
||||
|
||||
#define RECOVERY_PASS_ALL_FSCK BIT_ULL(63)
|
||||
|
||||
/*
|
||||
* Downgrade table:
|
||||
* When dowgrading past certain versions, we need to run certain recovery passes
|
||||
* and fix certain errors:
|
||||
* Upgrade, downgrade tables - run certain recovery passes, fix certain errors
|
||||
*
|
||||
* x(version, recovery_passes, errors...)
|
||||
*/
|
||||
#define UPGRADE_TABLE() \
|
||||
x(backpointers, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(inode_v3, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(unwritten_extents, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(bucket_gens, \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_bucket_gens_init)| \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(lru_v2, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(fragmentation_lru, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(no_bps_in_alloc_keys, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(snapshot_trees, \
|
||||
RECOVERY_PASS_ALL_FSCK) \
|
||||
x(snapshot_skiplists, \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_check_snapshots)) \
|
||||
x(deleted_inodes, \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_check_inodes), \
|
||||
BCH_FSCK_ERR_unlinked_inode_not_on_deleted_list) \
|
||||
x(rebalance_work, \
|
||||
BIT_ULL(BCH_RECOVERY_PASS_set_fs_needs_rebalance))
|
||||
|
||||
#define DOWNGRADE_TABLE()
|
||||
|
||||
struct downgrade_entry {
|
||||
struct upgrade_downgrade_entry {
|
||||
u64 recovery_passes;
|
||||
u16 version;
|
||||
u16 nr_errors;
|
||||
const u16 *errors;
|
||||
};
|
||||
|
||||
#define x(ver, passes, ...) static const u16 ver_##errors[] = { __VA_ARGS__ };
|
||||
DOWNGRADE_TABLE()
|
||||
#define x(ver, passes, ...) static const u16 upgrade_##ver##_errors[] = { __VA_ARGS__ };
|
||||
UPGRADE_TABLE()
|
||||
#undef x
|
||||
|
||||
static const struct downgrade_entry downgrade_table[] = {
|
||||
static const struct upgrade_downgrade_entry upgrade_table[] = {
|
||||
#define x(ver, passes, ...) { \
|
||||
.recovery_passes = passes, \
|
||||
.version = bcachefs_metadata_version_##ver,\
|
||||
.nr_errors = ARRAY_SIZE(ver_##errors), \
|
||||
.errors = ver_##errors, \
|
||||
.nr_errors = ARRAY_SIZE(upgrade_##ver##_errors), \
|
||||
.errors = upgrade_##ver##_errors, \
|
||||
},
|
||||
UPGRADE_TABLE()
|
||||
#undef x
|
||||
};
|
||||
|
||||
void bch2_sb_set_upgrade(struct bch_fs *c,
|
||||
unsigned old_version,
|
||||
unsigned new_version)
|
||||
{
|
||||
lockdep_assert_held(&c->sb_lock);
|
||||
|
||||
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
|
||||
|
||||
for (const struct upgrade_downgrade_entry *i = upgrade_table;
|
||||
i < upgrade_table + ARRAY_SIZE(upgrade_table);
|
||||
i++)
|
||||
if (i->version > old_version && i->version <= new_version) {
|
||||
u64 passes = i->recovery_passes;
|
||||
|
||||
if (passes & RECOVERY_PASS_ALL_FSCK)
|
||||
passes |= bch2_fsck_recovery_passes();
|
||||
passes &= ~RECOVERY_PASS_ALL_FSCK;
|
||||
|
||||
ext->recovery_passes_required[0] |=
|
||||
cpu_to_le64(bch2_recovery_passes_to_stable(passes));
|
||||
|
||||
for (const u16 *e = i->errors;
|
||||
e < i->errors + i->nr_errors;
|
||||
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__ };
|
||||
DOWNGRADE_TABLE()
|
||||
#undef x
|
||||
|
||||
static const struct upgrade_downgrade_entry downgrade_table[] = {
|
||||
#define x(ver, passes, ...) { \
|
||||
.recovery_passes = passes, \
|
||||
.version = bcachefs_metadata_version_##ver,\
|
||||
.nr_errors = ARRAY_SIZE(downgrade_##ver##_errors), \
|
||||
.errors = downgrade_##ver##_errors, \
|
||||
},
|
||||
DOWNGRADE_TABLE()
|
||||
#undef x
|
||||
|
@ -118,7 +188,7 @@ int bch2_sb_downgrade_update(struct bch_fs *c)
|
|||
darray_char table = {};
|
||||
int ret = 0;
|
||||
|
||||
for (const struct downgrade_entry *src = downgrade_table;
|
||||
for (const struct upgrade_downgrade_entry *src = downgrade_table;
|
||||
src < downgrade_table + ARRAY_SIZE(downgrade_table);
|
||||
src++) {
|
||||
if (BCH_VERSION_MAJOR(src->version) != BCH_VERSION_MAJOR(le16_to_cpu(c->disk_sb.sb->version)))
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
extern const struct bch_sb_field_ops bch_sb_field_ops_downgrade;
|
||||
|
||||
int bch2_sb_downgrade_update(struct bch_fs *);
|
||||
void bch2_sb_set_upgrade(struct bch_fs *, unsigned, unsigned);
|
||||
void bch2_sb_set_downgrade(struct bch_fs *, unsigned, unsigned);
|
||||
|
||||
#endif /* _BCACHEFS_SB_DOWNGRADE_H */
|
||||
|
|
|
@ -30,14 +30,12 @@ static const struct blk_holder_ops bch2_sb_handle_bdev_ops = {
|
|||
struct bch2_metadata_version {
|
||||
u16 version;
|
||||
const char *name;
|
||||
u64 recovery_passes;
|
||||
};
|
||||
|
||||
static const struct bch2_metadata_version bch2_metadata_versions[] = {
|
||||
#define x(n, v, _recovery_passes) { \
|
||||
#define x(n, v) { \
|
||||
.version = v, \
|
||||
.name = #n, \
|
||||
.recovery_passes = _recovery_passes, \
|
||||
},
|
||||
BCH_METADATA_VERSIONS()
|
||||
#undef x
|
||||
|
@ -70,24 +68,6 @@ unsigned bch2_latest_compatible_version(unsigned v)
|
|||
return v;
|
||||
}
|
||||
|
||||
u64 bch2_upgrade_recovery_passes(struct bch_fs *c,
|
||||
unsigned old_version,
|
||||
unsigned new_version)
|
||||
{
|
||||
u64 ret = 0;
|
||||
|
||||
for (const struct bch2_metadata_version *i = bch2_metadata_versions;
|
||||
i < bch2_metadata_versions + ARRAY_SIZE(bch2_metadata_versions);
|
||||
i++)
|
||||
if (i->version > old_version && i->version <= new_version) {
|
||||
if (i->recovery_passes & RECOVERY_PASS_ALL_FSCK)
|
||||
ret |= bch2_fsck_recovery_passes();
|
||||
ret |= i->recovery_passes;
|
||||
}
|
||||
|
||||
return ret &= ~RECOVERY_PASS_ALL_FSCK;
|
||||
}
|
||||
|
||||
const char * const bch2_sb_fields[] = {
|
||||
#define x(name, nr) #name,
|
||||
BCH_SB_FIELDS()
|
||||
|
|
|
@ -19,10 +19,6 @@ static inline bool bch2_version_compatible(u16 version)
|
|||
void bch2_version_to_text(struct printbuf *, unsigned);
|
||||
unsigned bch2_latest_compatible_version(unsigned);
|
||||
|
||||
u64 bch2_upgrade_recovery_passes(struct bch_fs *c,
|
||||
unsigned,
|
||||
unsigned);
|
||||
|
||||
static inline size_t bch2_sb_field_bytes(struct bch_sb_field *f)
|
||||
{
|
||||
return le32_to_cpu(f->u64s) * sizeof(u64);
|
||||
|
|
Loading…
Reference in New Issue