// SPDX-License-Identifier: GPL-2.0
/*
 * Moving/copying garbage collector
 *
 * Copyright 2012 Google, Inc.
 */

#include "bcache.h"
#include "btree.h"
#include "debug.h"
#include "request.h"

#include <trace/events/bcache.h>

struct moving_io {
	struct closure		cl;
	struct keybuf_key	*w;
	struct data_insert_op	op;
	struct bbio		bio;
};

static bool moving_pred(struct keybuf *buf, struct bkey *k)
{
	struct cache_set *c = container_of(buf, struct cache_set,
					   moving_gc_keys);
	unsigned int i;

	for (i = 0; i < KEY_PTRS(k); i++)
		if (ptr_available(c, k, i) &&
		    GC_MOVE(PTR_BUCKET(c, k, i)))
			return true;

	return false;
}

/* Moving GC - IO loop */

static CLOSURE_CALLBACK(moving_io_destructor)
{
	closure_type(io, struct moving_io, cl);

	kfree(io);
}

static CLOSURE_CALLBACK(write_moving_finish)
{
	closure_type(io, struct moving_io, cl);
	struct bio *bio = &io->bio.bio;

	bio_free_pages(bio);

	if (io->op.replace_collision)
		trace_bcache_gc_copy_collision(&io->w->key);

	bch_keybuf_del(&io->op.c->moving_gc_keys, io->w);

	up(&io->op.c->moving_in_flight);

	closure_return_with_destructor(cl, moving_io_destructor);
}

static void read_moving_endio(struct bio *bio)
{
	struct bbio *b = container_of(bio, struct bbio, bio);
	struct moving_io *io = container_of(bio->bi_private,
					    struct moving_io, cl);

	if (bio->bi_status)
		io->op.status = bio->bi_status;
	else if (!KEY_DIRTY(&b->key) &&
		 ptr_stale(io->op.c, &b->key, 0)) {
		io->op.status = BLK_STS_IOERR;
	}

	bch_bbio_endio(io->op.c, bio, bio->bi_status, "reading data to move");
}

static void moving_init(struct moving_io *io)
{
	struct bio *bio = &io->bio.bio;

	bio_init(bio, NULL, bio->bi_inline_vecs,
		 DIV_ROUND_UP(KEY_SIZE(&io->w->key), PAGE_SECTORS), 0);
	bio_get(bio);
	bio->bi_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);

	bio->bi_iter.bi_size	= KEY_SIZE(&io->w->key) << 9;
	bio->bi_private		= &io->cl;
	bch_bio_map(bio, NULL);
}

static CLOSURE_CALLBACK(write_moving)
{
	closure_type(io, struct moving_io, cl);
	struct data_insert_op *op = &io->op;

	if (!op->status) {
		moving_init(io);

		io->bio.bio.bi_iter.bi_sector = KEY_START(&io->w->key);
		op->write_prio		= 1;
		op->bio			= &io->bio.bio;

		op->writeback		= KEY_DIRTY(&io->w->key);
		op->csum		= KEY_CSUM(&io->w->key);

		bkey_copy(&op->replace_key, &io->w->key);
		op->replace		= true;

		closure_call(&op->cl, bch_data_insert, NULL, cl);
	}

	continue_at(cl, write_moving_finish, op->wq);
}

static CLOSURE_CALLBACK(read_moving_submit)
{
	closure_type(io, struct moving_io, cl);
	struct bio *bio = &io->bio.bio;

	bch_submit_bbio(bio, io->op.c, &io->w->key, 0);

	continue_at(cl, write_moving, io->op.wq);
}

