1#!/bin/sh 2 3# 4# Copyright (c) 2016 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 30 31. ../default.cfg 32 33# NFS test with deep directories. 34 35# Only issue seen is: 36# nfsdepth: mkdir(d93) l35: Permission denied 37 38[ -z "$nfs_export" ] && exit 0 39ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || 40 exit 0 41 42odir=`pwd` 43cd /tmp 44sed '1,/^EOF/d' < $odir/$0 > nfsdepth.c 45mycc -o nfsdepth -Wall -Wextra -g nfsdepth.c || exit 1 46rm -f nfsdepth.c 47cd $odir 48 49mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint 50mount -t nfs -o tcp -o rw -o soft $nfs_export $mntpoint 51 52work=$mntpoint/nfsdepth.`jot -rc 8 a z | tr -d '\n'`.dir 53mkdir -p $work 54chmod 777 $work 55 56su $testuser -c "cd $work; /tmp/nfsdepth" 57s=$? 58if [ $s -eq 0 ]; then 59 su $testuser -c "rm -rf $work 2>/dev/null" 60 rm -rf $work 61else 62 find $work -ls 63fi 64 65umount $mntpoint > /dev/null 2>&1 66while mount | grep "$mntpoint" | grep -q nfs; do 67 umount $mntpoint > /dev/null 2>&1 68done 69 70rm -f /tmp/nfsdepth 71exit $s 72 73EOF 74#include <sys/param.h> 75#include <sys/stat.h> 76#include <sys/wait.h> 77 78#include <err.h> 79#include <errno.h> 80#include <signal.h> 81#include <stdio.h> 82#include <stdlib.h> 83#include <unistd.h> 84 85static unsigned long actual, size; 86volatile int done_testing; 87int fail; 88 89#define DEPTH 200 90#define PARALLEL 8 91#define RUNTIME 180 92 93void 94handler(int s __unused) 95{ 96 done_testing = 1; 97} 98 99void 100mkDir(char *path, int level) { 101 int n, r; 102 char newPath[MAXPATHLEN + 1]; 103 104 n = 0; 105 do { 106 r = mkdir(path, 0770); 107 if (r == -1 && errno == EACCES && n < 10) { 108 warn("mkdir(%s) l%d", path, __LINE__); 109 n++; 110 errno = EAGAIN; 111 usleep(10000); 112 } 113 if (r == -1 && errno == EINTR) 114 (void)rmdir(path); 115 } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 116 117 if (r == -1) { 118 warn("mkdir(%s), pid %d, l%d", path, getpid(), __LINE__); 119 fail++; 120 } else { 121 actual++; 122 do { 123 r = chdir (path); 124 if (r == -1 && errno == EACCES && n < 10) { 125 warn("chdir(%s) .%d", path, __LINE__); 126 n++; 127 errno = EAGAIN; 128 usleep(10000); 129 } 130 } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 131 if (r == -1) 132 err(1, "chdir(%s), pid %d, l%d", path, getpid(), __LINE__); 133 } 134 135 if (done_testing == 0 && fail == 0 && level < (int)size) { 136 sprintf(newPath,"d%d", level + 1); 137 mkDir(newPath, level + 1); 138 } 139} 140 141void 142rmDir(char *path, int level) { 143 int n, r; 144 char newPath[MAXPATHLEN + 1]; 145 146 if (level == 0) 147 return; 148 149 if (level < (int)actual) { 150 sprintf(newPath,"d%d", level+1); 151 rmDir(newPath, level+1); 152 } 153 n = 0; 154 do { 155 r = chdir (".."); 156 if (r == -1 && errno == EACCES && n < 10) { 157 warn("chdir(%s) l%d", path, __LINE__); 158 n++; 159 errno = EAGAIN; 160 usleep(10000); 161 } 162 } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 163 if (r == -1) 164 err(1, "chdir(%s), pid %d, l%d", "..", getpid(), __LINE__); 165 n = 0; 166 do { 167 r = rmdir(path); 168 if (r == -1 && errno == EACCES && n < 10) { 169 warn("rmdir(%s) l%d", path, __LINE__); 170 n++; 171 errno = EAGAIN; 172 usleep(10000); 173 } 174 } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 175 if (r == -1) 176 err(1, "rmdir(%s), pid %d, l%d", path, getpid(), __LINE__); 177} 178 179int 180test2(void) 181{ 182 char path[MAXPATHLEN + 1]; 183 184 fail = actual = 0; 185 umask(0); 186 sprintf(path,"p%05d.d%d", getpid(), 1); 187 mkDir(path, 1); 188 rmDir(path, 1); 189 190 _exit (fail); 191} 192 193int 194test(void) 195{ 196 pid_t pid; 197 time_t start; 198 int status; 199 200 size = (arc4random() % DEPTH) + 1; 201 202 signal(SIGHUP, handler); 203 start = time(NULL); 204 while (time(NULL) - start < RUNTIME && fail == 0) { 205 if ((pid = fork()) == 0) { 206 done_testing = 0; 207 test2(); 208 } 209 210 status = 0; 211 while (wait4(pid, &status, WNOHANG, NULL) != pid) { 212 if (kill(pid, SIGHUP) == -1) 213 err(1, "kill(%d)", pid); 214 usleep(100000 + (arc4random() % 10000)); 215 } 216 if (status != 0) 217 fail++; 218 } 219 220 _exit (status != 0); 221} 222 223int 224main(void) 225{ 226 int e, i, pids[PARALLEL], status; 227 228 e = 0; 229 for (i = 0; i < PARALLEL; i++) { 230 if ((pids[i] = fork()) == 0) 231 test(); 232 } 233 for (i = 0; i < PARALLEL; i++) { 234 waitpid(pids[i], &status, 0); 235 e += status == 0 ? 0 : 1; 236 } 237 238 return (e); 239} 240