1#!/bin/sh 2 3# 4# Copyright (c) 2009 Peter Holm <pho@FreeBSD.org> 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# Test case for vfs.lookup_shared=1 that shows possible name cache 30# inconsistency: 31 32# $ ls -l /tmp/file.05015? 33# ls: /tmp/file.050150: No such file or directory 34# $ fsdb -r /dev/ad4s1e 35# ** /dev/ad4s1e (NO WRITE) 36# Examining file system `/dev/ad4s1e' 37# Last Mounted on /tmp 38# current inode: directory 39# I=2 MODE=41777 SIZE=5120 40# BTIME=May 7 05:54:47 2006 [0 nsec] 41# MTIME=Apr 2 11:27:36 2009 [0 nsec] 42# CTIME=Apr 2 11:27:36 2009 [0 nsec] 43# ATIME=Apr 2 12:00:30 2009 [0 nsec] 44# OWNER=root GRP=wheel LINKCNT=35 FLAGS=0 BLKCNT=c GEN=65f71df4 45# fsdb (inum: 2)> lookup file.050150 46# component `file.050150': current inode: regular file 47# I=198 MODE=100600 SIZE=0 48# BTIME=Apr 2 11:24:33 2009 [0 nsec] 49# MTIME=Apr 2 11:24:33 2009 [0 nsec] 50# CTIME=Apr 2 11:24:33 2009 [0 nsec] 51# ATIME=Apr 2 11:24:33 2009 [0 nsec] 52# OWNER=pho GRP=wheel LINKCNT=1 FLAGS=0 BLKCNT=0 GEN=1deaab3a 53# fsdb (inum: 198)> quit 54# $ 55 56# Consistency is restored by a umount + mount of the FS 57 58# Observations: 59# No problems seen with vfs.lookup_shared=0. 60# Does not fail in a "private" subdirectory 61 62. ../default.cfg 63 64odir=`pwd` 65cd /tmp 66sed '1,/^EOF/d' < $odir/$0 > namecache.c 67mycc -o namecache -Wall namecache.c 68rm -f namecache.c 69 70#dir=/tmp/namecache.dir # No problems seen 71dir=/tmp 72[ -d $dir ] || mkdir -p $dir 73cd $dir 74 75start=`date '+%s'` 76for i in `jot 30`; do 77 for j in `jot 10`; do 78 /tmp/namecache & 79 done 80 81 for j in `jot 10`; do 82 wait 83 done 84 [ $((`date '+%s'` - start)) -gt 1200 ] && break 85done 86 87if ls -l $dir/file.0* 2>&1 | egrep "file.0[0-9]" | grep -q "No such file"; then 88 echo FAIL 89 echo "ls -l $dir/file.0*" 90 ls -l $dir/file.0* 91fi 92 93rm -f /tmp/namecache # /$dir/file.0* 94exit 95EOF 96/* Test scenario for possible name cache problem */ 97 98#include <sys/types.h> 99#include <dirent.h> 100#include <err.h> 101#include <fcntl.h> 102#include <signal.h> 103#include <stdio.h> 104#include <stdlib.h> 105#include <string.h> 106#include <sys/param.h> 107#include <sys/stat.h> 108#include <sys/wait.h> 109#include <unistd.h> 110 111static char path[MAXPATHLEN+1]; 112static char buf[64 * 1024]; 113 114void 115pm(void) 116{ 117 int fd, n; 118 int space = sizeof(buf); 119 struct stat statb; 120 off_t base; 121 struct dirent *dp; 122 char *bp = buf; 123 124 if ((fd = open(".", O_RDONLY)) == -1) 125 err(1, "open(%s)", "."); 126 127 do { 128 if ((n = getdirentries(fd, bp, space, &base)) == -1) 129 err(1, "getdirentries"); 130 space = space - n; 131 bp = bp + n; 132 } while (n != 0); 133 close(fd); 134 135 bp = buf; 136 dp = (struct dirent *)bp; 137 for (;;) { 138 if (strcmp(path, dp->d_name) == 0) { 139 140 if (stat(dp->d_name, &statb) == -1) { 141 warn("stat(%s)", dp->d_name); 142 printf("name: %-10s, inode %7ju, " 143 "type %2d, namelen %d, d_reclen %d\n", 144 dp->d_name, (uintmax_t)dp->d_fileno, dp->d_type, 145 dp->d_namlen, dp->d_reclen); 146 fflush(stdout); 147 } else { 148 printf("stat(%s) succeeded!\n", path); 149 fflush(stdout); 150 } 151 152 } 153 bp = bp + dp->d_reclen; 154 dp = (struct dirent *)bp; 155 if (dp->d_reclen <= 0) 156 break; 157 } 158} 159 160static void 161reader(void) { 162 int fd; 163 164 if ((fd = open(path, O_RDWR, 0600)) < 0) { 165 warn("open(%s). %s:%d", path, __FILE__, __LINE__); 166 pm(); 167 exit(1); 168 } 169 close(fd); 170 return; 171} 172 173static void 174writer(void) { 175 int fd; 176 177 if ((fd = open(path, O_RDWR, 0600)) < 0) { 178 warn("open(%s). %s:%d", path, __FILE__, __LINE__); 179 pm(); 180 exit(1); 181 } 182 close(fd); 183 return; 184} 185 186int 187main(int argc, char **argv) 188{ 189 pid_t pid; 190 int fd, i, status; 191 192 for (i = 0; i < 10000; i++) { 193 if (sprintf(path, "file.0%d", getpid()) < 0) 194 err(1, "sprintf()"); 195 if ((fd = open(path, O_CREAT | O_RDWR, 0600)) == -1) 196 err(1, "open(%s)", path); 197 close(fd); 198 199 if ((pid = fork()) == 0) { 200 writer(); 201 exit(EXIT_SUCCESS); 202 203 } else if (pid > 0) { 204 reader(); 205 if (waitpid(pid, &status, 0) == -1) 206 warn("waitpid(%d)", pid); 207 } else 208 err(1, "fork(), %s:%d", __FILE__, __LINE__); 209 210 if (unlink(path) == -1) 211 err(1, "unlink(%s). %s:%d", path, __FILE__, __LINE__); 212 } 213 return (0); 214} 215