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 /*
29 * Copyright (c) 2013 by Delphix. All rights reserved.
30 */
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <pthread.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <errno.h>
41
42 /*
43 * The size of the output file, "go.out", should be 80*8192*2 = 1310720
44 *
45 * $ cd /tmp; go; ls -l go.out
46 * done.
47 * -rwxr-xr-x 1 jdm staff 1310720 Apr 13 19:45 go.out
48 * $ cd /zfs; go; ls -l go.out
49 * done.
50 * -rwxr-xr-x 1 jdm staff 663552 Apr 13 19:45 go.out
51 *
52 * The file on zfs is short as it does not appear that zfs is making the
53 * implicit seek to EOF and the actual write atomic. From the SUSv3
54 * interface spec, behavior is undefined if concurrent writes are performed
55 * from multi-processes to a single file. So I don't know if this is a
56 * standards violation, but I cannot find any such disclaimers in our
57 * man pages. This issue came up at a customer site in another context, and
58 * the suggestion was to open the file with O_APPEND, but that wouldn't
59 * help with zfs(see 4977529). Also see bug# 5031301.
60 */
61
62 static int outfd = 0;
63
64 static void *
go(void * data)65 go(void *data)
66 {
67 int ret, i = 0, n = *(int *)data;
68 char buf[8192] = {0};
69 (void) memset(buf, n, sizeof (buf));
70
71 for (i = 0; i < 80; i++) {
72 ret = write(outfd, buf, sizeof (buf));
73 if (ret != sizeof (buf))
74 perror("write");
75 }
76 return (NULL);
77 }
78
79 static void
usage(void)80 usage(void)
81 {
82 (void) fprintf(stderr,
83 "usage: zfs_threadsappend <file name>\n");
84 exit(1);
85 }
86
87 int
main(int argc,char ** argv)88 main(int argc, char **argv)
89 {
90 pthread_t tid;
91 int ret = 0;
92 long ncpus = 0;
93 int i;
94
95 if (argc != 2) {
96 usage();
97 }
98
99 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
100 if (ncpus < 0) {
101 (void) fprintf(stderr,
102 "Invalid return from sysconf(_SC_NPROCESSORS_ONLN)"
103 " : errno (decimal)=%d\n", errno);
104 exit(1);
105 }
106 if (ncpus < 2) {
107 (void) fprintf(stderr,
108 "Must execute this binary on a multi-processor system\n");
109 exit(1);
110 }
111
112 outfd = open(argv[optind++], O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777);
113 if (outfd == -1) {
114 (void) fprintf(stderr,
115 "zfs_threadsappend: "
116 "open(%s, O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777)"
117 " failed\n", argv[optind]);
118 perror("open");
119 exit(1);
120 }
121
122 for (i = 0; i < 2; i++) {
123 ret = pthread_create(&tid, NULL, go, (void *)&i);
124 if (ret != 0) {
125 (void) fprintf(stderr,
126 "zfs_threadsappend: thr_create(#%d) "
127 "failed error=%d\n", i+1, ret);
128 exit(1);
129 }
130 }
131
132 while (pthread_join(tid, NULL) == 0)
133 continue;
134
135 return (0);
136 }
137