root/tools/testing/selftests/vm/map_populate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parent_f
  2. child_f
  3. main

   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 
  20 #ifndef MMAP_SZ
  21 #define MMAP_SZ         4096
  22 #endif
  23 
  24 #define BUG_ON(condition, description)                                  \
  25         do {                                                            \
  26                 if (condition) {                                        \
  27                         fprintf(stderr, "[FAIL]\t%s:%d\t%s:%s\n", __func__, \
  28                                 __LINE__, (description), strerror(errno)); \
  29                         exit(1);                                        \
  30                 }                                                       \
  31         } while (0)
  32 
  33 static int 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         BUG_ON(!WIFEXITED(status), "child in unexpected state");
  49 
  50         return WEXITSTATUS(status);
  51 }
  52 
  53 static int child_f(int sock, unsigned long *smap, int fd)
  54 {
  55         int ret, buf = 0;
  56 
  57         smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
  58                         MAP_PRIVATE | MAP_POPULATE, fd, 0);
  59         BUG_ON(smap == MAP_FAILED, "mmap()");
  60 
  61         BUG_ON(*smap != 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");
  62 
  63         ret = write(sock, &buf, sizeof(int));
  64         BUG_ON(ret <= 0, "write(sock)");
  65 
  66         ret = read(sock, &buf, sizeof(int));
  67         BUG_ON(ret <= 0, "read(sock)");
  68 
  69         BUG_ON(*smap == 0x22222BAD, "MAP_POPULATE didn't COW private page");
  70         BUG_ON(*smap != 0xdeadbabe, "mapping was corrupted");
  71 
  72         return 0;
  73 }
  74 
  75 int main(int argc, char **argv)
  76 {
  77         int sock[2], child, ret;
  78         FILE *ftmp;
  79         unsigned long *smap;
  80 
  81         ftmp = tmpfile();
  82         BUG_ON(ftmp == 0, "tmpfile()");
  83 
  84         ret = ftruncate(fileno(ftmp), MMAP_SZ);
  85         BUG_ON(ret, "ftruncate()");
  86 
  87         smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
  88                         MAP_SHARED, fileno(ftmp), 0);
  89         BUG_ON(smap == MAP_FAILED, "mmap()");
  90 
  91         *smap = 0xdeadbabe;
  92         /* Probably unnecessary, but let it be. */
  93         ret = msync(smap, MMAP_SZ, MS_SYNC);
  94         BUG_ON(ret, "msync()");
  95 
  96         ret = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sock);
  97         BUG_ON(ret, "socketpair()");
  98 
  99         child = fork();
 100         BUG_ON(child == -1, "fork()");
 101 
 102         if (child) {
 103                 ret = close(sock[0]);
 104                 BUG_ON(ret, "close()");
 105 
 106                 return parent_f(sock[1], smap, child);
 107         }
 108 
 109         ret = close(sock[1]);
 110         BUG_ON(ret, "close()");
 111 
 112         return child_f(sock[0], smap, fileno(ftmp));
 113 }

/* [<][>][^][v][top][bottom][index][help] */