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);
}
}
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]);
}
}
-#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,
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;
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));
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);
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);
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;
}
}));
+ bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
+
/*
* XXX write repair code for these, flag stripe as possibly bad
*/
* 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))
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
* 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;
}
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);