File Index
Files and directories
Sign in
FILE

map_populate.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/mm/map_populate.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018 Dmitry Safonov, Arista Networks
  4 *
  5 * MAP_POPULATE | MAP_PRIVATE should COW VMA pages.
  6 */
  7
  8#define _GNU_SOURCE
  9#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#include "vm_util.h"
 22
 23#define MMAP_SZ		4096
 24
 25#define BUG_ON(condition, description)						\
 26	do {									\
 27		if (condition)							\
 28			ksft_exit_fail_msg("[FAIL]\t%s:%d\t%s:%s\n",		\
 29					   __func__, __LINE__, (description),	\
 30					   strerror(errno));			\
 31	} while (0)
 32
 33#define TESTS_IN_CHILD 2
 34
 35static void parent_f(int sock, unsigned long *smap, int child)
 36{
 37	int status, ret;
 38
 39	ret = read(sock, &status, sizeof(int));
 40	BUG_ON(ret <= 0, "read(sock)");
 41
 42	*smap = 0x22222BAD;
 43	ret = msync(smap, MMAP_SZ, MS_SYNC);
 44	BUG_ON(ret, "msync()");
 45
 46	ret = write(sock, &status, sizeof(int));
 47	BUG_ON(ret <= 0, "write(sock)");
 48
 49	waitpid(child, &status, 0);
 50
 51	/* The ksft macros don't keep counters between processes */
 52	ksft_cnt.ksft_pass = WEXITSTATUS(status);
 53	ksft_cnt.ksft_fail = TESTS_IN_CHILD - WEXITSTATUS(status);
 54}
 55
 56static int child_f(int sock, unsigned long *smap, int fd)
 57{
 58	int ret, buf = 0;
 59
 60	smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
 61			MAP_PRIVATE | MAP_POPULATE, fd, 0);
 62	BUG_ON(smap == MAP_FAILED, "mmap()");
 63
 64	BUG_ON(*smap != 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");
 65
 66	ret = write(sock, &buf, sizeof(int));
 67	BUG_ON(ret <= 0, "write(sock)");
 68
 69	ret = read(sock, &buf, sizeof(int));
 70	BUG_ON(ret <= 0, "read(sock)");
 71
 72	ksft_test_result(*smap != 0x22222BAD, "MAP_POPULATE COW private page\n");
 73	ksft_test_result(*smap == 0xdeadbabe, "The mapping state\n");
 74
 75	/* The ksft macros don't keep counters between processes */
 76	return ksft_cnt.ksft_pass;
 77}
 78
 79int main(int argc, char **argv)
 80{
 81	int sock[2], child, ret;
 82	FILE *ftmp;
 83	unsigned long *smap;
 84
 85	ksft_print_header();
 86	ksft_set_plan(TESTS_IN_CHILD);
 87
 88	ftmp = tmpfile();
 89	BUG_ON(!ftmp, "tmpfile()");
 90
 91	ret = ftruncate(fileno(ftmp), MMAP_SZ);
 92	if (ret < 0 && errno == ENOENT) {
 93		skip_test_dodgy_fs("ftruncate()");
 94	}
 95	BUG_ON(ret, "ftruncate()");
 96
 97	smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
 98			MAP_SHARED, fileno(ftmp), 0);
 99	BUG_ON(smap == MAP_FAILED, "mmap()");
100
101	*smap = 0xdeadbabe;
102	/* Probably unnecessary, but let it be. */
103	ret = msync(smap, MMAP_SZ, MS_SYNC);
104	BUG_ON(ret, "msync()");
105
106	ret = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sock);
107	BUG_ON(ret, "socketpair()");
108
109	child = fork();
110	BUG_ON(child == -1, "fork()");
111
112	if (child) {
113		ret = close(sock[0]);
114		BUG_ON(ret, "close()");
115
116		parent_f(sock[1], smap, child);
117
118		ksft_finished();
119	}
120
121	ret = close(sock[1]);
122	BUG_ON(ret, "close()");
123
124	return child_f(sock[0], smap, fileno(ftmp));
125}
~/ Read-only file preview.