1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2012 by Delphix. All rights reserved. 29 */ 30 31 /* 32 * -------------------------------------------------------------------- 33 * The purpose of this test is to see if the bug reported (#4723351) for 34 * UFS exists when using a ZFS file system. 35 * -------------------------------------------------------------------- 36 * 37 */ 38 #define _REENTRANT 1 39 #include <stdio.h> 40 #include <fcntl.h> 41 #include <pthread.h> 42 #include <thread.h> 43 #include <errno.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 #include <strings.h> 49 50 static const int TRUE = 1; 51 static char *filebase; 52 53 static int 54 pickidx() 55 { 56 return (random() % 1000); 57 } 58 59 /* ARGSUSED */ 60 static void * 61 mover(void *a) 62 { 63 char buf[256]; 64 int idx, len, ret; 65 66 len = strlen(filebase) + 5; 67 68 while (TRUE) { 69 idx = pickidx(); 70 (void) snprintf(buf, len, "%s.%03d", filebase, idx); 71 ret = rename(filebase, buf); 72 if (ret < 0 && errno != ENOENT) 73 (void) perror("renaming file"); 74 } 75 76 return (NULL); 77 } 78 79 /* ARGSUSED */ 80 static void * 81 cleaner(void *a) 82 { 83 char buf[256]; 84 int idx, len, ret; 85 86 len = strlen(filebase) + 5; 87 88 while (TRUE) { 89 idx = pickidx(); 90 (void) snprintf(buf, len, "%s.%03d", filebase, idx); 91 ret = remove(buf); 92 if (ret < 0 && errno != ENOENT) 93 (void) perror("removing file"); 94 } 95 96 return (NULL); 97 } 98 99 static void * 100 writer(void *a) 101 { 102 int *fd = (int *)a; 103 104 while (TRUE) { 105 (void) close (*fd); 106 *fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644); 107 if (*fd < 0) 108 perror("refreshing file"); 109 (void) write(*fd, "test\n", 5); 110 } 111 112 return (NULL); 113 } 114 115 int 116 main(int argc, char **argv) 117 { 118 int fd; 119 pthread_t tid; 120 121 if (argc == 1) { 122 (void) printf("Usage: %s <filebase>\n", argv[0]); 123 exit(-1); 124 } 125 126 filebase = argv[1]; 127 fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644); 128 if (fd < 0) { 129 perror("creating test file"); 130 exit(-1); 131 } 132 133 (void) thr_setconcurrency(4); /* 3 threads + main */ 134 (void) pthread_create(&tid, NULL, mover, NULL); 135 (void) pthread_create(&tid, NULL, cleaner, NULL); 136 (void) pthread_create(&tid, NULL, writer, (void *) &fd); 137 138 while (TRUE) { 139 int ret; 140 struct stat st; 141 142 ret = stat(filebase, &st); 143 if (ret == 0 && (st.st_nlink > 2 || st.st_nlink < 1)) { 144 (void) printf("st.st_nlink = %d, exiting\n", \ 145 (int)st.st_nlink); 146 exit(0); 147 } 148 (void) sleep(1); 149 } 150 151 return (0); 152 } 153