/*
 *
 * A test for the patch "Allow compaction of unevictable pages".
 * With this patch we should be able to allocate at least 1/4
 * of RAM in huge pages. Without the patch much less is
 * allocated.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

#define MAP_SIZE 1048576

struct map_list {
	void *map;
	struct map_list *next;
};

int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize)
{
	char  buffer[256] = {0};
	char *cmd = "cat /proc/meminfo | grep -i memfree | grep -o '[0-9]*'";
	FILE *cmdfile = popen(cmd, "r");

	if (!(fgets(buffer, sizeof(buffer), cmdfile))) {
		perror("Failed to read meminfo\n");
		return -1;
	}

	pclose(cmdfile);

	*memfree = atoll(buffer);
	cmd = "cat /proc/meminfo | grep -i hugepagesize | grep -o '[0-9]*'";
	cmdfile = popen(cmd, "r");

	if (!(fgets(buffer, sizeof(buffer), cmdfile))) {
		perror("Failed to read meminfo\n");
		return -1;
	}

	pclose(cmdfile);
	*hugepagesize = atoll(buffer);

	return 0;
}

int prereq(void)
{
	char allowed;
	int fd;

	fd = open("/proc/sys/vm/compact_unevictable_allowed",
		  O_RDONLY | O_NONBLOCK);
	if (fd < 0) {
		perror("Failed to open\n"
		       "/proc/sys/vm/compact_unevictable_allowed\n");
		return -1;
	}

	if (read(fd, &allowed, sizeof(char)) != sizeof(char)) {
		perror("Failed to read from\n"
		       "/proc/sys/vm/compact_unevictable_allowed\n");
		close(fd);
		return -1;
	}

	close(fd);
	if (allowed == '1')
		return 0;

	return -1;
}

int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
{
	int fd;
	int compaction_index = 0;
	char initial_nr_hugepages[10] = {0};
	char nr_hugepages[10] = {0};

	/* We want to test with 80% of available memory. Else, OOM killer comes
	   in to play */
	mem_free = mem_free * 0.8;

	fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK);
	if (fd < 0) {
		perror("Failed to open /proc/sys/vm/nr_hugepages");
		return -1;
	}

	if (read(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) <= 0) {
		perror("Failed to read from /proc/sys/vm/nr_hugepages");
		goto close_fd;
	}

	/* Start with the initial condition of 0 huge pages*/
	if (write(fd, "0", sizeof(char)) != sizeof(char)) {
		perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
		goto close_fd;
	}

	lseek(fd, 0, SEEK_SET);

	/* Request a large number of huge pages. The Kernel will allocate
	   as much as it can */
	if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
		perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
		goto close_fd;
	}

	lseek(fd, 0, SEEK_SET);

	if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
		perror("Failed to read from /proc/sys/vm/nr_hugepages\n");
		goto close_fd;
	}

	/* We should have been able to request at least 1/3 rd of the memory in
	   huge pages */
	compaction_index = mem_free/(atoi(nr_hugepages) * hugepage_size);

	if (compaction_index > 3) {
		printf("No of huge pages allocated = %d\n",
		       (atoi(nr_hugepages)));
		fprintf(stderr, "ERROR: Less that 1/%d of memory is available\n"
			"as huge pages\n", compaction_index);
		goto close_fd;
	}

	printf("No of huge pages allocated = %d\n",
	       (atoi(nr_hugepages)));

	if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
	    != strlen(initial_nr_hugepages)) {
		perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
		goto close_fd;
	}

	close(fd);
	return 0;

 close_fd:
	close(fd);
	printf("Not OK. Compaction test failed.");
	return -1;
}


int main(int argc, char **argv)
{
	struct rlimit lim;
	struct map_list *list, *entry;
	size_t page_size, i;
	void *map = NULL;
	unsigned long mem_free = 0;
	unsigned long hugepage_size = 0;
	unsigned long mem_fragmentable = 0;

	if (prereq() != 0) {
		printf("Either the sysctl compact_unevictable_allowed is not\n"
		       "set to 1 or couldn't read the proc file.\n"
		       "Skipping the test\n");
		return 0;
	}

	lim.rlim_cur = RLIM_INFINITY;
	lim.rlim_max = RLIM_INFINITY;
	if (setrlimit(RLIMIT_MEMLOCK, &lim)) {
		perror("Failed to set rlimit:\n");
		return -1;
	}

	page_size = getpagesize();

	list = NULL;

	if (read_memory_info(&mem_free, &hugepage_size) != 0) {
		printf("ERROR: Cannot read meminfo\n");
		return -1;
	}

	mem_fragmentable = mem_free * 0.8 / 1024;

	while (mem_fragmentable > 0) {
		map = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE,
			   MAP_ANONYMOUS | MAP_PRIVATE | MAP_LOCKED, -1, 0);
		if (map == MAP_FAILED)
			break;

		entry = malloc(sizeof(struct map_list));
		if (!entry) {
			munmap(map, MAP_SIZE);
			break;
		}
		entry->map = map;
		entry->next = list;
		list = entry;

		/* Write something (in this case the address of the map) to
		 * ensure that KSM can't merge the mapped pages
		 */
		for (i = 0; i < MAP_SIZE; i += page_size)
			*(unsigned long *)(map + i) = (unsigned long)map + i;

		mem_fragmentable--;
	}

	for (entry = list; entry != NULL; entry = entry->next) {
		munmap(entry->map, MAP_SIZE);
		if (!entry->next)
			break;
		entry = entry->next;
	}

	if (check_compaction(mem_free, hugepage_size) == 0)
		return 0;

	return -1;
}
