xref: /freebsd/tools/test/stress2/misc/namecache.sh (revision 9768746b)
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