brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 5c8a538 Raw
121 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Dmitry Safonov, Arista Networks4 *5 * MAP_POPULATE | MAP_PRIVATE should COW VMA pages.6 */7 8#define _GNU_SOURCE9#include <errno.h>10#include <fcntl.h>11#include <sys/mman.h>12#include <sys/socket.h>13#include <sys/types.h>14#include <sys/wait.h>15#include <stdio.h>16#include <stdlib.h>17#include <string.h>18#include <unistd.h>19#include "../kselftest.h"20 21#define MMAP_SZ		409622 23#define BUG_ON(condition, description)						\24	do {									\25		if (condition)							\26			ksft_exit_fail_msg("[FAIL]\t%s:%d\t%s:%s\n",		\27					   __func__, __LINE__, (description),	\28					   strerror(errno));			\29	} while (0)30 31#define TESTS_IN_CHILD 232 33static void parent_f(int sock, unsigned long *smap, int child)34{35	int status, ret;36 37	ret = read(sock, &status, sizeof(int));38	BUG_ON(ret <= 0, "read(sock)");39 40	*smap = 0x22222BAD;41	ret = msync(smap, MMAP_SZ, MS_SYNC);42	BUG_ON(ret, "msync()");43 44	ret = write(sock, &status, sizeof(int));45	BUG_ON(ret <= 0, "write(sock)");46 47	waitpid(child, &status, 0);48 49	/* The ksft macros don't keep counters between processes */50	ksft_cnt.ksft_pass = WEXITSTATUS(status);51	ksft_cnt.ksft_fail = TESTS_IN_CHILD - WEXITSTATUS(status);52}53 54static int child_f(int sock, unsigned long *smap, int fd)55{56	int ret, buf = 0;57 58	smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,59			MAP_PRIVATE | MAP_POPULATE, fd, 0);60	BUG_ON(smap == MAP_FAILED, "mmap()");61 62	BUG_ON(*smap != 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");63 64	ret = write(sock, &buf, sizeof(int));65	BUG_ON(ret <= 0, "write(sock)");66 67	ret = read(sock, &buf, sizeof(int));68	BUG_ON(ret <= 0, "read(sock)");69 70	ksft_test_result(*smap != 0x22222BAD, "MAP_POPULATE COW private page\n");71	ksft_test_result(*smap == 0xdeadbabe, "The mapping state\n");72 73	/* The ksft macros don't keep counters between processes */74	return ksft_cnt.ksft_pass;75}76 77int main(int argc, char **argv)78{79	int sock[2], child, ret;80	FILE *ftmp;81	unsigned long *smap;82 83	ksft_print_header();84	ksft_set_plan(TESTS_IN_CHILD);85 86	ftmp = tmpfile();87	BUG_ON(!ftmp, "tmpfile()");88 89	ret = ftruncate(fileno(ftmp), MMAP_SZ);90	BUG_ON(ret, "ftruncate()");91 92	smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,93			MAP_SHARED, fileno(ftmp), 0);94	BUG_ON(smap == MAP_FAILED, "mmap()");95 96	*smap = 0xdeadbabe;97	/* Probably unnecessary, but let it be. */98	ret = msync(smap, MMAP_SZ, MS_SYNC);99	BUG_ON(ret, "msync()");100 101	ret = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sock);102	BUG_ON(ret, "socketpair()");103 104	child = fork();105	BUG_ON(child == -1, "fork()");106 107	if (child) {108		ret = close(sock[0]);109		BUG_ON(ret, "close()");110 111		parent_f(sock[1], smap, child);112 113		ksft_finished();114	}115 116	ret = close(sock[1]);117	BUG_ON(ret, "close()");118 119	return child_f(sock[0], smap, fileno(ftmp));120}121