Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c
48529 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
23
/*
24
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25
* Use is subject to license terms.
26
*/
27
28
#include <unistd.h>
29
#include <fcntl.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <sys/mman.h>
34
#include <pthread.h>
35
#include <errno.h>
36
#include <err.h>
37
38
/*
39
* --------------------------------------------------------------------
40
* Bug Issue Id: #7512
41
* The bug time sequence:
42
* 1. context #1, zfs_write assign a txg "n".
43
* 2. In the same process, context #2, mmap page fault (which means the mm_sem
44
* is hold) occurred, zfs_dirty_inode open a txg failed, and wait previous
45
* txg "n" completed.
46
* 3. context #1 call zfs_uiomove to write, however page fault is occurred in
47
* zfs_uiomove, which means it needs mm_sem, but mm_sem is hold by
48
* context #2, so it stuck and can't complete, then txg "n" will not
49
* complete.
50
*
51
* So context #1 and context #2 trap into the "dead lock".
52
* --------------------------------------------------------------------
53
*/
54
55
#define NORMAL_WRITE_TH_NUM 2
56
#define MAX_WRITE_BYTES 262144000
57
58
static void *
59
normal_writer(void *filename)
60
{
61
char *file_path = filename;
62
int fd;
63
ssize_t write_num = 0;
64
int page_size = getpagesize();
65
66
fd = open(file_path, O_RDWR | O_CREAT, 0777);
67
if (fd == -1) {
68
err(1, "failed to open %s", file_path);
69
}
70
71
char buf = 'z';
72
off_t bytes_written = 0;
73
74
while (bytes_written < MAX_WRITE_BYTES) {
75
write_num = write(fd, &buf, 1);
76
if (write_num == 0) {
77
err(1, "write failed!");
78
break;
79
}
80
if ((bytes_written = lseek(fd, page_size, SEEK_CUR)) == -1) {
81
err(1, "lseek failed on %s: %s", file_path,
82
strerror(errno));
83
break;
84
}
85
}
86
87
if (close(fd) != 0)
88
err(1, "failed to close file");
89
90
return (NULL);
91
}
92
93
static void *
94
map_writer(void *filename)
95
{
96
int fd;
97
int ret = 0;
98
char *buf = NULL;
99
int page_size = getpagesize();
100
char *file_path = filename;
101
102
while (1) {
103
fd = open(file_path, O_RDWR);
104
if (fd == -1) {
105
if (errno == ENOENT) {
106
fd = open(file_path, O_RDWR | O_CREAT, 0777);
107
if (fd == -1) {
108
err(1, "open file failed");
109
}
110
ret = ftruncate(fd, page_size);
111
if (ret == -1) {
112
err(1, "truncate file failed");
113
}
114
} else {
115
err(1, "open file failed");
116
}
117
}
118
119
if ((buf = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
120
MAP_SHARED, fd, 0)) == MAP_FAILED) {
121
err(1, "map file failed");
122
}
123
124
if (fd != -1)
125
close(fd);
126
127
char s[10] = {0, };
128
memcpy(buf, s, 10);
129
ret = munmap(buf, page_size);
130
if (ret != 0) {
131
err(1, "unmap file failed");
132
}
133
}
134
}
135
136
int
137
main(int argc, char **argv)
138
{
139
pthread_t map_write_tid;
140
pthread_t normal_write_tid[NORMAL_WRITE_TH_NUM];
141
int i = 0;
142
143
if (argc != 3) {
144
(void) printf("usage: %s <normal write file name> "
145
"<map write file name>\n", argv[0]);
146
exit(1);
147
}
148
149
for (i = 0; i < NORMAL_WRITE_TH_NUM; i++) {
150
if (pthread_create(&normal_write_tid[i], NULL, normal_writer,
151
argv[1])) {
152
err(1, "pthread_create normal_writer failed.");
153
}
154
}
155
156
if (pthread_create(&map_write_tid, NULL, map_writer, argv[2])) {
157
err(1, "pthread_create map_writer failed.");
158
}
159
160
pthread_join(map_write_tid, NULL);
161
return (0);
162
}
163
164