Commit 3d3d23b3 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: improve journal entry read fsck error messages

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent a555bcf4
...@@ -17,6 +17,30 @@ ...@@ -17,6 +17,30 @@
#include "sb-clean.h" #include "sb-clean.h"
#include "trace.h" #include "trace.h"
void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
struct journal_replay *j)
{
darray_for_each(j->ptrs, i) {
struct bch_dev *ca = bch_dev_bkey_exists(c, i->dev);
u64 offset;
div64_u64_rem(i->sector, ca->mi.bucket_size, &offset);
if (i != j->ptrs.data)
prt_printf(out, " ");
prt_printf(out, "%u:%u:%u (sector %llu)",
i->dev, i->bucket, i->bucket_offset, i->sector);
}
}
static void bch2_journal_replay_to_text(struct printbuf *out, struct bch_fs *c,
struct journal_replay *j)
{
prt_printf(out, "seq %llu ", le64_to_cpu(j->j.seq));
bch2_journal_ptrs_to_text(out, c, j);
}
static struct nonce journal_nonce(const struct jset *jset) static struct nonce journal_nonce(const struct jset *jset)
{ {
return (struct nonce) {{ return (struct nonce) {{
...@@ -86,6 +110,7 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca, ...@@ -86,6 +110,7 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
struct journal_replay **_i, *i, *dup; struct journal_replay **_i, *i, *dup;
size_t bytes = vstruct_bytes(j); size_t bytes = vstruct_bytes(j);
u64 last_seq = !JSET_NO_FLUSH(j) ? le64_to_cpu(j->last_seq) : 0; u64 last_seq = !JSET_NO_FLUSH(j) ? le64_to_cpu(j->last_seq) : 0;
struct printbuf buf = PRINTBUF;
int ret = JOURNAL_ENTRY_ADD_OK; int ret = JOURNAL_ENTRY_ADD_OK;
/* Is this entry older than the range we need? */ /* Is this entry older than the range we need? */
...@@ -130,25 +155,37 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca, ...@@ -130,25 +155,37 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
*/ */
dup = *_i; dup = *_i;
if (dup) { if (dup) {
if (bytes == vstruct_bytes(&dup->j) && bool identical = bytes == vstruct_bytes(&dup->j) &&
!memcmp(j, &dup->j, bytes)) { !memcmp(j, &dup->j, bytes);
i = dup; bool not_identical = !identical &&
goto found; entry_ptr.csum_good &&
} dup->csum_good;
if (!entry_ptr.csum_good) { bool same_device = false;
i = dup; darray_for_each(dup->ptrs, ptr)
goto found; if (ptr->dev == ca->dev_idx)
} same_device = true;
ret = darray_push(&dup->ptrs, entry_ptr);
if (ret)
goto out;
if (!dup->csum_good) bch2_journal_replay_to_text(&buf, c, dup);
fsck_err_on(same_device,
c, journal_entry_dup_same_device,
"duplicate journal entry on same device\n %s",
buf.buf);
fsck_err_on(not_identical,
c, journal_entry_replicas_data_mismatch,
"found duplicate but non identical journal entries\n %s",
buf.buf);
if (entry_ptr.csum_good && !identical)
goto replace; goto replace;
fsck_err(c, journal_entry_replicas_data_mismatch, goto out;
"found duplicate but non identical journal entries (seq %llu)",
le64_to_cpu(j->seq));
i = dup;
goto found;
} }
replace: replace:
i = kvpmalloc(offsetof(struct journal_replay, j) + bytes, GFP_KERNEL); i = kvpmalloc(offsetof(struct journal_replay, j) + bytes, GFP_KERNEL);
...@@ -159,27 +196,20 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca, ...@@ -159,27 +196,20 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
i->csum_good = entry_ptr.csum_good; i->csum_good = entry_ptr.csum_good;
i->ignore = false; i->ignore = false;
unsafe_memcpy(&i->j, j, bytes, "embedded variable length struct"); unsafe_memcpy(&i->j, j, bytes, "embedded variable length struct");
darray_push(&i->ptrs, entry_ptr);
if (dup) { if (dup) {
/* The first ptr should represent the jset we kept: */ /* The first ptr should represent the jset we kept: */
darray_for_each(dup->ptrs, ptr) darray_for_each(dup->ptrs, ptr)
darray_push(&i->ptrs, *ptr); darray_push(&i->ptrs, *ptr);
__journal_replay_free(c, dup); __journal_replay_free(c, dup);
} else {
darray_push(&i->ptrs, entry_ptr);
} }
*_i = i; *_i = i;
found:
darray_for_each(i->ptrs, ptr)
if (ptr->dev == ca->dev_idx) {
bch_err(c, "duplicate journal entry %llu on same device",
le64_to_cpu(i->j.seq));
goto out;
}
ret = darray_push(&i->ptrs, entry_ptr);
out: out:
fsck_err: fsck_err:
printbuf_exit(&buf);
return ret; return ret;
} }
...@@ -1137,22 +1167,6 @@ static CLOSURE_CALLBACK(bch2_journal_read_device) ...@@ -1137,22 +1167,6 @@ static CLOSURE_CALLBACK(bch2_journal_read_device)
goto out; goto out;
} }
void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
struct journal_replay *j)
{
darray_for_each(j->ptrs, i) {
struct bch_dev *ca = bch_dev_bkey_exists(c, i->dev);
u64 offset;
div64_u64_rem(i->sector, ca->mi.bucket_size, &offset);
if (i != j->ptrs.data)
prt_printf(out, " ");
prt_printf(out, "%u:%u:%u (sector %llu)",
i->dev, i->bucket, i->bucket_offset, i->sector);
}
}
int bch2_journal_read(struct bch_fs *c, int bch2_journal_read(struct bch_fs *c,
u64 *last_seq, u64 *last_seq,
u64 *blacklist_seq, u64 *blacklist_seq,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment