Update bcachefs sources to 0d627739e9 bcachefs: Improve pointer marking checks and error messages

This commit is contained in:
Kent Overstreet 2019-08-29 11:44:11 -04:00
parent 7f35a52029
commit 68963f1816
4 changed files with 65 additions and 27 deletions

View File

@ -1 +1 @@
05ef7000f242c003918c8675a0b33670117057ed 0d627739e94c55ef19b6b6b9760133f7cf289f67

View File

@ -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); struct bucket *g2 = PTR_BUCKET(ca, ptr, false);
if (mustfix_fsck_err_on(!g->gen_valid, c, if (mustfix_fsck_err_on(!g->gen_valid, c,
"found ptr with missing gen in alloc btree,\n" "bucket %u:%zu data type %s ptr gen %u missing in alloc btree",
"type %u gen %u", ptr->dev, PTR_BUCKET_NR(ca, ptr),
k.k->type, ptr->gen)) { bch2_data_types[ptr_data_type(k.k, ptr)],
ptr->gen)) {
g2->_mark.gen = g->_mark.gen = ptr->gen; g2->_mark.gen = g->_mark.gen = ptr->gen;
g2->gen_valid = g->gen_valid = true; g2->gen_valid = g->gen_valid = true;
} }
if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c, if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
"%u ptr gen in the future: %u > %u", "bucket %u:%zu data type %s ptr gen in the future: %u > %u",
k.k->type, ptr->gen, g->mark.gen)) { 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->_mark.gen = g->_mark.gen = ptr->gen;
g2->gen_valid = g->gen_valid = true; 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); set_bit(BCH_FS_FIXED_GENS, &c->flags);
} }
} }

View File

@ -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); 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(); preempt_disable();
dev_usage = this_cpu_ptr(ca->usage[gc]); 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, static inline void update_replicas(struct bch_fs *c,
struct bch_fs_usage *fs_usage, struct bch_fs_usage *fs_usage,
struct bch_replicas_entry *r, 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 *g = __bucket(ca, b, gc);
struct bucket_mark old, new; 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)); BUG_ON(!is_available_bucket(new));
new.owned_by_allocator = true; new.owned_by_allocator = true;
@ -643,6 +629,8 @@ static int __bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
new.gen++; new.gen++;
})); }));
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
if (old.cached_sectors) if (old.cached_sectors)
update_cached_sectors(c, fs_usage, ca->dev_idx, update_cached_sectors(c, fs_usage, ca->dev_idx,
-((s64) old.cached_sectors)); -((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 *g = __bucket(ca, b, gc);
struct bucket_mark old, new; 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; new.owned_by_allocator = owned_by_allocator;
})); }));
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
BUG_ON(!gc && BUG_ON(!gc &&
!owned_by_allocator && !old.owned_by_allocator); !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); 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, bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %u > U16_MAX", "bucket sector count overflow: %u + %u > U16_MAX",
old.dirty_sectors, sectors); 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 *g = PTR_BUCKET(ca, ptr, gc);
struct bucket_mark new, old; struct bucket_mark new, old;
old = bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({ old = bucket_cmpxchg(g, new, ({
new.stripe = enabled; new.stripe = enabled;
if (journal_seq) { if (journal_seq) {
new.journal_seq_valid = 1; 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 * 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 * the allocator invalidating a bucket after we've already
* checked the gen * 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 */ /* XXX write repair code for this */
if (!p.ptr.cached && if (!p.ptr.cached &&
test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))
@ -935,6 +939,14 @@ static bool bch2_mark_pointer(struct bch_fs *c,
old.v.counter, old.v.counter,
new.v.counter)) != 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, bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %lli > U16_MAX", "bucket sector count overflow: %u + %lli > U16_MAX",
!p.ptr.cached !p.ptr.cached
@ -1444,9 +1456,9 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
* Unless we're already updating that key: * Unless we're already updating that key:
*/ */
if (k.k->type != KEY_TYPE_alloc) { if (k.k->type != KEY_TYPE_alloc) {
bch_err_ratelimited(c, "pointer to nonexistent bucket %llu:%llu", bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
iter->pos.inode, "pointer to nonexistent bucket %llu:%llu",
iter->pos.offset); iter->pos.inode, iter->pos.offset);
ret = -1; ret = -1;
goto out; goto out;
} }
@ -1459,6 +1471,17 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
goto out; 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) { if (!p.ptr.cached) {
old = u.dirty_sectors; old = u.dirty_sectors;
overflow = checked_add(u.dirty_sectors, sectors); overflow = checked_add(u.dirty_sectors, sectors);

View File

@ -94,6 +94,15 @@ static inline struct bucket *PTR_BUCKET(struct bch_dev *ca,
return __bucket(ca, PTR_BUCKET_NR(ca, ptr), gc); 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, static inline struct bucket_mark ptr_bucket_mark(struct bch_dev *ca,
const struct bch_extent_ptr *ptr) const struct bch_extent_ptr *ptr)
{ {