/*
 * MTD engine
 *
 * IO engine that reads/writes from MTD character devices.
 *
 */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>

#include "../fio.h"
#include "../verify.h"
#include "../oslib/libmtd.h"

static libmtd_t desc;

struct fio_mtd_data {
	struct mtd_dev_info info;
};

static int fio_mtd_maybe_mark_bad(struct thread_data *td,
				  struct fio_mtd_data *fmd,
				  struct io_u *io_u, int eb)
{
	int ret;
	if (errno == EIO) {
		ret = mtd_mark_bad(&fmd->info, io_u->file->fd, eb);
		if (ret != 0) {
			io_u->error = errno;
			td_verror(td, errno, "mtd_mark_bad");
			return -1;
		}
	}
	return 0;
}

static int fio_mtd_is_bad(struct thread_data *td,
			  struct fio_mtd_data *fmd,
			  struct io_u *io_u, int eb)
{
	int ret = mtd_is_bad(&fmd->info, io_u->file->fd, eb);
	if (ret == -1) {
		io_u->error = errno;
		td_verror(td, errno, "mtd_is_bad");
	} else if (ret == 1)
		io_u->error = EIO;	/* Silent failure--don't flood stderr */
	return ret;
}

static int fio_mtd_queue(struct thread_data *td, struct io_u *io_u)
{
	struct fio_file *f = io_u->file;
	struct fio_mtd_data *fmd = FILE_ENG_DATA(f);
	int local_offs = 0;
	int ret;

	fio_ro_check(td, io_u);

	/*
	 * Errors tend to pertain to particular erase blocks, so divide up
	 * I/O to erase block size.
	 * If an error is encountered, log it and keep going onto the next
	 * block because the error probably just pertains to that block.
	 * TODO(dehrenberg): Divide up reads and writes into page-sized
	 * operations to get more fine-grained information about errors.
	 */
	while (local_offs < io_u->buflen) {
		int eb = (io_u->offset + local_offs) / fmd->info.eb_size;
		int eb_offs = (io_u->offset + local_offs) % fmd->info.eb_size;
		/* The length is the smaller of the length remaining in the
		 * buffer and the distance to the end of the erase block */
		int len = min((int)io_u->buflen - local_offs,
			      (int)fmd->info.eb_size - eb_offs);
		char *buf = ((char *)io_u->buf) + local_offs;

		if (td->o.skip_bad) {
			ret = fio_mtd_is_bad(td, fmd, io_u, eb);
			if (ret == -1)
				break;
			else if (ret == 1)
				goto next;
		}
		if (io_u->ddir == DDIR_READ) {
			ret = mtd_read(&fmd->info, f->fd, eb, eb_offs, buf, len);
			if (ret != 0) {
				io_u->error = errno;
				td_verror(td, errno, "mtd_read");
				if (fio_mtd_maybe_mark_bad(td, fmd, io_u, eb))
					break;
			}
		} else if (io_u->ddir == DDIR_WRITE) {
			ret = mtd_write(desc, &fmd->info, f->fd, eb,
					    eb_offs, buf, len, NULL, 0, 0);
			if (ret != 0) {
				io_u->error = errno;
				td_verror(td, errno, "mtd_write");
				if (fio_mtd_maybe_mark_bad(td, fmd, io_u, eb))
					break;
			}
		} else if (io_u->ddir == DDIR_TRIM) {
			if (eb_offs != 0 || len != fmd->info.eb_size) {
				io_u->error = EINVAL;
				td_verror(td, EINVAL,
					  "trim on MTD must be erase block-aligned");
			}
			ret = mtd_erase(desc, &fmd->info, f->fd, eb);
			if (ret != 0) {
				io_u->error = errno;
				td_verror(td, errno, "mtd_erase");
				if (fio_mtd_maybe_mark_bad(td, fmd, io_u, eb))
					break;
			}
		} else {
			io_u->error = ENOTSUP;
			td_verror(td, io_u->error, "operation not supported on mtd");
		}

next:
		local_offs += len;
	}

	return FIO_Q_COMPLETED;
}

static int fio_mtd_open_file(struct thread_data *td, struct fio_file *f)
{
	struct fio_mtd_data *fmd;
	int ret;

	ret = generic_open_file(td, f);
	if (ret)
		return ret;

	fmd = calloc(1, sizeof(*fmd));
	if (!fmd)
		goto err_close;

	ret = mtd_get_dev_info(desc, f->file_name, &fmd->info);
	if (ret != 0) {
		td_verror(td, errno, "mtd_get_dev_info");
		goto err_free;
	}

	FILE_SET_ENG_DATA(f, fmd);
	return 0;

err_free:
	free(fmd);
err_close:
	{
		int fio_unused __ret;
		__ret = generic_close_file(td, f);
		return 1;
	}
}

static int fio_mtd_close_file(struct thread_data *td, struct fio_file *f)
{
	struct fio_mtd_data *fmd = FILE_ENG_DATA(f);

	FILE_SET_ENG_DATA(f, NULL);
	free(fmd);

	return generic_close_file(td, f);
}

static int fio_mtd_get_file_size(struct thread_data *td, struct fio_file *f)
{
	struct mtd_dev_info info;

	int ret = mtd_get_dev_info(desc, f->file_name, &info);
	if (ret != 0) {
		td_verror(td, errno, "mtd_get_dev_info");
		return errno;
	}
	f->real_file_size = info.size;

	return 0;
}

static struct ioengine_ops ioengine = {
	.name		= "mtd",
	.version	= FIO_IOOPS_VERSION,
	.queue		= fio_mtd_queue,
	.open_file	= fio_mtd_open_file,
	.close_file	= fio_mtd_close_file,
	.get_file_size	= fio_mtd_get_file_size,
	.flags		= FIO_SYNCIO | FIO_NOEXTEND,
};

static void fio_init fio_mtd_register(void)
{
	desc = libmtd_open();
	register_ioengine(&ioengine);
}

static void fio_exit fio_mtd_unregister(void)
{
	unregister_ioengine(&ioengine);
	libmtd_close(desc);
	desc = NULL;
}



