bcachefs: convert journal replay ptrs to darray

Eliminates some error paths - no longer have a hardcoded
BCH_REPLICAS_MAX limit.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-01-27 00:05:03 -05:00
parent 5b6271b509
commit a555bcf4fa
3 changed files with 36 additions and 58 deletions

View File

@ -1153,7 +1153,6 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq)
struct journal_replay *i, **_i; struct journal_replay *i, **_i;
struct genradix_iter iter; struct genradix_iter iter;
bool had_entries = false; bool had_entries = false;
unsigned ptr;
u64 last_seq = cur_seq, nr, seq; u64 last_seq = cur_seq, nr, seq;
genradix_for_each_reverse(&c->journal_entries, iter, _i) { genradix_for_each_reverse(&c->journal_entries, iter, _i) {
@ -1207,8 +1206,8 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq)
p = journal_seq_pin(j, seq); p = journal_seq_pin(j, seq);
p->devs.nr = 0; p->devs.nr = 0;
for (ptr = 0; ptr < i->nr_ptrs; ptr++) darray_for_each(i->ptrs, ptr)
bch2_dev_list_add_dev(&p->devs, i->ptrs[ptr].dev); bch2_dev_list_add_dev(&p->devs, ptr->dev);
had_entries = true; had_entries = true;
} }

View File

