1 // SPDX-License-Identifier: GPL-2.0-or-newer
3 * Copyright (c) 2019 Oracle.
6 * Create writable mappings to multiple files and write them all to test
7 * concurrent mmap writes to the same shared blocks.
10 #include <sys/types.h>
34 unsigned int nr_files;
40 printf("Usage: %s len offset file [offset file]...\n", argv[0]);
44 /* Parse mwrite length. */
46 length = strtoul(argv[1], &endptr, 0);
51 if (*endptr != '\0') {
52 fprintf(stderr, "%s: not a proper file length?\n", argv[2]);
56 /* Allocate file info */
57 nr_files = (argc - 2) / 2;
59 fi = calloc(nr_files, sizeof(struct file_info));
61 perror("calloc file info");
71 for (i = 0; i < nr_files; i++) {
73 char *offset = argv[((i + 1) * 2)];
74 char *fname = argv[((i + 1) * 2) + 1];
76 /* Open file, create mapping for the range we want. */
77 fi[i].fd = open(fname, O_RDWR);
83 /* Parse mwrite offset */
85 fi[i].file_offset = strtoul(offset, &endptr, 0);
91 /* Remember file size */
92 ret = fstat(fi[i].fd, &statbuf);
97 fi[i].file_length = statbuf.st_size;
99 if (fi[i].file_offset + length > fi[i].file_length) {
100 fprintf(stderr, "%s: file must be %llu bytes\n",
102 (unsigned long long)fi[i].file_offset + length);
106 /* Create the mapping */
107 fi[i].mapping = mmap(NULL, fi[i].file_length,
108 PROT_READ | PROT_WRITE, MAP_SHARED,
110 if (fi[i].mapping == MAP_FAILED) {
116 * Make sure the mapping for region we're going to write is
117 * already populated in the page cache.
119 memcpy(buf, fi[i].mapping + fi[i].file_offset, length);
122 /* Dirty the same region in each file to test COW. */
123 for (i = 0; i < nr_files; i++) {
124 memset(buf, 0x62 + i, length);
125 memcpy(fi[i].mapping + fi[i].file_offset, buf, length);
127 for (i = 0; i < nr_files; i++) {
128 ret = msync(fi[i].mapping, fi[i].file_offset + length, MS_SYNC);
135 /* Close everything. */
136 for (i = 0; i < nr_files; i++) {
137 ret = munmap(fi[i].mapping, fi[i].file_length);
143 ret = close(fi[i].fd);
150 /* Free everything. */