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