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