static void read_moving(struct cache_set *c)
{
	struct keybuf_key *w;
	struct moving_io *io;
	struct bio *bio;
	struct closure cl;

	closure_init_stack(&cl);

	/* XXX: if we error, background writeback could stall indefinitely */

	while (!test_bit(CACHE_SET_STOPPING, &c->flags)) {
		w = bch_keybuf_next_rescan(c, &c->moving_gc_keys,
					   &MAX_KEY, moving_pred);
		if (!w)
			break;

		if (ptr_stale(c, &w->key, 0)) {
			bch_keybuf_del(&c->moving_gc_keys, w);
			continue;
		}

		io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
					 DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
			     GFP_KERNEL);
		if (!io)
			goto err;

		w->private	= io;
		io->w		= w;
		io->op.inode	= KEY_INODE(&w->key);
		io->op.c	= c;
		io->op.wq	= c->moving_gc_wq;

		moving_init(io);
		bio = &io->bio.bio;

		bio->bi_opf = REQ_OP_READ;
		bio->bi_end_io	= read_moving_endio;

		if (bch_bio_alloc_pages(bio, GFP_KERNEL))
			goto err;

		trace_bcache_gc_copy(&w->key);

		down(&c->moving_in_flight);
		closure_call(&io->cl, read_moving_submit, NULL, &cl);
	}

	if (0) {
err:		if (!IS_ERR_OR_NULL(w->private))
			kfree(w->private);

		bch_keybuf_del(&c->moving_gc_keys, w);
	}

	closure_sync(&cl);
}

static bool new_bucket_cmp(const void *l, const void *r, void __always_unused *args)
{
	struct bucket **_l = (struct bucket **)l;
	struct bucket **_r = (struct bucket **)r;

	return GC_SECTORS_USED(*_l) >= GC_SECTORS_USED(*_r);
}

static unsigned int bucket_heap_top(struct cache *ca)
{
	struct bucket *b;

	return (b = min_heap_peek(&ca->heap)[0]) ? GC_SECTORS_USED(b) : 0;
}

void bch_moving_gc(struct cache_set *c)
{
	struct cache *ca = c->cache;
	struct bucket *b;
	unsigned long sectors_to_move, reserve_sectors;
	const struct min_heap_callbacks callbacks = {
		.less = new_bucket_cmp,
		.swp = NULL,
	};

	if (!c->copy_gc_enabled)
		return;

	mutex_lock(&c->bucket_lock);

	sectors_to_move = 0;
	reserve_sectors = ca->sb.bucket_size *
			     fifo_used(&ca->free[RESERVE_MOVINGGC]);

	ca->heap.nr = 0;

	for_each_bucket(b, ca) {
		if (GC_MARK(b) == GC_MARK_METADATA ||
		    !GC_SECTORS_USED(b) ||
		    GC_SECTORS_USED(b) == ca->sb.bucket_size ||
		    atomic_read(&b->pin))
			continue;

		if (!min_heap_full(&ca->heap)) {
			sectors_to_move += GC_SECTORS_USED(b);
			min_heap_push(&ca->heap, &b, &callbacks, NULL);
		} else if (!new_bucket_cmp(&b, min_heap_peek(&ca->heap), ca)) {
			sectors_to_move -= bucket_heap_top(ca);
			sectors_to_move += GC_SECTORS_USED(b);

			ca->heap.data[0] = b;
			min_heap_sift_down(&ca->heap, 0, &callbacks, NULL);
		}
	}

	while (sectors_to_move > reserve_sectors) {
		if (ca->heap.nr) {
			b = min_heap_peek(&ca->heap)[0];
			min_heap_pop(&ca->heap, &callbacks, NULL);
		}
		sectors_to_move -= GC_SECTORS_USED(b);
	}

	while (ca->heap.nr) {
		b = min_heap_peek(&ca->heap)[0];
		min_heap_pop(&ca->heap, &callbacks, NULL);
		SET_GC_MOVE(b, 1);
	}

	mutex_unlock(&c->bucket_lock);

	c->moving_gc_keys.last_scanned = ZERO_KEY;

	read_moving(c);
}

void bch_moving_init_cache_set(struct cache_set *c)
{
	bch_keybuf_init(&c->moving_gc_keys);
	sema_init(&c->moving_in_flight, 64);
}
