mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
Update bcachefs sources to 0d627739e9 bcachefs: Improve pointer marking checks and error messages
This commit is contained in:
parent
7f35a52029
commit
68963f1816
@ -1 +1 @@
|
||||
05ef7000f242c003918c8675a0b33670117057ed
|
||||
0d627739e94c55ef19b6b6b9760133f7cf289f67
|
||||
|
@ -142,18 +142,24 @@ static int bch2_gc_mark_key(struct bch_fs *c, struct bkey_s_c k,
|
||||
struct bucket *g2 = PTR_BUCKET(ca, ptr, false);
|
||||
|
||||
if (mustfix_fsck_err_on(!g->gen_valid, c,
|
||||
"found ptr with missing gen in alloc btree,\n"
|
||||
"type %u gen %u",
|
||||
k.k->type, ptr->gen)) {
|
||||
"bucket %u:%zu data type %s ptr gen %u missing in alloc btree",
|
||||
ptr->dev, PTR_BUCKET_NR(ca, ptr),
|
||||
bch2_data_types[ptr_data_type(k.k, ptr)],
|
||||
ptr->gen)) {
|
||||
g2->_mark.gen = g->_mark.gen = ptr->gen;
|
||||
g2->gen_valid = g->gen_valid = true;
|
||||
}
|
||||
|
||||
if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
|
||||
"%u ptr gen in the future: %u > %u",
|
||||
k.k->type, ptr->gen, g->mark.gen)) {
|
||||
"bucket %u:%zu data type %s ptr gen in the future: %u > %u",
|
||||
ptr->dev, PTR_BUCKET_NR(ca, ptr),
|
||||
bch2_data_types[ptr_data_type(k.k, ptr)],
|
||||
ptr->gen, g->mark.gen)) {
|
||||
g2->_mark.gen = g->_mark.gen = ptr->gen;
|
||||
g2->gen_valid = g->gen_valid = true;
|
||||
g2->_mark.data_type = 0;
|
||||
g2->_mark.dirty_sectors = 0;
|
||||
g2->_mark.cached_sectors = 0;
|
||||
set_bit(BCH_FS_FIXED_GENS, &c->flags);
|
||||
}
|
||||
}
|
||||
|
@ -445,12 +445,6 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
|
||||
|
||||
percpu_rwsem_assert_held(&c->mark_lock);
|
||||
|
||||
bch2_fs_inconsistent_on(old.data_type && new.data_type &&
|
||||
old.data_type != new.data_type, c,
|
||||
"different types of data in same bucket: %s, %s",
|
||||
bch2_data_types[old.data_type],
|
||||
bch2_data_types[new.data_type]);
|
||||
|
||||
preempt_disable();
|
||||
dev_usage = this_cpu_ptr(ca->usage[gc]);
|
||||
|
||||
@ -505,14 +499,6 @@ void bch2_dev_usage_from_buckets(struct bch_fs *c)
|
||||
}
|
||||
}
|
||||
|
||||
#define bucket_data_cmpxchg(c, ca, fs_usage, g, new, expr) \
|
||||
({ \
|
||||
struct bucket_mark _old = bucket_cmpxchg(g, new, expr); \
|
||||
\
|
||||
bch2_dev_usage_update(c, ca, fs_usage, _old, new, gc); \
|
||||
_old; \
|
||||
})
|
||||
|
||||
static inline void update_replicas(struct bch_fs *c,
|
||||
struct bch_fs_usage *fs_usage,
|
||||
struct bch_replicas_entry *r,
|
||||
@ -633,7 +619,7 @@ static int __bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
struct bucket *g = __bucket(ca, b, gc);
|
||||
struct bucket_mark old, new;
|
||||
|
||||
old = bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({
|
||||
old = bucket_cmpxchg(g, new, ({
|
||||
BUG_ON(!is_available_bucket(new));
|
||||
|
||||
new.owned_by_allocator = true;
|
||||
@ -643,6 +629,8 @@ static int __bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
new.gen++;
|
||||
}));
|
||||
|
||||
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
|
||||
|
||||
if (old.cached_sectors)
|
||||
update_cached_sectors(c, fs_usage, ca->dev_idx,
|
||||
-((s64) old.cached_sectors));
|
||||
@ -671,10 +659,12 @@ static int __bch2_mark_alloc_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
struct bucket *g = __bucket(ca, b, gc);
|
||||
struct bucket_mark old, new;
|
||||
|
||||
old = bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({
|
||||
old = bucket_cmpxchg(g, new, ({
|
||||
new.owned_by_allocator = owned_by_allocator;
|
||||
}));
|
||||
|
||||
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
|
||||
|
||||
BUG_ON(!gc &&
|
||||
!owned_by_allocator && !old.owned_by_allocator);
|
||||
|
||||
@ -780,6 +770,12 @@ static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
overflow = checked_add(new.dirty_sectors, sectors);
|
||||
}));
|
||||
|
||||
bch2_fs_inconsistent_on(old.data_type &&
|
||||
old.data_type != type, c,
|
||||
"different types of data in same bucket: %s, %s",
|
||||
bch2_data_types[old.data_type],
|
||||
bch2_data_types[type]);
|
||||
|
||||
bch2_fs_inconsistent_on(overflow, c,
|
||||
"bucket sector count overflow: %u + %u > U16_MAX",
|
||||
old.dirty_sectors, sectors);
|
||||
@ -849,7 +845,7 @@ static void bucket_set_stripe(struct bch_fs *c,
|
||||
struct bucket *g = PTR_BUCKET(ca, ptr, gc);
|
||||
struct bucket_mark new, old;
|
||||
|
||||
old = bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({
|
||||
old = bucket_cmpxchg(g, new, ({
|
||||
new.stripe = enabled;
|
||||
if (journal_seq) {
|
||||
new.journal_seq_valid = 1;
|
||||
@ -857,6 +853,8 @@ static void bucket_set_stripe(struct bch_fs *c,
|
||||
}
|
||||
}));
|
||||
|
||||
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
|
||||
|
||||
/*
|
||||
* XXX write repair code for these, flag stripe as possibly bad
|
||||
*/
|
||||
@ -901,7 +899,13 @@ static bool bch2_mark_pointer(struct bch_fs *c,
|
||||
* the allocator invalidating a bucket after we've already
|
||||
* checked the gen
|
||||
*/
|
||||
if (gen_after(new.gen, p.ptr.gen)) {
|
||||
if (gen_after(p.ptr.gen, new.gen)) {
|
||||
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
|
||||
"pointer gen in the future");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (new.gen != p.ptr.gen) {
|
||||
/* XXX write repair code for this */
|
||||
if (!p.ptr.cached &&
|
||||
test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))
|
||||
@ -935,6 +939,14 @@ static bool bch2_mark_pointer(struct bch_fs *c,
|
||||
old.v.counter,
|
||||
new.v.counter)) != old.v.counter);
|
||||
|
||||
if (old.data_type && old.data_type != data_type)
|
||||
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
|
||||
"bucket %u:%zu gen %u different types of data in same bucket: %s, %s",
|
||||
p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
|
||||
new.gen,
|
||||
bch2_data_types[old.data_type],
|
||||
bch2_data_types[data_type]);
|
||||
|
||||
bch2_fs_inconsistent_on(overflow, c,
|
||||
"bucket sector count overflow: %u + %lli > U16_MAX",
|
||||
!p.ptr.cached
|
||||
@ -1444,9 +1456,9 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
|
||||
* Unless we're already updating that key:
|
||||
*/
|
||||
if (k.k->type != KEY_TYPE_alloc) {
|
||||
bch_err_ratelimited(c, "pointer to nonexistent bucket %llu:%llu",
|
||||
iter->pos.inode,
|
||||
iter->pos.offset);
|
||||
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
|
||||
"pointer to nonexistent bucket %llu:%llu",
|
||||
iter->pos.inode, iter->pos.offset);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@ -1459,6 +1471,17 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (u.data_type && u.data_type != data_type) {
|
||||
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
|
||||
"bucket %llu:%llu gen %u different types of data in same bucket: %s, %s",
|
||||
iter->pos.inode, iter->pos.offset,
|
||||
u.gen,
|
||||
bch2_data_types[u.data_type],
|
||||
bch2_data_types[data_type]);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!p.ptr.cached) {
|
||||
old = u.dirty_sectors;
|
||||
overflow = checked_add(u.dirty_sectors, sectors);
|
||||
|
@ -94,6 +94,15 @@ static inline struct bucket *PTR_BUCKET(struct bch_dev *ca,
|
||||
return __bucket(ca, PTR_BUCKET_NR(ca, ptr), gc);
|
||||
}
|
||||
|
||||
static inline enum bch_data_type ptr_data_type(const struct bkey *k,
|
||||
const struct bch_extent_ptr *ptr)
|
||||
{
|
||||
if (k->type == KEY_TYPE_btree_ptr)
|
||||
return BCH_DATA_BTREE;
|
||||
|
||||
return ptr->cached ? BCH_DATA_CACHED : BCH_DATA_USER;
|
||||
}
|
||||
|
||||
static inline struct bucket_mark ptr_bucket_mark(struct bch_dev *ca,
|
||||
const struct bch_extent_ptr *ptr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user