xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
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