Index: user/pho/stress2/misc/rename6.sh =================================================================== --- user/pho/stress2/misc/rename6.sh (revision 315637) +++ user/pho/stress2/misc/rename6.sh (revision 315638) @@ -1,148 +1,150 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Demonstrate rename(2) cache problem, where the original name lingers in the VFS cache. # Original test scenario by Anton Yuzhaninov . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > rename6.c mycc -o rename6 -Wall -Wextra -O2 rename6.c rm -f rename6.c cd $here mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart bsdlabel -w md$mdstart auto newfs $newfs_flags md${mdstart}$part > /dev/null mount /dev/md${mdstart}$part $mntpoint chmod 777 $mntpoint su ${testuser} -c "cd $mntpoint; /tmp/rename6" while mount | grep -q md${mdstart}$part; do umount $mntpoint || sleep 1 done mdconfig -d -u $mdstart rm -f /tmp/rename6 exit EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t spid; const char *logfile = "test.log"; void cleanup() { kill(spid, SIGINT); } static void Stat() { struct stat sb; int i; setproctitle("Stat"); for (;;) { for (i = 0; i < 1000; i++) { stat(logfile, &sb); } usleep(1000); } } int main(void) { struct stat sb1, sb2; int fd, i; char new[128]; if ((spid = fork()) == 0) Stat(); setproctitle("main"); atexit(cleanup); for (i = 0; i < 20000; i++) { sprintf(new, "test.log.%05d", i); if ((fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) err(1, "creat(%s)", logfile); close(fd); #if 1 if (rename(logfile, new) == -1) warn("rename(%s, %s)", logfile, new); #else /* No cache problem is seen */ if (link(logfile, new) == -1) err(1, "link(%s, %s)", logfile, new); if (unlink(logfile) == -1) err(1, "unlink(%s)", logfile); #endif /* * stat() for logfile and new will be identical sometimes, * but only when Stat() is running. */ if (stat(logfile, &sb1) == 0 && stat(new, &sb2) == 0 && bcmp(&sb1, &sb2, sizeof(sb1)) == 0) { fprintf(stderr, "At loop #%d\n", i); - fprintf(stderr, "%-15s: ino = %d, nlink = %d, size = %jd\n", - logfile, sb1.st_ino, sb1.st_nlink, sb1.st_blocks); - fprintf(stderr, "%-15s: ino = %d, nlink = %d, size = %jd\n", - new , sb2.st_ino, sb2.st_nlink, sb2.st_blocks); + fprintf(stderr, "%-15s: ino = %ju, nlink = %ju," + " size = %jd\n", logfile, (uintmax_t)sb1.st_ino, + (uintmax_t)sb1.st_nlink, sb1.st_blocks); + fprintf(stderr, "%-15s: ino = %ju, nlink = %ju, " + "size = %jd\n", new , (uintmax_t)sb2.st_ino, + (uintmax_t)sb2.st_nlink, sb2.st_blocks); } unlink(new); } kill(spid, SIGINT); wait(NULL); return (0); } Index: user/pho/stress2/misc/rename8.sh =================================================================== --- user/pho/stress2/misc/rename8.sh (revision 315637) +++ user/pho/stress2/misc/rename8.sh (revision 315638) @@ -1,174 +1,175 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Cache inconsistency seen on "to" file for rename(2). # Scenario by jhb@ . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > rename8.c mycc -o rename8 -Wall -Wextra -O2 rename8.c rm -f rename8.c cd $here mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart bsdlabel -w md$mdstart auto newfs $newfs_flags md${mdstart}$part > /dev/null mount /dev/md${mdstart}$part $mntpoint chmod 777 $mntpoint su ${testuser} -c "cd $mntpoint; mkdir r; /tmp/rename8 r" ls -li $mntpoint/r | egrep -v "^total" for i in `jot 10`; do mount | grep -q md${mdstart}$part && \ umount $mntpoint && mdconfig -d -u $mdstart && break sleep 1 done if mount | grep -q md${mdstart}$part; then fuser $mntpoint echo "umount $mntpoint failed" exit 1 fi mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart rm -f /tmp/rename8 exit EOF #include #include #include #include #include #include #include #include #include #include static char *always, *file1, *file2; static ino_t always_ino; static void usage(void) { fprintf(stderr, "Usage: rename_race \n"); exit(1); } static void child(void) { struct stat sb; /* Exit as soon as our parent exits. */ while (getppid() != 1) { stat(file1, &sb); } exit(0); } static void create_file(const char *path) { int fd; fd = open(path, O_CREAT, 0666); if (fd < 0) err(1, "open(%s)", path); close(fd); } int main(int ac, char **av) { struct stat sb, sb2; pid_t pid; int i, r; if (ac != 2) usage(); if (stat(av[1], &sb) != 0) err(1, "stat(%s)", av[1]); if (!S_ISDIR(sb.st_mode)) errx(1, "%s not a directory", av[1]); asprintf(&always, "%s/file.always", av[1]); asprintf(&file1, "%s/file1", av[1]); asprintf(&file2, "%s/file2", av[1]); create_file(always); if (stat(always, &sb) != 0) err(1, "stat(%s)", always); always_ino = sb.st_ino; pid = fork(); if (pid < 0) err(1, "fork"); if (pid == 0) child(); r = 0; for (i = 0; i < 100000; i++) { if (unlink(file1) < 0 && errno != ENOENT) err(1, "unlink(%s)", file1); if (link(always, file1) < 0) err(1, "link(%s, %s)", always, file1); create_file(file2); if (stat(file2, &sb2) < 0) err(1, "stat(%s)", file2); if (rename(file2, file1) < 0) err(1, "rename(%s, %s)", file2, file1); if (stat(file1, &sb) < 0) err(1, "stat(%s)", file1); if (sb.st_ino != sb2.st_ino || sb.st_ino == always_ino) { - printf("FAIL. Bad stat: always: %d file1: %d (should be %d)\n", - always_ino, sb.st_ino, sb2.st_ino); + printf("FAIL. Bad stat: always: %ju file1: %ju (should be %ju)\n", + (uintmax_t)always_ino, (uintmax_t)sb.st_ino, + (uintmax_t)sb2.st_ino); r = EXIT_FAILURE; break; } } kill(pid, SIGINT); wait(NULL); if (r == 0) { unlink(always); unlink(file1); unlink(file2); } return (r); } Index: user/pho/stress2/misc/rename9.sh =================================================================== --- user/pho/stress2/misc/rename9.sh (revision 315637) +++ user/pho/stress2/misc/rename9.sh (revision 315638) @@ -1,164 +1,171 @@ #!/bin/sh # # Copyright (c) 2012 Peter Holm # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Variation of rename6.sh. Cache problem of "to" file name seen. . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > rename9.c mycc -o rename9 -Wall -Wextra -O2 rename9.c rm -f rename9.c cd $here mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart bsdlabel -w md$mdstart auto newfs $newfs_flags md${mdstart}$part > /dev/null mount /dev/md${mdstart}$part $mntpoint rm -rf $mntpoint/.snap chmod 777 $mntpoint (while true; do ls -lRi $mntpoint > /dev/null 2>&1; done) & su ${testuser} -c "cd $mntpoint; /tmp/rename9" kill $! > /dev/null 2>&1 wait ls -ilR $mntpoint | egrep -v "^total " while mount | grep -q md${mdstart}$part; do umount $mntpoint || sleep 1 done mdconfig -d -u $mdstart rm -f /tmp/rename9 exit EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t spid; char *fromFile = "fromFile.log"; char toFile[128]; void cleanup() { kill(spid, SIGINT); } static void statFrom() { struct stat sb; setproctitle("Stat"); for (;;) { stat(fromFile, &sb); } } int main(void) { struct stat fb, tb, fa, ta; int fd, i; if ((spid = fork()) == 0) statFrom(); setproctitle("main"); atexit(cleanup); for (i = 0;i < 100000; i++) { bzero(&fb, sizeof(fb)); bzero(&tb, sizeof(tb)); bzero(&fa, sizeof(fa)); bzero(&ta, sizeof(ta)); - if ((fd = open(fromFile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) + if ((fd = open(fromFile, O_RDWR | O_CREAT | O_TRUNC, 0644)) + == -1) err(1, "creat(%s)", fromFile); close(fd); sprintf(toFile, "toFile.log.%05d", i); - if ((fd = open(toFile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) + if ((fd = open(toFile, O_RDWR | O_CREAT | O_TRUNC, 0644)) + == -1) err(1, "creat(%s)", toFile); write(fd, "xxx", 3); close(fd); stat(fromFile, &fb); stat(toFile, &tb); if (rename(fromFile, toFile) == -1) warn("rename(%s, %s)", fromFile, toFile); stat(fromFile, &fa); if (stat(toFile, &ta) == -1) err(1, "stat(%s)", toFile); if (tb.st_ino == ta.st_ino) { - fprintf(stderr, "FAIL: old and new \"To\" inode number is identical\n"); + fprintf(stderr, "FAIL: old and new \"To\" inode " + "number is identical\n"); fprintf(stderr, "stat() before the rename():\n"); fprintf(stderr, - "%-16s: ino = %4d, nlink = %d, size = %jd\n", - fromFile, fb.st_ino, fb.st_nlink, fb.st_blocks); + "%-16s: ino = %4ju, nlink = %ju, size = %jd\n", + fromFile, (uintmax_t)fb.st_ino, (uintmax_t)fb.st_nlink, + fb.st_blocks); fprintf(stderr, - "%-16s: ino = %4d, nlink = %d, size = %jd\n", - toFile, tb.st_ino, tb.st_nlink, tb.st_blocks); + "%-16s: ino = %4ju, nlink = %ju, size = %jd\n", + toFile, (uintmax_t)tb.st_ino, (uintmax_t)tb.st_nlink, + tb.st_blocks); fprintf(stderr, "\nstat() after the rename():\n"); if (fa.st_ino != 0) fprintf(stderr, - "%-16s: ino = %4d, nlink = %d, size = %jd\n", - fromFile, fa.st_ino, fa.st_nlink, fa.st_blocks); + "%-16s: ino = %4ju, nlink = %ju, size = " + "%jd\n", fromFile, (uintmax_t)fa.st_ino, + (uintmax_t)fa.st_nlink, fa.st_blocks); fprintf(stderr, - "%-16s: ino = %4d, nlink = %d, size = %jd\n", - toFile, ta.st_ino, ta.st_nlink, ta.st_blocks); + "%-16s: ino = %4ju, nlink = %ju, size = %jd\n", + toFile, (uintmax_t)ta.st_ino, (uintmax_t)ta.st_nlink, + ta.st_blocks); kill(spid, SIGINT); exit(1); } unlink(toFile); } kill(spid, SIGINT); wait(NULL); return (0); } Index: user/pho/stress2/misc/tmpfs8.sh =================================================================== --- user/pho/stress2/misc/tmpfs8.sh (revision 315637) +++ user/pho/stress2/misc/tmpfs8.sh (revision 315638) @@ -1,174 +1,180 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Demonstrate rename(2) cache problem for tmpfs(5). Fixed in r226987. # Variation of rename6.sh . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > tmpfs8.c mycc -o tmpfs8 -Wall -Wextra -O2 tmpfs8.c rm -f tmpfs8.c cd $here mount | grep $mntpoint | grep -q tmpfs && umount -f $mntpoint mount -t tmpfs tmpfs $mntpoint chmod 777 $mntpoint su ${testuser} -c "cd $mntpoint; /tmp/tmpfs8" while mount | grep $mntpoint | grep -q tmpfs; do umount $mntpoint || sleep 1 done rm -f /tmp/tmpfs8 exit EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t spid; const char *logfile = "test.log"; char new[128]; void cleanup() { kill(spid, SIGINT); } static void Stat() { struct stat sb; int i; setproctitle("Stat"); for (;;) { for (i = 0; i < 1000; i++) { stat(logfile, &sb); stat(new, &sb); } // usleep(1000); usleep(100); } } int main(void) { struct stat sb1, sb2, sb3; int fd, i, r1, r2, r3; if ((spid = fork()) == 0) Stat(); setproctitle("main"); atexit(cleanup); for (i = 0; i < 200000; i++) { bzero(&sb1, sizeof(sb1)); bzero(&sb2, sizeof(sb2)); if ((fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) err(1, "creat(%s)", logfile); close(fd); sprintf(new, "test.log.%05d", i); if ((fd = open(new, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) err(1, "creat(%s)", new); write(fd, "xxx", 3); close(fd); if ((r3 = stat(new, &sb3)) == -1) err(1, "stat(%s)", new); #if 1 if (rename(logfile, new) == -1) warn("rename(%s, %s)", logfile, new); #else /* No cache problem is seen */ if (link(logfile, new) == -1) err(1, "link(%s, %s)", logfile, new); if (unlink(logfile) == -1) err(1, "unlink(%s)", logfile); #endif /* * stat() for logfile and new will be identical sometimes, * but only when Stat() is running. */ r1 = stat(logfile, &sb1); r2 = stat(new, &sb2); if (r1 == 0 && r2 == 0 && bcmp(&sb1, &sb2, sizeof(sb1)) == 0) { fprintf(stderr, "FAIL 1\n"); - fprintf(stderr, "%-15s: ino = %4d, nlink = %d, size = %jd\n", - logfile, sb1.st_ino, sb1.st_nlink, sb1.st_blocks); - fprintf(stderr, "%-15s: ino = %4d, nlink = %d, size = %jd\n", - new , sb2.st_ino, sb2.st_nlink, sb2.st_blocks); + fprintf(stderr, "%-15s: ino = %4ju, nlink = %ju, " + "size = %jd\n", logfile, (uintmax_t)sb1.st_ino, + (uintmax_t)sb1.st_nlink, sb1.st_blocks); + fprintf(stderr, "%-15s: ino = %4ju, nlink = %ju, " + "size = %jd\n", new , (uintmax_t)sb2.st_ino, + (uintmax_t)sb2.st_nlink, sb2.st_blocks); } if (bcmp(&sb2, &sb3, sizeof(sb2)) == 0) { fprintf(stderr, "Old to file is lingering\n"); } if (sb2.st_ino == sb3.st_ino) { fprintf(stderr, "FAIL 2\n"); if (r1 == 0) fprintf(stderr, - "sb1: %-15s: ino = %4d, nlink = %d, size = %jd\n", - logfile, sb1.st_ino, sb1.st_nlink, sb1.st_blocks); + "sb1: %-15s: ino = %4ju, nlink = %ju, " + "size = %jd\n", logfile, + (uintmax_t)sb1.st_ino, + (uintmax_t)sb1.st_nlink, sb1.st_blocks); if (r2 == 0) fprintf(stderr, - "sb2: %-15s: ino = %4d, nlink = %d, size = %jd\n", - new, sb2.st_ino, sb2.st_nlink, sb2.st_blocks); + "sb2: %-15s: ino = %4ju, nlink = %ju, " + "size = %jd\n", new, (uintmax_t)sb2.st_ino, + (uintmax_t)sb2.st_nlink, sb2.st_blocks); if (r3 == 0) fprintf(stderr, - "sb3: %-15s: ino = %4d, nlink = %d, size = %jd\n", - new , sb3.st_ino, sb3.st_nlink, sb3.st_blocks); + "sb3: %-15s: ino = %4ju, nlink = %ju, " + "size = %jd\n", new, (uintmax_t)sb3.st_ino, + (uintmax_t)sb3.st_nlink, sb3.st_blocks); exit(1); } unlink(new); } kill(spid, SIGINT); wait(NULL); return (0); }