diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-03-06 11:29:12 +0100 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 23:09:56 +0200 |
commit | 2640faeb1741db94b717d2678f6cd644f90e3061 (patch) | |
tree | e22afd0d0eb1186592e9caaace85aac0f50e466b /fs/bcachefs/journal_sb.c | |
parent | bcachefs: bch2_btree_iter_peek_node_and_restart() (diff) | |
download | linux-2640faeb1741db94b717d2678f6cd644f90e3061.tar.xz linux-2640faeb1741db94b717d2678f6cd644f90e3061.zip |
bcachefs: Journal resize fixes
- Fix a sleeping-in-atomic bug due to calling
bch2_journal_buckets_to_sb() under the journal lock.
- Additionally, now we mark buckets as journal buckets before adding
them to the journal in memory and the superblock. This ensures that
if we crash part way through we'll never be writing to journal
buckets that aren't marked correctly.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/journal_sb.c')
-rw-r--r-- | fs/bcachefs/journal_sb.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/fs/bcachefs/journal_sb.c b/fs/bcachefs/journal_sb.c index 9b933330a4c3..5be7882342e0 100644 --- a/fs/bcachefs/journal_sb.c +++ b/fs/bcachefs/journal_sb.c @@ -175,46 +175,45 @@ const struct bch_sb_field_ops bch_sb_field_ops_journal_v2 = { .to_text = bch2_sb_journal_v2_to_text, }; -int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca) +int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca, + u64 *buckets, unsigned nr) { - struct journal_device *ja = &ca->journal; struct bch_sb_field_journal_v2 *j; - unsigned i, dst = 0, nr = 1; + unsigned i, dst = 0, nr_compacted = 1; if (c) lockdep_assert_held(&c->sb_lock); - if (!ja->nr) { + if (!nr) { bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal); bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal_v2); return 0; } - for (i = 0; i + 1 < ja->nr; i++) - if (ja->buckets[i] + 1 != ja->buckets[i + 1]) - nr++; + for (i = 0; i + 1 < nr; i++) + if (buckets[i] + 1 != buckets[i + 1]) + nr_compacted++; j = bch2_sb_resize_journal_v2(&ca->disk_sb, - (sizeof(*j) + sizeof(j->d[0]) * nr) / sizeof(u64)); + (sizeof(*j) + sizeof(j->d[0]) * nr_compacted) / sizeof(u64)); if (!j) return -BCH_ERR_ENOSPC_sb_journal; bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal); - j->d[dst].start = le64_to_cpu(ja->buckets[0]); + j->d[dst].start = le64_to_cpu(buckets[0]); j->d[dst].nr = le64_to_cpu(1); - for (i = 1; i < ja->nr; i++) { - if (ja->buckets[i] == ja->buckets[i - 1] + 1) { + for (i = 1; i < nr; i++) { + if (buckets[i] == buckets[i - 1] + 1) { le64_add_cpu(&j->d[dst].nr, 1); } else { dst++; - j->d[dst].start = le64_to_cpu(ja->buckets[i]); + j->d[dst].start = le64_to_cpu(buckets[i]); j->d[dst].nr = le64_to_cpu(1); } } - BUG_ON(dst + 1 != nr); - + BUG_ON(dst + 1 != nr_compacted); return 0; } |