1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018 Dmitry Safonov, Arista Networks
5 * MAP_POPULATE | MAP_PRIVATE should COW VMA pages.
12 #include <sys/socket.h>
13 #include <sys/types.h>
24 #define BUG_ON(condition, description) \
27 fprintf(stderr, "[FAIL]\t%s:%d\t%s:%s\n", __func__, \
28 __LINE__, (description), strerror(errno)); \
33 static int parent_f(int sock
, unsigned long *smap
, int child
)
37 ret
= read(sock
, &status
, sizeof(int));
38 BUG_ON(ret
<= 0, "read(sock)");
41 ret
= msync(smap
, MMAP_SZ
, MS_SYNC
);
42 BUG_ON(ret
, "msync()");
44 ret
= write(sock
, &status
, sizeof(int));
45 BUG_ON(ret
<= 0, "write(sock)");
47 waitpid(child
, &status
, 0);
48 BUG_ON(!WIFEXITED(status
), "child in unexpected state");
50 return WEXITSTATUS(status
);
53 static int child_f(int sock
, unsigned long *smap
, int fd
)
57 smap
= mmap(0, MMAP_SZ
, PROT_READ
| PROT_WRITE
,
58 MAP_PRIVATE
| MAP_POPULATE
, fd
, 0);
59 BUG_ON(smap
== MAP_FAILED
, "mmap()");
61 BUG_ON(*smap
!= 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");
63 ret
= write(sock
, &buf
, sizeof(int));
64 BUG_ON(ret
<= 0, "write(sock)");
66 ret
= read(sock
, &buf
, sizeof(int));
67 BUG_ON(ret
<= 0, "read(sock)");
69 BUG_ON(*smap
== 0x22222BAD, "MAP_POPULATE didn't COW private page");
70 BUG_ON(*smap
!= 0xdeadbabe, "mapping was corrupted");
75 int main(int argc
, char **argv
)
77 int sock
[2], child
, ret
;
82 BUG_ON(ftmp
== 0, "tmpfile()");
84 ret
= ftruncate(fileno(ftmp
), MMAP_SZ
);
85 BUG_ON(ret
, "ftruncate()");
87 smap
= mmap(0, MMAP_SZ
, PROT_READ
| PROT_WRITE
,
88 MAP_SHARED
, fileno(ftmp
), 0);
89 BUG_ON(smap
== MAP_FAILED
, "mmap()");
92 /* Probably unnecessary, but let it be. */
93 ret
= msync(smap
, MMAP_SZ
, MS_SYNC
);
94 BUG_ON(ret
, "msync()");
96 ret
= socketpair(PF_LOCAL
, SOCK_SEQPACKET
, 0, sock
);
97 BUG_ON(ret
, "socketpair()");
100 BUG_ON(child
== -1, "fork()");
103 ret
= close(sock
[0]);
104 BUG_ON(ret
, "close()");
106 return parent_f(sock
[1], smap
, child
);
109 ret
= close(sock
[1]);
110 BUG_ON(ret
, "close()");
112 return child_f(sock
[0], smap
, fileno(ftmp
));