// SPDX-License-Identifier: GPL-2.0

#include "bcachefs.h"
#include "journal_sb.h"
#include "darray.h"

#include <linux/sort.h>

/* BCH_SB_FIELD_journal: */

static int u64_cmp(const void *_l, const void *_r)
{
	const u64 *l = _l;
	const u64 *r = _r;

	return cmp_int(*l, *r);
}

static int bch2_sb_journal_validate(struct bch_sb *sb, struct bch_sb_field *f,
				enum bch_validate_flags flags, struct printbuf *err)
{
	struct bch_sb_field_journal *journal = field_to_type(f, journal);
	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;

	nr = bch2_nr_journal_buckets(journal);
	if (!nr)
		return 0;

	b = kmalloc_array(nr, sizeof(u64), GFP_KERNEL);
	if (!b)
		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]) {
		prt_printf(err, "journal bucket at sector 0");
		goto err;
	}

	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)) {
		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]) {
			prt_printf(err, "duplicate journal buckets %llu", b[i]);
			goto err;
		}

	ret = 0;
err:
	kfree(b);
	return ret;
}

static void bch2_sb_journal_to_text(struct printbuf *out, struct bch_sb *sb,
				    struct bch_sb_field *f)
{
	struct bch_sb_field_journal *journal = field_to_type(f, journal);
	unsigned i, nr = bch2_nr_journal_buckets(journal);

	prt_printf(out, "Buckets: ");
	for (i = 0; i < nr; i++)
		prt_printf(out, " %llu", le64_to_cpu(journal->buckets[i]));
	prt_newline(out);
}

const struct bch_sb_field_ops bch_sb_field_ops_journal = {
	.validate	= bch2_sb_journal_validate,
	.to_text	= bch2_sb_journal_to_text,
};

struct u64_range {
	u64	start;
	u64	end;
};

static int u64_range_cmp(const void *_l, const void *_r)
{
	const struct u64_range *l = _l;
	const struct u64_range *r = _r;

	return cmp_int(l->start, r->start);
}

static int bch2_sb_journal_v2_validate(struct bch_sb *sb, struct bch_sb_field *f,
				enum bch_validate_flags flags, struct printbuf *err)
{
	struct bch_sb_field_journal_v2 *journal = field_to_type(f, journal_v2);
	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;

	nr = bch2_sb_field_journal_v2_nr_entries(journal);
	if (!nr)
		return 0;

	b = kmalloc_array(nr, sizeof(*b), GFP_KERNEL);
	if (!b)
		return -BCH_ERR_ENOMEM_sb_journal_v2_validate;

	for (i = 0; i < nr; i++) {
		b[i].start = le64_to_cpu(journal->d[i].start);
		b[i].end = b[i].start + le64_to_cpu(journal->d[i].nr);
	}

	sort(b, nr, sizeof(*b), u64_range_cmp, NULL);

	if (!b[0].start) {
		prt_printf(err, "journal bucket at sector 0");
		goto err;
	}

	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)) {
		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) {
			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;
		}
	}

	ret = 0;
err:
	kfree(b);
	return ret;
}

static void bch2_sb_journal_v2_to_text(struct printbuf *out, struct bch_sb *sb,
				    struct bch_sb_field *f)
{
	struct bch_sb_field_journal_v2 *journal = field_to_type(f, journal_v2);
	unsigned i, nr = bch2_sb_field_journal_v2_nr_entries(journal);

	prt_printf(out, "Buckets: ");
	for (i = 0; i < nr; i++)
		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));
	prt_newline(out);
}

const struct bch_sb_field_ops bch_sb_field_ops_journal_v2 = {
	.validate	= bch2_sb_journal_v2_validate,
	.to_text	= bch2_sb_journal_v2_to_text,
};

int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca,
			       u64 *buckets, unsigned nr)
{
	struct bch_sb_field_journal_v2 *j;
	unsigned i, dst = 0, nr_compacted = 1;

	if (c)
		lockdep_assert_held(&c->sb_lock);

	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 < nr; i++)
		if (buckets[i] + 1 != buckets[i + 1])
			nr_compacted++;

	j = bch2_sb_field_resize(&ca->disk_sb, journal_v2,
			 (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 = cpu_to_le64(buckets[0]);
	j->d[dst].nr	= cpu_to_le64(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 = cpu_to_le64(buckets[i]);
			j->d[dst].nr	= cpu_to_le64(1);
		}
	}

	BUG_ON(dst + 1 != nr_compacted);
	return 0;
}
