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