int main(int argc, char **argv)
{
	int fd;
	char *p;
	char buf[256];

	signal(SIGUSR1, sighandler);
	fd = open_check(argv[1], O_RDWR, 0644);

	p = mmap_check((void *)0x700000000000, 0x202*PS, PROTECTION,
		       MAP_SHARED, fd, 0);

	buf[0] = p[0];
	buf[1] = p[PS];
	buf[2] = p[PS*0x10];
	buf[3] = p[PS*0x11];
	buf[4] = p[PS*0x200];
	buf[5] = p[PS*0x201];
	pause();

	return 0;
}
Exemplo n.º 2
0
static int stress_mremap_child(
	const args_t *args,
	const size_t sz,
	size_t new_sz,
	const size_t page_size,
	const size_t mremap_bytes,
	int *flags)
{
	do {
		uint8_t *buf = NULL;
		size_t old_sz;

		if (!g_keep_stressing_flag)
			break;

		buf = mmap(NULL, new_sz, PROT_READ | PROT_WRITE, *flags, -1, 0);
		if (buf == MAP_FAILED) {
			/* Force MAP_POPULATE off, just in case */
#if defined(MAP_POPULATE)
			*flags &= ~MAP_POPULATE;
#endif
			continue;	/* Try again */
		}
		(void)madvise_random(buf, new_sz);
		(void)mincore_touch_pages(buf, mremap_bytes);

		/* Ensure we can write to the mapped pages */
		if (g_opt_flags & OPT_FLAGS_VERIFY) {
			mmap_set(buf, new_sz, page_size);
			if (mmap_check(buf, sz, page_size) < 0) {
				pr_fail("%s: mmap'd region of %zu "
					"bytes does not contain expected data\n",
					args->name, sz);
				(void)munmap(buf, new_sz);
				return EXIT_FAILURE;
			}
		}

		old_sz = new_sz;
		new_sz >>= 1;
		while (new_sz > page_size) {
			if (try_remap(args, &buf, old_sz, new_sz) < 0) {
				(void)munmap(buf, old_sz);
				return EXIT_FAILURE;
			}
			(void)madvise_random(buf, new_sz);
			if (g_opt_flags & OPT_FLAGS_VERIFY) {
				if (mmap_check(buf, new_sz, page_size) < 0) {
					pr_fail("%s: mremap'd region "
						"of %zu bytes does "
						"not contain expected data\n",
						args->name, sz);
					(void)munmap(buf, new_sz);
					return EXIT_FAILURE;
				}
			}
			old_sz = new_sz;
			new_sz >>= 1;
		}

		new_sz <<= 1;
		while (new_sz < mremap_bytes) {
			if (try_remap(args, &buf, old_sz, new_sz) < 0) {
				(void)munmap(buf, old_sz);
				return EXIT_FAILURE;
			}
			(void)madvise_random(buf, new_sz);
			old_sz = new_sz;
			new_sz <<= 1;
		}
		(void)munmap(buf, old_sz);

		inc_counter(args);
	} while (keep_stressing());

	return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
	int fd;
	int sem;
	int nrpages = 1;
	int ret = 0;
	int tmp = 0;
	int offset = 0;
	char c;
	char *filename;
	char *actype;
	char *onerror;
	char *p;
	pid_t pid;
	int wait_status;
	uint64_t pflag;
	struct sembuf sembuf;
	struct pagestat pgstat;

	if (argc != 5) {
		printf("Usage: %s filename nrpages accesstype onerror\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	filename = argv[1];
	nrpages = strtol(argv[2], NULL, 10);
	actype = argv[3];
	onerror = argv[4];
	DEB("filename = %s, nrpages = %d, actype = %s, onerror = %s\n",
	       filename, nrpages, actype, onerror);

	if (strcmp(onerror, "onerror") == 0)
		offset = 0;
	else
		offset = PS;

	sem = create_and_init_semaphore();

	fd = open_check(filename, O_RDWR, 0);
	tmp = pread(fd, rbuf, nrpages*PS, 0);
	DEB("parent first read %d [%c,%c]\n", tmp, rbuf[0], rbuf[PS]);

	get_semaphore(sem, &sembuf);
	if ((pid = fork()) == 0) {
		get_semaphore(sem, &sembuf); /* wait parent to dirty page */
		p = mmap_check((void *)REFADDR, nrpages * PS,
			       PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
		if (p != (void *)REFADDR)
			err("mmap");
		if (nrpages == 1) {
			DEB("child read (after dirty) [%c]\n", p[0]);
#ifdef DEBUG
			get_pagestat(p, &pgstat);
#endif
		} else {
			DEB("child read (after dirty) [%c,%c]\n", p[0], p[PS]);
#ifdef DEBUG
			get_pagestat(p, &pgstat);
			get_pagestat(p+PS, &pgstat);
#endif
		}
		DEB("child hwpoison to vaddr %p\n", p);
		madvise(&p[0], PS, 100); /* hwpoison */
		put_semaphore(sem, &sembuf);
		get_semaphore(sem, &sembuf);
		DEB("child terminated\n");
		put_semaphore(sem, &sembuf);
		get_pflags(pgstat.pfn, &pflag, 1);
		exit(EXIT_SUCCESS);
	} else {
		DEB("parent dirty\n");
		usleep(1000);
		memset(wbuf, 49, nrpages * PS);
		pwrite(fd, wbuf, nrpages * PS, 0);
		tmp = pread(fd, rbuf, nrpages * PS, 0);
		DEB("parent second read (after dirty) %d [%c,%c]\n",
		       tmp, rbuf[0], rbuf[PS]);

		put_semaphore(sem, &sembuf); /* kick child to inject error */
		get_semaphore(sem, &sembuf); /* pagecache should be hwpoison */
		DEB("parent check\n");
		if (strcmp(actype, "read") == 0) {
			tmp = pread(fd, rbuf, PS, offset);
			if (tmp < 0)
				DEB("parent first read failed.\n");
			tmp = pread(fd, rbuf, PS, offset);
			DEB("parent read after hwpoison %d [%c,%c]\n",
			       tmp, rbuf[0], rbuf[PS]);
			if (tmp < 0) {
				ret = -1;
				perror("read");
			} else {
				ret = 0;
			}
		} else if (strcmp(actype, "writefull") == 0) {
			memset(wbuf, 50, nrpages * PS);
			tmp = pwrite(fd, wbuf, PS, offset);
			tmp = pwrite(fd, wbuf, PS, offset);
			DEB("parent write after hwpoison %d\n", tmp);
			if (tmp < 0) {
				ret = -1;
				perror("writefull");
			} else {
				ret = 0;
			}
		} else if (strcmp(actype, "writepart") == 0) {
			memset(wbuf, 50, nrpages * PS);
			tmp = pwrite(fd, wbuf, PS / 2, offset);
			tmp = pwrite(fd, wbuf, PS / 2, offset);
			DEB("parent write after hwpoison %d\n", tmp);
			if (tmp < 0) {
				ret = -1;
				perror("writefull");
			} else {
				ret = 0;
			}
		} else if (strcmp(actype, "fsync") == 0) {
			ret = fsync(fd);
			ret = fsync(fd);
			DEB("parent fsync after hwpoison [ret %d]\n", ret);
			if (ret)
				perror("fsync");
		} else if (strcmp(actype, "sync_range_write") == 0) {
			ret = sync_file_range(fd, offset, PS, SYNC_FILE_RANGE_WRITE);
			ret = sync_file_range(fd, offset, PS, SYNC_FILE_RANGE_WRITE);
			if (ret)
				perror("sync_range_write");
		} else if (strcmp(actype, "sync_range_wait") == 0) {
			ret = sync_file_range(fd, offset, PS, SYNC_FILE_RANGE_WAIT_BEFORE);
			ret = sync_file_range(fd, offset, PS, SYNC_FILE_RANGE_WAIT_BEFORE);
			if (ret)
				perror("sync_range_wait");
		} else if (strcmp(actype, "mmapread") == 0) {
			/*
			 * If mmap access failed, this program should be
			 * terminated by segmentation fault with non-zero
			 * returned value. So we don't set ret here.
			 */
			p = mmap_check((void *)REFADDR, nrpages * PS,
				       PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
			if (p != (void *)REFADDR)
				err("mmap");
			c = p[offset];
			DEB("parent mmap() read after hwpoison [%c]\n", p[offset]);
		} else if (strcmp(actype, "mmapwrite") == 0) {
			p = mmap_check((void *)REFADDR, nrpages * PS,
				       PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
			if (p != (void *)REFADDR)
				err("mmap");
			memset(&p[offset], 50, PS);
			DEB("parent mmap() write after hwpoison [%c]\n", p[offset]);
		}
	}
	put_semaphore(sem, &sembuf);

	waitpid(pid, &wait_status, 0);
	if (!WIFEXITED(wait_status))
		err("waitpid");

	delete_semaphore(sem);
	DEB("parent exit %d.\n", ret);
	return ret;
}
int main(int argc, char **argv)
{
	char *p;
	int c;
	int len = HPS;
	int inject = 0;
	int collapse = 0;
	int mremap_flag = 0;
	int pfn_get = 0;
	int split = 0;
	int verbose = 0;
	char buf[256];
	uint64_t pfn_buf[10];

	while ((c = getopt(argc, argv, "m:w:crpsiv")) != -1) {
		switch (c) {
		case 'm':
			len = strtol(optarg, NULL, 10) * HPS;
			break;
		case 'c':
			collapse = 1;
			break;
		case 'r':
			mremap_flag = 1;
			break;
		case 'p':
			pfn_get = 1;
			break;
		case 's':
			split = 1;
			break;
		case 'i':
			inject = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		default:
			usage(argv[0]);
		}
	}

	signal(SIGUSR1, sighandler);

	p = mmap_check((void *)0x7f0000000000, len, PROTECTION,
		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	Dprintf(verbose, "p = %p\n", p);
	madvise(p, len, MADV_HUGEPAGE);

	/* directly allocate thp in page fault. */
	write_bytes(p, len);
	pause();

	if (inject)
		madvise(p, 1, MADV_SOFT_OFFLINE);

	if (split) {
		mlock(p, 4096);
		munlock(p, 4096);
	}

	if (mremap_flag) {
		Dprintf(verbose, "mremap old p is %p!\n", p);
		p = mremap(p, len, len + HPS, 0, MREMAP_FIXED);
		/* p = mremap(p, len, len + HPS, 0, NULL); */
		if (p == (void *)-1)
			err("mremap");
		Dprintf(verbose, "mremap new p is %p!\n", p);
	}

	/* splitted thp will be collapsed again in the next khugepaged scan */
	if (split && collapse) {
		/* split thp */
		write_bytes(p, len);
	}
	pause();

	munmap(p, len);
	return 0;
}