#include "bcachefs.h"
#include "journal_sb.h"
+#include <linux/darray.h>
#include <linux/sort.h>
/* BCH_SB_FIELD_journal: */
struct printbuf *err)
{
struct bch_sb_field_journal *journal = field_to_type(f, journal);
- struct bch_member *m = bch2_sb_get_members(sb)->members + sb->dev_idx;
- int ret = -EINVAL;
+ struct bch_member m = bch2_sb_member_get(sb, sb->dev_idx);
+ int ret = -BCH_ERR_invalid_sb_journal;
unsigned nr;
unsigned i;
u64 *b;
if (!nr)
return 0;
- b = kmalloc_array(sizeof(u64), nr, GFP_KERNEL);
+ b = kmalloc_array(nr, sizeof(u64), GFP_KERNEL);
if (!b)
- return -ENOMEM;
+ return -BCH_ERR_ENOMEM_sb_journal_validate;
for (i = 0; i < nr; i++)
b[i] = le64_to_cpu(journal->buckets[i]);
sort(b, nr, sizeof(u64), u64_cmp, NULL);
if (!b[0]) {
- pr_buf(err, "journal bucket at sector 0");
+ prt_printf(err, "journal bucket at sector 0");
goto err;
}
- if (b[0] < le16_to_cpu(m->first_bucket)) {
- pr_buf(err, "journal bucket %llu before first bucket %u",
- b[0], le16_to_cpu(m->first_bucket));
+ if (b[0] < le16_to_cpu(m.first_bucket)) {
+ prt_printf(err, "journal bucket %llu before first bucket %u",
+ b[0], le16_to_cpu(m.first_bucket));
goto err;
}
- if (b[nr - 1] >= le64_to_cpu(m->nbuckets)) {
- pr_buf(err, "journal bucket %llu past end of device (nbuckets %llu)",
- b[nr - 1], le64_to_cpu(m->nbuckets));
+ if (b[nr - 1] >= le64_to_cpu(m.nbuckets)) {
+ prt_printf(err, "journal bucket %llu past end of device (nbuckets %llu)",
+ b[nr - 1], le64_to_cpu(m.nbuckets));
goto err;
}
for (i = 0; i + 1 < nr; i++)
if (b[i] == b[i + 1]) {
- pr_buf(err, "duplicate journal buckets %llu", b[i]);
+ prt_printf(err, "duplicate journal buckets %llu", b[i]);
goto err;
}
struct bch_sb_field_journal *journal = field_to_type(f, journal);
unsigned i, nr = bch2_nr_journal_buckets(journal);
- pr_buf(out, "Buckets: ");
+ prt_printf(out, "Buckets: ");
for (i = 0; i < nr; i++)
- pr_buf(out, " %llu", le64_to_cpu(journal->buckets[i]));
- pr_newline(out);
+ prt_printf(out, " %llu", le64_to_cpu(journal->buckets[i]));
+ prt_newline(out);
}
const struct bch_sb_field_ops bch_sb_field_ops_journal = {
struct printbuf *err)
{
struct bch_sb_field_journal_v2 *journal = field_to_type(f, journal_v2);
- struct bch_member *m = bch2_sb_get_members(sb)->members + sb->dev_idx;
- int ret = -EINVAL;
+ struct bch_member m = bch2_sb_member_get(sb, sb->dev_idx);
+ int ret = -BCH_ERR_invalid_sb_journal;
unsigned nr;
unsigned i;
struct u64_range *b;
if (!nr)
return 0;
- b = kmalloc_array(sizeof(*b), nr, GFP_KERNEL);
+ b = kmalloc_array(nr, sizeof(*b), GFP_KERNEL);
if (!b)
- return -ENOMEM;
+ return -BCH_ERR_ENOMEM_sb_journal_v2_validate;
for (i = 0; i < nr; i++) {
b[i].start = le64_to_cpu(journal->d[i].start);
sort(b, nr, sizeof(*b), u64_range_cmp, NULL);
if (!b[0].start) {
- pr_buf(err, "journal bucket at sector 0");
+ prt_printf(err, "journal bucket at sector 0");
goto err;
}
- if (b[0].start < le16_to_cpu(m->first_bucket)) {
- pr_buf(err, "journal bucket %llu before first bucket %u",
- b[0].start, le16_to_cpu(m->first_bucket));
+ if (b[0].start < le16_to_cpu(m.first_bucket)) {
+ prt_printf(err, "journal bucket %llu before first bucket %u",
+ b[0].start, le16_to_cpu(m.first_bucket));
goto err;
}
- if (b[nr - 1].end > le64_to_cpu(m->nbuckets)) {
- pr_buf(err, "journal bucket %llu past end of device (nbuckets %llu)",
- b[nr - 1].end - 1, le64_to_cpu(m->nbuckets));
+ if (b[nr - 1].end > le64_to_cpu(m.nbuckets)) {
+ prt_printf(err, "journal bucket %llu past end of device (nbuckets %llu)",
+ b[nr - 1].end - 1, le64_to_cpu(m.nbuckets));
goto err;
}
for (i = 0; i + 1 < nr; i++) {
- if (b[i].end == b[i + 1].start) {
- pr_buf(err, "contiguous journal buckets ranges %llu-%llu, %llu-%llu",
- b[i].start, b[i].end, b[i + 1].start, b[i + 1].end);
- goto err;
- }
-
if (b[i].end > b[i + 1].start) {
- pr_buf(err, "duplicate journal buckets in ranges %llu-%llu, %llu-%llu",
+ prt_printf(err, "duplicate journal buckets in ranges %llu-%llu, %llu-%llu",
b[i].start, b[i].end, b[i + 1].start, b[i + 1].end);
goto err;
}
struct bch_sb_field_journal_v2 *journal = field_to_type(f, journal_v2);
unsigned i, nr = bch2_sb_field_journal_v2_nr_entries(journal);
- pr_buf(out, "Buckets: ");
+ prt_printf(out, "Buckets: ");
for (i = 0; i < nr; i++)
- pr_buf(out, " %llu-%llu",
+ prt_printf(out, " %llu-%llu",
le64_to_cpu(journal->d[i].start),
le64_to_cpu(journal->d[i].start) + le64_to_cpu(journal->d[i].nr));
- pr_newline(out);
+ prt_newline(out);
}
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;
- lockdep_assert_held(&c->sb_lock);
+ 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));
+ j = bch2_sb_field_resize(&ca->disk_sb, journal_v2,
+ (sizeof(*j) + sizeof(j->d[0]) * nr_compacted) / sizeof(u64));
if (!j)
- return -ENOSPC;
+ 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].nr = le64_to_cpu(1);
+ j->d[dst].start = cpu_to_le64(buckets[0]);
+ j->d[dst].nr = cpu_to_le64(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].nr = le64_to_cpu(1);
+ j->d[dst].start = cpu_to_le64(buckets[i]);
+ j->d[dst].nr = cpu_to_le64(1);
}
}
+ BUG_ON(dst + 1 != nr_compacted);
return 0;
}