1#!/bin/sh 2 3# 4# Copyright (c) 2016 Dell EMC Isilon 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# Demonstrate "wrong handling for suspend". 30# https://www.mail-archive.com/freebsd-current@freebsd.org/msg166333.html 31 32# panic: Failed to register NFS lock locally - error=11 33# https://people.freebsd.org/~pho/stress/log/kostik897.txt 34# Fixed in r302013. 35 36[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 37pgrep -q lockd || { echo "lockd not running."; exit 1; } 38 39. ../default.cfg 40 41[ -z "$nfs_export" ] && exit 0 42ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || 43 exit 0 44 45here=`pwd` 46cd /tmp 47sed '1,/^EOF/d' < $here/$0 > nfs15lockd.c 48mycc -o nfs15lockd -Wall -Wextra -O2 -g nfs15lockd.c -lpthread || exit 1 49rm -f nfs15lockd.c 50cd $here 51 52mount | grep "on $mntpoint " | grep nfs > /dev/null && umount $mntpoint 53 54[ $# -ne 0 ] && 55 # Problem only seen with lockd 56 { echo "Not using lockd"; debug="-o nolockd"; } 57mount -t nfs -o tcp -o retrycnt=3 -o soft -o rw $debug \ 58 $nfs_export $mntpoint 59sleep 2 60 61s=0 62lockf -t 10 $mntpoint/$$.lock sleep 2 > /tmp/$$.log 2>&1 63if grep -q "No locks available" /tmp/$$.log; then 64 echo "Is lockd running on the remote host?" 65 rm /tmp/$$.log 66 s=1 67fi 68 69wd=$mntpoint/nfs15lockd-`jot -rc 8 a z | tr -d '\n'`.dir 70rm -rf $wd 71mkdir $wd 72 73echo "Expect: nfs15lockd exited on signal 6 (core dumped)" 74(cd $wd; /tmp/nfs15lockd) & 75start=`date '+%s'` 76while [ $((`date '+%s'` - start)) -lt 600 ]; do 77 pgrep -q nfs15lockd || break 78 sleep 2 79done 80if pgrep -q nfs15lockd; then 81 s=2 82 echo "Thread suspension issue:" 83 ps -lx | grep -v grep | grep nfs15lockd | grep "T+" | \ 84 awk '{print $2}' | while read pid; do 85 ps -lp$pid 86 procstat -k $pid 87 kill -9 $pid 88 done 89 pkill nfs15lockd 90fi 91wait 92rm -rf $wd 93 94n=0 95while mount | grep "on $mntpoint " | grep -q nfs; do 96 umount $mntpoint && break 97 n=$((n + 1)) 98 if [ $n -gt 60 ]; then 99 fstat -mf $mntpoint 100 s=3 101 break 102 fi 103 sleep 2 104done 2>&1 | awk '!seen[$0]++' 105mount | grep -q "on $mntpoint " && umount -f $mntpoint 106 107rm -f /tmp/nfs15lockd nfs15lockd.core 108exit $s 109EOF 110#include <sys/stat.h> 111#include <sys/param.h> 112#include <sys/mman.h> 113#include <sys/wait.h> 114 115#include <machine/atomic.h> 116 117#include <err.h> 118#include <errno.h> 119#include <fcntl.h> 120#include <pthread.h> 121#include <signal.h> 122#include <stdio.h> 123#include <stdlib.h> 124#include <string.h> 125#include <unistd.h> 126 127#define PARALLEL 4 128#define RUNTIME 300 129#define SYNC 0 130 131volatile u_int *share; 132 133static void * 134t1(void *data __unused) 135{ 136 atomic_add_int(&share[SYNC], 1); 137 usleep(arc4random() % 8000); 138 raise(SIGABRT); 139 140 return (NULL); 141} 142 143static void * 144t2(void *data __unused) 145{ 146 int fd, i, r; 147 char file[80]; 148 149 for (i = 0; i < 100; i++) { 150 atomic_add_int(&share[SYNC], 1); 151 snprintf(file, sizeof(file), "file.%06d", i); 152 if ((fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 153 DEFFILEMODE)) == -1) 154 err(1, "open(%s)", file); 155 do { 156 r = lockf(fd, F_LOCK, 0); 157 } while (r == -1 && (errno == EDEADLK || errno == EINTR)); 158 if (r == -1) 159 err(1, "lockf(%s, F_LOCK)", file); 160 write(fd, "x", 1); 161 usleep(arc4random() % 1000); 162 if (lseek(fd, 0, SEEK_SET) == -1) 163 err(1, "lseek"); 164 if (lockf(fd, F_ULOCK, 0) == -1) 165 err(1, "lockf(%s, F_ULOCK)", file); 166 close(fd); 167 } 168 169 return (NULL); 170} 171 172int 173test(void) 174{ 175 pthread_t tid[3]; 176 int i, rc; 177 178 for (i = 0; i < 10; i++) { 179 if ((rc = pthread_create(&tid[0], NULL, t2, NULL)) == -1) 180 errc(1, rc, "pthread_create"); 181 if ((rc = pthread_create(&tid[1], NULL, t2, NULL)) == -1) 182 errc(1, rc, "pthread_create"); 183 if ((rc = pthread_create(&tid[2], NULL, t1, NULL)) == -1) 184 errc(1, rc, "pthread_create"); 185 186 if ((rc = pthread_join(tid[0], NULL)) == -1) 187 errc(1, rc, "pthread_join"); 188 if ((rc = pthread_join(tid[1], NULL)) == -1) 189 errc(1, rc, "pthread_join"); 190 if ((rc = pthread_join(tid[2], NULL)) == -1) 191 errc(1, rc, "pthread_join"); 192 } 193 194 _exit(0); 195} 196 197int 198main(void) 199{ 200 pid_t pids[PARALLEL]; 201 size_t len; 202 time_t start; 203 int i, status; 204 205 len = PAGE_SIZE; 206 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 207 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 208 err(1, "mmap"); 209 210 start = time(NULL); 211 while (time(NULL) - start < RUNTIME) { 212 for (i = 0; i < PARALLEL; i++) { 213 if ((pids[i] = fork()) == 0) 214 test(); 215 } 216 217 for(;;) { 218 if (share[SYNC] > 0) 219 atomic_add_int(&share[SYNC], -1); 220 for (i = 0; i < PARALLEL; i++) 221 kill(pids[i], SIGSTOP); 222 usleep(1000); 223 for (i = 0; i < PARALLEL; i++) 224 kill(pids[i], SIGCONT); 225 usleep(100 + arc4random() % 400); 226 if (share[SYNC] == 0) { /* If all procs are done */ 227 usleep(500); 228 if (share[SYNC] == 0) 229 break; 230 } 231 } 232 233 for (i = 0; i < PARALLEL; i++) { 234 if (waitpid(pids[i], &status, 0) != pids[i]) 235 err(1, "waitpid"); 236 } 237 } 238 239 return (0); 240} 241