1716fd348SMartin Matuska /* 2716fd348SMartin Matuska * CDDL HEADER START 3716fd348SMartin Matuska * 4716fd348SMartin Matuska * The contents of this file are subject to the terms of the 5716fd348SMartin Matuska * Common Development and Distribution License (the "License"). 6716fd348SMartin Matuska * You may not use this file except in compliance with the License. 7716fd348SMartin Matuska * 8716fd348SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10716fd348SMartin Matuska * See the License for the specific language governing permissions 11716fd348SMartin Matuska * and limitations under the License. 12716fd348SMartin Matuska * 13716fd348SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14716fd348SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15716fd348SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16716fd348SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17716fd348SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18716fd348SMartin Matuska * 19716fd348SMartin Matuska * CDDL HEADER END 20716fd348SMartin Matuska */ 21716fd348SMartin Matuska 22716fd348SMartin Matuska /* 23716fd348SMartin Matuska * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24716fd348SMartin Matuska * Use is subject to license terms. 25716fd348SMartin Matuska */ 26716fd348SMartin Matuska 27716fd348SMartin Matuska /* 28716fd348SMartin Matuska * Copyright (c) 2013 by Delphix. All rights reserved. 29716fd348SMartin Matuska */ 30716fd348SMartin Matuska 31716fd348SMartin Matuska #include <sys/types.h> 32716fd348SMartin Matuska #include <sys/stat.h> 33716fd348SMartin Matuska #include <fcntl.h> 34716fd348SMartin Matuska #include <pthread.h> 35716fd348SMartin Matuska #include <string.h> 36716fd348SMartin Matuska #include <stdio.h> 37716fd348SMartin Matuska #include <unistd.h> 38716fd348SMartin Matuska #include <stdlib.h> 39716fd348SMartin Matuska #include <errno.h> 40716fd348SMartin Matuska 41716fd348SMartin Matuska /* 42716fd348SMartin Matuska * The size of the output file, "go.out", should be 80*8192*2 = 1310720 43716fd348SMartin Matuska * 44716fd348SMartin Matuska * $ cd /tmp; go; ls -l go.out 45716fd348SMartin Matuska * done. 46716fd348SMartin Matuska * -rwxr-xr-x 1 jdm staff 1310720 Apr 13 19:45 go.out 47716fd348SMartin Matuska * $ cd /zfs; go; ls -l go.out 48716fd348SMartin Matuska * done. 49716fd348SMartin Matuska * -rwxr-xr-x 1 jdm staff 663552 Apr 13 19:45 go.out 50716fd348SMartin Matuska * 51716fd348SMartin Matuska * The file on zfs is short as it does not appear that zfs is making the 52716fd348SMartin Matuska * implicit seek to EOF and the actual write atomic. From the SUSv3 53716fd348SMartin Matuska * interface spec, behavior is undefined if concurrent writes are performed 54716fd348SMartin Matuska * from multi-processes to a single file. So I don't know if this is a 55716fd348SMartin Matuska * standards violation, but I cannot find any such disclaimers in our 56716fd348SMartin Matuska * man pages. This issue came up at a customer site in another context, and 57716fd348SMartin Matuska * the suggestion was to open the file with O_APPEND, but that wouldn't 58716fd348SMartin Matuska * help with zfs(see 4977529). Also see bug# 5031301. 59716fd348SMartin Matuska */ 60716fd348SMartin Matuska 61716fd348SMartin Matuska static int outfd = 0; 62716fd348SMartin Matuska 63716fd348SMartin Matuska static void * 64716fd348SMartin Matuska go(void *data) 65716fd348SMartin Matuska { 66716fd348SMartin Matuska int ret, i = 0, n = *(int *)data; 67716fd348SMartin Matuska char buf[8192] = {0}; 68716fd348SMartin Matuska (void) memset(buf, n, sizeof (buf)); 69716fd348SMartin Matuska 70716fd348SMartin Matuska for (i = 0; i < 80; i++) { 71716fd348SMartin Matuska ret = write(outfd, buf, sizeof (buf)); 72716fd348SMartin Matuska if (ret != sizeof (buf)) 73716fd348SMartin Matuska perror("write"); 74716fd348SMartin Matuska } 75716fd348SMartin Matuska return (NULL); 76716fd348SMartin Matuska } 77716fd348SMartin Matuska 78716fd348SMartin Matuska static void 79716fd348SMartin Matuska usage(void) 80716fd348SMartin Matuska { 81716fd348SMartin Matuska (void) fprintf(stderr, 82716fd348SMartin Matuska "usage: zfs_threadsappend <file name>\n"); 83716fd348SMartin Matuska exit(1); 84716fd348SMartin Matuska } 85716fd348SMartin Matuska 86716fd348SMartin Matuska int 87716fd348SMartin Matuska main(int argc, char **argv) 88716fd348SMartin Matuska { 89716fd348SMartin Matuska pthread_t tid; 90716fd348SMartin Matuska int ret = 0; 91716fd348SMartin Matuska long ncpus = 0; 92716fd348SMartin Matuska int i; 93716fd348SMartin Matuska 94716fd348SMartin Matuska if (argc != 2) { 95716fd348SMartin Matuska usage(); 96716fd348SMartin Matuska } 97716fd348SMartin Matuska 98716fd348SMartin Matuska ncpus = sysconf(_SC_NPROCESSORS_ONLN); 99716fd348SMartin Matuska if (ncpus < 0) { 100716fd348SMartin Matuska (void) fprintf(stderr, 101716fd348SMartin Matuska "Invalid return from sysconf(_SC_NPROCESSORS_ONLN)" 102716fd348SMartin Matuska " : errno (decimal)=%d\n", errno); 103716fd348SMartin Matuska exit(1); 104716fd348SMartin Matuska } 105716fd348SMartin Matuska if (ncpus < 2) { 106716fd348SMartin Matuska (void) fprintf(stderr, 107716fd348SMartin Matuska "Must execute this binary on a multi-processor system\n"); 108716fd348SMartin Matuska exit(1); 109716fd348SMartin Matuska } 110716fd348SMartin Matuska 111716fd348SMartin Matuska outfd = open(argv[optind++], O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777); 112716fd348SMartin Matuska if (outfd == -1) { 113716fd348SMartin Matuska (void) fprintf(stderr, 114716fd348SMartin Matuska "zfs_threadsappend: " 115716fd348SMartin Matuska "open(%s, O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777)" 116716fd348SMartin Matuska " failed\n", argv[optind]); 117716fd348SMartin Matuska perror("open"); 118716fd348SMartin Matuska exit(1); 119716fd348SMartin Matuska } 120716fd348SMartin Matuska 121716fd348SMartin Matuska for (i = 0; i < 2; i++) { 122716fd348SMartin Matuska ret = pthread_create(&tid, NULL, go, (void *)&i); 123716fd348SMartin Matuska if (ret != 0) { 124716fd348SMartin Matuska (void) fprintf(stderr, 125716fd348SMartin Matuska "zfs_threadsappend: thr_create(#%d) " 126716fd348SMartin Matuska "failed error=%d\n", i+1, ret); 127716fd348SMartin Matuska exit(1); 128716fd348SMartin Matuska } 129716fd348SMartin Matuska } 130716fd348SMartin Matuska 131716fd348SMartin Matuska while (pthread_join(tid, NULL) == 0) 132716fd348SMartin Matuska continue; 133716fd348SMartin Matuska 134716fd348SMartin Matuska return (0); 135716fd348SMartin Matuska } 136