/*
 * Copyright (c) International Business Machines Corp., 2006
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Author: Artem B. Bityutskiy
 *
 * This test does a lot of I/O to volumes in parallel.
 */

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "libubi.h"
#define TESTNAME "io_paral"
#include "common.h"

#define THREADS_NUM 4
#define ITERATIONS  (1024 * 1)
#define VOL_LEBS    10

static libubi_t libubi;
static struct ubi_dev_info dev_info;
static const char *node;
static int vol_size;

static struct ubi_mkvol_request reqests[THREADS_NUM + 1];
static char vol_name[THREADS_NUM + 1][100];
static char vol_nodes[THREADS_NUM + 1][strlen(UBI_VOLUME_PATTERN) + 100];
static unsigned char *wbufs[THREADS_NUM + 1];
static unsigned char *rbufs[THREADS_NUM + 1];

static int update_volume(int vol_id, int bytes)
{
	int i, fd, ret, written = 0, rd = 0;
	char *vol_node = vol_nodes[vol_id];
	unsigned char *wbuf = wbufs[vol_id];
	unsigned char *rbuf = rbufs[vol_id];

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		err_msg("cannot open \"%s\"\n", vol_node);
		return -1;
	}

	for (i = 0; i < bytes; i++)
		wbuf[i] = random() % 255;
	memset(rbuf, '\0', bytes);

	ret = ubi_update_start(libubi, fd, bytes);
	if (ret) {
		failed("ubi_update_start");
		err_msg("volume id is %d", vol_id);
		goto err_close;
	}

	while (written < bytes) {
		int to_write = random() % (bytes - written);

		if (to_write == 0)
			to_write = 1;

		ret = write(fd, wbuf + written, to_write);
		if (ret != to_write) {
			failed("write");
			err_msg("failed to write %d bytes at offset %d "
				"of volume %d", to_write, written,
				vol_id);
			err_msg("update: %d bytes", bytes);
			goto err_close;
		}

		written += to_write;
	}

	close(fd);

	fd = open(vol_node, O_RDONLY);
	if (fd == -1) {
		failed("open");
		err_msg("cannot open \"%s\"\n", node);
		return -1;
	}

	/* read data back and check */
	while (rd < bytes) {
		int to_read = random() % (bytes - rd);

		if (to_read == 0)
			to_read = 1;

		ret = read(fd, rbuf + rd, to_read);
		if (ret != to_read) {
			failed("read");
			err_msg("failed to read %d bytes at offset %d "
				"of volume %d", to_read, rd, vol_id);
			goto err_close;
		}

		rd += to_read;
	}

	if (memcmp(wbuf, rbuf, bytes)) {
		err_msg("written and read data are different");
		goto err_close;
	}

	close(fd);
	return 0;

err_close:
	close(fd);
	return -1;
}

static void *update_thread(void *ptr)
{
	int vol_id = (long)ptr, i;

	for (i = 0; i < ITERATIONS; i++) {
		int ret, bytes = (random() % (vol_size - 1)) + 1;
		int remove = !(random() % 16);

		/* From time to time remove the volume */
		if (remove) {
			ret = ubi_rmvol(libubi, node, vol_id);
			if (ret) {
				failed("ubi_rmvol");
				err_msg("cannot remove volume %d", vol_id);
				return NULL;
			}
			ret = ubi_mkvol(libubi, node, &reqests[vol_id]);
			if (ret) {
				failed("ubi_mkvol");
				err_msg("cannot create volume %d", vol_id);
				return NULL;
			}
		}

		ret = update_volume(vol_id, bytes);
		if (ret)
			return NULL;
	}

	return NULL;
}

