bcachefs fixes for 6.10-rc5
Lots of (mostly boring) fixes for syzbot bugs and rare(r) CI bugs. The LRU_TIME_BITS fix was slightly more involved; we only have 48 bits for the LRU position (we would prefer 64), so wraparound is possible for the cached data LRUs on a filesystem that has done sufficient (petabytes) reads; this is now handled. One notable user reported bugfix, where we were forgetting to correctly set the bucket data type, which should have been BCH_DATA_need_gc_gens instead of BCH_DATA_free; this was causing us to go emergency read-only on a filesystem that had seen heavy enough use to see bucket gen wraparoud. We're now starting to fix simple (safe) errors without requiring user intervention - i.e. a small incremental step towards full self healing. This is currently limited to just certain allocation information counters, and the error is still logged in the superblock; see that patch for more information. ("bcachefs: Fix safe errors by default"). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEKnAFLkS8Qha+jvQrE6szbY3KbnYFAmZ22GAACgkQE6szbY3K bnYJaQ/+Pzep1M9JU9bQRCjmbR1pDkHswqeiVR0DSPTqDSCR0KmoypA+iwAbAmzC X0Z3bHgh9X36QdnF5s+JSLSzeAdzD74btLeyCI58iH//QaIg7da6tE2FgJCstMt8 11i9a172fhiYLH7YjigZczV10nrWApClS/9qHgY+paVEgMeJgx/3zJwysC1UhuT9 6bsSZKeGMhkGDca3k5hd7mZZKUvFXpE//xe6axK05aTHvd2wDQbDOaMdn07XC+hF KIWloxYVu9utqprjIq2XHWLJaxRhguHwlI4xq+n8eljLw8Kt6S9lZp7CA85Hq4RA hLmv1qoqJvh8+YZ7twwYAhflm9mcz58GGKrIqPCG/YaftIktJx3DCOkZzn2b7TmD iVXBVYkcmlZqLpZzPisKO8omqVkH4YIN/WPIGa1JU/+jkw5Qzpw62K+9AjYowUCp q47TVWRNtAuL5sct2KVUdTkC5Dkhx7lu3NDvx4jVXfbPsv0ssNYiTKMNnAUqefz/ eM37MCVzmy7OwAymdb5d83CzMIHm0JKetc7CgLBAjOcMLMoLDjRdGEcFGxq/iBMB 2Ty4rUWGFbXlwV1umcYd2cODqIt+iLwmHWCAIXjtTlOw1h5YuwX67wb9zw/tzB1W JUEetJQWzQ7P/Q1huntNUbiIHw2GbWzeB2u0wBPaVVEgyHWftyk= =ktka -----END PGP SIGNATURE----- Merge tag 'bcachefs-2024-06-22' of https://evilpiepirate.org/git/bcachefs Pull bcachefs fixes from Kent Overstreet: "Lots of (mostly boring) fixes for syzbot bugs and rare(r) CI bugs. The LRU_TIME_BITS fix was slightly more involved; we only have 48 bits for the LRU position (we would prefer 64), so wraparound is possible for the cached data LRUs on a filesystem that has done sufficient (petabytes) reads; this is now handled. One notable user reported bugfix, where we were forgetting to correctly set the bucket data type, which should have been BCH_DATA_need_gc_gens instead of BCH_DATA_free; this was causing us to go emergency read-only on a filesystem that had seen heavy enough use to see bucket gen wraparoud. We're now starting to fix simple (safe) errors without requiring user intervention - i.e. a small incremental step towards full self healing. This is currently limited to just certain allocation information counters, and the error is still logged in the superblock; see that patch for more information. ("bcachefs: Fix safe errors by default")" * tag 'bcachefs-2024-06-22' of https://evilpiepirate.org/git/bcachefs: (22 commits) bcachefs: Move the ei_flags setting to after initialization bcachefs: Fix a UAF after write_super() bcachefs: Use bch2_print_string_as_lines for long err bcachefs: Fix I_NEW warning in race path in bch2_inode_insert() bcachefs: Replace bare EEXIST with private error codes bcachefs: Fix missing alloc_data_type_set() closures: Change BUG_ON() to WARN_ON() bcachefs: fix alignment of VMA for memory mapped files on THP bcachefs: Fix safe errors by default bcachefs: Fix bch2_trans_put() bcachefs: set_worker_desc() for delete_dead_snapshots bcachefs: Fix bch2_sb_downgrade_update() bcachefs: Handle cached data LRU wraparound bcachefs: Guard against overflowing LRU_TIME_BITS bcachefs: delete_dead_snapshots() doesn't need to go RW bcachefs: Fix early init error path in journal code bcachefs: Check for invalid btree IDs bcachefs: Fix btree ID bitmasks bcachefs: Fix shift overflow in read_one_super() bcachefs: Fix a locking bug in the do_discard_fast() path ...
This commit is contained in:
commit
c3de9b572f
@ -259,6 +259,14 @@ int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||
"invalid data type (got %u should be %u)",
|
||||
a.v->data_type, alloc_data_type(*a.v, a.v->data_type));
|
||||
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
bkey_fsck_err_on(a.v->io_time[i] > LRU_TIME_MAX,
|
||||
c, err,
|
||||
alloc_key_io_time_bad,
|
||||
"invalid io_time[%s]: %llu, max %llu",
|
||||
i == READ ? "read" : "write",
|
||||
a.v->io_time[i], LRU_TIME_MAX);
|
||||
|
||||
switch (a.v->data_type) {
|
||||
case BCH_DATA_free:
|
||||
case BCH_DATA_need_gc_gens:
|
||||
@ -757,8 +765,8 @@ int bch2_trigger_alloc(struct btree_trans *trans,
|
||||
alloc_data_type_set(new_a, new_a->data_type);
|
||||
|
||||
if (bch2_bucket_sectors_total(*new_a) > bch2_bucket_sectors_total(*old_a)) {
|
||||
new_a->io_time[READ] = max_t(u64, 1, atomic64_read(&c->io_clock[READ].now));
|
||||
new_a->io_time[WRITE]= max_t(u64, 1, atomic64_read(&c->io_clock[WRITE].now));
|
||||
new_a->io_time[READ] = bch2_current_io_time(c, READ);
|
||||
new_a->io_time[WRITE]= bch2_current_io_time(c, WRITE);
|
||||
SET_BCH_ALLOC_V4_NEED_INC_GEN(new_a, true);
|
||||
SET_BCH_ALLOC_V4_NEED_DISCARD(new_a, true);
|
||||
}
|
||||
@ -768,6 +776,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
|
||||
!bch2_bucket_is_open_safe(c, new.k->p.inode, new.k->p.offset)) {
|
||||
new_a->gen++;
|
||||
SET_BCH_ALLOC_V4_NEED_INC_GEN(new_a, false);
|
||||
alloc_data_type_set(new_a, new_a->data_type);
|
||||
}
|
||||
|
||||
if (old_a->data_type != new_a->data_type ||
|
||||
@ -781,7 +790,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
|
||||
|
||||
if (new_a->data_type == BCH_DATA_cached &&
|
||||
!new_a->io_time[READ])
|
||||
new_a->io_time[READ] = max_t(u64, 1, atomic64_read(&c->io_clock[READ].now));
|
||||
new_a->io_time[READ] = bch2_current_io_time(c, READ);
|
||||
|
||||
u64 old_lru = alloc_lru_idx_read(*old_a);
|
||||
u64 new_lru = alloc_lru_idx_read(*new_a);
|
||||
@ -882,7 +891,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
|
||||
closure_wake_up(&c->freelist_wait);
|
||||
|
||||
if (statechange(a->data_type == BCH_DATA_need_discard) &&
|
||||
!bch2_bucket_is_open(c, new.k->p.inode, new.k->p.offset) &&
|
||||
!bch2_bucket_is_open_safe(c, new.k->p.inode, new.k->p.offset) &&
|
||||
bucket_flushed(new_a))
|
||||
bch2_discard_one_bucket_fast(c, new.k->p);
|
||||
|
||||
@ -1579,7 +1588,7 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
a_mut->v.io_time[READ] = atomic64_read(&c->io_clock[READ].now);
|
||||
a_mut->v.io_time[READ] = bch2_current_io_time(c, READ);
|
||||
ret = bch2_trans_update(trans, alloc_iter,
|
||||
&a_mut->k_i, BTREE_TRIGGER_norun);
|
||||
if (ret)
|
||||
@ -1634,7 +1643,7 @@ static int discard_in_flight_add(struct bch_fs *c, struct bpos bucket)
|
||||
mutex_lock(&c->discard_buckets_in_flight_lock);
|
||||
darray_for_each(c->discard_buckets_in_flight, i)
|
||||
if (bkey_eq(*i, bucket)) {
|
||||
ret = -EEXIST;
|
||||
ret = -BCH_ERR_EEXIST_discard_in_flight_add;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1788,8 +1797,9 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
|
||||
}
|
||||
|
||||
SET_BCH_ALLOC_V4_NEED_DISCARD(&a->v, false);
|
||||
alloc_data_type_set(&a->v, a->v.data_type);
|
||||
write:
|
||||
alloc_data_type_set(&a->v, a->v.data_type);
|
||||
|
||||
ret = bch2_trans_update(trans, &iter, &a->k_i, 0) ?:
|
||||
bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_WATERMARK_btree|
|
||||
@ -1975,8 +1985,8 @@ static int invalidate_one_bucket(struct btree_trans *trans,
|
||||
a->v.data_type = 0;
|
||||
a->v.dirty_sectors = 0;
|
||||
a->v.cached_sectors = 0;
|
||||
a->v.io_time[READ] = atomic64_read(&c->io_clock[READ].now);
|
||||
a->v.io_time[WRITE] = atomic64_read(&c->io_clock[WRITE].now);
|
||||
a->v.io_time[READ] = bch2_current_io_time(c, READ);
|
||||
a->v.io_time[WRITE] = bch2_current_io_time(c, WRITE);
|
||||
|
||||
ret = bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_WATERMARK_btree|
|
||||
@ -2011,6 +2021,21 @@ err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct bch_dev *ca, bool *wrapped)
|
||||
{
|
||||
struct bkey_s_c k;
|
||||
again:
|
||||
k = bch2_btree_iter_peek_upto(iter, lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX));
|
||||
if (!k.k && !*wrapped) {
|
||||
bch2_btree_iter_set_pos(iter, lru_pos(ca->dev_idx, 0, 0));
|
||||
*wrapped = true;
|
||||
goto again;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
static void bch2_do_invalidates_work(struct work_struct *work)
|
||||
{
|
||||
struct bch_fs *c = container_of(work, struct bch_fs, invalidate_work);
|
||||
@ -2024,12 +2049,33 @@ static void bch2_do_invalidates_work(struct work_struct *work)
|
||||
for_each_member_device(c, ca) {
|
||||
s64 nr_to_invalidate =
|
||||
should_invalidate_buckets(ca, bch2_dev_usage_read(ca));
|
||||
struct btree_iter iter;
|
||||
bool wrapped = false;
|
||||
|
||||
ret = for_each_btree_key_upto(trans, iter, BTREE_ID_lru,
|
||||
lru_pos(ca->dev_idx, 0, 0),
|
||||
lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX),
|
||||
BTREE_ITER_intent, k,
|
||||
invalidate_one_bucket(trans, &iter, k, &nr_to_invalidate));
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_lru,
|
||||
lru_pos(ca->dev_idx, 0,
|
||||
((bch2_current_io_time(c, READ) + U32_MAX) &
|
||||
LRU_TIME_MAX)), 0);
|
||||
|
||||
while (true) {
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
struct bkey_s_c k = next_lru_key(trans, &iter, ca, &wrapped);
|
||||
ret = bkey_err(k);
|
||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
|
||||
continue;
|
||||
if (ret)
|
||||
break;
|
||||
if (!k.k)
|
||||
break;
|
||||
|
||||
ret = invalidate_one_bucket(trans, &iter, k, &nr_to_invalidate);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
bch2_btree_iter_advance(&iter);
|
||||
}
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
|
||||
if (ret < 0) {
|
||||
bch2_dev_put(ca);
|
||||
@ -2204,7 +2250,7 @@ int bch2_bucket_io_time_reset(struct btree_trans *trans, unsigned dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
now = atomic64_read(&c->io_clock[rw].now);
|
||||
now = bch2_current_io_time(c, rw);
|
||||
if (a->v.io_time[rw] == now)
|
||||
goto out;
|
||||
|
||||
|
@ -141,7 +141,13 @@ static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a,
|
||||
!bch2_bucket_sectors_fragmented(ca, a))
|
||||
return 0;
|
||||
|
||||
u64 d = bch2_bucket_sectors_dirty(a);
|
||||
/*
|
||||
* avoid overflowing LRU_TIME_BITS on a corrupted fs, when
|
||||
* bucket_sectors_dirty is (much) bigger than bucket_size
|
||||
*/
|
||||
u64 d = min(bch2_bucket_sectors_dirty(a),
|
||||
ca->mi.bucket_size);
|
||||
|
||||
return div_u64(d * (1ULL << 31), ca->mi.bucket_size);
|
||||
}
|
||||
|
||||
|
@ -1214,6 +1214,11 @@ static inline s64 bch2_current_time(const struct bch_fs *c)
|
||||
return timespec_to_bch2_time(c, now);
|
||||
}
|
||||
|
||||
static inline u64 bch2_current_io_time(const struct bch_fs *c, int rw)
|
||||
{
|
||||
return max(1ULL, (u64) atomic64_read(&c->io_clock[rw].now) & LRU_TIME_MAX);
|
||||
}
|
||||
|
||||
static inline struct stdio_redirect *bch2_fs_stdio_redirect(struct bch_fs *c)
|
||||
{
|
||||
struct stdio_redirect *stdio = c->stdio;
|
||||
|
@ -476,6 +476,9 @@ struct bch_lru {
|
||||
|
||||
#define LRU_ID_STRIPES (1U << 16)
|
||||
|
||||
#define LRU_TIME_BITS 48
|
||||
#define LRU_TIME_MAX ((1ULL << LRU_TIME_BITS) - 1)
|
||||
|
||||
/* Optional/variable size superblock sections: */
|
||||
|
||||
struct bch_sb_field {
|
||||
@ -987,8 +990,9 @@ enum bch_version_upgrade_opts {
|
||||
|
||||
#define BCH_ERROR_ACTIONS() \
|
||||
x(continue, 0) \
|
||||
x(ro, 1) \
|
||||
x(panic, 2)
|
||||
x(fix_safe, 1) \
|
||||
x(panic, 2) \
|
||||
x(ro, 3)
|
||||
|
||||
enum bch_error_actions {
|
||||
#define x(t, n) BCH_ON_ERROR_##t = n,
|
||||
@ -1382,9 +1386,10 @@ enum btree_id {
|
||||
|
||||
/*
|
||||
* Maximum number of btrees that we will _ever_ have under the current scheme,
|
||||
* where we refer to them with bitfields
|
||||
* where we refer to them with 64 bit bitfields - and we also need a bit for
|
||||
* the interior btree node type:
|
||||
*/
|
||||
#define BTREE_ID_NR_MAX 64
|
||||
#define BTREE_ID_NR_MAX 63
|
||||
|
||||
static inline bool btree_id_is_alloc(enum btree_id id)
|
||||
{
|
||||
|
@ -1064,7 +1064,7 @@ void bch2_bkey_swab_key(const struct bkey_format *_f, struct bkey_packed *k)
|
||||
{
|
||||
const struct bkey_format *f = bkey_packed(k) ? _f : &bch2_bkey_format_current;
|
||||
u8 *l = k->key_start;
|
||||
u8 *h = (u8 *) (k->_data + f->key_u64s) - 1;
|
||||
u8 *h = (u8 *) ((u64 *) k->_data + f->key_u64s) - 1;
|
||||
|
||||
while (l < h) {
|
||||
swap(*l, *h);
|
||||
|
@ -398,8 +398,12 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
|
||||
for (i = 0; i < nr_compat; i++)
|
||||
switch (!write ? i : nr_compat - 1 - i) {
|
||||
case 0:
|
||||
if (big_endian != CPU_BIG_ENDIAN)
|
||||
if (big_endian != CPU_BIG_ENDIAN) {
|
||||
bch2_bkey_swab_key(f, k);
|
||||
} else if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG)) {
|
||||
bch2_bkey_swab_key(f, k);
|
||||
bch2_bkey_swab_key(f, k);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (version < bcachefs_metadata_version_bkey_renumber)
|
||||
|
@ -129,7 +129,8 @@ static inline void bch2_bkey_compat(unsigned level, enum btree_id btree_id,
|
||||
struct bkey_packed *k)
|
||||
{
|
||||
if (version < bcachefs_metadata_version_current ||
|
||||
big_endian != CPU_BIG_ENDIAN)
|
||||
big_endian != CPU_BIG_ENDIAN ||
|
||||
IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
|
||||
__bch2_bkey_compat(level, btree_id, version,
|
||||
big_endian, write, f, k);
|
||||
|
||||
|
@ -3161,6 +3161,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
|
||||
list_add_done:
|
||||
seqmutex_unlock(&c->btree_trans_lock);
|
||||
got_trans:
|
||||
trans->ref.closure_get_happened = false;
|
||||
trans->c = c;
|
||||
trans->last_begin_time = local_clock();
|
||||
trans->fn_idx = fn_idx;
|
||||
@ -3235,7 +3236,6 @@ void bch2_trans_put(struct btree_trans *trans)
|
||||
trans_for_each_update(trans, i)
|
||||
__btree_path_put(trans->paths + i->path, true);
|
||||
trans->nr_updates = 0;
|
||||
trans->locking_wait.task = NULL;
|
||||
|
||||
check_btree_paths_leaked(trans);
|
||||
|
||||
@ -3256,6 +3256,13 @@ void bch2_trans_put(struct btree_trans *trans)
|
||||
if (unlikely(trans->journal_replay_not_finished))
|
||||
bch2_journal_keys_put(c);
|
||||
|
||||
/*
|
||||
* trans->ref protects trans->locking_wait.task, btree_paths arary; used
|
||||
* by cycle detector
|
||||
*/
|
||||
closure_sync(&trans->ref);
|
||||
trans->locking_wait.task = NULL;
|
||||
|
||||
unsigned long *paths_allocated = trans->paths_allocated;
|
||||
trans->paths_allocated = NULL;
|
||||
trans->paths = NULL;
|
||||
@ -3273,8 +3280,6 @@ void bch2_trans_put(struct btree_trans *trans)
|
||||
trans = this_cpu_xchg(c->btree_trans_bufs->trans, trans);
|
||||
|
||||
if (trans) {
|
||||
closure_sync(&trans->ref);
|
||||
|
||||
seqmutex_lock(&c->btree_trans_lock);
|
||||
list_del(&trans->list);
|
||||
seqmutex_unlock(&c->btree_trans_lock);
|
||||
|
@ -761,13 +761,13 @@ static inline bool btree_node_type_needs_gc(enum btree_node_type type)
|
||||
|
||||
static inline bool btree_node_type_is_extents(enum btree_node_type type)
|
||||
{
|
||||
const unsigned mask = 0
|
||||
const u64 mask = 0
|
||||
#define x(name, nr, flags, ...) |((!!((flags) & BTREE_ID_EXTENTS)) << (nr + 1))
|
||||
BCH_BTREE_IDS()
|
||||
#undef x
|
||||
;
|
||||
|
||||
return (1U << type) & mask;
|
||||
return BIT_ULL(type) & mask;
|
||||
}
|
||||
|
||||
static inline bool btree_id_is_extents(enum btree_id btree)
|
||||
@ -777,35 +777,35 @@ static inline bool btree_id_is_extents(enum btree_id btree)
|
||||
|
||||
static inline bool btree_type_has_snapshots(enum btree_id id)
|
||||
{
|
||||
const unsigned mask = 0
|
||||
const u64 mask = 0
|
||||
#define x(name, nr, flags, ...) |((!!((flags) & BTREE_ID_SNAPSHOTS)) << nr)
|
||||
BCH_BTREE_IDS()
|
||||
#undef x
|
||||
;
|
||||
|
||||
return (1U << id) & mask;
|
||||
return BIT_ULL(id) & mask;
|
||||
}
|
||||
|
||||
static inline bool btree_type_has_snapshot_field(enum btree_id id)
|
||||
{
|
||||
const unsigned mask = 0
|
||||
const u64 mask = 0
|
||||
#define x(name, nr, flags, ...) |((!!((flags) & (BTREE_ID_SNAPSHOT_FIELD|BTREE_ID_SNAPSHOTS))) << nr)
|
||||
BCH_BTREE_IDS()
|
||||
#undef x
|
||||
;
|
||||
|
||||
return (1U << id) & mask;
|
||||
return BIT_ULL(id) & mask;
|
||||
}
|
||||
|
||||
static inline bool btree_type_has_ptrs(enum btree_id id)
|
||||
{
|
||||
const unsigned mask = 0
|
||||
const u64 mask = 0
|
||||
#define x(name, nr, flags, ...) |((!!((flags) & BTREE_ID_DATA)) << nr)
|
||||
BCH_BTREE_IDS()
|
||||
#undef x
|
||||
;
|
||||
|
||||
return (1U << id) & mask;
|
||||
return BIT_ULL(id) & mask;
|
||||
}
|
||||
|
||||
struct btree_root {
|
||||
|
@ -116,6 +116,9 @@
|
||||
x(ENOENT, ENOENT_dev_idx_not_found) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_dir_not_empty) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_subvol_not_empty) \
|
||||
x(EEXIST, EEXIST_str_hash_set) \
|
||||
x(EEXIST, EEXIST_discard_in_flight_add) \
|
||||
x(EEXIST, EEXIST_subvolume_create) \
|
||||
x(0, open_buckets_empty) \
|
||||
x(0, freelist_empty) \
|
||||
x(BCH_ERR_freelist_empty, no_buckets_found) \
|
||||
|
@ -15,6 +15,7 @@ bool bch2_inconsistent_error(struct bch_fs *c)
|
||||
switch (c->opts.errors) {
|
||||
case BCH_ON_ERROR_continue:
|
||||
return false;
|
||||
case BCH_ON_ERROR_fix_safe:
|
||||
case BCH_ON_ERROR_ro:
|
||||
if (bch2_fs_emergency_read_only(c))
|
||||
bch_err(c, "inconsistency detected - emergency read only at journal seq %llu",
|
||||
@ -191,6 +192,12 @@ static void prt_actioning(struct printbuf *out, const char *action)
|
||||
prt_str(out, "ing");
|
||||
}
|
||||
|
||||
static const u8 fsck_flags_extra[] = {
|
||||
#define x(t, n, flags) [BCH_FSCK_ERR_##t] = flags,
|
||||
BCH_SB_ERRS()
|
||||
#undef x
|
||||
};
|
||||
|
||||
int bch2_fsck_err(struct bch_fs *c,
|
||||
enum bch_fsck_flags flags,
|
||||
enum bch_sb_error_id err,
|
||||
@ -203,6 +210,9 @@ int bch2_fsck_err(struct bch_fs *c,
|
||||
int ret = -BCH_ERR_fsck_ignore;
|
||||
const char *action_orig = "fix?", *action = action_orig;
|
||||
|
||||
if (!WARN_ON(err >= ARRAY_SIZE(fsck_flags_extra)))
|
||||
flags |= fsck_flags_extra[err];
|
||||
|
||||
if ((flags & FSCK_CAN_FIX) &&
|
||||
test_bit(err, c->sb.errors_silent))
|
||||
return -BCH_ERR_fsck_fix;
|
||||
@ -265,7 +275,14 @@ int bch2_fsck_err(struct bch_fs *c,
|
||||
prt_printf(out, bch2_log_msg(c, ""));
|
||||
#endif
|
||||
|
||||
if (!test_bit(BCH_FS_fsck_running, &c->flags)) {
|
||||
if ((flags & FSCK_CAN_FIX) &&
|
||||
(flags & FSCK_AUTOFIX) &&
|
||||
(c->opts.errors == BCH_ON_ERROR_continue ||
|
||||
c->opts.errors == BCH_ON_ERROR_fix_safe)) {
|
||||
prt_str(out, ", ");
|
||||
prt_actioning(out, action);
|
||||
ret = -BCH_ERR_fsck_fix;
|
||||
} else if (!test_bit(BCH_FS_fsck_running, &c->flags)) {
|
||||
if (c->opts.errors != BCH_ON_ERROR_continue ||
|
||||
!(flags & (FSCK_CAN_FIX|FSCK_CAN_IGNORE))) {
|
||||
prt_str(out, ", shutting down");
|
||||
|
@ -108,13 +108,6 @@ struct fsck_err_state {
|
||||
char *last_msg;
|
||||
};
|
||||
|
||||
enum bch_fsck_flags {
|
||||
FSCK_CAN_FIX = 1 << 0,
|
||||
FSCK_CAN_IGNORE = 1 << 1,
|
||||
FSCK_NEED_FSCK = 1 << 2,
|
||||
FSCK_NO_RATELIMIT = 1 << 3,
|
||||
};
|
||||
|
||||
#define fsck_err_count(_c, _err) bch2_sb_err_count(_c, BCH_FSCK_ERR_##_err)
|
||||
|
||||
__printf(4, 5) __cold
|
||||
|
@ -373,7 +373,7 @@ retry:
|
||||
}
|
||||
|
||||
if (dst_dentry->d_inode) {
|
||||
error = -EEXIST;
|
||||
error = -BCH_ERR_EEXIST_subvolume_create;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
|
@ -188,6 +188,12 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino
|
||||
BUG_ON(!old);
|
||||
|
||||
if (unlikely(old != inode)) {
|
||||
/*
|
||||
* bcachefs doesn't use I_NEW; we have no use for it since we
|
||||
* only insert fully created inodes in the inode hash table. But
|
||||
* discard_new_inode() expects it to be set...
|
||||
*/
|
||||
inode->v.i_flags |= I_NEW;
|
||||
discard_new_inode(&inode->v);
|
||||
inode = old;
|
||||
} else {
|
||||
@ -195,8 +201,10 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino
|
||||
list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list);
|
||||
mutex_unlock(&c->vfs_inodes_lock);
|
||||
/*
|
||||
* we really don't want insert_inode_locked2() to be setting
|
||||
* I_NEW...
|
||||
* Again, I_NEW makes no sense for bcachefs. This is only needed
|
||||
* for clearing I_NEW, but since the inode was already fully
|
||||
* created and initialized we didn't actually want
|
||||
* inode_insert5() to set it for us.
|
||||
*/
|
||||
unlock_new_inode(&inode->v);
|
||||
}
|
||||
@ -1157,6 +1165,7 @@ static const struct file_operations bch_file_operations = {
|
||||
.read_iter = bch2_read_iter,
|
||||
.write_iter = bch2_write_iter,
|
||||
.mmap = bch2_mmap,
|
||||
.get_unmapped_area = thp_get_unmapped_area,
|
||||
.fsync = bch2_fsync,
|
||||
.splice_read = filemap_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
@ -1488,11 +1497,6 @@ static void bch2_vfs_inode_init(struct btree_trans *trans, subvol_inum inum,
|
||||
bch2_iget5_set(&inode->v, &inum);
|
||||
bch2_inode_update_after_write(trans, inode, bi, ~0);
|
||||
|
||||
if (BCH_SUBVOLUME_SNAP(subvol))
|
||||
set_bit(EI_INODE_SNAPSHOT, &inode->ei_flags);
|
||||
else
|
||||
clear_bit(EI_INODE_SNAPSHOT, &inode->ei_flags);
|
||||
|
||||
inode->v.i_blocks = bi->bi_sectors;
|
||||
inode->v.i_ino = bi->bi_inum;
|
||||
inode->v.i_rdev = bi->bi_dev;
|
||||
@ -1504,6 +1508,9 @@ static void bch2_vfs_inode_init(struct btree_trans *trans, subvol_inum inum,
|
||||
inode->ei_qid = bch_qid(bi);
|
||||
inode->ei_subvol = inum.subvol;
|
||||
|
||||
if (BCH_SUBVOLUME_SNAP(subvol))
|
||||
set_bit(EI_INODE_SNAPSHOT, &inode->ei_flags);
|
||||
|
||||
inode->v.i_mapping->a_ops = &bch_address_space_operations;
|
||||
|
||||
switch (inode->v.i_mode & S_IFMT) {
|
||||
|
@ -1167,6 +1167,9 @@ void bch2_dev_journal_stop(struct journal *j, struct bch_dev *ca)
|
||||
|
||||
void bch2_fs_journal_stop(struct journal *j)
|
||||
{
|
||||
if (!test_bit(JOURNAL_running, &j->flags))
|
||||
return;
|
||||
|
||||
bch2_journal_reclaim_stop(j);
|
||||
bch2_journal_flush_all_pins(j);
|
||||
|
||||
|
@ -1967,7 +1967,6 @@ CLOSURE_CALLBACK(bch2_journal_write)
|
||||
struct journal *j = container_of(w, struct journal, buf[w->idx]);
|
||||
struct bch_fs *c = container_of(j, struct bch_fs, journal);
|
||||
struct bch_replicas_padded replicas;
|
||||
struct printbuf journal_debug_buf = PRINTBUF;
|
||||
unsigned nr_rw_members = 0;
|
||||
int ret;
|
||||
|
||||
@ -2011,11 +2010,15 @@ CLOSURE_CALLBACK(bch2_journal_write)
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
__bch2_journal_debug_to_text(&journal_debug_buf, j);
|
||||
struct printbuf buf = PRINTBUF;
|
||||
buf.atomic++;
|
||||
|
||||
prt_printf(&buf, bch2_fmt(c, "Unable to allocate journal write: %s"),
|
||||
bch2_err_str(ret));
|
||||
__bch2_journal_debug_to_text(&buf, j);
|
||||
spin_unlock(&j->lock);
|
||||
bch_err(c, "Unable to allocate journal write:\n%s",
|
||||
journal_debug_buf.buf);
|
||||
printbuf_exit(&journal_debug_buf);
|
||||
bch2_print_string_as_lines(KERN_ERR, buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,6 @@
|
||||
#ifndef _BCACHEFS_LRU_H
|
||||
#define _BCACHEFS_LRU_H
|
||||
|
||||
#define LRU_TIME_BITS 48
|
||||
#define LRU_TIME_MAX ((1ULL << LRU_TIME_BITS) - 1)
|
||||
|
||||
static inline u64 lru_pos_id(struct bpos pos)
|
||||
{
|
||||
return pos.inode >> LRU_TIME_BITS;
|
||||
|
@ -137,7 +137,7 @@ enum fsck_err_opts {
|
||||
x(errors, u8, \
|
||||
OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
|
||||
OPT_STR(bch2_error_actions), \
|
||||
BCH_SB_ERROR_ACTION, BCH_ON_ERROR_ro, \
|
||||
BCH_SB_ERROR_ACTION, BCH_ON_ERROR_fix_safe, \
|
||||
NULL, "Action to take on filesystem error") \
|
||||
x(metadata_replicas, u8, \
|
||||
OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
|
||||
|
@ -326,6 +326,12 @@ static int journal_replay_entry_early(struct bch_fs *c,
|
||||
case BCH_JSET_ENTRY_btree_root: {
|
||||
struct btree_root *r;
|
||||
|
||||
if (fsck_err_on(entry->btree_id >= BTREE_ID_NR_MAX,
|
||||
c, invalid_btree_id,
|
||||
"invalid btree id %u (max %u)",
|
||||
entry->btree_id, BTREE_ID_NR_MAX))
|
||||
return 0;
|
||||
|
||||
while (entry->btree_id >= c->btree_roots_extra.nr + BTREE_ID_NR) {
|
||||
ret = darray_push(&c->btree_roots_extra, (struct btree_root) { NULL });
|
||||
if (ret)
|
||||
@ -415,7 +421,7 @@ static int journal_replay_entry_early(struct bch_fs *c,
|
||||
atomic64_set(&c->io_clock[clock->rw].now, le64_to_cpu(clock->time));
|
||||
}
|
||||
}
|
||||
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -658,10 +664,10 @@ int bch2_fs_recovery(struct bch_fs *c)
|
||||
if (check_version_upgrade(c))
|
||||
write_sb = true;
|
||||
|
||||
c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
|
||||
|
||||
if (write_sb)
|
||||
bch2_write_super(c);
|
||||
|
||||
c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
if (c->opts.fsck && IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
|
||||
|
@ -228,7 +228,7 @@ int bch2_sb_downgrade_update(struct bch_fs *c)
|
||||
|
||||
dst = (void *) &darray_top(table);
|
||||
dst->version = cpu_to_le16(src->version);
|
||||
dst->recovery_passes[0] = cpu_to_le64(src->recovery_passes);
|
||||
dst->recovery_passes[0] = cpu_to_le64(bch2_recovery_passes_to_stable(src->recovery_passes));
|
||||
dst->recovery_passes[1] = 0;
|
||||
dst->nr_errors = cpu_to_le16(src->nr_errors);
|
||||
for (unsigned i = 0; i < src->nr_errors; i++)
|
||||
|
@ -2,281 +2,294 @@
|
||||
#ifndef _BCACHEFS_SB_ERRORS_FORMAT_H
|
||||
#define _BCACHEFS_SB_ERRORS_FORMAT_H
|
||||
|
||||
#define BCH_SB_ERRS() \
|
||||
x(clean_but_journal_not_empty, 0) \
|
||||
x(dirty_but_no_journal_entries, 1) \
|
||||
x(dirty_but_no_journal_entries_post_drop_nonflushes, 2) \
|
||||
x(sb_clean_journal_seq_mismatch, 3) \
|
||||
x(sb_clean_btree_root_mismatch, 4) \
|
||||
x(sb_clean_missing, 5) \
|
||||
x(jset_unsupported_version, 6) \
|
||||
x(jset_unknown_csum, 7) \
|
||||
x(jset_last_seq_newer_than_seq, 8) \
|
||||
x(jset_past_bucket_end, 9) \
|
||||
x(jset_seq_blacklisted, 10) \
|
||||
x(journal_entries_missing, 11) \
|
||||
x(journal_entry_replicas_not_marked, 12) \
|
||||
x(journal_entry_past_jset_end, 13) \
|
||||
x(journal_entry_replicas_data_mismatch, 14) \
|
||||
x(journal_entry_bkey_u64s_0, 15) \
|
||||
x(journal_entry_bkey_past_end, 16) \
|
||||
x(journal_entry_bkey_bad_format, 17) \
|
||||
x(journal_entry_bkey_invalid, 18) \
|
||||
x(journal_entry_btree_root_bad_size, 19) \
|
||||
x(journal_entry_blacklist_bad_size, 20) \
|
||||
x(journal_entry_blacklist_v2_bad_size, 21) \
|
||||
x(journal_entry_blacklist_v2_start_past_end, 22) \
|
||||
x(journal_entry_usage_bad_size, 23) \
|
||||
x(journal_entry_data_usage_bad_size, 24) \
|
||||
x(journal_entry_clock_bad_size, 25) \
|
||||
x(journal_entry_clock_bad_rw, 26) \
|
||||
x(journal_entry_dev_usage_bad_size, 27) \
|
||||
x(journal_entry_dev_usage_bad_dev, 28) \
|
||||
x(journal_entry_dev_usage_bad_pad, 29) \
|
||||
x(btree_node_unreadable, 30) \
|
||||
x(btree_node_fault_injected, 31) \
|
||||
x(btree_node_bad_magic, 32) \
|
||||
x(btree_node_bad_seq, 33) \
|
||||
x(btree_node_unsupported_version, 34) \
|
||||
x(btree_node_bset_older_than_sb_min, 35) \
|
||||
x(btree_node_bset_newer_than_sb, 36) \
|
||||
x(btree_node_data_missing, 37) \
|
||||
x(btree_node_bset_after_end, 38) \
|
||||
x(btree_node_replicas_sectors_written_mismatch, 39) \
|
||||
x(btree_node_replicas_data_mismatch, 40) \
|
||||
x(bset_unknown_csum, 41) \
|
||||
x(bset_bad_csum, 42) \
|
||||
x(bset_past_end_of_btree_node, 43) \
|
||||
x(bset_wrong_sector_offset, 44) \
|
||||
x(bset_empty, 45) \
|
||||
x(bset_bad_seq, 46) \
|
||||
x(bset_blacklisted_journal_seq, 47) \
|
||||
x(first_bset_blacklisted_journal_seq, 48) \
|
||||
x(btree_node_bad_btree, 49) \
|
||||
x(btree_node_bad_level, 50) \
|
||||
x(btree_node_bad_min_key, 51) \
|
||||
x(btree_node_bad_max_key, 52) \
|
||||
x(btree_node_bad_format, 53) \
|
||||
x(btree_node_bkey_past_bset_end, 54) \
|
||||
x(btree_node_bkey_bad_format, 55) \
|
||||
x(btree_node_bad_bkey, 56) \
|
||||
x(btree_node_bkey_out_of_order, 57) \
|
||||
x(btree_root_bkey_invalid, 58) \
|
||||
x(btree_root_read_error, 59) \
|
||||
x(btree_root_bad_min_key, 60) \
|
||||
x(btree_root_bad_max_key, 61) \
|
||||
x(btree_node_read_error, 62) \
|
||||
x(btree_node_topology_bad_min_key, 63) \
|
||||
x(btree_node_topology_bad_max_key, 64) \
|
||||
x(btree_node_topology_overwritten_by_prev_node, 65) \
|
||||
x(btree_node_topology_overwritten_by_next_node, 66) \
|
||||
x(btree_node_topology_interior_node_empty, 67) \
|
||||
x(fs_usage_hidden_wrong, 68) \
|
||||
x(fs_usage_btree_wrong, 69) \
|
||||
x(fs_usage_data_wrong, 70) \
|
||||
x(fs_usage_cached_wrong, 71) \
|
||||
x(fs_usage_reserved_wrong, 72) \
|
||||
x(fs_usage_persistent_reserved_wrong, 73) \
|
||||
x(fs_usage_nr_inodes_wrong, 74) \
|
||||
x(fs_usage_replicas_wrong, 75) \
|
||||
x(dev_usage_buckets_wrong, 76) \
|
||||
x(dev_usage_sectors_wrong, 77) \
|
||||
x(dev_usage_fragmented_wrong, 78) \
|
||||
x(dev_usage_buckets_ec_wrong, 79) \
|
||||
x(bkey_version_in_future, 80) \
|
||||
x(bkey_u64s_too_small, 81) \
|
||||
x(bkey_invalid_type_for_btree, 82) \
|
||||
x(bkey_extent_size_zero, 83) \
|
||||
x(bkey_extent_size_greater_than_offset, 84) \
|
||||
x(bkey_size_nonzero, 85) \
|
||||
x(bkey_snapshot_nonzero, 86) \
|
||||
x(bkey_snapshot_zero, 87) \
|
||||
x(bkey_at_pos_max, 88) \
|
||||
x(bkey_before_start_of_btree_node, 89) \
|
||||
x(bkey_after_end_of_btree_node, 90) \
|
||||
x(bkey_val_size_nonzero, 91) \
|
||||
x(bkey_val_size_too_small, 92) \
|
||||
x(alloc_v1_val_size_bad, 93) \
|
||||
x(alloc_v2_unpack_error, 94) \
|
||||
x(alloc_v3_unpack_error, 95) \
|
||||
x(alloc_v4_val_size_bad, 96) \
|
||||
x(alloc_v4_backpointers_start_bad, 97) \
|
||||
x(alloc_key_data_type_bad, 98) \
|
||||
x(alloc_key_empty_but_have_data, 99) \
|
||||
x(alloc_key_dirty_sectors_0, 100) \
|
||||
x(alloc_key_data_type_inconsistency, 101) \
|
||||
x(alloc_key_to_missing_dev_bucket, 102) \
|
||||
x(alloc_key_cached_inconsistency, 103) \
|
||||
x(alloc_key_cached_but_read_time_zero, 104) \
|
||||
x(alloc_key_to_missing_lru_entry, 105) \
|
||||
x(alloc_key_data_type_wrong, 106) \
|
||||
x(alloc_key_gen_wrong, 107) \
|
||||
x(alloc_key_dirty_sectors_wrong, 108) \
|
||||
x(alloc_key_cached_sectors_wrong, 109) \
|
||||
x(alloc_key_stripe_wrong, 110) \
|
||||
x(alloc_key_stripe_redundancy_wrong, 111) \
|
||||
x(bucket_sector_count_overflow, 112) \
|
||||
x(bucket_metadata_type_mismatch, 113) \
|
||||
x(need_discard_key_wrong, 114) \
|
||||
x(freespace_key_wrong, 115) \
|
||||
x(freespace_hole_missing, 116) \
|
||||
x(bucket_gens_val_size_bad, 117) \
|
||||
x(bucket_gens_key_wrong, 118) \
|
||||
x(bucket_gens_hole_wrong, 119) \
|
||||
x(bucket_gens_to_invalid_dev, 120) \
|
||||
x(bucket_gens_to_invalid_buckets, 121) \
|
||||
x(bucket_gens_nonzero_for_invalid_buckets, 122) \
|
||||
x(need_discard_freespace_key_to_invalid_dev_bucket, 123) \
|
||||
x(need_discard_freespace_key_bad, 124) \
|
||||
x(backpointer_bucket_offset_wrong, 125) \
|
||||
x(backpointer_to_missing_device, 126) \
|
||||
x(backpointer_to_missing_alloc, 127) \
|
||||
x(backpointer_to_missing_ptr, 128) \
|
||||
x(lru_entry_at_time_0, 129) \
|
||||
x(lru_entry_to_invalid_bucket, 130) \
|
||||
x(lru_entry_bad, 131) \
|
||||
x(btree_ptr_val_too_big, 132) \
|
||||
x(btree_ptr_v2_val_too_big, 133) \
|
||||
x(btree_ptr_has_non_ptr, 134) \
|
||||
x(extent_ptrs_invalid_entry, 135) \
|
||||
x(extent_ptrs_no_ptrs, 136) \
|
||||
x(extent_ptrs_too_many_ptrs, 137) \
|
||||
x(extent_ptrs_redundant_crc, 138) \
|
||||
x(extent_ptrs_redundant_stripe, 139) \
|
||||
x(extent_ptrs_unwritten, 140) \
|
||||
x(extent_ptrs_written_and_unwritten, 141) \
|
||||
x(ptr_to_invalid_device, 142) \
|
||||
x(ptr_to_duplicate_device, 143) \
|
||||
x(ptr_after_last_bucket, 144) \
|
||||
x(ptr_before_first_bucket, 145) \
|
||||
x(ptr_spans_multiple_buckets, 146) \
|
||||
x(ptr_to_missing_backpointer, 147) \
|
||||
x(ptr_to_missing_alloc_key, 148) \
|
||||
x(ptr_to_missing_replicas_entry, 149) \
|
||||
x(ptr_to_missing_stripe, 150) \
|
||||
x(ptr_to_incorrect_stripe, 151) \
|
||||
x(ptr_gen_newer_than_bucket_gen, 152) \
|
||||
x(ptr_too_stale, 153) \
|
||||
x(stale_dirty_ptr, 154) \
|
||||
x(ptr_bucket_data_type_mismatch, 155) \
|
||||
x(ptr_cached_and_erasure_coded, 156) \
|
||||
x(ptr_crc_uncompressed_size_too_small, 157) \
|
||||
x(ptr_crc_csum_type_unknown, 158) \
|
||||
x(ptr_crc_compression_type_unknown, 159) \
|
||||
x(ptr_crc_redundant, 160) \
|
||||
x(ptr_crc_uncompressed_size_too_big, 161) \
|
||||
x(ptr_crc_nonce_mismatch, 162) \
|
||||
x(ptr_stripe_redundant, 163) \
|
||||
x(reservation_key_nr_replicas_invalid, 164) \
|
||||
x(reflink_v_refcount_wrong, 165) \
|
||||
x(reflink_p_to_missing_reflink_v, 166) \
|
||||
x(stripe_pos_bad, 167) \
|
||||
x(stripe_val_size_bad, 168) \
|
||||
x(stripe_sector_count_wrong, 169) \
|
||||
x(snapshot_tree_pos_bad, 170) \
|
||||
x(snapshot_tree_to_missing_snapshot, 171) \
|
||||
x(snapshot_tree_to_missing_subvol, 172) \
|
||||
x(snapshot_tree_to_wrong_subvol, 173) \
|
||||
x(snapshot_tree_to_snapshot_subvol, 174) \
|
||||
x(snapshot_pos_bad, 175) \
|
||||
x(snapshot_parent_bad, 176) \
|
||||
x(snapshot_children_not_normalized, 177) \
|
||||
x(snapshot_child_duplicate, 178) \
|
||||
x(snapshot_child_bad, 179) \
|
||||
x(snapshot_skiplist_not_normalized, 180) \
|
||||
x(snapshot_skiplist_bad, 181) \
|
||||
x(snapshot_should_not_have_subvol, 182) \
|
||||
x(snapshot_to_bad_snapshot_tree, 183) \
|
||||
x(snapshot_bad_depth, 184) \
|
||||
x(snapshot_bad_skiplist, 185) \
|
||||
x(subvol_pos_bad, 186) \
|
||||
x(subvol_not_master_and_not_snapshot, 187) \
|
||||
x(subvol_to_missing_root, 188) \
|
||||
x(subvol_root_wrong_bi_subvol, 189) \
|
||||
x(bkey_in_missing_snapshot, 190) \
|
||||
x(inode_pos_inode_nonzero, 191) \
|
||||
x(inode_pos_blockdev_range, 192) \
|
||||
x(inode_unpack_error, 193) \
|
||||
x(inode_str_hash_invalid, 194) \
|
||||
x(inode_v3_fields_start_bad, 195) \
|
||||
x(inode_snapshot_mismatch, 196) \
|
||||
x(inode_unlinked_but_clean, 197) \
|
||||
x(inode_unlinked_but_nlink_nonzero, 198) \
|
||||
x(inode_checksum_type_invalid, 199) \
|
||||
x(inode_compression_type_invalid, 200) \
|
||||
x(inode_subvol_root_but_not_dir, 201) \
|
||||
x(inode_i_size_dirty_but_clean, 202) \
|
||||
x(inode_i_sectors_dirty_but_clean, 203) \
|
||||
x(inode_i_sectors_wrong, 204) \
|
||||
x(inode_dir_wrong_nlink, 205) \
|
||||
x(inode_dir_multiple_links, 206) \
|
||||
x(inode_multiple_links_but_nlink_0, 207) \
|
||||
x(inode_wrong_backpointer, 208) \
|
||||
x(inode_wrong_nlink, 209) \
|
||||
x(inode_unreachable, 210) \
|
||||
x(deleted_inode_but_clean, 211) \
|
||||
x(deleted_inode_missing, 212) \
|
||||
x(deleted_inode_is_dir, 213) \
|
||||
x(deleted_inode_not_unlinked, 214) \
|
||||
x(extent_overlapping, 215) \
|
||||
x(extent_in_missing_inode, 216) \
|
||||
x(extent_in_non_reg_inode, 217) \
|
||||
x(extent_past_end_of_inode, 218) \
|
||||
x(dirent_empty_name, 219) \
|
||||
x(dirent_val_too_big, 220) \
|
||||
x(dirent_name_too_long, 221) \
|
||||
x(dirent_name_embedded_nul, 222) \
|
||||
x(dirent_name_dot_or_dotdot, 223) \
|
||||
x(dirent_name_has_slash, 224) \
|
||||
x(dirent_d_type_wrong, 225) \
|
||||
x(inode_bi_parent_wrong, 226) \
|
||||
x(dirent_in_missing_dir_inode, 227) \
|
||||
x(dirent_in_non_dir_inode, 228) \
|
||||
x(dirent_to_missing_inode, 229) \
|
||||
x(dirent_to_missing_subvol, 230) \
|
||||
x(dirent_to_itself, 231) \
|
||||
x(quota_type_invalid, 232) \
|
||||
x(xattr_val_size_too_small, 233) \
|
||||
x(xattr_val_size_too_big, 234) \
|
||||
x(xattr_invalid_type, 235) \
|
||||
x(xattr_name_invalid_chars, 236) \
|
||||
x(xattr_in_missing_inode, 237) \
|
||||
x(root_subvol_missing, 238) \
|
||||
x(root_dir_missing, 239) \
|
||||
x(root_inode_not_dir, 240) \
|
||||
x(dir_loop, 241) \
|
||||
x(hash_table_key_duplicate, 242) \
|
||||
x(hash_table_key_wrong_offset, 243) \
|
||||
x(unlinked_inode_not_on_deleted_list, 244) \
|
||||
x(reflink_p_front_pad_bad, 245) \
|
||||
x(journal_entry_dup_same_device, 246) \
|
||||
x(inode_bi_subvol_missing, 247) \
|
||||
x(inode_bi_subvol_wrong, 248) \
|
||||
x(inode_points_to_missing_dirent, 249) \
|
||||
x(inode_points_to_wrong_dirent, 250) \
|
||||
x(inode_bi_parent_nonzero, 251) \
|
||||
x(dirent_to_missing_parent_subvol, 252) \
|
||||
x(dirent_not_visible_in_parent_subvol, 253) \
|
||||
x(subvol_fs_path_parent_wrong, 254) \
|
||||
x(subvol_root_fs_path_parent_nonzero, 255) \
|
||||
x(subvol_children_not_set, 256) \
|
||||
x(subvol_children_bad, 257) \
|
||||
x(subvol_loop, 258) \
|
||||
x(subvol_unreachable, 259) \
|
||||
x(btree_node_bkey_bad_u64s, 260) \
|
||||
x(btree_node_topology_empty_interior_node, 261) \
|
||||
x(btree_ptr_v2_min_key_bad, 262) \
|
||||
x(btree_root_unreadable_and_scan_found_nothing, 263) \
|
||||
x(snapshot_node_missing, 264) \
|
||||
x(dup_backpointer_to_bad_csum_extent, 265) \
|
||||
x(btree_bitmap_not_marked, 266) \
|
||||
x(sb_clean_entry_overrun, 267) \
|
||||
x(btree_ptr_v2_written_0, 268) \
|
||||
x(subvol_snapshot_bad, 269) \
|
||||
x(subvol_inode_bad, 270)
|
||||
enum bch_fsck_flags {
|
||||
FSCK_CAN_FIX = 1 << 0,
|
||||
FSCK_CAN_IGNORE = 1 << 1,
|
||||
FSCK_NEED_FSCK = 1 << 2,
|
||||
FSCK_NO_RATELIMIT = 1 << 3,
|
||||
FSCK_AUTOFIX = 1 << 4,
|
||||
};
|
||||
|
||||
#define BCH_SB_ERRS() \
|
||||
x(clean_but_journal_not_empty, 0, 0) \
|
||||
x(dirty_but_no_journal_entries, 1, 0) \
|
||||
x(dirty_but_no_journal_entries_post_drop_nonflushes, 2, 0) \
|
||||
x(sb_clean_journal_seq_mismatch, 3, 0) \
|
||||
x(sb_clean_btree_root_mismatch, 4, 0) \
|
||||
x(sb_clean_missing, 5, 0) \
|
||||
x(jset_unsupported_version, 6, 0) \
|
||||
x(jset_unknown_csum, 7, 0) \
|
||||
x(jset_last_seq_newer_than_seq, 8, 0) \
|
||||
x(jset_past_bucket_end, 9, 0) \
|
||||
x(jset_seq_blacklisted, 10, 0) \
|
||||
x(journal_entries_missing, 11, 0) \
|
||||
x(journal_entry_replicas_not_marked, 12, 0) \
|
||||
x(journal_entry_past_jset_end, 13, 0) \
|
||||
x(journal_entry_replicas_data_mismatch, 14, 0) \
|
||||
x(journal_entry_bkey_u64s_0, 15, 0) \
|
||||
x(journal_entry_bkey_past_end, 16, 0) \
|
||||
x(journal_entry_bkey_bad_format, 17, 0) \
|
||||
x(journal_entry_bkey_invalid, 18, 0) \
|
||||
x(journal_entry_btree_root_bad_size, 19, 0) \
|
||||
x(journal_entry_blacklist_bad_size, 20, 0) \
|
||||
x(journal_entry_blacklist_v2_bad_size, 21, 0) \
|
||||
x(journal_entry_blacklist_v2_start_past_end, 22, 0) \
|
||||
x(journal_entry_usage_bad_size, 23, 0) \
|
||||
x(journal_entry_data_usage_bad_size, 24, 0) \
|
||||
x(journal_entry_clock_bad_size, 25, 0) \
|
||||
x(journal_entry_clock_bad_rw, 26, 0) \
|
||||
x(journal_entry_dev_usage_bad_size, 27, 0) \
|
||||
x(journal_entry_dev_usage_bad_dev, 28, 0) \
|
||||
x(journal_entry_dev_usage_bad_pad, 29, 0) \
|
||||
x(btree_node_unreadable, 30, 0) \
|
||||
x(btree_node_fault_injected, 31, 0) \
|
||||
x(btree_node_bad_magic, 32, 0) \
|
||||
x(btree_node_bad_seq, 33, 0) \
|
||||
x(btree_node_unsupported_version, 34, 0) \
|
||||
x(btree_node_bset_older_than_sb_min, 35, 0) \
|
||||
x(btree_node_bset_newer_than_sb, 36, 0) \
|
||||
x(btree_node_data_missing, 37, 0) \
|
||||
x(btree_node_bset_after_end, 38, 0) \
|
||||
x(btree_node_replicas_sectors_written_mismatch, 39, 0) \
|
||||
x(btree_node_replicas_data_mismatch, 40, 0) \
|
||||
x(bset_unknown_csum, 41, 0) \
|
||||
x(bset_bad_csum, 42, 0) \
|
||||
x(bset_past_end_of_btree_node, 43, 0) \
|
||||
x(bset_wrong_sector_offset, 44, 0) \
|
||||
x(bset_empty, 45, 0) \
|
||||
x(bset_bad_seq, 46, 0) \
|
||||
x(bset_blacklisted_journal_seq, 47, 0) \
|
||||
x(first_bset_blacklisted_journal_seq, 48, 0) \
|
||||
x(btree_node_bad_btree, 49, 0) \
|
||||
x(btree_node_bad_level, 50, 0) \
|
||||
x(btree_node_bad_min_key, 51, 0) \
|
||||
x(btree_node_bad_max_key, 52, 0) \
|
||||
x(btree_node_bad_format, 53, 0) \
|
||||
x(btree_node_bkey_past_bset_end, 54, 0) \
|
||||
x(btree_node_bkey_bad_format, 55, 0) \
|
||||
x(btree_node_bad_bkey, 56, 0) \
|
||||
x(btree_node_bkey_out_of_order, 57, 0) \
|
||||
x(btree_root_bkey_invalid, 58, 0) \
|
||||
x(btree_root_read_error, 59, 0) \
|
||||
x(btree_root_bad_min_key, 60, 0) \
|
||||
x(btree_root_bad_max_key, 61, 0) \
|
||||
x(btree_node_read_error, 62, 0) \
|
||||
x(btree_node_topology_bad_min_key, 63, 0) \
|
||||
x(btree_node_topology_bad_max_key, 64, 0) \
|
||||
x(btree_node_topology_overwritten_by_prev_node, 65, 0) \
|
||||
x(btree_node_topology_overwritten_by_next_node, 66, 0) \
|
||||
x(btree_node_topology_interior_node_empty, 67, 0) \
|
||||
x(fs_usage_hidden_wrong, 68, FSCK_AUTOFIX) \
|
||||
x(fs_usage_btree_wrong, 69, FSCK_AUTOFIX) \
|
||||
x(fs_usage_data_wrong, 70, FSCK_AUTOFIX) \
|
||||
x(fs_usage_cached_wrong, 71, FSCK_AUTOFIX) \
|
||||
x(fs_usage_reserved_wrong, 72, FSCK_AUTOFIX) \
|
||||
x(fs_usage_persistent_reserved_wrong, 73, FSCK_AUTOFIX) \
|
||||
x(fs_usage_nr_inodes_wrong, 74, FSCK_AUTOFIX) \
|
||||
x(fs_usage_replicas_wrong, 75, FSCK_AUTOFIX) \
|
||||
x(dev_usage_buckets_wrong, 76, FSCK_AUTOFIX) \
|
||||
x(dev_usage_sectors_wrong, 77, FSCK_AUTOFIX) \
|
||||
x(dev_usage_fragmented_wrong, 78, FSCK_AUTOFIX) \
|
||||
x(dev_usage_buckets_ec_wrong, 79, FSCK_AUTOFIX) \
|
||||
x(bkey_version_in_future, 80, 0) \
|
||||
x(bkey_u64s_too_small, 81, 0) \
|
||||
x(bkey_invalid_type_for_btree, 82, 0) \
|
||||
x(bkey_extent_size_zero, 83, 0) \
|
||||
x(bkey_extent_size_greater_than_offset, 84, 0) \
|
||||
x(bkey_size_nonzero, 85, 0) \
|
||||
x(bkey_snapshot_nonzero, 86, 0) \
|
||||
x(bkey_snapshot_zero, 87, 0) \
|
||||
x(bkey_at_pos_max, 88, 0) \
|
||||
x(bkey_before_start_of_btree_node, 89, 0) \
|
||||
x(bkey_after_end_of_btree_node, 90, 0) \
|
||||
x(bkey_val_size_nonzero, 91, 0) \
|
||||
x(bkey_val_size_too_small, 92, 0) \
|
||||
x(alloc_v1_val_size_bad, 93, 0) \
|
||||
x(alloc_v2_unpack_error, 94, 0) \
|
||||
x(alloc_v3_unpack_error, 95, 0) \
|
||||
x(alloc_v4_val_size_bad, 96, 0) \
|
||||
x(alloc_v4_backpointers_start_bad, 97, 0) \
|
||||
x(alloc_key_data_type_bad, 98, 0) \
|
||||
x(alloc_key_empty_but_have_data, 99, 0) \
|
||||
x(alloc_key_dirty_sectors_0, 100, 0) \
|
||||
x(alloc_key_data_type_inconsistency, 101, 0) \
|
||||
x(alloc_key_to_missing_dev_bucket, 102, 0) \
|
||||
x(alloc_key_cached_inconsistency, 103, 0) \
|
||||
x(alloc_key_cached_but_read_time_zero, 104, 0) \
|
||||
x(alloc_key_to_missing_lru_entry, 105, 0) \
|
||||
x(alloc_key_data_type_wrong, 106, FSCK_AUTOFIX) \
|
||||
x(alloc_key_gen_wrong, 107, FSCK_AUTOFIX) \
|
||||
x(alloc_key_dirty_sectors_wrong, 108, FSCK_AUTOFIX) \
|
||||
x(alloc_key_cached_sectors_wrong, 109, FSCK_AUTOFIX) \
|
||||
x(alloc_key_stripe_wrong, 110, FSCK_AUTOFIX) \
|
||||
x(alloc_key_stripe_redundancy_wrong, 111, FSCK_AUTOFIX) \
|
||||
x(bucket_sector_count_overflow, 112, 0) \
|
||||
x(bucket_metadata_type_mismatch, 113, 0) \
|
||||
x(need_discard_key_wrong, 114, 0) \
|
||||
x(freespace_key_wrong, 115, 0) \
|
||||
x(freespace_hole_missing, 116, 0) \
|
||||
x(bucket_gens_val_size_bad, 117, 0) \
|
||||
x(bucket_gens_key_wrong, 118, 0) \
|
||||
x(bucket_gens_hole_wrong, 119, 0) \
|
||||
x(bucket_gens_to_invalid_dev, 120, 0) \
|
||||
x(bucket_gens_to_invalid_buckets, 121, 0) \
|
||||
x(bucket_gens_nonzero_for_invalid_buckets, 122, 0) \
|
||||
x(need_discard_freespace_key_to_invalid_dev_bucket, 123, 0) \
|
||||
x(need_discard_freespace_key_bad, 124, 0) \
|
||||
x(backpointer_bucket_offset_wrong, 125, 0) \
|
||||
x(backpointer_to_missing_device, 126, 0) \
|
||||
x(backpointer_to_missing_alloc, 127, 0) \
|
||||
x(backpointer_to_missing_ptr, 128, 0) \
|
||||
x(lru_entry_at_time_0, 129, 0) \
|
||||
x(lru_entry_to_invalid_bucket, 130, 0) \
|
||||
x(lru_entry_bad, 131, 0) \
|
||||
x(btree_ptr_val_too_big, 132, 0) \
|
||||
x(btree_ptr_v2_val_too_big, 133, 0) \
|
||||
x(btree_ptr_has_non_ptr, 134, 0) \
|
||||
x(extent_ptrs_invalid_entry, 135, 0) \
|
||||
x(extent_ptrs_no_ptrs, 136, 0) \
|
||||
x(extent_ptrs_too_many_ptrs, 137, 0) \
|
||||
x(extent_ptrs_redundant_crc, 138, 0) \
|
||||
x(extent_ptrs_redundant_stripe, 139, 0) \
|
||||
x(extent_ptrs_unwritten, 140, 0) \
|
||||
x(extent_ptrs_written_and_unwritten, 141, 0) \
|
||||
x(ptr_to_invalid_device, 142, 0) \
|
||||
x(ptr_to_duplicate_device, 143, 0) \
|
||||
x(ptr_after_last_bucket, 144, 0) \
|
||||
x(ptr_before_first_bucket, 145, 0) \
|
||||
x(ptr_spans_multiple_buckets, 146, 0) \
|
||||
x(ptr_to_missing_backpointer, 147, 0) \
|
||||
x(ptr_to_missing_alloc_key, 148, 0) \
|
||||
x(ptr_to_missing_replicas_entry, 149, 0) \
|
||||
x(ptr_to_missing_stripe, 150, 0) \
|
||||
x(ptr_to_incorrect_stripe, 151, 0) \
|
||||
x(ptr_gen_newer_than_bucket_gen, 152, 0) \
|
||||
x(ptr_too_stale, 153, 0) \
|
||||
x(stale_dirty_ptr, 154, 0) \
|
||||
x(ptr_bucket_data_type_mismatch, 155, 0) \
|
||||
x(ptr_cached_and_erasure_coded, 156, 0) \
|
||||
x(ptr_crc_uncompressed_size_too_small, 157, 0) \
|
||||
x(ptr_crc_csum_type_unknown, 158, 0) \
|
||||
x(ptr_crc_compression_type_unknown, 159, 0) \
|
||||
x(ptr_crc_redundant, 160, 0) \
|
||||
x(ptr_crc_uncompressed_size_too_big, 161, 0) \
|
||||
x(ptr_crc_nonce_mismatch, 162, 0) \
|
||||
x(ptr_stripe_redundant, 163, 0) \
|
||||
x(reservation_key_nr_replicas_invalid, 164, 0) \
|
||||
x(reflink_v_refcount_wrong, 165, 0) \
|
||||
x(reflink_p_to_missing_reflink_v, 166, 0) \
|
||||
x(stripe_pos_bad, 167, 0) \
|
||||
x(stripe_val_size_bad, 168, 0) \
|
||||
x(stripe_sector_count_wrong, 169, 0) \
|
||||
x(snapshot_tree_pos_bad, 170, 0) \
|
||||
x(snapshot_tree_to_missing_snapshot, 171, 0) \
|
||||
x(snapshot_tree_to_missing_subvol, 172, 0) \
|
||||
x(snapshot_tree_to_wrong_subvol, 173, 0) \
|
||||
x(snapshot_tree_to_snapshot_subvol, 174, 0) \
|
||||
x(snapshot_pos_bad, 175, 0) \
|
||||
x(snapshot_parent_bad, 176, 0) \
|
||||
x(snapshot_children_not_normalized, 177, 0) \
|
||||
x(snapshot_child_duplicate, 178, 0) \
|
||||
x(snapshot_child_bad, 179, 0) \
|
||||
x(snapshot_skiplist_not_normalized, 180, 0) \
|
||||
x(snapshot_skiplist_bad, 181, 0) \
|
||||
x(snapshot_should_not_have_subvol, 182, 0) \
|
||||
x(snapshot_to_bad_snapshot_tree, 183, 0) \
|
||||
x(snapshot_bad_depth, 184, 0) \
|
||||
x(snapshot_bad_skiplist, 185, 0) \
|
||||
x(subvol_pos_bad, 186, 0) \
|
||||
x(subvol_not_master_and_not_snapshot, 187, 0) \
|
||||
x(subvol_to_missing_root, 188, 0) \
|
||||
x(subvol_root_wrong_bi_subvol, 189, 0) \
|
||||
x(bkey_in_missing_snapshot, 190, 0) \
|
||||
x(inode_pos_inode_nonzero, 191, 0) \
|
||||
x(inode_pos_blockdev_range, 192, 0) \
|
||||
x(inode_unpack_error, 193, 0) \
|
||||
x(inode_str_hash_invalid, 194, 0) \
|
||||
x(inode_v3_fields_start_bad, 195, 0) \
|
||||
x(inode_snapshot_mismatch, 196, 0) \
|
||||
x(inode_unlinked_but_clean, 197, 0) \
|
||||
x(inode_unlinked_but_nlink_nonzero, 198, 0) \
|
||||
x(inode_checksum_type_invalid, 199, 0) \
|
||||
x(inode_compression_type_invalid, 200, 0) \
|
||||
x(inode_subvol_root_but_not_dir, 201, 0) \
|
||||
x(inode_i_size_dirty_but_clean, 202, 0) \
|
||||
x(inode_i_sectors_dirty_but_clean, 203, 0) \
|
||||
x(inode_i_sectors_wrong, 204, 0) \
|
||||
x(inode_dir_wrong_nlink, 205, 0) \
|
||||
x(inode_dir_multiple_links, 206, 0) \
|
||||
x(inode_multiple_links_but_nlink_0, 207, 0) \
|
||||
x(inode_wrong_backpointer, 208, 0) \
|
||||
x(inode_wrong_nlink, 209, 0) \
|
||||
x(inode_unreachable, 210, 0) \
|
||||
x(deleted_inode_but_clean, 211, 0) \
|
||||
x(deleted_inode_missing, 212, 0) \
|
||||
x(deleted_inode_is_dir, 213, 0) \
|
||||
x(deleted_inode_not_unlinked, 214, 0) \
|
||||
x(extent_overlapping, 215, 0) \
|
||||
x(extent_in_missing_inode, 216, 0) \
|
||||
x(extent_in_non_reg_inode, 217, 0) \
|
||||
x(extent_past_end_of_inode, 218, 0) \
|
||||
x(dirent_empty_name, 219, 0) \
|
||||
x(dirent_val_too_big, 220, 0) \
|
||||
x(dirent_name_too_long, 221, 0) \
|
||||
x(dirent_name_embedded_nul, 222, 0) \
|
||||
x(dirent_name_dot_or_dotdot, 223, 0) \
|
||||
x(dirent_name_has_slash, 224, 0) \
|
||||
x(dirent_d_type_wrong, 225, 0) \
|
||||
x(inode_bi_parent_wrong, 226, 0) \
|
||||
x(dirent_in_missing_dir_inode, 227, 0) \
|
||||
x(dirent_in_non_dir_inode, 228, 0) \
|
||||
x(dirent_to_missing_inode, 229, 0) \
|
||||
x(dirent_to_missing_subvol, 230, 0) \
|
||||
x(dirent_to_itself, 231, 0) \
|
||||
x(quota_type_invalid, 232, 0) \
|
||||
x(xattr_val_size_too_small, 233, 0) \
|
||||
x(xattr_val_size_too_big, 234, 0) \
|
||||
x(xattr_invalid_type, 235, 0) \
|
||||
x(xattr_name_invalid_chars, 236, 0) \
|
||||
x(xattr_in_missing_inode, 237, 0) \
|
||||
x(root_subvol_missing, 238, 0) \
|
||||
x(root_dir_missing, 239, 0) \
|
||||
x(root_inode_not_dir, 240, 0) \
|
||||
x(dir_loop, 241, 0) \
|
||||
x(hash_table_key_duplicate, 242, 0) \
|
||||
x(hash_table_key_wrong_offset, 243, 0) \
|
||||
x(unlinked_inode_not_on_deleted_list, 244, 0) \
|
||||
x(reflink_p_front_pad_bad, 245, 0) \
|
||||
x(journal_entry_dup_same_device, 246, 0) \
|
||||
x(inode_bi_subvol_missing, 247, 0) \
|
||||
x(inode_bi_subvol_wrong, 248, 0) \
|
||||
x(inode_points_to_missing_dirent, 249, 0) \
|
||||
x(inode_points_to_wrong_dirent, 250, 0) \
|
||||
x(inode_bi_parent_nonzero, 251, 0) \
|
||||
x(dirent_to_missing_parent_subvol, 252, 0) \
|
||||
x(dirent_not_visible_in_parent_subvol, 253, 0) \
|
||||
x(subvol_fs_path_parent_wrong, 254, 0) \
|
||||
x(subvol_root_fs_path_parent_nonzero, 255, 0) \
|
||||
x(subvol_children_not_set, 256, 0) \
|
||||
x(subvol_children_bad, 257, 0) \
|
||||
x(subvol_loop, 258, 0) \
|
||||
x(subvol_unreachable, 259, 0) \
|
||||
x(btree_node_bkey_bad_u64s, 260, 0) \
|
||||
x(btree_node_topology_empty_interior_node, 261, 0) \
|
||||
x(btree_ptr_v2_min_key_bad, 262, 0) \
|
||||
x(btree_root_unreadable_and_scan_found_nothing, 263, 0) \
|
||||
x(snapshot_node_missing, 264, 0) \
|
||||
x(dup_backpointer_to_bad_csum_extent, 265, 0) \
|
||||
x(btree_bitmap_not_marked, 266, 0) \
|
||||
x(sb_clean_entry_overrun, 267, 0) \
|
||||
x(btree_ptr_v2_written_0, 268, 0) \
|
||||
x(subvol_snapshot_bad, 269, 0) \
|
||||
x(subvol_inode_bad, 270, 0) \
|
||||
x(alloc_key_stripe_sectors_wrong, 271, 0) \
|
||||
x(accounting_mismatch, 272, 0) \
|
||||
x(accounting_replicas_not_marked, 273, 0) \
|
||||
x(invalid_btree_id, 274, 0) \
|
||||
x(alloc_key_io_time_bad, 275, 0)
|
||||
|
||||
enum bch_sb_error_id {
|
||||
#define x(t, n) BCH_FSCK_ERR_##t = n,
|
||||
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
|
||||
BCH_SB_ERRS()
|
||||
#undef x
|
||||
BCH_SB_ERR_MAX
|
||||
|
@ -1565,13 +1565,6 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
|
||||
if (!test_and_clear_bit(BCH_FS_need_delete_dead_snapshots, &c->flags))
|
||||
return 0;
|
||||
|
||||
if (!test_bit(BCH_FS_started, &c->flags)) {
|
||||
ret = bch2_fs_read_write_early(c);
|
||||
bch_err_msg(c, ret, "deleting dead snapshots: error going rw");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
trans = bch2_trans_get(c);
|
||||
|
||||
/*
|
||||
@ -1687,6 +1680,8 @@ void bch2_delete_dead_snapshots_work(struct work_struct *work)
|
||||
{
|
||||
struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete_work);
|
||||
|
||||
set_worker_desc("bcachefs-delete-dead-snapshots/%s", c->name);
|
||||
|
||||
bch2_delete_dead_snapshots(c);
|
||||
bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ not_found:
|
||||
if (!found && (flags & STR_HASH_must_replace)) {
|
||||
ret = -BCH_ERR_ENOENT_str_hash_set_must_replace;
|
||||
} else if (found && (flags & STR_HASH_must_create)) {
|
||||
ret = -EEXIST;
|
||||
ret = -BCH_ERR_EEXIST_str_hash_set;
|
||||
} else {
|
||||
if (!found && slot.path)
|
||||
swap(iter, slot);
|
||||
|
@ -649,9 +649,10 @@ reread:
|
||||
|
||||
bytes = vstruct_bytes(sb->sb);
|
||||
|
||||
if (bytes > 512ULL << min(BCH_SB_LAYOUT_SIZE_BITS_MAX, sb->sb->layout.sb_max_size_bits)) {
|
||||
prt_printf(err, "Invalid superblock: too big (got %zu bytes, layout max %lu)",
|
||||
bytes, 512UL << sb->sb->layout.sb_max_size_bits);
|
||||
u64 sb_size = 512ULL << min(BCH_SB_LAYOUT_SIZE_BITS_MAX, sb->sb->layout.sb_max_size_bits);
|
||||
if (bytes > sb_size) {
|
||||
prt_printf(err, "Invalid superblock: too big (got %zu bytes, layout max %llu)",
|
||||
bytes, sb_size);
|
||||
return -BCH_ERR_invalid_sb_too_big;
|
||||
}
|
||||
|
||||
|
@ -912,9 +912,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
|
||||
bch2_io_clock_init(&c->io_clock[WRITE]) ?:
|
||||
bch2_fs_journal_init(&c->journal) ?:
|
||||
bch2_fs_replicas_init(c) ?:
|
||||
bch2_fs_btree_iter_init(c) ?:
|
||||
bch2_fs_btree_cache_init(c) ?:
|
||||
bch2_fs_btree_key_cache_init(&c->btree_key_cache) ?:
|
||||
bch2_fs_btree_iter_init(c) ?:
|
||||
bch2_fs_btree_interior_update_init(c) ?:
|
||||
bch2_fs_buckets_waiting_for_journal_init(c) ?:
|
||||
bch2_fs_btree_write_buffer_init(c) ?:
|
||||
@ -931,12 +931,13 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < c->sb.nr_devices; i++)
|
||||
if (bch2_member_exists(c->disk_sb.sb, i) &&
|
||||
bch2_dev_alloc(c, i)) {
|
||||
ret = -EEXIST;
|
||||
for (i = 0; i < c->sb.nr_devices; i++) {
|
||||
if (!bch2_member_exists(c->disk_sb.sb, i))
|
||||
continue;
|
||||
ret = bch2_dev_alloc(c, i);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
bch2_journal_entry_res_resize(&c->journal,
|
||||
&c->btree_root_journal_res,
|
||||
|
@ -17,12 +17,18 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
|
||||
{
|
||||
int r = flags & CLOSURE_REMAINING_MASK;
|
||||
|
||||
BUG_ON(flags & CLOSURE_GUARD_MASK);
|
||||
BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR));
|
||||
if (WARN(flags & CLOSURE_GUARD_MASK,
|
||||
"closure has guard bits set: %x (%u)",
|
||||
flags & CLOSURE_GUARD_MASK, (unsigned) __fls(r)))
|
||||
r &= ~CLOSURE_GUARD_MASK;
|
||||
|
||||
if (!r) {
|
||||
smp_acquire__after_ctrl_dep();
|
||||
|
||||
WARN(flags & ~CLOSURE_DESTRUCTOR,
|
||||
"closure ref hit 0 with incorrect flags set: %x (%u)",
|
||||
flags & ~CLOSURE_DESTRUCTOR, (unsigned) __fls(flags));
|
||||
|
||||
cl->closure_get_happened = false;
|
||||
|
||||
if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
|
||||
|
Loading…
Reference in New Issue
Block a user