static void found_btree_node_to_text(struct printbuf *out, struct bch_fs *c, const struct found_btree_node *n)
{
- prt_printf(out, "%s l=%u seq=%u cookie=%llx ", bch2_btree_id_str(n->btree_id), n->level, n->seq, n->cookie);
+ prt_printf(out, "%s l=%u seq=%u journal_seq=%llu cookie=%llx ",
+ bch2_btree_id_str(n->btree_id), n->level, n->seq,
+ n->journal_seq, n->cookie);
bch2_bpos_to_text(out, n->min_key);
prt_str(out, "-");
bch2_bpos_to_text(out, n->max_key);
memcpy(bp->v.start, f->ptrs, sizeof(struct bch_extent_ptr) * f->nr_ptrs);
}
+static inline u64 bkey_journal_seq(struct bkey_s_c k)
+{
+ switch (k.k->type) {
+ case KEY_TYPE_inode_v3:
+ return le64_to_cpu(bkey_s_c_to_inode_v3(k).v->bi_journal_seq);
+ default:
+ return 0;
+ }
+}
+
static bool found_btree_node_is_readable(struct btree_trans *trans,
struct found_btree_node *f)
{
- struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } k;
+ struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } tmp;
- found_btree_node_to_key(&k.k, f);
+ found_btree_node_to_key(&tmp.k, f);
- struct btree *b = bch2_btree_node_get_noiter(trans, &k.k, f->btree_id, f->level, false);
+ struct btree *b = bch2_btree_node_get_noiter(trans, &tmp.k, f->btree_id, f->level, false);
bool ret = !IS_ERR_OR_NULL(b);
if (!ret)
return ret;
f->sectors_written = b->written;
+ f->journal_seq = le64_to_cpu(b->data->keys.journal_seq);
+
+ struct bkey_s_c k;
+ struct bkey unpacked;
+ struct btree_node_iter iter;
+ for_each_btree_node_key_unpack(b, k, &iter, &unpacked)
+ f->journal_seq = max(f->journal_seq, bkey_journal_seq(k));
+
six_unlock_read(&b->c.lock);
/*
* this node
*/
if (b != btree_node_root(trans->c, b))
- bch2_btree_node_evict(trans, &k.k);
+ bch2_btree_node_evict(trans, &tmp.k);
return ret;
}
static int found_btree_node_cmp_time(const struct found_btree_node *l,
const struct found_btree_node *r)
{
- return cmp_int(l->seq, r->seq);
+ return cmp_int(l->seq, r->seq) ?:
+ cmp_int(l->journal_seq, r->journal_seq);
}
static int found_btree_node_cmp_pos(const void *_l, const void *_r)
} else if (n->level) {
n->overwritten = true;
} else {
- struct printbuf buf = PRINTBUF;
-
- prt_str(&buf, "overlapping btree nodes with same seq! halting\n ");
- found_btree_node_to_text(&buf, c, start);
- prt_str(&buf, "\n ");
- found_btree_node_to_text(&buf, c, n);
- bch_err(c, "%s", buf.buf);
- printbuf_exit(&buf);
- return -BCH_ERR_fsck_repair_unimplemented;
+ if (bpos_cmp(start->max_key, n->max_key) >= 0)
+ n->overwritten = true;
+ else {
+ n->range_updated = true;
+ n->min_key = bpos_successor(start->max_key);
+ n->range_updated = true;
+ bubble_up(n, end);
+ goto again;
+ }
}
}