static void *write_thread(void *ptr)
{
	int ret, fd, vol_id = (long)ptr, i;
	char *vol_node = vol_nodes[vol_id];
	unsigned char *wbuf = wbufs[vol_id];
	unsigned char *rbuf = rbufs[vol_id];

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		err_msg("cannot open \"%s\"\n", vol_node);
		return NULL;
	}

	ret = ubi_set_property(fd, UBI_PROP_DIRECT_WRITE, 1);
	if (ret) {
		failed("ubi_set_property");
		err_msg("cannot set property for \"%s\"\n", vol_node);
	}

	for (i = 0; i < ITERATIONS * VOL_LEBS; i++) {
		int j, leb = random() % VOL_LEBS;
		off_t offs = dev_info.leb_size * leb;

		ret = ubi_leb_unmap(fd, leb);
		if (ret) {
			failed("ubi_leb_unmap");
			err_msg("cannot unmap LEB %d", leb);
			break;
		}

		for (j = 0; j < dev_info.leb_size; j++)
			wbuf[j] = random() % 255;
		memset(rbuf, '\0', dev_info.leb_size);

		ret = pwrite(fd, wbuf, dev_info.leb_size, offs);
		if (ret != dev_info.leb_size) {
			failed("pwrite");
			err_msg("cannot write %d bytes to offs %lld, wrote %d",
				dev_info.leb_size, offs, ret);
			break;
		}

		/* read data back and check */
		ret = pread(fd, rbuf, dev_info.leb_size, offs);
		if (ret != dev_info.leb_size) {
			failed("read");
			err_msg("failed to read %d bytes at offset %d "
				"of volume %d", dev_info.leb_size, offs,
				vol_id);
			break;
		}

		if (memcmp(wbuf, rbuf, dev_info.leb_size)) {
			err_msg("written and read data are different");
			break;
		}
	}

	close(fd);
	return NULL;
}

int main(int argc, char * const argv[])
{
	int i, ret;
	pthread_t threads[THREADS_NUM];

	if (initial_check(argc, argv))
		return 1;

	node = argv[1];

	libubi = libubi_open();
	if (libubi == NULL) {
		failed("libubi_open");
		return 1;
	}

	if (ubi_get_dev_info(libubi, node, &dev_info)) {
		failed("ubi_get_dev_info");
		goto close;
	}

	/*
	 * Create 1 volume more than threads count. The last volume
	 * will not change to let WL move more stuff.
	 */
	vol_size = dev_info.leb_size * VOL_LEBS;
	for (i = 0; i <= THREADS_NUM; i++) {
		reqests[i].alignment = 1;
		reqests[i].bytes = vol_size;
		reqests[i].vol_id = i;
		sprintf(vol_name[i], TESTNAME":%d", i);
		reqests[i].name = vol_name[i];
		reqests[i].vol_type = UBI_DYNAMIC_VOLUME;
		if (i == THREADS_NUM)
			reqests[i].vol_type = UBI_STATIC_VOLUME;
		sprintf(vol_nodes[i], UBI_VOLUME_PATTERN, dev_info.dev_num, i);

		if (ubi_mkvol(libubi, node, &reqests[i])) {
			failed("ubi_mkvol");
			goto remove;
		}

		wbufs[i] = malloc(vol_size);
		rbufs[i] = malloc(vol_size);
		if (!wbufs[i] || !rbufs[i]) {
			failed("malloc");
			goto remove;
		}

		ret = update_volume(i, vol_size);
		if (ret)
			goto remove;
	}

	for (i = 0; i < THREADS_NUM / 2; i++) {
		ret = pthread_create(&threads[i], NULL, &write_thread, (void *)(long)i);
		if (ret) {
			failed("pthread_create");
			goto remove;
		}
	}

	for (i = THREADS_NUM / 2; i < THREADS_NUM; i++) {
		ret = pthread_create(&threads[i], NULL, &update_thread, (void *)(long)i);
		if (ret) {
			failed("pthread_create");
			goto remove;
		}
	}

	for (i = 0; i < THREADS_NUM; i++)
		pthread_join(threads[i], NULL);

	for (i = 0; i <= THREADS_NUM; i++) {
		if (ubi_rmvol(libubi, node, i)) {
			failed("ubi_rmvol");
			goto remove;
		}
		if (wbufs[i])
			free(wbufs[i]);
		if (rbufs[i])
			free(rbufs[i]);
		wbufs[i] = NULL;
		rbufs[i] = NULL;
	}

	libubi_close(libubi);
	return 0;

remove:
	for (i = 0; i <= THREADS_NUM; i++) {
		ubi_rmvol(libubi, node, i);
		if (wbufs[i])
			free(wbufs[i]);
		if (rbufs[i])
			free(rbufs[i]);
		wbufs[i] = NULL;
		rbufs[i] = NULL;
	}

close:
	libubi_close(libubi);
	return 1;
}