@ -84,7 +84,6 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
{ {
struct genradix_iter iter; struct genradix_iter iter;
struct journal_replay **_i, *i, *dup; struct journal_replay **_i, *i, *dup;
struct journal_ptr *ptr;
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;
int ret = JOURNAL_ENTRY_ADD_OK; int ret = JOURNAL_ENTRY_ADD_OK;
@ -156,45 +155,29 @@ replace:
if (!i) if (!i)
return -BCH_ERR_ENOMEM_journal_entry_add; return -BCH_ERR_ENOMEM_journal_entry_add;
i->nr_ptrs = 0; darray_init(&i->ptrs);
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");
i->ptrs[i->nr_ptrs++] = entry_ptr; darray_push(&i->ptrs, entry_ptr);
if (dup) { if (dup) {
if (dup->nr_ptrs >= ARRAY_SIZE(dup->ptrs)) {
bch_err(c, "found too many copies of journal entry %llu",
le64_to_cpu(i->j.seq));
dup->nr_ptrs = ARRAY_SIZE(dup->ptrs) - 1;
}
/* The first ptr should represent the jset we kept: */ /* The first ptr should represent the jset we kept: */
memcpy(i->ptrs + i->nr_ptrs, darray_for_each(dup->ptrs, ptr)
dup->ptrs, darray_push(&i->ptrs, *ptr);
sizeof(dup->ptrs[0]) * dup->nr_ptrs);
i->nr_ptrs += dup->nr_ptrs;
__journal_replay_free(c, dup); __journal_replay_free(c, dup);
} }
*_i = i; *_i = i;
return 0;
found: found:
for (ptr = i->ptrs; ptr < i->ptrs + i->nr_ptrs; ptr++) { darray_for_each(i->ptrs, ptr)
if (ptr->dev == ca->dev_idx) { if (ptr->dev == ca->dev_idx) {
bch_err(c, "duplicate journal entry %llu on same device", bch_err(c, "duplicate journal entry %llu on same device",
le64_to_cpu(i->j.seq)); le64_to_cpu(i->j.seq));
goto out; goto out;
} }
}
if (i->nr_ptrs >= ARRAY_SIZE(i->ptrs)) { ret = darray_push(&i->ptrs, entry_ptr);
bch_err(c, "found too many copies of journal entry %llu",
le64_to_cpu(i->j.seq));
goto out;
}
i->ptrs[i->nr_ptrs++] = entry_ptr;
out: out:
fsck_err: fsck_err:
return ret; return ret;
@ -1102,16 +1085,15 @@ static CLOSURE_CALLBACK(bch2_journal_read_device)
if (!r) if (!r)
continue; continue;
for (i = 0; i < r->nr_ptrs; i++) { darray_for_each(r->ptrs, i)
if (r->ptrs[i].dev == ca->dev_idx) { if (i->dev == ca->dev_idx) {
unsigned wrote = bucket_remainder(ca, r->ptrs[i].sector) + unsigned wrote = bucket_remainder(ca, i->sector) +
vstruct_sectors(&r->j, c->block_bits); vstruct_sectors(&r->j, c->block_bits);
ja->cur_idx = r->ptrs[i].bucket; ja->cur_idx = i->bucket;
ja->sectors_free = ca->mi.bucket_size - wrote; ja->sectors_free = ca->mi.bucket_size - wrote;
goto found; goto found;
} }
}
} }
found: found:
mutex_unlock(&jlist->lock); mutex_unlock(&jlist->lock);
@ -1158,21 +1140,16 @@ err:
void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c, void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
struct journal_replay *j) struct journal_replay *j)
{ {
unsigned i; darray_for_each(j->ptrs, i) {
struct bch_dev *ca = bch_dev_bkey_exists(c, i->dev);
for (i = 0; i < j->nr_ptrs; i++) {
struct bch_dev *ca = bch_dev_bkey_exists(c, j->ptrs[i].dev);
u64 offset; u64 offset;
div64_u64_rem(j->ptrs[i].sector, ca->mi.bucket_size, &offset); div64_u64_rem(i->sector, ca->mi.bucket_size, &offset);
if (i) if (i != j->ptrs.data)
prt_printf(out, " "); prt_printf(out, " ");
prt_printf(out, "%u:%u:%u (sector %llu)", prt_printf(out, "%u:%u:%u (sector %llu)",
j->ptrs[i].dev, i->dev, i->bucket, i->bucket_offset, i->sector);
j->ptrs[i].bucket,
j->ptrs[i].bucket_offset,
j->ptrs[i].sector);
} }
} }
@ -1353,32 +1330,31 @@ int bch2_journal_read(struct bch_fs *c,
.e.data_type = BCH_DATA_journal, .e.data_type = BCH_DATA_journal,
.e.nr_required = 1, .e.nr_required = 1,
}; };
unsigned ptr;
i = *_i; i = *_i;
if (!i || i->ignore) if (!i || i->ignore)
continue; continue;
for (ptr = 0; ptr < i->nr_ptrs; ptr++) { darray_for_each(i->ptrs, ptr) {
struct bch_dev *ca = bch_dev_bkey_exists(c, i->ptrs[ptr].dev); struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
if (!i->ptrs[ptr].csum_good) if (!ptr->csum_good)
bch_err_dev_offset(ca, i->ptrs[ptr].sector, bch_err_dev_offset(ca, ptr->sector,
"invalid journal checksum, seq %llu%s", "invalid journal checksum, seq %llu%s",
le64_to_cpu(i->j.seq), le64_to_cpu(i->j.seq),
i->csum_good ? " (had good copy on another device)" : ""); i->csum_good ? " (had good copy on another device)" : "");
} }
ret = jset_validate(c, ret = jset_validate(c,
bch_dev_bkey_exists(c, i->ptrs[0].dev), bch_dev_bkey_exists(c, i->ptrs.data[0].dev),
&i->j, &i->j,
i->ptrs[0].sector, i->ptrs.data[0].sector,
READ); READ);
if (ret) if (ret)
goto err; goto err;
for (ptr = 0; ptr < i->nr_ptrs; ptr++) darray_for_each(i->ptrs, ptr)
replicas.e.devs[replicas.e.nr_devs++] = i->ptrs[ptr].dev; replicas.e.devs[replicas.e.nr_devs++] = ptr->dev;
bch2_replicas_entry_sort(&replicas.e); bch2_replicas_entry_sort(&replicas.e);

View File

@ -2,19 +2,22 @@
#ifndef _BCACHEFS_JOURNAL_IO_H #ifndef _BCACHEFS_JOURNAL_IO_H
#define _BCACHEFS_JOURNAL_IO_H #define _BCACHEFS_JOURNAL_IO_H
#include "darray.h"
struct journal_ptr {
bool csum_good;
u8 dev;
u32 bucket;
u32 bucket_offset;
u64 sector;
};
/* /*
* Only used for holding the journal entries we read in btree_journal_read() * Only used for holding the journal entries we read in btree_journal_read()
* during cache_registration * during cache_registration
*/ */
struct journal_replay { struct journal_replay {
struct journal_ptr { DARRAY_PREALLOCATED(struct journal_ptr, 8) ptrs;
bool csum_good;
u8 dev;
u32 bucket;
u32 bucket_offset;
u64 sector;
} ptrs[BCH_REPLICAS_MAX];
unsigned nr_ptrs;
bool csum_good; bool csum_good;
bool ignore; bool ignore;