/*
 * Copyright 2010 by Garmin Ltd. or its subsidiaries
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Performs a simple write/readback test to verify correct functionality
 * of direct i/o on a block device node.
 */

/* For large-file support */
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE

/* For O_DIRECT */
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <linux/fs.h>

#define NUM_TEST_BLKS 128

/*
 * Allocate page-aligned memory.  Could use posix_memalign(3), but some
 * systems don't support it.  Also pre-faults memory since we'll be using
 * it all right away anyway.
 */
static void *pagealign_alloc(size_t size)
{
	void *ret = mmap(NULL, size, PROT_READ | PROT_WRITE,
			MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_LOCKED,
			-1, 0);
	if (ret == MAP_FAILED) {
		perror("mmap");
		ret = NULL;
	}
	return ret;
}

static void pagealign_free(void *addr, size_t size)
{
	int ret = munmap(addr, size);
	if (ret == -1)
		perror("munmap");
}

static ssize_t do_read(int fd, void *buf, off64_t start, size_t count)
{
	ssize_t ret;
	size_t bytes_read = 0;

	lseek64(fd, start, SEEK_SET);

	do {
		ret = read(fd, (char *)buf + bytes_read, count - bytes_read);
		if (ret == -1) {
			perror("read");
			return -1;
		} else if (ret == 0) {
			fprintf(stderr, "Unexpected end-of-file\n");
			return -1;
		}
		bytes_read += ret;
	} while (bytes_read < count);

	return bytes_read;
}

static ssize_t do_write(int fd, const void *buf, off64_t start, size_t count)
{
	ssize_t ret;
	size_t bytes_out = 0;

	lseek64(fd, start, SEEK_SET);

	do {
		ret = write(fd, (char *)buf + bytes_out, count - bytes_out);
		if (ret == -1) {
			perror("write");
			return -1;
		} else if (ret == 0) {
			fprintf(stderr, "write returned 0\n");
			return -1;
		}
		bytes_out += ret;
	} while (bytes_out < count);

	return bytes_out;
}

/*
 * Initializes test buffer with locally-unique test pattern.  High 16-bits of
 * each 32-bit word contain first disk block number of the test area, low
 * 16-bits contain word offset into test area.  The goal is that a given test
 * area should never contain the same data as a nearby test area, and that the
 * data for a given test area be easily reproducable given the start block and
 * test area size.
 */
static void init_test_buf(void *buf, uint64_t start_blk, size_t len)
{
	uint32_t *data = buf;
	size_t i;

	len /= sizeof(uint32_t);
	for (i = 0; i < len; i++)
		data[i] = (start_blk & 0xFFFF) << 16 | (i & 0xFFFF);
}

static void dump_hex(const void *buf, int len)
{
	const uint8_t *data = buf;
	int i;
	char ascii_buf[17];

	ascii_buf[16] = '\0';

	for (i = 0; i < len; i++) {
		int val = data[i];
		int off = i % 16;

		if (off == 0)
			printf("%08x  ", i);
		printf("%02x ", val);
		ascii_buf[off] = isprint(val) ? val : '.';
		if (off == 15)
			printf(" %-16s\n", ascii_buf);
	}

	i %= 16;
	if (i) {
		ascii_buf[i] = '\0';
		while (i++ < 16)
			printf("   ");
		printf(" %-16s\n", ascii_buf);
	}
}

static void update_progress(int current, int total)
{
	double pct_done = (double)current * 100 / total;
	printf("Testing area %d/%d (%6.2f%% complete)\r", current, total,
			pct_done);
	fflush(stdout);
}

int main(int argc, const char *argv[])
{
	int ret = 1;
	const char *path;
	int fd;
	struct stat stat;
	void *read_buf = NULL, *write_buf = NULL;
	int blk_size;
	uint64_t num_blks;
	size_t test_size;
	int test_areas, i;

	if (argc != 2) {
		printf("Usage: directiotest blkdev_path\n");
		exit(1);
	}

	path = argv[1];
	fd = open(path, O_RDWR | O_DIRECT | O_LARGEFILE);
	if (fd == -1) {
		perror("open");
		exit(1);
	}
	if (fstat(fd, &stat) == -1) {
		perror("stat");
		goto cleanup;
	} else if (!S_ISBLK(stat.st_mode)) {
		fprintf(stderr, "%s is not a block device\n", path);
		goto cleanup;
	}

	if (ioctl(fd, BLKSSZGET, &blk_size) == -1) {
		perror("ioctl");
		goto cleanup;
	}
	if (ioctl(fd, BLKGETSIZE64, &num_blks) == -1) {
		perror("ioctl");
		goto cleanup;
	}
	num_blks /= blk_size;

	test_size = (size_t)blk_size * NUM_TEST_BLKS;
	read_buf = pagealign_alloc(test_size);
	write_buf = pagealign_alloc(test_size);
	if (!read_buf || !write_buf) {
		fprintf(stderr, "Error allocating test buffers\n");
		goto cleanup;
	}

	/*
	 * Start the actual test.  Go through the entire device, writing
	 * locally-unique patern to each test block and then reading it
	 * back.
	 */
	if (num_blks / NUM_TEST_BLKS > INT_MAX) {
		printf("Warning: Device too large for test variables\n");
		printf("Entire device will not be tested\n");
		test_areas = INT_MAX;
	} else {
		test_areas = num_blks / NUM_TEST_BLKS;
	}

	printf("Starting test\n");

	for (i = 0; i < test_areas; i++) {
		uint64_t cur_blk = (uint64_t)i * NUM_TEST_BLKS;

		update_progress(i + 1, test_areas);

		init_test_buf(write_buf, cur_blk, test_size);

		if (do_write(fd, write_buf, cur_blk * blk_size, test_size) !=
				(ssize_t)test_size) {
			fprintf(stderr, "write failed, aborting test\n");
			goto cleanup;
		}
		if (do_read(fd, read_buf, cur_blk * blk_size, test_size) !=
				(ssize_t)test_size) {
			fprintf(stderr, "read failed, aborting test\n");
			goto cleanup;
		}

		if (memcmp(write_buf, read_buf, test_size)) {
			printf("Readback verification failed at block %llu\n\n",
					cur_blk);
			printf("Written data:\n");
			dump_hex(write_buf, test_size);
			printf("\nRead data:\n");
			dump_hex(read_buf, test_size);
			goto cleanup;
		}
	}

	printf("\nTest complete\n");
	ret = 0;

cleanup:
	if (read_buf)
		pagealign_free(read_buf, test_size);
	if (write_buf)
		pagealign_free(write_buf, test_size);
	close(fd);
	return ret;
}
