1*f38cb554SJohn Wren Kennedy /*
2*f38cb554SJohn Wren Kennedy  * CDDL HEADER START
3*f38cb554SJohn Wren Kennedy  *
4*f38cb554SJohn Wren Kennedy  * The contents of this file are subject to the terms of the
5*f38cb554SJohn Wren Kennedy  * Common Development and Distribution License (the "License").
6*f38cb554SJohn Wren Kennedy  * You may not use this file except in compliance with the License.
7*f38cb554SJohn Wren Kennedy  *
8*f38cb554SJohn Wren Kennedy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*f38cb554SJohn Wren Kennedy  * or http://www.opensolaris.org/os/licensing.
10*f38cb554SJohn Wren Kennedy  * See the License for the specific language governing permissions
11*f38cb554SJohn Wren Kennedy  * and limitations under the License.
12*f38cb554SJohn Wren Kennedy  *
13*f38cb554SJohn Wren Kennedy  * When distributing Covered Code, include this CDDL HEADER in each
14*f38cb554SJohn Wren Kennedy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*f38cb554SJohn Wren Kennedy  * If applicable, add the following below this CDDL HEADER, with the
16*f38cb554SJohn Wren Kennedy  * fields enclosed by brackets "[]" replaced with your own identifying
17*f38cb554SJohn Wren Kennedy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*f38cb554SJohn Wren Kennedy  *
19*f38cb554SJohn Wren Kennedy  * CDDL HEADER END
20*f38cb554SJohn Wren Kennedy  */
21*f38cb554SJohn Wren Kennedy 
22*f38cb554SJohn Wren Kennedy /*
23*f38cb554SJohn Wren Kennedy  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*f38cb554SJohn Wren Kennedy  * Use is subject to license terms.
25*f38cb554SJohn Wren Kennedy  */
26*f38cb554SJohn Wren Kennedy 
27*f38cb554SJohn Wren Kennedy /*
28*f38cb554SJohn Wren Kennedy  * Copyright (c) 2013 by Delphix. All rights reserved.
29*f38cb554SJohn Wren Kennedy  */
30*f38cb554SJohn Wren Kennedy 
31*f38cb554SJohn Wren Kennedy #include <sys/types.h>
32*f38cb554SJohn Wren Kennedy #include <sys/stat.h>
33*f38cb554SJohn Wren Kennedy #include <fcntl.h>
34*f38cb554SJohn Wren Kennedy #include <thread.h>
35*f38cb554SJohn Wren Kennedy #include <string.h>
36*f38cb554SJohn Wren Kennedy #include <stdio.h>
37*f38cb554SJohn Wren Kennedy #include <unistd.h>
38*f38cb554SJohn Wren Kennedy #include <stdlib.h>
39*f38cb554SJohn Wren Kennedy #include <errno.h>
40*f38cb554SJohn Wren Kennedy 
41*f38cb554SJohn Wren Kennedy /*
42*f38cb554SJohn Wren Kennedy  * The size of the output file, "go.out", should be 80*8192*2 = 1310720
43*f38cb554SJohn Wren Kennedy  *
44*f38cb554SJohn Wren Kennedy  * $ cd /tmp; go; ls -l go.out
45*f38cb554SJohn Wren Kennedy  * done.
46*f38cb554SJohn Wren Kennedy  * -rwxr-xr-x	1 jdm	staff	1310720 Apr 13 19:45 go.out
47*f38cb554SJohn Wren Kennedy  * $ cd /zfs; go; ls -l go.out
48*f38cb554SJohn Wren Kennedy  * done.
49*f38cb554SJohn Wren Kennedy  * -rwxr-xr-x	1 jdm	staff	663552 Apr 13 19:45 go.out
50*f38cb554SJohn Wren Kennedy  *
51*f38cb554SJohn Wren Kennedy  * The file on zfs is short as it does not appear that zfs is making the
52*f38cb554SJohn Wren Kennedy  * implicit seek to EOF and the actual write atomic. From the SUSv3
53*f38cb554SJohn Wren Kennedy  * interface spec, behavior is undefined if concurrent writes are performed
54*f38cb554SJohn Wren Kennedy  * from multi-processes to a single file. So I don't know if this is a
55*f38cb554SJohn Wren Kennedy  * standards violation, but I cannot find any such disclaimers in our
56*f38cb554SJohn Wren Kennedy  * man pages. This issue came up at a customer site in another context, and
57*f38cb554SJohn Wren Kennedy  * the suggestion was to open the file with O_APPEND, but that wouldn't
58*f38cb554SJohn Wren Kennedy  * help with zfs(see 4977529). Also see bug# 5031301.
59*f38cb554SJohn Wren Kennedy  */
60*f38cb554SJohn Wren Kennedy 
61*f38cb554SJohn Wren Kennedy static int outfd = 0;
62*f38cb554SJohn Wren Kennedy 
63*f38cb554SJohn Wren Kennedy static void *
go(void * data)64*f38cb554SJohn Wren Kennedy go(void *data)
65*f38cb554SJohn Wren Kennedy {
66*f38cb554SJohn Wren Kennedy 	int i = 0, n = *(int *)data;
67*f38cb554SJohn Wren Kennedy 	char buf[8192] = {0};
68*f38cb554SJohn Wren Kennedy 	(void) memset(buf, n, sizeof (buf));
69*f38cb554SJohn Wren Kennedy 
70*f38cb554SJohn Wren Kennedy 	for (i = 0; i < 80; i++) {
71*f38cb554SJohn Wren Kennedy 		(void) write(outfd, buf, sizeof (buf));
72*f38cb554SJohn Wren Kennedy 	}
73*f38cb554SJohn Wren Kennedy 	return (NULL);
74*f38cb554SJohn Wren Kennedy }
75*f38cb554SJohn Wren Kennedy 
76*f38cb554SJohn Wren Kennedy static void
usage()77*f38cb554SJohn Wren Kennedy usage()
78*f38cb554SJohn Wren Kennedy {
79*f38cb554SJohn Wren Kennedy 	(void) fprintf(stderr,
80*f38cb554SJohn Wren Kennedy 	    "usage: zfs_threadsappend <file name>\n");
81*f38cb554SJohn Wren Kennedy 	exit(1);
82*f38cb554SJohn Wren Kennedy }
83*f38cb554SJohn Wren Kennedy 
84*f38cb554SJohn Wren Kennedy int
main(int argc,char ** argv)85*f38cb554SJohn Wren Kennedy main(int argc, char **argv)
86*f38cb554SJohn Wren Kennedy {
87*f38cb554SJohn Wren Kennedy 	int	ret = 0;
88*f38cb554SJohn Wren Kennedy 	long	ncpus = 0;
89*f38cb554SJohn Wren Kennedy 	int	i;
90*f38cb554SJohn Wren Kennedy 
91*f38cb554SJohn Wren Kennedy 	if (argc != 2) {
92*f38cb554SJohn Wren Kennedy 		usage();
93*f38cb554SJohn Wren Kennedy 	}
94*f38cb554SJohn Wren Kennedy 
95*f38cb554SJohn Wren Kennedy 	ncpus = sysconf(_SC_NPROCESSORS_ONLN);
96*f38cb554SJohn Wren Kennedy 	if (ncpus < 0) {
97*f38cb554SJohn Wren Kennedy 		(void) fprintf(stderr,
98*f38cb554SJohn Wren Kennedy 		    "Invalid return from sysconf(_SC_NPROCESSORS_ONLN)"
99*f38cb554SJohn Wren Kennedy 		    " : errno (decimal)=%d\n", errno);
100*f38cb554SJohn Wren Kennedy 		exit(1);
101*f38cb554SJohn Wren Kennedy 	}
102*f38cb554SJohn Wren Kennedy 	if (ncpus < 2) {
103*f38cb554SJohn Wren Kennedy 		(void) fprintf(stderr,
104*f38cb554SJohn Wren Kennedy 		    "Must execute this binary on a multi-processor system\n");
105*f38cb554SJohn Wren Kennedy 		exit(1);
106*f38cb554SJohn Wren Kennedy 	}
107*f38cb554SJohn Wren Kennedy 
108*f38cb554SJohn Wren Kennedy 	outfd = open(argv[optind++], O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777);
109*f38cb554SJohn Wren Kennedy 	if (outfd == -1) {
110*f38cb554SJohn Wren Kennedy 		(void) fprintf(stderr,
111*f38cb554SJohn Wren Kennedy 		    "zfs_threadsappend: "
112*f38cb554SJohn Wren Kennedy 		    "open(%s, O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777)"
113*f38cb554SJohn Wren Kennedy 		    " failed\n", argv[optind]);
114*f38cb554SJohn Wren Kennedy 		perror("open");
115*f38cb554SJohn Wren Kennedy 		exit(1);
116*f38cb554SJohn Wren Kennedy 	}
117*f38cb554SJohn Wren Kennedy 
118*f38cb554SJohn Wren Kennedy 	for (i = 0; i < 2; i++) {
119*f38cb554SJohn Wren Kennedy 		ret = thr_create(NULL, 0, go, (void *)&i, 0, NULL);
120*f38cb554SJohn Wren Kennedy 		if (ret != 0) {
121*f38cb554SJohn Wren Kennedy 			(void) fprintf(stderr,
122*f38cb554SJohn Wren Kennedy 			    "zfs_threadsappend: thr_create(#%d) "
123*f38cb554SJohn Wren Kennedy 			    "failed error=%d\n", i+1, ret);
124*f38cb554SJohn Wren Kennedy 			exit(1);
125*f38cb554SJohn Wren Kennedy 		}
126*f38cb554SJohn Wren Kennedy 	}
127*f38cb554SJohn Wren Kennedy 
128*f38cb554SJohn Wren Kennedy 	while (thr_join(0, NULL, NULL) == 0)
129*f38cb554SJohn Wren Kennedy 		continue;
130*f38cb554SJohn Wren Kennedy 
131*f38cb554SJohn Wren Kennedy 	return (0);
132*f38cb554SJohn Wren Kennedy }
133