From 1365b5f1af0c1cc3894d279008de5831984b2990 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 5 Aug 2010 01:36:53 +0200 Subject: [PATCH] Bring in FreeBSD's stress2 stress testing suite. Great for crashing the system. See test/stress/stress2/README for instructions. Thanks to Peter Holm for writing it. Thanks to Damian Lubosch for helping with testing on DragonFly. This might need further adjustment in the future. --- test/stress/stress2/Makefile | 5 + test/stress/stress2/Makefile.gnu | 28 + test/stress/stress2/README | 59 ++ test/stress/stress2/all.cfg | 8 + test/stress/stress2/beaver1.sentex.ca | 15 + test/stress/stress2/creat.cfg | 10 + test/stress/stress2/default.cfg | 76 ++ test/stress/stress2/df.cfg | 12 + test/stress/stress2/disk.cfg | 10 + test/stress/stress2/doc/README | 5 + test/stress/stress2/doc/linuxforum06.pdf | Bin 0 -> 523790 bytes test/stress/stress2/doc/stress.pdf | Bin 0 -> 39840 bytes .../stress/stress2/hydra1.netperf.freebsd.org | 13 + .../stress/stress2/hydra2.netperf.freebsd.org | 13 + test/stress/stress2/include/stress.h | 66 ++ test/stress/stress2/io.cfg | 11 + test/stress/stress2/jeff.cfg | 10 + test/stress/stress2/lib/Makefile | 8 + test/stress/stress2/lib/main.c | 204 ++++++ test/stress/stress2/lib/options.c | 262 +++++++ test/stress/stress2/lib/random_int.c | 54 ++ test/stress/stress2/lib/resources.c | 283 +++++++ test/stress/stress2/link.cfg | 11 + test/stress/stress2/load.cfg | 18 + test/stress/stress2/lockf.cfg | 11 + test/stress/stress2/marcus.cfg | 25 + test/stress/stress2/misc/README | 6 + test/stress/stress2/misc/all.sh | 139 ++++ test/stress/stress2/misc/altbufferflushes.sh | 99 +++ .../stress2/misc/alternativeFlushPath.sh | 108 +++ test/stress/stress2/misc/backingstore.sh | 81 ++ test/stress/stress2/misc/backingstore2.sh | 73 ++ test/stress/stress2/misc/backingstore3.sh | 74 ++ test/stress/stress2/misc/cdevsw.sh | 220 ++++++ test/stress/stress2/misc/cleanup.sh | 48 ++ test/stress/stress2/misc/core.sh | 81 ++ test/stress/stress2/misc/crossmp.sh | 88 +++ test/stress/stress2/misc/crossmp2.sh | 76 ++ test/stress/stress2/misc/datamove.sh | 208 ++++++ test/stress/stress2/misc/datamove2.sh | 210 ++++++ test/stress/stress2/misc/datamove3.sh | 219 ++++++ test/stress/stress2/misc/devfs.sh | 70 ++ test/stress/stress2/misc/devfs2.sh | 108 +++ test/stress/stress2/misc/extattr.sh | 96 +++ test/stress/stress2/misc/extattrctl.sh | 74 ++ test/stress/stress2/misc/fdescfs.sh | 71 ++ test/stress/stress2/misc/fpclone.sh | 197 +++++ test/stress/stress2/misc/fpclone2.sh | 115 +++ test/stress/stress2/misc/fpu.sh | 105 +++ test/stress/stress2/misc/fragments.sh | 266 +++++++ test/stress/stress2/misc/fs.sh | 71 ++ test/stress/stress2/misc/fullpath.sh | 113 +++ test/stress/stress2/misc/fuzz.sh | 180 +++++ test/stress/stress2/misc/inversion.sh | 91 +++ test/stress/stress2/misc/isofs.sh | 64 ++ test/stress/stress2/misc/jail.sh | 68 ++ test/stress/stress2/misc/jail2.sh | 78 ++ test/stress/stress2/misc/jail3.sh | 78 ++ test/stress/stress2/misc/jail4.sh | 80 ++ test/stress/stress2/misc/kevent.sh | 173 +++++ test/stress/stress2/misc/kevent2.sh | 175 +++++ test/stress/stress2/misc/kevent3.sh | 72 ++ test/stress/stress2/misc/kevent4.sh | 202 +++++ test/stress/stress2/misc/kevent5.sh | 161 ++++ test/stress/stress2/misc/kinfo.sh | 164 +++++ test/stress/stress2/misc/kinfo2.sh | 176 +++++ test/stress/stress2/misc/kinfo3.sh | 191 +++++ test/stress/stress2/misc/ldt.sh | 369 ++++++++++ test/stress/stress2/misc/ldt2.sh | 102 +++ test/stress/stress2/misc/libMicro.sh | 71 ++ test/stress/stress2/misc/lockf.sh | 54 ++ test/stress/stress2/misc/lookup_shared.sh | 41 ++ test/stress/stress2/misc/mac.sh | 40 + test/stress/stress2/misc/mac_chkexec.sh | 58 ++ test/stress/stress2/misc/md.sh | 58 ++ test/stress/stress2/misc/md2.sh | 53 ++ test/stress/stress2/misc/md3.sh | 58 ++ test/stress/stress2/misc/mlockall.sh | 81 ++ test/stress/stress2/misc/mmap.sh | 66 ++ test/stress/stress2/misc/mmap2.sh | 176 +++++ test/stress/stress2/misc/mmap3.sh | 159 ++++ test/stress/stress2/misc/mmap4.sh | 118 +++ test/stress/stress2/misc/mount.sh | 76 ++ test/stress/stress2/misc/mount2.sh | 81 ++ test/stress/stress2/misc/mountro.sh | 67 ++ test/stress/stress2/misc/mountro2.sh | 57 ++ test/stress/stress2/misc/mountro3.sh | 58 ++ test/stress/stress2/misc/msdos.sh | 53 ++ test/stress/stress2/misc/msdos2.sh | 60 ++ test/stress/stress2/misc/msdos3.sh | 54 ++ test/stress/stress2/misc/msdos4.sh | 65 ++ test/stress/stress2/misc/namecache.sh | 212 ++++++ test/stress/stress2/misc/nbufkv.sh | 136 ++++ test/stress/stress2/misc/newfs.sh | 66 ++ test/stress/stress2/misc/newfs2.sh | 59 ++ test/stress/stress2/misc/newfs3.sh | 72 ++ test/stress/stress2/misc/newfs4.sh | 126 ++++ test/stress/stress2/misc/nfs.sh | 47 ++ test/stress/stress2/misc/nfs2.sh | 67 ++ test/stress/stress2/misc/nfs3.sh | 57 ++ test/stress/stress2/misc/nfs4.sh | 55 ++ test/stress/stress2/misc/nfs5.sh | 67 ++ test/stress/stress2/misc/nfs6.sh | 75 ++ test/stress/stress2/misc/nfs7.sh | 55 ++ test/stress/stress2/misc/nfs8.sh | 58 ++ test/stress/stress2/misc/nfs9.sh | 62 ++ test/stress/stress2/misc/nfsrename.sh | 215 ++++++ test/stress/stress2/misc/nullfs.sh | 70 ++ test/stress/stress2/misc/nullfs2.sh | 52 ++ test/stress/stress2/misc/nullfs3.sh | 55 ++ test/stress/stress2/misc/nullfs4.sh | 52 ++ test/stress/stress2/misc/nullfs5.sh | 73 ++ test/stress/stress2/misc/nullfs6.sh | 51 ++ test/stress/stress2/misc/pmc.sh | 48 ++ test/stress/stress2/misc/procfs.sh | 76 ++ test/stress/stress2/misc/pthread.sh | 140 ++++ test/stress/stress2/misc/quota1.sh | 57 ++ test/stress/stress2/misc/quota10.sh | 102 +++ test/stress/stress2/misc/quota2.sh | 61 ++ test/stress/stress2/misc/quota3.sh | 62 ++ test/stress/stress2/misc/quota4.sh | 60 ++ test/stress/stress2/misc/quota5.sh | 44 ++ test/stress/stress2/misc/quota6.sh | 66 ++ test/stress/stress2/misc/quota7.sh | 77 ++ test/stress/stress2/misc/quota8.sh | 79 ++ test/stress/stress2/misc/quota9.sh | 94 +++ test/stress/stress2/misc/recursiveflushes.sh | 65 ++ test/stress/stress2/misc/rename.sh | 121 +++ test/stress/stress2/misc/rename2.sh | 102 +++ test/stress/stress2/misc/rename3.sh | 49 ++ test/stress/stress2/misc/rename4.sh | 64 ++ test/stress/stress2/misc/revoke.sh | 118 +++ test/stress/stress2/misc/sem.sh | 145 ++++ test/stress/stress2/misc/sendfile.sh | 215 ++++++ test/stress/stress2/misc/snap.sh | 53 ++ test/stress/stress2/misc/snap2-1.sh | 58 ++ test/stress/stress2/misc/snap2.sh | 60 ++ test/stress/stress2/misc/snap3.sh | 58 ++ test/stress/stress2/misc/snap4.sh | 52 ++ test/stress/stress2/misc/snap5-1.sh | 55 ++ test/stress/stress2/misc/snap5.sh | 52 ++ test/stress/stress2/misc/snap6.sh | 44 ++ test/stress/stress2/misc/snap7.sh | 53 ++ test/stress/stress2/misc/snap8.sh | 95 +++ test/stress/stress2/misc/snapbackup.sh | 62 ++ test/stress/stress2/misc/softupdate.sh | 60 ++ test/stress/stress2/misc/statfs.sh | 129 ++++ test/stress/stress2/misc/suj.sh | 51 ++ test/stress/stress2/misc/symlink.sh | 129 ++++ test/stress/stress2/misc/symlink2.sh | 121 +++ test/stress/stress2/misc/syscall.sh | 58 ++ test/stress/stress2/misc/syscall2.sh | 224 ++++++ test/stress/stress2/misc/tmpfs.sh | 46 ++ test/stress/stress2/misc/tmpfs2.sh | 78 ++ test/stress/stress2/misc/tmpfs3.sh | 46 ++ test/stress/stress2/misc/tmpfs4.sh | 49 ++ test/stress/stress2/misc/truncate.sh | 95 +++ test/stress/stress2/misc/truncate2.sh | 102 +++ test/stress/stress2/misc/ucom.sh | 71 ++ test/stress/stress2/misc/umount.sh | 52 ++ test/stress/stress2/misc/umountf.sh | 62 ++ test/stress/stress2/misc/umountf2.sh | 67 ++ test/stress/stress2/misc/umountf3.sh | 122 +++ test/stress/stress2/misc/umountf4.sh | 89 +++ test/stress/stress2/misc/union.sh | 70 ++ test/stress/stress2/misc/unionfs.sh | 53 ++ test/stress/stress2/misc/unionfs2.sh | 48 ++ test/stress/stress2/misc/unionfs3.sh | 52 ++ test/stress/stress2/misc/zfs.sh | 63 ++ test/stress/stress2/misc/zfs2.sh | 66 ++ test/stress/stress2/misc/zfs3.sh | 74 ++ test/stress/stress2/misc/zfs4.sh | 77 ++ test/stress/stress2/misc/zfs5.sh | 66 ++ test/stress/stress2/mkdir.cfg | 11 + test/stress/stress2/mkfifo.cfg | 10 + test/stress/stress2/norw.cfg | 8 + test/stress/stress2/noswap.cfg | 8 + .../stress2/orangutan.netperf.freebsd.org | 17 + test/stress/stress2/pty.cfg | 10 + test/stress/stress2/run.sh | 79 ++ test/stress/stress2/rw.cfg | 10 + test/stress/stress2/syscall.cfg | 13 + test/stress/stress2/sysctl.cfg | 14 + test/stress/stress2/testcases/Makefile | 29 + test/stress/stress2/testcases/Makefile.inc | 8 + test/stress/stress2/testcases/README | 11 + .../stress/stress2/testcases/badcode/Makefile | 5 + .../stress2/testcases/badcode/badcode.c | 121 +++ test/stress/stress2/testcases/creat/Makefile | 5 + test/stress/stress2/testcases/creat/creat.c | 140 ++++ test/stress/stress2/testcases/fts/Makefile | 5 + test/stress/stress2/testcases/fts/fts.c | 103 +++ test/stress/stress2/testcases/link/Makefile | 5 + test/stress/stress2/testcases/link/link.c | 147 ++++ test/stress/stress2/testcases/lockf/Makefile | 5 + test/stress/stress2/testcases/lockf/lockf.c | 134 ++++ test/stress/stress2/testcases/lockf2/Makefile | 5 + test/stress/stress2/testcases/lockf2/lockf2.c | 101 +++ test/stress/stress2/testcases/mkdir/Makefile | 5 + test/stress/stress2/testcases/mkdir/mkdir.c | 135 ++++ test/stress/stress2/testcases/mkfifo/Makefile | 6 + test/stress/stress2/testcases/mkfifo/mkfifo.c | 144 ++++ test/stress/stress2/testcases/mmap/Makefile | 5 + test/stress/stress2/testcases/mmap/mmap.c | 125 ++++ test/stress/stress2/testcases/openat/Makefile | 5 + test/stress/stress2/testcases/openat/doat.c | 693 ++++++++++++++++++ test/stress/stress2/testcases/openat/openat.c | 162 ++++ test/stress/stress2/testcases/pty/Makefile | 6 + test/stress/stress2/testcases/pty/pty.c | 111 +++ test/stress/stress2/testcases/rename/Makefile | 5 + test/stress/stress2/testcases/rename/rename.c | 144 ++++ test/stress/stress2/testcases/run/Makefile | 5 + test/stress/stress2/testcases/run/run.c | 122 +++ test/stress/stress2/testcases/rw/Makefile | 5 + test/stress/stress2/testcases/rw/rw.c | 181 +++++ test/stress/stress2/testcases/shm/Makefile | 6 + test/stress/stress2/testcases/shm/shm.c | 185 +++++ test/stress/stress2/testcases/socket/Makefile | 5 + test/stress/stress2/testcases/socket/socket.c | 121 +++ test/stress/stress2/testcases/swap/Makefile | 5 + test/stress/stress2/testcases/swap/swap.c | 130 ++++ .../stress/stress2/testcases/symlink/Makefile | 5 + .../stress2/testcases/symlink/symlink.c | 137 ++++ .../stress/stress2/testcases/syscall/Makefile | 5 + .../stress2/testcases/syscall/syscall.c | 155 ++++ test/stress/stress2/testcases/sysctl/Makefile | 5 + test/stress/stress2/testcases/sysctl/sysctl.c | 63 ++ test/stress/stress2/testcases/tcp/Makefile | 5 + test/stress/stress2/testcases/tcp/tcp.c | 179 +++++ test/stress/stress2/testcases/thr1/Makefile | 7 + test/stress/stress2/testcases/thr1/thr1.c | 75 ++ test/stress/stress2/testcases/thr2/Makefile | 7 + test/stress/stress2/testcases/thr2/thr2.c | 93 +++ test/stress/stress2/testcases/udp/Makefile | 5 + test/stress/stress2/testcases/udp/udp.c | 113 +++ test/stress/stress2/tools/df.sh | 44 ++ test/stress/stress2/tools/freeze.sh | 44 ++ test/stress/stress2/tools/freeze2.sh | 45 ++ test/stress/stress2/tools/fstool.c | 193 +++++ test/stress/stress2/tools/iwatch.sh | 49 ++ test/stress/stress2/tools/l3.sh | 65 ++ test/stress/stress2/tools/leaks.sh | 118 +++ test/stress/stress2/tools/leaks2.sh | 117 +++ test/stress/stress2/tools/module/Makefile | 8 + test/stress/stress2/tools/module/ptest.c | 96 +++ test/stress/stress2/tools/monitor.sh | 42 ++ test/stress/stress2/tools/ptsleak.sh | 41 ++ test/stress/stress2/tools/ptyleak.sh | 42 ++ test/stress/stress2/tools/rwatch.sh | 61 ++ test/stress/stress2/udp.cfg | 11 + test/stress/stress2/vfs.cfg | 10 + 251 files changed, 19905 insertions(+) create mode 100644 test/stress/stress2/Makefile create mode 100644 test/stress/stress2/Makefile.gnu create mode 100644 test/stress/stress2/README create mode 100644 test/stress/stress2/all.cfg create mode 100644 test/stress/stress2/beaver1.sentex.ca create mode 100644 test/stress/stress2/creat.cfg create mode 100644 test/stress/stress2/default.cfg create mode 100644 test/stress/stress2/df.cfg create mode 100644 test/stress/stress2/disk.cfg create mode 100644 test/stress/stress2/doc/README create mode 100644 test/stress/stress2/doc/linuxforum06.pdf create mode 100644 test/stress/stress2/doc/stress.pdf create mode 100644 test/stress/stress2/hydra1.netperf.freebsd.org create mode 100644 test/stress/stress2/hydra2.netperf.freebsd.org create mode 100644 test/stress/stress2/include/stress.h create mode 100644 test/stress/stress2/io.cfg create mode 100644 test/stress/stress2/jeff.cfg create mode 100644 test/stress/stress2/lib/Makefile create mode 100644 test/stress/stress2/lib/main.c create mode 100644 test/stress/stress2/lib/options.c create mode 100644 test/stress/stress2/lib/random_int.c create mode 100644 test/stress/stress2/lib/resources.c create mode 100644 test/stress/stress2/link.cfg create mode 100644 test/stress/stress2/load.cfg create mode 100644 test/stress/stress2/lockf.cfg create mode 100644 test/stress/stress2/marcus.cfg create mode 100644 test/stress/stress2/misc/README create mode 100755 test/stress/stress2/misc/all.sh create mode 100755 test/stress/stress2/misc/altbufferflushes.sh create mode 100755 test/stress/stress2/misc/alternativeFlushPath.sh create mode 100755 test/stress/stress2/misc/backingstore.sh create mode 100755 test/stress/stress2/misc/backingstore2.sh create mode 100755 test/stress/stress2/misc/backingstore3.sh create mode 100755 test/stress/stress2/misc/cdevsw.sh create mode 100755 test/stress/stress2/misc/cleanup.sh create mode 100755 test/stress/stress2/misc/core.sh create mode 100755 test/stress/stress2/misc/crossmp.sh create mode 100755 test/stress/stress2/misc/crossmp2.sh create mode 100755 test/stress/stress2/misc/datamove.sh create mode 100755 test/stress/stress2/misc/datamove2.sh create mode 100755 test/stress/stress2/misc/datamove3.sh create mode 100755 test/stress/stress2/misc/devfs.sh create mode 100755 test/stress/stress2/misc/devfs2.sh create mode 100755 test/stress/stress2/misc/extattr.sh create mode 100755 test/stress/stress2/misc/extattrctl.sh create mode 100755 test/stress/stress2/misc/fdescfs.sh create mode 100755 test/stress/stress2/misc/fpclone.sh create mode 100755 test/stress/stress2/misc/fpclone2.sh create mode 100755 test/stress/stress2/misc/fpu.sh create mode 100755 test/stress/stress2/misc/fragments.sh create mode 100755 test/stress/stress2/misc/fs.sh create mode 100755 test/stress/stress2/misc/fullpath.sh create mode 100755 test/stress/stress2/misc/fuzz.sh create mode 100755 test/stress/stress2/misc/inversion.sh create mode 100755 test/stress/stress2/misc/isofs.sh create mode 100755 test/stress/stress2/misc/jail.sh create mode 100755 test/stress/stress2/misc/jail2.sh create mode 100755 test/stress/stress2/misc/jail3.sh create mode 100755 test/stress/stress2/misc/jail4.sh create mode 100755 test/stress/stress2/misc/kevent.sh create mode 100755 test/stress/stress2/misc/kevent2.sh create mode 100755 test/stress/stress2/misc/kevent3.sh create mode 100755 test/stress/stress2/misc/kevent4.sh create mode 100755 test/stress/stress2/misc/kevent5.sh create mode 100755 test/stress/stress2/misc/kinfo.sh create mode 100755 test/stress/stress2/misc/kinfo2.sh create mode 100755 test/stress/stress2/misc/kinfo3.sh create mode 100755 test/stress/stress2/misc/ldt.sh create mode 100755 test/stress/stress2/misc/ldt2.sh create mode 100755 test/stress/stress2/misc/libMicro.sh create mode 100755 test/stress/stress2/misc/lockf.sh create mode 100755 test/stress/stress2/misc/lookup_shared.sh create mode 100755 test/stress/stress2/misc/mac.sh create mode 100755 test/stress/stress2/misc/mac_chkexec.sh create mode 100755 test/stress/stress2/misc/md.sh create mode 100755 test/stress/stress2/misc/md2.sh create mode 100755 test/stress/stress2/misc/md3.sh create mode 100755 test/stress/stress2/misc/mlockall.sh create mode 100755 test/stress/stress2/misc/mmap.sh create mode 100755 test/stress/stress2/misc/mmap2.sh create mode 100755 test/stress/stress2/misc/mmap3.sh create mode 100755 test/stress/stress2/misc/mmap4.sh create mode 100755 test/stress/stress2/misc/mount.sh create mode 100755 test/stress/stress2/misc/mount2.sh create mode 100755 test/stress/stress2/misc/mountro.sh create mode 100755 test/stress/stress2/misc/mountro2.sh create mode 100755 test/stress/stress2/misc/mountro3.sh create mode 100755 test/stress/stress2/misc/msdos.sh create mode 100755 test/stress/stress2/misc/msdos2.sh create mode 100755 test/stress/stress2/misc/msdos3.sh create mode 100755 test/stress/stress2/misc/msdos4.sh create mode 100755 test/stress/stress2/misc/namecache.sh create mode 100755 test/stress/stress2/misc/nbufkv.sh create mode 100755 test/stress/stress2/misc/newfs.sh create mode 100755 test/stress/stress2/misc/newfs2.sh create mode 100755 test/stress/stress2/misc/newfs3.sh create mode 100755 test/stress/stress2/misc/newfs4.sh create mode 100755 test/stress/stress2/misc/nfs.sh create mode 100755 test/stress/stress2/misc/nfs2.sh create mode 100755 test/stress/stress2/misc/nfs3.sh create mode 100755 test/stress/stress2/misc/nfs4.sh create mode 100755 test/stress/stress2/misc/nfs5.sh create mode 100755 test/stress/stress2/misc/nfs6.sh create mode 100755 test/stress/stress2/misc/nfs7.sh create mode 100755 test/stress/stress2/misc/nfs8.sh create mode 100755 test/stress/stress2/misc/nfs9.sh create mode 100755 test/stress/stress2/misc/nfsrename.sh create mode 100755 test/stress/stress2/misc/nullfs.sh create mode 100755 test/stress/stress2/misc/nullfs2.sh create mode 100755 test/stress/stress2/misc/nullfs3.sh create mode 100755 test/stress/stress2/misc/nullfs4.sh create mode 100755 test/stress/stress2/misc/nullfs5.sh create mode 100755 test/stress/stress2/misc/nullfs6.sh create mode 100755 test/stress/stress2/misc/pmc.sh create mode 100755 test/stress/stress2/misc/procfs.sh create mode 100755 test/stress/stress2/misc/pthread.sh create mode 100755 test/stress/stress2/misc/quota1.sh create mode 100755 test/stress/stress2/misc/quota10.sh create mode 100755 test/stress/stress2/misc/quota2.sh create mode 100755 test/stress/stress2/misc/quota3.sh create mode 100755 test/stress/stress2/misc/quota4.sh create mode 100755 test/stress/stress2/misc/quota5.sh create mode 100755 test/stress/stress2/misc/quota6.sh create mode 100755 test/stress/stress2/misc/quota7.sh create mode 100755 test/stress/stress2/misc/quota8.sh create mode 100755 test/stress/stress2/misc/quota9.sh create mode 100755 test/stress/stress2/misc/recursiveflushes.sh create mode 100755 test/stress/stress2/misc/rename.sh create mode 100755 test/stress/stress2/misc/rename2.sh create mode 100755 test/stress/stress2/misc/rename3.sh create mode 100755 test/stress/stress2/misc/rename4.sh create mode 100755 test/stress/stress2/misc/revoke.sh create mode 100755 test/stress/stress2/misc/sem.sh create mode 100755 test/stress/stress2/misc/sendfile.sh create mode 100755 test/stress/stress2/misc/snap.sh create mode 100755 test/stress/stress2/misc/snap2-1.sh create mode 100755 test/stress/stress2/misc/snap2.sh create mode 100755 test/stress/stress2/misc/snap3.sh create mode 100755 test/stress/stress2/misc/snap4.sh create mode 100755 test/stress/stress2/misc/snap5-1.sh create mode 100755 test/stress/stress2/misc/snap5.sh create mode 100755 test/stress/stress2/misc/snap6.sh create mode 100755 test/stress/stress2/misc/snap7.sh create mode 100755 test/stress/stress2/misc/snap8.sh create mode 100755 test/stress/stress2/misc/snapbackup.sh create mode 100755 test/stress/stress2/misc/softupdate.sh create mode 100755 test/stress/stress2/misc/statfs.sh create mode 100755 test/stress/stress2/misc/suj.sh create mode 100755 test/stress/stress2/misc/symlink.sh create mode 100755 test/stress/stress2/misc/symlink2.sh create mode 100755 test/stress/stress2/misc/syscall.sh create mode 100755 test/stress/stress2/misc/syscall2.sh create mode 100755 test/stress/stress2/misc/tmpfs.sh create mode 100755 test/stress/stress2/misc/tmpfs2.sh create mode 100755 test/stress/stress2/misc/tmpfs3.sh create mode 100755 test/stress/stress2/misc/tmpfs4.sh create mode 100755 test/stress/stress2/misc/truncate.sh create mode 100755 test/stress/stress2/misc/truncate2.sh create mode 100755 test/stress/stress2/misc/ucom.sh create mode 100755 test/stress/stress2/misc/umount.sh create mode 100755 test/stress/stress2/misc/umountf.sh create mode 100755 test/stress/stress2/misc/umountf2.sh create mode 100755 test/stress/stress2/misc/umountf3.sh create mode 100755 test/stress/stress2/misc/umountf4.sh create mode 100755 test/stress/stress2/misc/union.sh create mode 100755 test/stress/stress2/misc/unionfs.sh create mode 100755 test/stress/stress2/misc/unionfs2.sh create mode 100755 test/stress/stress2/misc/unionfs3.sh create mode 100755 test/stress/stress2/misc/zfs.sh create mode 100755 test/stress/stress2/misc/zfs2.sh create mode 100755 test/stress/stress2/misc/zfs3.sh create mode 100755 test/stress/stress2/misc/zfs4.sh create mode 100755 test/stress/stress2/misc/zfs5.sh create mode 100644 test/stress/stress2/mkdir.cfg create mode 100644 test/stress/stress2/mkfifo.cfg create mode 100644 test/stress/stress2/norw.cfg create mode 100644 test/stress/stress2/noswap.cfg create mode 100644 test/stress/stress2/orangutan.netperf.freebsd.org create mode 100644 test/stress/stress2/pty.cfg create mode 100755 test/stress/stress2/run.sh create mode 100644 test/stress/stress2/rw.cfg create mode 100644 test/stress/stress2/syscall.cfg create mode 100644 test/stress/stress2/sysctl.cfg create mode 100644 test/stress/stress2/testcases/Makefile create mode 100644 test/stress/stress2/testcases/Makefile.inc create mode 100644 test/stress/stress2/testcases/README create mode 100644 test/stress/stress2/testcases/badcode/Makefile create mode 100644 test/stress/stress2/testcases/badcode/badcode.c create mode 100644 test/stress/stress2/testcases/creat/Makefile create mode 100644 test/stress/stress2/testcases/creat/creat.c create mode 100644 test/stress/stress2/testcases/fts/Makefile create mode 100644 test/stress/stress2/testcases/fts/fts.c create mode 100644 test/stress/stress2/testcases/link/Makefile create mode 100644 test/stress/stress2/testcases/link/link.c create mode 100644 test/stress/stress2/testcases/lockf/Makefile create mode 100644 test/stress/stress2/testcases/lockf/lockf.c create mode 100644 test/stress/stress2/testcases/lockf2/Makefile create mode 100644 test/stress/stress2/testcases/lockf2/lockf2.c create mode 100644 test/stress/stress2/testcases/mkdir/Makefile create mode 100644 test/stress/stress2/testcases/mkdir/mkdir.c create mode 100644 test/stress/stress2/testcases/mkfifo/Makefile create mode 100644 test/stress/stress2/testcases/mkfifo/mkfifo.c create mode 100644 test/stress/stress2/testcases/mmap/Makefile create mode 100644 test/stress/stress2/testcases/mmap/mmap.c create mode 100644 test/stress/stress2/testcases/openat/Makefile create mode 100644 test/stress/stress2/testcases/openat/doat.c create mode 100644 test/stress/stress2/testcases/openat/openat.c create mode 100644 test/stress/stress2/testcases/pty/Makefile create mode 100644 test/stress/stress2/testcases/pty/pty.c create mode 100644 test/stress/stress2/testcases/rename/Makefile create mode 100644 test/stress/stress2/testcases/rename/rename.c create mode 100644 test/stress/stress2/testcases/run/Makefile create mode 100644 test/stress/stress2/testcases/run/run.c create mode 100644 test/stress/stress2/testcases/rw/Makefile create mode 100644 test/stress/stress2/testcases/rw/rw.c create mode 100644 test/stress/stress2/testcases/shm/Makefile create mode 100644 test/stress/stress2/testcases/shm/shm.c create mode 100644 test/stress/stress2/testcases/socket/Makefile create mode 100644 test/stress/stress2/testcases/socket/socket.c create mode 100644 test/stress/stress2/testcases/swap/Makefile create mode 100644 test/stress/stress2/testcases/swap/swap.c create mode 100644 test/stress/stress2/testcases/symlink/Makefile create mode 100644 test/stress/stress2/testcases/symlink/symlink.c create mode 100644 test/stress/stress2/testcases/syscall/Makefile create mode 100644 test/stress/stress2/testcases/syscall/syscall.c create mode 100644 test/stress/stress2/testcases/sysctl/Makefile create mode 100644 test/stress/stress2/testcases/sysctl/sysctl.c create mode 100644 test/stress/stress2/testcases/tcp/Makefile create mode 100644 test/stress/stress2/testcases/tcp/tcp.c create mode 100644 test/stress/stress2/testcases/thr1/Makefile create mode 100644 test/stress/stress2/testcases/thr1/thr1.c create mode 100644 test/stress/stress2/testcases/thr2/Makefile create mode 100644 test/stress/stress2/testcases/thr2/thr2.c create mode 100644 test/stress/stress2/testcases/udp/Makefile create mode 100644 test/stress/stress2/testcases/udp/udp.c create mode 100755 test/stress/stress2/tools/df.sh create mode 100755 test/stress/stress2/tools/freeze.sh create mode 100755 test/stress/stress2/tools/freeze2.sh create mode 100644 test/stress/stress2/tools/fstool.c create mode 100755 test/stress/stress2/tools/iwatch.sh create mode 100755 test/stress/stress2/tools/l3.sh create mode 100755 test/stress/stress2/tools/leaks.sh create mode 100755 test/stress/stress2/tools/leaks2.sh create mode 100644 test/stress/stress2/tools/module/Makefile create mode 100644 test/stress/stress2/tools/module/ptest.c create mode 100755 test/stress/stress2/tools/monitor.sh create mode 100755 test/stress/stress2/tools/ptsleak.sh create mode 100755 test/stress/stress2/tools/ptyleak.sh create mode 100755 test/stress/stress2/tools/rwatch.sh create mode 100644 test/stress/stress2/udp.cfg create mode 100644 test/stress/stress2/vfs.cfg diff --git a/test/stress/stress2/Makefile b/test/stress/stress2/Makefile new file mode 100644 index 0000000000..02987a1dd7 --- /dev/null +++ b/test/stress/stress2/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +SUBDIR= lib testcases + +.include diff --git a/test/stress/stress2/Makefile.gnu b/test/stress/stress2/Makefile.gnu new file mode 100644 index 0000000000..06f8c7a127 --- /dev/null +++ b/test/stress/stress2/Makefile.gnu @@ -0,0 +1,28 @@ +#MAKE=gmake + +# Gnu Makefile by "Brad Knotwell" + +LIBOBJS=$(subst .c,.o,$(wildcard lib/*.c)) +TESTDIRS=run swap mkdir creat thr1 syscall rw sysctl tcp udp +EXES=$(foreach dir,$(TESTDIRS),testcases/$(dir)/$(dir).test) +OBJS=$(subst .test,.o,$(EXES)) +SRCS=$(subst .o,.c,$(OBJS)) +LIBS=./lib/libstress.a +CFLAGS=-g -Wall -I./include + +all: $(EXES) + +lib/libstress.a: lib/libstress.a($(LIBOBJS)) + ranlib lib/libstress.a + +lib/libstress.a(*.o): $(LIBOBJS) + +$(OBJS): %.o: %.c + +$(EXES): %.test: %.o lib/libstress.a + +%.test: %.o + $(CC) $(CFLAGS) $(LIBS) $< -o $@ + +clean: + rm -fr $(LIBOBJS) lib/libstress.a $(EXES) $(OBJS) diff --git a/test/stress/stress2/README b/test/stress/stress2/README new file mode 100644 index 0000000000..f430533e80 --- /dev/null +++ b/test/stress/stress2/README @@ -0,0 +1,59 @@ +$FreeBSD$ + +This is the FreeBSD kernel stress test suite. The purpose is to crash the +computer, by stressing selected parts of the kernel, thus exposing inadequate +error handling. + +Do not run the syscall test as root. + +To build and use: + +make +sh ./run.sh + +The "run.sh" script accepts an optional configuration file in order to test specific areas. +For example: + +./run.sh vfs.sh + + +To run all of the different test scenarios type: + +./run.sh -a + +You may have to tune the stress test to make sure that your test box run low +on resources. For example: + +INCARNATIONS=125 ./run.sh + +The following sub-directories exists: + +./doc Documentation +./include Include file for building the test programs in ./testcases +./lib Common support files for the test programs +./misc Various test scenarios. Mostly regression tests +./testcases Test programs +./tools Supplementary tools used in stress testing + +The name stress2 indicates that this is the second generation of the Kernel Stress Test Suite. +The first version (stress) was based mostly on scripts. + + +20090120: des@ pointed out it would be nice to be able to set the + random seed in order to be able to reproduce errors in time. + A test of this show that the occurrence of panics are still + non-deterministic even with a fixed seed. The known broken + unionfs was used to test this: + http://people.freebsd.org/~pho/stress/log/marcus006.txt. + First panic occurred after 29 loops and the second after 8 + with a seed of "123". + + The randomness that is provided by lack of synchronization + with timer interrupt, disk block layout and disk access + latencies caused by platter and heads speed changes, disk + firmware internal operations, and so on are _much_ bigger + then the undeterminism caused by the non-repeatable random + seed. + + Anyway, I have always view the this issue as only a slight + inconvenience. diff --git a/test/stress/stress2/all.cfg b/test/stress/stress2/all.cfg new file mode 100644 index 0000000000..74db0bb7a0 --- /dev/null +++ b/test/stress/stress2/all.cfg @@ -0,0 +1,8 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration: run all test programs + +# Default values +. ./default.cfg + +export TESTPROGS="" diff --git a/test/stress/stress2/beaver1.sentex.ca b/test/stress/stress2/beaver1.sentex.ca new file mode 100644 index 0000000000..f1733eb7ee --- /dev/null +++ b/test/stress/stress2/beaver1.sentex.ca @@ -0,0 +1,15 @@ +# $FreeBSD$ + +# Configuration needed for the beaver1 test box + +export RUNDIR=/usr/tmp/stressX +TZ=Europe/Copenhagen; export TZ + +###export BLASTHOST=192.168.5.105 # orangutan +export BLASTHOST=127.0.0.1 # + +export DISKIMAGE=/usr/tmp/diskimage # Location of 1G disk image +export MNTPOINT=/mnt # Disk image mount point +export TESTUSER=test # Name of non root test user +###export MDSTART=5 # Start of free md units +###INCARNATIONS=125 diff --git a/test/stress/stress2/creat.cfg b/test/stress/stress2/creat.cfg new file mode 100644 index 0000000000..ef62b9d1b2 --- /dev/null +++ b/test/stress/stress2/creat.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/creat/creat" +export creatNODELAY=1 +export creatLOAD=100 diff --git a/test/stress/stress2/default.cfg b/test/stress/stress2/default.cfg new file mode 100644 index 0000000000..5096b69a9e --- /dev/null +++ b/test/stress/stress2/default.cfg @@ -0,0 +1,76 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +export RUNDIR=${RUNDIR:-/tmp/stressX} +export RUNTIME=${RUNTIME:-2m} +export VERBOSE=${VERBOSE:-1} +export LOAD=20 + +# The INCARNATIONS variable should be set to match the number of CPUs and +# the amount of RAM in the test box. +# 10 for a 1,8 GHz Celeron with 256 Mb of RAM +# 100 for a dual Xeon 1,8 GHz with 1024 Gb of RAM + +export INCARNATIONS=${INCARNATIONS:-20} + +# Change hostname! +#export BLASTHOST=192.168.1.2 # host with udp disacard enabled in inetd.conf +export BLASTHOST=192.168.1.3 # host with udp disacard enabled in inetd.conf + + +# Run all test cases: +export runRUNTIME=${runRUNTIME:-3d} # Run tests for three days +export runINCARNATIONS=1 +export runLOAD=100 + +export swapINCARNATIONS=$((2 * INCARNATIONS)) +export swapLOAD=80 + +export syscallKILL=1 + +export rwLOAD=70 +export mkdirLOAD=80 +export creatLOAD=80 + +export symlinkLOAD=20 + +export tcpKILL=1 +#export shmKILL=1 +export shmINCARNATIONS=5 + +export TESTPROGS=" +testcases/rw/rw +testcases/swap/swap +testcases/creat/creat +testcases/mkdir/mkdir +testcases/thr1/thr1 +testcases/udp/udp +testcases/tcp/tcp +" + +[ -r default.cfg ] && ulimit -t 200 # Do not run this for the misc sub directory + +# +# Defaults for ./misc tests +# + +diskimage=/var/tmp/diskimage # Location of 1G disk image +mntpoint=/mnt # Disk image mount point +testuser=pho # Name of non root test user +mdstart=5 # Start of free md units +part=a # partitition to use on a md FS + +# Wrapper for dd +dede () { # file, blocksize, count + local log=/tmp/$0.$$ + dd if=/dev/zero of=$1 bs=$2 count=$3 > $log 2>&1 + local status=$? + egrep -v "records in|records out|bytes transferred" $log + rm -f $log + return $status +} + +[ -f "./`hostname`" ] && . "./`hostname`" # source in local configuration +[ -f "../`hostname`" ] && . "../`hostname`" # source in local configuration diff --git a/test/stress/stress2/df.cfg b/test/stress/stress2/df.cfg new file mode 100644 index 0000000000..c3731be20f --- /dev/null +++ b/test/stress/stress2/df.cfg @@ -0,0 +1,12 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg +###export creatVERBOSE=3 # Remove comments for test +###export rwVERBOSE=3 # Remove comments for test + +# Only run these two test programs for VFS tests + +export TESTPROGS="testcases/creat/creat testcases/rw/rw" diff --git a/test/stress/stress2/disk.cfg b/test/stress/stress2/disk.cfg new file mode 100644 index 0000000000..3f621a096d --- /dev/null +++ b/test/stress/stress2/disk.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/rw/rw testcases/creat/creat testcases/mkdir/mkdir" +export rwNODELAY=1 +export rwLOAD=100 diff --git a/test/stress/stress2/doc/README b/test/stress/stress2/doc/README new file mode 100644 index 0000000000..100905e8e9 --- /dev/null +++ b/test/stress/stress2/doc/README @@ -0,0 +1,5 @@ +$FreeBSD$ + +stress.pdf An old (and out of date) document escribing the first + generation of the test suite. +linuxforum06.pdf The slides from a presentation at Linux Forum 2006 diff --git a/test/stress/stress2/doc/linuxforum06.pdf b/test/stress/stress2/doc/linuxforum06.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab9d685b36c383fe63baf10362a76b8c7a42fe99 GIT binary patch literal 523790 zcmeFYcT`i|_9z+!M0!VhP(YC0J48g92uPP26%YXd>7hnJdhgPugOo_`gx(RPMSAZ7 z2{k|nFW))8bML!%j5}T%D<7Dgpfn5xDPLGV3ot<4s)$XIajVtc^<6C!|=QdW();46s zii%{!Ztku&Zym{qA(_bu^Dpp3C_|3$yhCqIg-74I20nT{AD9|U0DM};ZcruF-ahFh zX|`x!N}qz%+RA{|{6?p&kuWuw%Jlp-2pr2sTnl77A%7cFjA6ARRJenOc>}?B7D?Va z;3@A|iXgVg7h7ogmTK(kE=igtdEV}Dl4emT$LH&f3|&}~JP7cvFiyL0bE$NUeQDtN zv@%beoj1B?E6`6Vq(4(FxAAY-JCES~)98}YJqN4GWd=fbux_&;;@zJ8bH_%uqRL@y zkLTjwZIoQ5q_FGuVM^S#Rh1Q&Icd?>(aM>UOgG!Eav3oyWEm73j^pJUHa#cW#Ba_U zIru>?ty7>npQ;ZwPS*b+2JY}*v?L?`hlKw+WM>zZkR~Jk?<3;>8Tp6c2Hu}+*o9u} zytB8la{o8Q^*!FX|Ld%V<6B!CvH#(Mv7I%JEt0~*|L&^W*x7z?XO|NBul_STcehtI zuFB4ipPZd+oZQ)Q6aI6Xvhzo0SN%_Kt#ETZxAC;Ive8p}_V1zp@b$T}!GE~=&mI4@ z03;-3WF-GbKHvViT>((OP}NWc+_?h)+`+v7xAOpH0N&lZ|GaSxANMA>Pe6c=Pe4pa zc<(+bF)1ktF$oD7IW;92ITbkx2_-!x6%8#N9UUpf0|t6p25MS5+JAoJ4j%3vd;%f@ z0wP*65;EHV$L+QQKz09a-`&@EcOC)mQr*F$x^vqD0OFpL;Lg7q;J@0PySQh(M|huz zm;`r09VOuI9X!0d_;~+3HSTJE+&BQAih%l|h|)b8-M55~TxdnV#OL1UcvjU(r}rDl zDfZ4akcgQ60Rtlw*JEy;C%obkl2Xz#vdYg@RMpfqUg#Sb8X3PfF}1R`d2jo{&fd-4 z!_y1m?GyAhI3zSIJR%`6DLEzeTUvTvenDYTaY^Zq>YCcR`i91)=C1CZ-oE~U!J&!C zsp%QSpV_(9we^k7t?ixNJ=F2Z>Dl=O`ts@@yzT(-{*4yy^WTX5Pk2$`@VbkSkB3kA z4_=5T+^2mOpIg;Q#381KqCLXEObIIubsp?=TK~ zgF?eu;HNpT*&da5eFK$w@1&m~D^x@uv0;3mbq#{Vp0gsvDS&=tsF>1~EJD*Mea)$l z**n9IcKn(B57kK7`1!1*-xaFLqK>f4H|6jTM_>Q`#JoViE%sBLuo_G>MN0IidX^A^ zs|SPl*czV(rH4l4(y@7$oH%+pMqafU2fS`@JSe@WqdRd9gs{B%e+x@=seHS!9vSp`kBH1pao{&<#)(Uu!>=Uw2`EeXY9% zpn0YGVay{FXi!Hx6EYy-I!dSfvcVYNc5~a6Jm++baOQ_d(qdkv`NJnID&{xVdGLqs zM`)g$1LeF0f!^tcKo7LqQjLQQ2fqRyUlGN+W%0@pny<2>ncx052ZzS6YZ!Fa-rHJ6a;m&JU8i%ix0c+}E-xus3SaMIf%Y7qf)|_%r z!%pesg-wrR$@=|_Y;FM5nT@i%i!7HV7er+FwE z-U0%DLOftlD;TA@YGF)H$)82md}%hHJ{|0Hn8_ptblyhaWsxt0@7T|3z;p~lKWVR= zOa1$6i78}#uo0!$R`db2a;$02hm}`#n5hM_?FJ4lA$aI{W+Y@fI{@T$Czp#aIrCr8 z**G+rA)EF#fA&1lHkdwez;cVMQ+&Omh$`o-Le$EUy`SzE2G11?UkY=a!ic8eZ^tM; z_+;$CDg2bybb_y1Kp9(TTfGDxO)GS+48yrOIp5#=5?ZoIvT7lP=oeQut-DF=w}57c z?p)$2iOy*|Zw18zINn5=tcQD#KK#dxm!ig`pU$SzSt= zeswriU?O&s#_S4;p*;uU4>~%c5?8q+u&k}oRcCSr7Row=RVT)FGN-Tl_rcH2(Jm}j zfNQGPbD>`!HHGJ;5Trb2;C=cqG?y^q{E6-BJtpJ8^y{3<07CrZzg!k}gS|KVm|Fmi z=Bn*MB+_bK%&d1+C(K7;^Q`}>O?C@fy_h)3_Oitsd$$=Fy$r+<^fmY0`p6aGxm&jYo0(*18?90gNB1+()5BZ9N-c;iw@I`YdEMu_v-DPFiiyu- zK`bixL?pY_=?AzLjG-IudIh=LHMUZ1?tqm*JbJ>CIup%g$C&_^mAV?NxiECiBI5L` zK&kbB8O+c$-L4h`fp!~;T6IkWa8Y(8dn*Z`sdW*L3vg^c@a@O%Si0mj3!kyBX0DmyfK7plNtZd%5g!8Gg~ZQ_P11}K z75vWvYjqmDJy_@-I6i8CmWg5X*Bqs~n5>rV-7ZDQ=?t8_nXgM)t+7u%ILRHNt3rF0 zY4qgs#j$kAjUabBCv;njauoG)$5-nZ8T?P{q)*T^T@5(aOBkZOBJvmC72E>e+r@}6 zRR&z@Py34v$0v5&X^W2A=1k1i;Fc+tw<@`G&fR=_yqEUXzwP~y?dK~mx_(HgPBZdXAtAGdORIG zqT-F1i3K^}B+9IQa3Pu5H?ECuV-aXlKmGS@OHE_U;fxJ=!gJShiU9AkmCs7}l=s<9 zTk1j%m(&ZRxf{|vTlILXU3P{b9Dfk0fqnd%=WY`pPHV8F`Oiom1ZM3H8yt<)&0CJ; zH(l$m3Nh?hDvUdNz{&RMWzS>XrIh`P&H0f73TYa^Q2SX}mouTx8axooo(M*pthL+% z2J%T2~Z$ROEB*vuxDCg4hCf>dg81-9hV?VkCZ_s?M}??zTUis<0gL z|7~WbTI1&C@>u$nhQ;@dWIT>XE#RPAK)qLwx}q@J7bmKy1Wq+aX?hZFVuoM+cHI0r zznCDIAI{9B?J|k}GDb?+xh{+@eP=%%-BRdps+p%aNunjsV(%(NV7=+=A@v)+pSuIE zpJ`o^L~kRRS22$5R6j=7%;Wvg2#gKLV8XM9+CG0ubJKkKD zgkl6v&_~}BbV+9Sz<0ya9UGtwOEA0(EMjFS=2M8_nEbJw{(J-W|2GlHdEJI#E@%M=obPzUsDMnq*gB z=r1APJo}!mckqK>{I#;5vd$d$dFsrWI~3GqNgTJ+%JydGSi<1W8Xc5lR79w*58=r|PNK4P)wE|&F5FhR8CwgEaCg{N=R zH(y($oVoGP29);%<1qDwW2wpIby1n?vI8`2@6*y<31PQht_qF8e<(k%YClFSKK9IG*AwxCU*nN5q~K1_6MRbF zKv^tpb762wP4U9(r2;Sdn%tPznaClZSm#%2?4Q-xjWf~2$JO6J&ea3(L}u_Vha;DEL^VfpHqUejXJW5zhrxO>Jk_&jQP_7*_e?3r3I z_Pi<9mg6w{>=z`Xdxq`tWcKi@FScKr7_SEw({!wk(C!kGxuk{6x#jbJqFx$c=`I-A zWErk3e?h4iy%f14MNKx7vyyj*osZ?fv$p35RO(-kl3BD>Z?y#kzDire?=s+e;Uk(j zBV;g$-v^Pt^h{8?2}VMr+;zg(7$*HxR!6m$O~%g{o}V|T*kx*)7#38Y{TypPX> z5t?#**xryp5|;9TQxC=*6+&1=Hx)1ptW$+wQ$vpVDe#)yis$^y=Q*X^8 zHRs z;D${Mozmc=&k8RhFed15oJ@a#zCrys-@MHS?Ao%<5{rNk}D%hr*FoR7MxWFjdw;p5G69-Li~ z8rrEJAc6t5*VUkhSAVbF0w{p-XL8b3foBx&*hC-3-2$qgCEo1aD5Jrs;f`AXLpy8t zdMpVfaN?pnCU~E4nNEkzv+1q#yQ-OwaDGn?bRx-ltOf^qo^%Zxx8b#lieF zX!k0!o(A(8xzZRuq&S?gbASJ&gg4+j;yYSsJ+vDhcEl1uheCw()zj1VQsO%&F|$eH}wIJ(Z%OKZ;BX0&mVNd2%85z>%HH%XFd0w)9y`P$SYm-OkvN?E<}c|_5~p)yODNmY?Bjxzr9^$ z5^S-U=;@3FEJFncp}@;R304ZeTR<@PwE@O24Y)?pw|hz=>P4a@xZ1(EM{2ajDSh#{ zrA-V=)PlOVf>(^4SQ4rpSOM0uL06=nwI?By7;V?QaKOyW2a!|G>|i#=R$Q0rt$1y{w9h65}@%Y2dtg!6~|&(njK?u4+k; zj6_ZlumKqQhT<)1|HV|+J-?=iN}VFhKijDCYl=DF^Lg~s3c_#iUoEk74 zv(7$0(B^XsC_4gspaaeM+$?q1N-urNsN6bhbI|;{$n8Xm9%$gwBjiG1{h&nV{M5;` zo^|XzI(DWF)&WEs+yZ8|`@MAMHPopUDx2t~Fkjr+F%3r8Ss;iX%Fq7{|gEtsi9|) zWNtc%hl_TIC-Q3WrDrM*#wUXgxscG6^YW{lZaDLPHeC}bkiNm0!BzGi&(pVmI}i;R zaU2b6F(1)ZUSz3J-zO9w*;OHrL`lr**(Q1b>o+B1Gr2{PT4Lwb5tmlyzPO9yFihwh zy0-5K!XQ5lj*r+r6iqql!7bor;aDoW^oq6A^`rJeBl6s&5IxcRJ9eZVw7O3T{;$A~ z;QC|0l59v~1=x=tE#u3G5(hOS{0xN8uY}oSdBpw_79$e**4Ia*y`Cn_+eBH&KXfU$uNtnq%lu)<7z+_{78c(rSD0)Y4N6`vBQi z`2{}&B)WG`MRCI8%PApgm{Q zlBn0#tofnBB#+aG7GoCDXZGFQOk_tsxK}<675m;YV>( z*2*E!K@X;o_kRER+i2ltUyd8k=_94hK&X(OYQj-;H+tHACLg9$XW3>$;X4nfGv z{MemkUozFaH?w<^YYC6`rq8&xz=$`uGC39hScJSoM@53EUTayaDa@w6!D#t_LfRif zta`@}f6J>C?hO>j{si|bQsfdtvmkV?Bc9~uXCHY0Tc(NL?}o0V9{koPP(2#ZUQ*D&rIgc8fMMtQ5aZr-MA=+txF1h~g%k~%;;W{f7GEz`t9Fh=K4~GoD&)zqiKT-e;(BfsU z_-lC|T!ee%ur3Tbuli0+x_@}xD_K7tZtBIVH_HqNKHP|DrRu{(L)V~b@9!peEzM5CjF!WXm=LbwFZHJ1 z3Q>gNmG7PWE@n2#6*HddqJzwBd%*V`ELqKjXgVt`_lEQ0AJ)T3_}fk1z^ zQGkAhGQz$NjH;z zR=<`tPo{1)O@fWo86zxw7n42;aloq^nu0HSMft;S0ZV$K6l=mzrtCFP-BUFb>``NE z(1``K>j6R5nq%Y71Wl>2R|9_~bH2}kcn|aaV<_w+==N+H+aaLfo1H7;7pXMXKeJRS z)VX*09Gum1$8`D$E3Eg@{o9M}Bnn3~#i>h;RavO8z6j;A`LIeNphpv3wD1Pv)beh* zh=G+vxiwr2eInjHMq=r1n;+S*;0wjjM4o45oI}tBiqw#XS8-_Oo(8~9YO27oiKR$~ zp3WU>Y5kpfv(J6-Hx8G7Q4PWCDD6m2j*ZsHi~1V8zy$KlE4I*+Jp%urYe{IQk-Wz( z;J&pdn*iFR46-Cd(M?vA3xjwMFX9E3aU$tB-0)=_hlmJ^99B-ED5m&!kqYqPO{^Lh zV{`loNcYS_d;a;vkp%PXb9&FXww{TG=PG(5I^%fYF{uMWRI$lTE!<8s`kl9J{e&R* zwP30($6fx99D^(F3kG62xY!>9Y!WBikh<`|Wd^9NP=u*!;u>ECNzVzy^=gR>Xjbo_ znZ^ZS#dpcp&ERGr%dyAg-eg!Aqi(t-MN_Ehu8yLhj~ur5G!w|x&qWu+UB1mpdmlXE zykVZYQda+6-U=#Kep_tDRZ+lK_sDWte<6G0On$nmmyhZxD_>VkbIp}T7j0fHfpx8h z`@`1iAlSspw%*?xT);CWO60taAnXGednH+3qOx)NQ^+S&I(itOwW&uvNdFds7IcD54(GmIn z7w!!V#%9MNeX?!ruElo3?FnW|OSD{KELr1=po_fyXXRPo^N-oTd;5Yasl=^ixh80B zIO3j%FN6L@oLAgmkPIrUo2#~z$ZF9p7k(bXCDec2GhH*$!ahG;)0?81GE-2lgk^E4-4MbTkkJ z@5-qa>TZ+k3!s2szfbj)Y;}?xb>z854#B(jbjG77)!7ki7cufw#pok72jpHZ4 z>ZpT1?{mzi(;5bcZL+ok0;&ZAlFu7L->mX&QT&@$tU?j%Z%5+F|Tyh*b>BMvt z#RGG{v0r=$zqc;f>Q?36$#s7d3bz4yTeqH86j&Zz4VBWBznQxbVm3d}aP>7FyP9fu z%6)h$UA|#Q-K;J9BGB+c+PMQUz6=04!6TPz7JJJTfhdbU*!Sn%&`^&VDf(XNq5j4# z#e1T`0U_;fc{LIsoF#8FhJFI=rkG=O6puDq^&?u>5DwLtet(xaoLssga}~^;S3h&E z;IKc3HO8O+Y(n@A(7}1En0!@;i@J5+w6^NNAT26rvGwb!vbn{%W;E2S>75{LUqPfd z!!4kkKsT`J@{2{&8&v?v;6q*nfaiY!d}|;ykIq4b7t(c3D0rEC;{?mIKTf)+s${`7 zTa)%W8$Vc?ZjAVQ(~6+~I?g34sCAyTU0EtySJ0w9#z6CSO&v69mll7@ah%Nwn}qHB zSVV#2WChx*D)wa&QGOOu^R13+nnAul%$wt^7L)~=gDwn(n=E^u-2#S1vgM5)OWXU6 z1%yr^x0KDoM25+9)GKTRf8PS6sx2^yG@b1f^~mHPCE8doFZpbb#nagnr$Pmb@NGtc zTDH$QYwx+si66!?_Pg5iy}n%XAy2E+T$^cfD}=nzv`~CvJMCd&tX&g9sac!g@|jSk z&*doMa)h5dtn`4p%=YxXBbX$9^A=#--Jg=h^A}z*zj)@XzY9Y@PVJmk6!Ei}!3ynr zR)B&ryhp_lyZ3}c31^?F7uY$->If}+5zQ`FIhMB9l74J;Xdv0= zb)ye-W*lz;+bOyBiLi~82&53(Eud2dZVLEA=HNF}6D zghy7vSKmZu`)c1Pxj2f(u{wYn3WU9XR=9UOyNG69%L#M$jg~*GszVW8`AKdE)l2F{ zGjNh3mzBY?kjV3oH~D^e-jCBtFdU62&AxdW1LVP9S2J_+kp~2+%b(1Bh|kEZuq1rz zzOyE^6koRZToqMY+p}H$e+?KIOGshpZUO6&W8VU(cfucBu>HEsI5{CauC#BoH=Ho! zfbI`m9Jelu4Q@Vp!z=CPTsV1 zS%E<2e5c{e7||%{KE8?jm3ZehH$UVZuU~8Cf+4Z1ZN;H=6_nL;dvh-zXh=`C@!pfpRJVYZuN)_Wpk!kpZR^|h z0tYAw+N0uK+_%xwgEpE5(r0-&RxN*wlUZ6Qmwqgj-#mh`Y`DZ8+BYZos){5pFC}2K zfBbrlF}v3B6Z_46cf;-~%GfQKxjxw={tMgieQsRbho`x&W{Q2*%Yk6TI)PpVKR^xR za58-EG+BrySo2rw@!1a9MtPRH+)+OguTUbbA6gi|7rQ?a)8oJS&LxhJGpE!&XYLlT z+7t3iz-iqO>EAp4@F9vmRibL(EDjI2-rO!1A&PPInQAY4p%*MYhnlWmT#7UZ&?5CI z3xh?BJgCVs0jFq`ah4~~Y3#%@-uw`kvk*IvL0XsEv1Vna6U>>F6Vs8FZC$4I--x*^ zPyF2f4R=t$Epw@_ej@9OB(Epye4WYdd7ZWh#}((4X1 zz!Y4?>Mr;iSA0&|vpMC`6<^D=IPxvJzR(gojUg&~!S^5}$aq`-OfLc)6sgkU-W98_ z(mNvgsr5qienqZ6=RZ~u<9o%9yHMhI;r#f|1m4hIGSmHDslgS0x*+p~1Apxe_u9{t zpP+M2(x)BU-u)AA*i+#G)Z%OAZuwe29MWActms-2XNC509t(cL4w~b@%Ucw@q~jyq zheug_!lSds2mjIhK8HN9c-~~bIF+E)fm+Zl_!VFq4sbIn8-nT2O($K~{5|%gIDZdT zzPGsWDDiCnxb3h048rv}Hm~V2RN}V-#|;~>&~4HKw!_Adkz%3I-hXV&H2Lb62(iLI znf|#m>IUB7JeTuqM(8l0f7O|m&(1V)13!G3ne!tO5U1MPCO_u0(Wh-sNBElz7u)j$Pd(6_8Smo;$e(2!{Us<3v@) z8{f0e=Q?ViB<_G+@()lWDxURwp8R^*-jtvruhWsg;Kp@`aNB|{n!W)~c-pDFa_VN% z;p2Gx*>F8nr>`!fg5h3+_67t&d`IAzoTx=0Y5WiVCmTnb0jDCVlUkd)U?-MyLqo^I5q0bMvj$*n2%^ zc5<}{ULulk3(!R#L|u^k)P@i&Kxq;!v%q(uodR%20jag4&!@{@=N5$R0tAtLnQ^bZ z!TdhaQ7=l$zh`qPMGwiweuGki+xIz+SN=%>!p3j`z~v~LpJ=jGiur4> zt)EnTK7*DMcyI2(24m4rKw;oDp@ZMZ?v5h!-7A75 z`>uH-VWW_XNZZv*m>%l+G9OlAJzKEx`s|0OZ9KZmk3V@$Q7GpKQ3>hu<2yk}tXblE zCkATzeSTgZ^)jlyOvsjo6G2X=rpIk=YjopOT8VS5{xPr9hg5%4NAQ&J^VOiiYZg}B zSZQQTZk`UO>936Pd7a|s!NBUvh^PJL^tuOw>*?!!vmk2_A$K&~4j#-TpD$vLj+ild zP-zvR5)Z#i6%2r?Yh(p|x>Gg4R=f82i*Zis zTk?|Qsg4Tc^@uOephB=;+qE^cQ?*s#TEb#<6-YK4%jEaM24MH8O7fh)d-GaZXvB=+ z5!Yqd-YZI-Enp;0v%SMkC~|{o{VY%tO9j_y6}1J4A0_v+Js$}TQeO*=s2LHaZ&z4m z-9It#R46Zd+;1z<7DJqoxOXLFT#Z@Q%yICu!^I%GOwBEH^86@~9{mv#fO*x1isz`g z672EQ0yzq=52zR=SdyRHI&Q0jfrB7wESJ6TuHMZ7g_?`Ab4+IfdsTwiRH)*amB#OK zcRumj$%A*b_1f`0-ziGZ6t~k`X4+lr9rR4~jKJa7?fR>gB;-jaPnr|{*2XTQK$z6= z^;(@EHnQKJL9=;RuK=Q!Rf%5hlgHTPITO2cdMf23diuXgwQ;d(J!C-D8?sEsmTln&mLvg$evnROx2jiEwUJ*-)HFrf+6RTb7khQ zRX!DHFsT=p*x(!fIh6X;%{`@$j1tTF)z-||W0P;&Zw0ZhkXw>cV=VC#MgGc*srlgf z6u$H!kE&s-QDSr$3B6`bcP80y&Ivt~{Ti{F{s=l}z7aIO5r1I$V|;~L*4NND8IRIo zHbyYo(2jE~yk|p1`;Z>$vMCC=?pwO^NnWd{8)o+ggSdiF4FoBu0|Wto4XoF<_bnq= z#@KcPgsU8)DPCFC-1~4xM3ZVAS6SeCZ#9|wb6=urv!;o|pI zZ+Rk)>++_Zdtwa&Usj!Cm|$VG>MJ$K#b2ecB97$sdDbGA9$Xf^JA1d|^lco$H8{i= z%QH=5glaps*Xz>=dRaF#|CDI=Pj=9Lt#uuQZc$pPoAUGkvEeTX=51`%;s=xeu02n5 z*(@Hqh+0Z@P;GKLtmSM)omZ`2r~X8~lPJo$c#k6Ju`zHvxlg&080FWGZ<|NS)Er9; zQS9!L6d=p18Rhd%To~%zOuMcT+4Baaoyq)ZXo#4g4Plt!iE}h~dbi{+fR(UL(~|Y0 zW+~8?V3=)rE1)!aL$`ApvS5Bw`S7NwJTFIG?Qi9g7viTbqL6kcbTo0?&HQIjDHp@x zSV4u6_>-aXrEv573OG+tRz6)PdcF4(L|HB2&|H4>SeYC;145JIYM8<*yY(B%I1@zf zsJV?3qjV_dfl;^(x|=lk-3|^)S>XE);*H17yQ*1ykHX}^T_J@DHgSRIidz6V&QTn} zN{-|k%a3j{y*MuA6UxA}T(YWl!9rcp5gw?}2;&1|F)FU)g8Yr=dzA*~+q|+?*{&i7 znw`JwB@CnKXbE)t0KG5jF1bFcynMO%BG&Ed0soNjtR$1PpDdzmpL-dT`uqtCvE5eI zxc=*tQ3LXbC|ms(K6*YA@dK4R`J*L-m&DHYUKLUj^LRr)`lL)9*z9JvzAYf!DFpNR z_8uVZJjE;)+6Uh1jkqL!*^y2Bb7!V?ze|y<9Yq-7)M~Nj0Oqx2GYrX+BnsrGBq1LS zgq*!s@bP&Ih*5PJ6Ax+OU_OLMr&GbChn)6g=f_%3cl`F(IA`Ft@Q5o=B!r$gjonk4Wq3W)?A|dmaD3O36!68%F zG041?YaK?0zIYj_i=2TMK?1uB7gA+y7QCo_o()m+dBPRsb#bQjHriXVL;^}^;Q%L> zNS3!iTj@cdsF`1c)yYM6iWD~$?W8(15b)YkDvIyL*8}V@sv?6Ui4~CMB_}C87-yWU zDb-~#p|=@ezZ|n1KBzAQBTK#kmF474ql*RW18`-nN{YgeIzYm(c5`~yW48oS8-X}j z)oT{4;@LR`M(U^+bl2{J67%9F8>8glQm+!JkNi4ZYDQ0TT*E%7lw&OKc>o4r`?12v zEu1bPV!?8t2nu5(JRF~<Yx#j7>kWfc+it8s$QSvuiuBc>E<~ixXaK+WVsH% z1&lvxo>mHVQ+{eScBVd1I<2%5tK_m!LVl|RTBe3n_8a)|`SS&$@EgfA$g-W+(vB-e zA&5xZ>$AP~CmC}4eez(J6NL{^vm2JeIda#=;gBvr=cAc6=iUp(6B!r{D!NZ9J&$TN zhf46cQUL;!tQ_mVV6G(2ZmJZmO4&mF!3BpB0^0|1E9n(P*H8J{7VWgA{=6)IH?=uj z;aLu6PX(GW6$OiKM(oC7sQ9}2_SbNAj8yk^60Hi&Uh_xEG8PHNRtoIko&C>+0spa* z?r&$yec((tew`Ps+0xYU>YfJo1f0~*8TA-Cr+glQ8tZi^7AltL-dO^M9Y3mxa^zPa ziVjh$=m|wToWilhI;a?M5V+bn;_#!BCE_*0^MjG7>ZhT}?NRpg9zMzYJ1*dFiiF5Z zBs^HWO(1bNWp2^P=4h+l()>Eq6P!nUT*Lb-nM7bIbXOiPSxw{@hf!WDPbD<_H^$?n zs!b2)4wrM!<&{?WB<_N_RNM?APCz9h)f?RgsquW7q((Yn?hejWI|v`gwHhRG5Y}lnFgP>+1~=RzTLy`6&Na0UHTqKoYUjd zIk1+49A4cDUo|6wi4Vt@4!dexzu$CT+z!@jedD26yd!Lt&(Fne#C8U!&|h)Qj9@IX zB?Z>$2Kltt|7~3wNbSs_SRLnVoT_8on8qmkj0$WOdiH79#K)K)e$3X^;7&}?F(>bf z&`!RbHm#`;^lquSLI@2bo8GfYn{(2>fdeJ48WtmHn>z4w>`Q+*$i5HEs8i6M=wJ??kc}XI@=FEF-mU`H;+{>a|CcUGB%qFLJRG)^_>^5q#frmK0 zKgCR#FO6)p_^eQZT%T*KP+n>HDq-!xWH)(uzsub8 z#lWlchi(n0mG8Vzww;$rds5Ws)ULF-_jqDvq)2V=8}(a&*Q1svZ$C8_+Uwa}W()Fx zejUqjr@x9Sy#+`}{%zCOfa%Y~&lnD6UPX9V@61JKHxzf5+BJ~4*$FRHX18^+DzOSX zXmF7}ix2eiMPz`4>a_ zK|N*nvc>kKAD^_mCKAoWwosHh?rz0uS${&_skNyt;*(xkePU8qx=8;*%@IG0!Wd|o&6C~rc}C+C|>(WjEPOT>{Eh42LVleP0&cW3-%QE81z5vR1HM$Dg! z`Q}PL0CMO<_PrQX5=oXu)Zw2E9xh#-@w>Qkrb*>p^VkEjhZck{wLc-a!ml3U%AqaC zR(-8&k-rjYtu{5K4O|dZCBW}=dng4v*@zr15FfU9%a1HL*nFb$k?&+ob~Ua9#{)4k zby^HldU>Qrp#*+FbDsX$F0`pQQ8)eI%a*~rJL%@u6BL`8`xaGd8M1A}Js5A|_mCu!g1&b=gji(7&FcxdrUhmw}NlglHQ= zu!@jyldy(HTz8HJFsg;y)cJUwDuxuj zf^ROA`>M=@({|7SZd4sc+aF>_+X3kGSe$y33Odbtr+f<#*s9kRzEZ!3LNnRK_Ap<+ zYPa9M>BELJD}dI%iUI_6*T;aeD9a_FOvjX0R3_I2o5#z0k9kL*aBM}ZVTm?Zk0=&M zaze9(QQ+>u>EUuF&+n6S3D7p$Gy!y-+O-Hq17#cf1P2-aQ@Y1eLGGs75Rx>ODk`pU)V8@lO|%n zDLR9(ZT{z4F?e2-MqOsdiELmsWgNVI;qSvzca#s3gzdj|O zO(+J)F{IaiQ{8I4=+RpNNi6JBztw=rpjiG;M10Vb@9)(|aZ9XW1sgZ_XXK4#a7rN> z0*gEp2B-gKtQqjLaLEx%M+q_N)PXb4VCE>t{;Oa94&4|>w_}a53Q^tF0MVS$DfLR9 z+Eyi@tdar$eaWA`StM_8`-ar-p{W5`LK7oiCEvL*_C9Q7uom`3Q53~LSnJ?(luW`_ z!9v9|c5}uN+ksd&7pNNiC0yK42Ym`gzFfXPh^rd^Q?t6E4|oiZSl9aq^>hel1);i< z?wry6FAAK1X;7rmEr1qC<)?`jK(72yNX?Oi2gLr))1wT~VC~-qOXhk$onW147}>b6 z8U$rKz;ECl8L@QG&Zmb5*(#I}t8U?W-fJxy;F$joNXeYluhLm=D$1ARO0Jt!Gz5<- zyrEYDh#>&q0-T7`|9l4SzM4we-r|@tP7L*|02&0qzNuvp848XtVCy>em@Kw?vW(Vd zkGOs!>uSDPQ?gcr2gq5R4w&MM7ecOLRVOMQ=uZV#$yG5ASrL*BH4?JTTH~KDD5!kw zUXAqSdBxCY_>>Ap+#c9oCNYvi%o{9qqySC;u?)FJ$h4^$)8e-KgZC-NK5`%~-}Wnk z%1@qPQa>&m`;zo~Ih#ClOlBVOvC|oxH*UJ~5YhSW=5ntk;PJ;d@m))=xhY4oqkXqYmhDP8ojBtqrkh{=-uR@SYI9e z!ZpZK%S?-{El1UQH~poo!dH6FD(_FvS`6J1&$yd7|Ebkbu-{Htnzl7=oy5qzL8K>- zc>c8gU^}?bpH~7%v6?lY_U9`@E_Z^XvSq6^mq{@|M5X%$XT`4uc_wKOmb;~L&To8e zj05@dl8Mn7Lz!l{cxvESdLN2hH-Tro$M99PhRWkP3-Jg~i+brqX7XvV0^|B4M-Qe! z+6dj`KEqB1_6P)OEEtz?$;t&%VpxBmd7pfH1YXM1dh>dnl_xB^@%g1wna*|X3So`Dg9DtwxP-9lT1=u+ScPmm5G7*-w4EN8J-EExD-x!a+kdN*?1zAR`m?qh)m4fUI zrT5h-)}L1FiuF|nE4aN{;(5pbw9?Pab{Q4@aPghB*TX1QL9R0NG4YT5F!OoQELu8V zZ53`y0`E{nq@LOXloa0NOhE)7-;Ff8E1Ws~{F5}$k&8DYz_x#zae4a9?pv(jO_;6! zI%^wm(xP-(0(qUbCvhuc_YXrKkt**1hC?{>M}tgDy*IqCjdE{^xG|X)7dUF*U<-N( z=XwVvK6NJ8Bl-c+S8LRcwIu?91>CM~0lX*BsHKNYIzdivW3*~4g&WM>I&rB@vhT4y zhGUNdP4kF~6qlk(wirLPLUrh;| zw(vy`ml}~kC|eUmR-abxu-TY!X4uAJf46g)`3v?dN5g$T-2y%&QCw~{5mQXZKv(FF zfK}i?tPq4`l?s&_5mcy&$1xHze|MNUmhZL+b%7XLY1UPRKV|xgeSj#rQs>2T0l~KT*wk;pv$-WbTvp z@DG&QVWrBPBGqUns*rHs1HF&V9u?&3?S4_EhXJk@uR!1#^($`z?+-;K+xv`hDu3cH zIEnMYtrW~QTEwOVU9%?CL$jj8h_i4lDJMM`ImUDA+kL~H3vgze4kTD>giRBT$s^i# zEeX)m6$*6~7kxZ=lld}se``q~hXsW7F2RaljekwAkb*_eCGys{(xI;KEuX5jR*4Fu z44t7dOl(mvGJNjoygK88G-w+IW4VbCPg9h@PApSn#h2i7?gyeeXjO4~tDNMgC!Cgl zc<=nux!U?M$NkqT7m{~qjEaqJbzGOT3lp#^*(Z$ynwP%`_-gzo=bj=9+IKZJ#8Do! z>iC$9S?x>O#0+VCQ;bPCXM)C_2CR1VkP+LRxi?ih_Jq&Ty5-EPJ*!^PP4ZWY4a4MD z89jvWGEyN!E!J9j*OVqx)xJGF<1HQ6`a4m+zq2R9R%tT@9THpFTp6LTr-;H1XZsTh zTCMJrQPan2Dd_6;O&^pFgATU3&7l{8=Wt@ly-pGfA2t0aZBf4-&ew(Ua5a(vF`a`R zEW8D$Bb|YZ2N6oyAKt{WPH~Y^3pxAO4+VC_BQ z+5Z23f2yj~R(nKCYg2nmTeXX#q-Kh$Rn%S~TB~M^q9|!=&$Nh5Y*j_=qDJi9#E6i@ z=j3z#zjMy_cFzA?I~U%!gqsT)Z?D($`FK7a_t)tjdCF*Nm zr#^mI!D_{_=`I#p&^MOD?Xi02iRfOMCl9`Byj7nadO7Y<7cowfMQ6Es`{XZ15 zI)EP8iI7y>*!{`E3(}l3JqxR%jBuT7&ma$@{qM9ZsRoL(?iZ3gfmz6uY9|R>w`{I7 zM)sQ&MMqaU>T!~IJ+HMfW;=-GjF;7x;nzYV8QNY^23|SV%w0ie>fC4@wxCBrfIWF5 zCf(3ZIg8B6AY!Y~kz|lNBj@m~>z-x@TO!rP#M-}SLNRzp!VQQazQ~mkv07ubj1Edy zqZOPKLK>0m-ydm^+xeELHNahA#|*~nt2u){zfpb5S2S*whxAPLi>-lgxTo``n5b8= zBd4Tp(QM{I5Q{(GX}vUl_xtMG-}6vICocAN6!NfxCJyC-Na8$Wss2_L=d;Sv(o=6h zrTd9w9UGB9jH!gzKd~Z4lE#LF`p$d$Bu!^rB4^JcR3mvIu;CpAVw&!CjkjfjiLhrK zbr^U&*~_i-)5^-1`-Kp(>-J22oP4*-RdbHL7Uw7a zf73k2p)XBiB(P1m_@<;MO^JKmg;!JgK~EAcU$joGFXHt1oUiIuz7$d!f(eyClvtzt zSJ~O?7SDw)sMJUaT08}D?HK4pUQqW#+Yp3JmbL#KGjJ+CCIv!rx!;MX4;`##~s7n+vu*O?>sj?Qp!Qb8H%J@VG7DP#57 z@^wV*Rf{>kVVU?l{zqBP8MvQ=d`HD^GV~WOkim=(Y9$67xF?BbpLcn*5H5^GCCgp7 zS*x5It*Xw?wI!GyG6ak<7;zg+lqX|Cvn53O^*Cd)iaR&kw6=-4g*UTRwqj@WKhhX5 zA6i*_7d)exX-06mUmNZV10)=9o;4oTq^vj~d?dWKNQ2_b#?#vZs(5E#f-=OR9q;Qe zIf)0G=}tk!!u{r)8KI$WBa3UA>gi*=QPq0{%igNm?LX`;r`J$g?>#m?o0!rnX-G?vC@BMY?xZ4W9 z^Um~>ptW4t+c0xs30{spW2)wgo9q5FA2Aq|oQ~PRjKQSec#7t(n98V!-D{7IpKaH| zLC9DwTfkJ@OS;mQMQ5vL%u%6b9v8n8p1lAuRPMg?`#C}VAj3M9f`156+cTVH56^$8 z_})9c3!>lLf`uiY6wu8w$hT^9iNNHnC|nnKP1nFC?yV7>S!LbsZr2;%3cr;+JsN*l z8i6Yx>wp|%jEsHQAqG>5TMRhQJ1>(nCk!a{XLs4cnJ%`#`pz5dnDc>KGYFr5Q}%PO zIcNt`AU&SeotE23=-q?kcN;5{U)^s$H$Oq#rrAE_n$eh4%L`R41qCoE6>&DI|I#Ox z?^z->AM#6>w01NSR?YpT3xV!Lk9$i?J)I<94igP(dp0GGI2r{WQ_K;8W6k z^Zg>)qRD10lF80AVukm{!bjS}_2y)+=@MR%urziKqs5ogKX z4bE3Gbg!3uh&3A$iIRxMx(<+4bvq3Me^Oaki-1lpJteusz1$`a;cCC{wDczSnfDIn zRcGjVg$G}Qdr6J_thmY|7M!6SYqo0)IbHMN-UD#A>p7!kuJ4?MB`(@sKd6y%axJ`Y zSQh2(T7QEt{7Cj6({(aH>`09ehdiISh9RL}MIWR_PV$Q;Uvbv%0PxFz9=Smc3WmtO z%kTeCd@YNDzE~9V4)_giYIoIeu-{6MaTai=`Kw2FbQ|{D@3k_UrP!i1px~u-eZNDN zln@?;ry+|tSIqfO9G1?JWfK99wE@X85YkV9*K@TO!>3H^z;&l=5`MAyt z$TsLhhodidur!C&;BRPM@7Ilxf+TmNQFf}$OCa|D0Tu5!s+Gf()W-n zB93ednKPlg=mZ?;2W%ip3qVSO07(Uywu6!cFT)G#Z^>Ra-gOaw!3R29F@J!5?WQZx zc&4~cfe@d^Av0pn>ykz+4{q_o|Dh1L+p*RA?R9BeMuSBHYAd}^|!Ji52e637*?ru<-39pW8FYs#N5kl z#WB)R9n%2H?f**Mp*r@wyrGOae1VDYMI@>PXdiR}rWs<6qQ~!Cd6poMBrF{90+D@C z`?=$-dXf(wmuuw)-OG$3PZd(@X7^185z!Z*K~#*E2x+ZRbx|~x+x8j+AdtDAf{uzRfp7e^!@wD*UX)$ZOtzNNc84Z%Z_+b*={5X zUF*!J|&(`O;kg4f8VDVx>7~t9*3e8@EcWouMECnYAWX*9AReVsoJ-uL4NR0 z<;WTiz_esTjogg7x~oexQA8ft}7_^~w~&c|&B?Xp)RxhK0-uY_8uR}EfdDJASGDL+2OA?whd zdq>GK(_ekPJf*-pc)%#1!3T|AxdM0_Qy`>?2z@vafFPGlDNV&n?V_tw6EkIZC)NKdM3GLRG=^yxv;p`>&<4`=(pCYqoj-c2-m+Z?{cJDW& zhYFx|7QY^A{IB5h!Iq zhff+{RZcj4IE2hF%Cbro2<`I?b&n=Zc8yA`p^|uR;D=2oAOJ?Ja*|>dKh2rm)=_Bz z&z}nX&UsTSP#F^?> z5toV7_>76bk}sX*#Qhq%7d+il2S=r?2G?|4JXl$E=j~2BA$k-LCi=j1BJi zv2mvuroO=6AeVDX?ommhU<5xU*Vxii&8pP`dCR1J0p3Yu2y-!LW=BPP`UWEiqY8+P ztlPtVd6dqrEpg?#kl^h4g&P*nI~b{j4`Fc<;GQm4dY3yd=}lX>sMlH@Yx)ZW>-!KH zcCT+RV4uW&VH&4e)Uz3Qk1g^*CvX=@MBuqIrDx7|%%ZLSI{zN1ob4HW3boc*q!d1_ zx~H^0SYlPyMF3=WSDE}AZBShq_cfLXC|$dG`K80=F}@XBe_P~Q?4CBAN!Iou>{h2W zBmbU+P0nysVOCY*0G4%g`kOu8o_lQ*NadQhdp2PG+x3lId}<(78Qx<(IzfcggN1i| zB%5(RSA~(@wZ6KTrCEF0f|W@KfHD0R&E5n(8>e!X``-N&@c6a=_VkHK*&U^^{%_NE zEp7YZGF?neS_zoT8wsFStsfB~e$DFg8v{&;KS2T$bSL$*?6#)gnkK71A?yF4fISn^ zza@M${w3yN1g>(khS2~qTKN=*yrZ>sk_~!$IWoMBRvQq%L|8{k!7Tc(B|nLfc*gV8 znJLVz#F@CwzIZhh$rX%H!Jn;C7KL2dTm-*5J8ayhDI**D2Oj`Z!hkiQeVyz%YkCKo z?b5Bzwgu$^mdSDY(PleL>xdg9? zoVhKjU!KT*^SLM&g+qY~p7rq?im=`=M>&7}u1YabZBKY1 zPZocJQ1?YkUmKd|Z)Ud1Yp9}A0NwMNotd9@g2I$?yp?)g9Iy1!JI~#ukT6LU75=xY zlsF=HbJ$g()#YS3btG@E$_s|OWx+nP2`>8MuyLpSW5iS*(UtTCV)73K2WqAGQmpxC zy1HHHmBMd*)xj(--7!?Y0xAcoP`m%QAk(!r#81Ft^4DwyJ`B+E*C7zy9Jw?231Lpo zXp{uY$9jkP#5^AzT~pkT$sN1 zmygB%J}dH%!_xmzR$N~ahv#f|$oKg>+6tVmJ4iHlMf(05&j2Qsq4)aQ!M;DU_Q=k_ zRnx(mkR0;Nn>d{|CWOrz;4nO28{`yl!OfqU^4K{FZ+3=bH9EbEm!?@266MIB!S^Y# z@zQg4KTcu#!ngV6woxuuanvn1?oUiJ2>fm3*diEtK+6s>{+iP|C8e;vA%u4}5O(~B zB0c8>F{S702p)f zHY4~^xAW-G4&#t zL*)CER@d}ryaXm3lj~kU>ST(99N*)_#YL#irRC-dRP2oH_(PoB+DsS}h?A{Ax=Y!l z{AKzDH>L5+a!;EW9uK`js$98H{@34W080qu3BUMocOiFuy?vVdg>i;XVPg6~6x%ud zY=0yr23HLy??$ng{P;vFrIHnU-OHt;4HzebPqWTl%@{MvT?$PDL~W!(d?q>$QT8ZB zcz$7F+l?8Gn%FXO>YaKcrt&u#)a&e~GF23P`1h<$rW?>Otd{DoVG>aEqKKLAxbA8^(4H#Rm3#FPpA!qGVB?HLPHo%XuEFqK&#|A*kL? zE6hEFzqf5rgy9#RF+vDpO4CJ-0YWbQsYNF4)@Pz=5|O?=~vX?XzeWlqN@ z?hTsb@N{WMB6s>VuKC8-wi{E- zN6*&>A{RZTi{<;DOvhiygCYS20w$^sG_c)t8C>dsS0b1i=2&R#557{p+_%j7H?T#> zk^epG<4^wanarO?)ynEJl{flhq?1`H4EyW{OI!e;5FUD-ZTj}&5UQJmcRGg`2NG?JHp2#A%NiDG zY;_3k<@v3V2_jru&Irk)Q_x_PVky0`I@1w_Z#n9wux~ISJfc$Nrsf zMd0rM-_rC0=Jy5w%q6$>iSn+untp7_{qc^I4tEkJF9_oJvRXJJp5|Gb)rlXe=d>9u%Er;sxa*IHFmuI zNIkN_Xmp^kdLyiYgEX42t`>h!yC{5wx$04Dg=V#{=C>y9ZSfHubXHH@@2+6nS;}?)1 z`8-I4w9(Bht$8dBr6cx`G9gLndy1eSP|1*IG+Gg{XBX*%&&6%v{PN zQFTE{uYLca(6o)aD0j4Hb@%pvp#1GDCuRj5g0LE2TVS1C>#QQ*yN38GNKl9by0f69 zzilJuNox3v5awtK&{KDZykw?c&L|Hj*+yu65A5UN0~1s|HZwa1pIX?$k!Lh4c^iQh zubC!Lf=tAlRk&}+7|D6Bl!5WLTfOK6^1Cnr-ZEpti<=&BQw@?z(DodgiiA~Tx{xGT zd73kZ{d)b$USB;~kv(E!A3NJyCBIr~Cv0e7k{v$0xGm}`+_fcdvA$5Bo)=))1R&nb z@8!W-PDAcgy659v8=F(fE7&dCDr4@3F(+(9*R3PZKBBEw@H7E2?~0yH?3F5eSJdP` zy0BfyG#v-D**GOR%~~`mbAawGcJ)dKv(lJreQEd;S1=}w?H{`<$llqA;6zDTyrZeSg#r$+n*%TEP~@Cvr^QUPC@WjRpO3^=wyrCkP{BBUF$ z$*(rb`v|x{@P=kv!uRG>7g-MjFto5TaJ_60N(TMxi2yXJkk(w2Mkp5OuAx-4~r@|1Z zMV;;ge1(V&s_ZTt)0sgC$P;hPa80Awnj-^`4h1IF-bMhw6TVO3?BvY`tDt!#CREKG zBey1U0m^7lnSm!5AV26%CU0>cIJjahR_Sf{URx)`cqt??pMT3R5eLK6UJ2YJ!I2{l z(;QOTCUpdJ6SW*Jk@MMY##oi3*4eW*KvoaZrq=AUPjJ;PL14ISH|XNyZKKeuNxKY? zTLe3ApN0IcD8H%|+aA5L3+sO<_MXDOnI1SQrxNuz-c&TRJ-*kXX$-`bIm#Rip^@EM zroAn2t$ZXi&5 z;-3mM{2fOantAvV=0E8Pdd8>&ImdcFtHT8MNk}{mYzqI~zD}{0_S*9|glUx>doAf^ z%;qCXo5nu$mx@6aBQ*3)e{A0ruC5n^&mL=4Q$zUvnofKRZT0+VTUhmbGw}VnF~pwy zEsIXLw30p`3ry%kF9eDlD+UKbt!IE6V&s*vqKY&LmWo`=7I{L-ioElvs<}3I%b7I9 zGIkm5Frql3Yk+f&H*21a$q9fsR;LR}tEtda`}@K2qwTNOZ0^h?>n$~Dj}g9ny+as4 zahBG6zKmLN9n+ONOq;h{XDJjDrJ+guePXRxu?ysBpcSMmq3tVLs+HNZe=5+ZLH~oN zf{HE~SHW9yZx(6lyk7Z<>URBU+=BNs=IMb^Q6vR&$gr!`vkA3WvUzT5T)Dfy9=(9bC{dhk><9nN%{%4 z`V1H$)4Gb6Fz7}z_V&0WmRQNGUSn6@DOwY6&iUBqLzdf=|)k9CQa5=bfw(AAy%RdyZOza`%nrl{x zfCDMXPeTMd!FG3;-g%MMs3*p?E3fL0tzzuJdTYbEMicsNbZX%uP`rF-(8+~eYU~Nw z`5lNzXwo6-Rr~>4(=2ji*KAn#@4U;QgtZ-Nol2*db-N{|J-8{Va)XDO>ZrO(P)_3W zTBOjl8+lO|DI*Lan#;XzI? zI$z2}GbdYV){``c1_8=zwQcY>R=l36!h4lu>s_T@m6E++sVoji_75&QkDD9jnQrdW z{OG((N()eJADmG198n$mG5ESl!SjG9b&+>$?1~G+qM}{GQv`Noeg%K~&@U#i>wA91 z^Pp|Ted(Lk`Y=W;Mn9T5?q>%a*rH>n1~%zJ(m`M`B1G)@~RZ z2_HMm^kuZ~x`)-kgmyt@V5(`K@1?F@Sbu=*H!CioZ^g0_H&+Hmv!9G zLivOY&u+YF-z4@4gWiGWp%?=wt=_8Xf{0FQA$exVDkX4i_8=M3e^n4pyngwVl2G*@ zRn7mRNdK=^iDqM~&()3Gd;+-Eyio1q4NbhZB3I`B_;34pKxsU{bI_*v-WKk!nRr|C zcUaQmUwp*)vrCN(vc===d!mOsts^PDEM{o*rmYQqxPRWprFh6&vU7U^e2r+X+W3Ci z?I_K+VML&xf?EzLI-M7@?|$Tx^H!6#%> zhhh*tMz^D;b*jo+>e{AyMmhwp+(rRA1(r(l*ZA)q>dxKdydl(d_LML4oC<78yowE2 z(uf~GF(1A$&;YOUCVe;SJhIh$_eJ}JPOpp|`^U`8qWio9D0C2F%Ot7mYAjP9jE5G$ zav}d^c==hXCZxC!xEdM^CmbRrkq1V`39AjL=Ej6L?%VInfl-Qw=Dh=*Jb4|}u)Hb> z%Pd0u!Pr73?gN=9j@{Fb?p0nr9DbPeJ#UrmedrCBD4}xp)2;n1tQvrGM;4~+Kg2BT z+9`qc`RPO$x>KKFYC}L>(jH^4=|l9q%JetlRwxvA2#TknW;@Q``*f#o*?YrRB1@*j zqmS}FC_Mp~SxVbcD;}lW6gCvbUHeMpIZwhZv@5~u$nefVhcdlvElsXi;Ah2??0Vp} z&VLKcOnjrU`U(?KD5y3mVs+7BQV-_O{P4Wc^WLD(qBz_Y;lUA0`|qZtu)BKe`r*9R zt5$7>WLdtrR7H!zK6)$qqRo|=O@!bd-!YAsU;k{tR1y83Ys)TZ-<72oU|G9h&T4P{_3=hb~DyBu(_zNgZ3r#5Gx6S!E zH>H$_t2O@82P9BLDo*0=wrAp^rY?I|=5Et#FOKn1Fs|i@kQ-O3OX^dEHe<)}Mt$Wn zsB5ZfE>c~lubY$?;93|FZkJn743!?@PYq^WdKLc%CVdaOR}#M9Z^zWlaCIBXq)@Y$ z;2o1QcKSXFb6D0aLtp*|Cb6-vA{Um}L7QX1 zJd*nk+axlDsBj9w*5p zf^y)@k*qh!(MOED-J-kUBdgZ@BO|e$n|)`5TGNrYMxf1^q*X!<8@LrSmQ?NXOT)lf z7TMg?rY#_B@wOPyI(P63r}2xX(tR-9-Xt#!1Sm69sfC+-@Qr?Iq%Nh}3Nn7)^~TN{ z?wjmye<$TP1$h^mv1wg#&GVWwXOxiR{X=)R{SWfFIcnQ8cdC`=PiN~@o-IY%H+Mh3 z8Qp!h*%EO-Vs}T8oAPc;fzF^JeS=>Z4(?O2VBi%c7K2=VlU&DSyEWk3u)_&GX zTbM8M2;jWiNkYL}z+Z=I!%mJo47EaDh!RY%p~wQ^N`e5JvVaD@WEB)uH}~7d{hJ-j zz>D<7_kd!t3(yt{rl9}oMdIb+qvu~i54y&l+$Sb}%a>n{B5G_Mw^oIINWr5TutmbhJ<^ zXE5)ZjPdOcJ;$42HQy!UZRY1-*W3fI8!|y?Mj{Jh$1s*VVxwP7$Fz_6Oc^#mc+_Tm z77Ow z=&*=#eSloJb4WsY$bJwgV*n!7CKt<;6xenH#`aZ=UgmZBpjWf=`qI;SuQd${+JUgy z%EsoL^y1Imi4H8sM@{@NZ9J%F3xD=uD%l<38+bT2t0E+Lkyr3a+hNAWZ&4}xqGmFp z)wW|S7a7hzsR3Op&`|Mf&2+e{J}4&5w8E{o_GC5?>)8#mYHin&m=yASb5)mj@7aKj zCuBYA)MYdRqp6C%nr8nnha=$LiF5hy=cQxVHz$5`;El1XjAXfn@DWS z{K$`hrIxo8IpgTKf#XghwcW(Z*b}_D_|KG$o~pt`YDW)cE-OS{3FAvoD@b|ojCACg z;yH}qgx~2DznltFj+J_0&>%x;%RAioAkAl!B1WY2>GiMb%>Tmmp~%?-`Lf8dNcxo3 zWRJ*uGdFDA!qogGjgv!D)pcVkoR0QoUgoWss9N6)=P4L_mh=XP&c=5{o_%UAH!!)^L&h#b&iR(ft+>RF9ct#)r!Yw z-ctR&oL)KNS@HNm_P+LhR{E+B*Y?tlH^S4Ws5^7PdRIe3OQ~L;Kk-kl;LZ0~XK52m z#CtqbF&xL`;SB08GT91;sSRc-^s@8z#6%H;i1hXc{0{&&5@Uj-V#qBC$ycotw^U>l z-|OhL^z~gnZ1a)$#&Xw297K?md=90j%Nd>Rf>tZ1^Zh@Nc}(kZ8G66gghmXq)t?$K@0l~|QkE~| z;kMy7-dWM}mv)AbihN$QV;Pf*?sKm{`?)}aRY+#nn_VYQemX`X7`HrJ3sn(tBWRB+ z!LUtD-DZbVGKeZo=L;Xx^CLZSyCpICX-c&er%xm#+U=sZS1KTZFEcJXY&4GsO_K~8 zQ-4st^Ro0R>K-*$Wcf_Aq&A(dxUGFtv?PiBiCh>w>`7QUSh{v`j=));!X^InlB+o9 z%Xs9KGMh+QV-s@U9r);YSC+Q_-i5`&)k!A1)wWMCr6PJ~qUR4J@cIz87nh3<#T;Jc zWU*hiUHBueHS=u!^<)NFQe50~DF1mSbCRkf5Q;GbQW|0PaCO+=zJ$*P4Jd|reZkz! zH=5nD+D)3o_xYL^VY3x+DT`x2n+MtUF=?Ng@`;>84%qK-Tes?iFHNymU-!LL(AloM zMnSB!5k=?|A^*;R{`X5_3pF2)TkJ9pl)V~qQiji22?@2=)3ply{P;8^G()R>MU6fJO`ZgyQnk2I z=}yh9nTE|Y4E($76lc6~dRvK?QJ#I53Xua~nn=yT*O!tQUHILyd)(9eZ2L{0QsYNq z)SW5m2aokOuccJmdfbzoX_B?;3p2P8Z-GzTuJOU9dQL&ejrLV1m`P_gIn(dje}lv@ z>}{m!!MYO0q{UhWc&fNsC`igAqY7fHpKGzyVW;1}@(nHhqbDyHJviJVytPPMnyXP} zE%15J##)gcv4mhJFLRgD5TFV<-UVaXF_T#;IFJ@H?M^0})V5YgRRPz0`IoXPZB$eo zW1g3xuv8b8c2=$(_Fz|ynL7tdl$-4tWIq|^3)O~B`Pk(?9WbA6poLU=Ld!H%=Ha^g z4Mr-=8g!mQ)XEon7NGJ~H=6-?u+l~EhlXXQ-QXsMo=1sXnZF?|ic2BRDMJD_VJfn8yz9`rvXLd!5UN*;CzHCX6CT>DM=^)OVcA3UQHvm&3~#BLo2AHr=qy z1_2wi16DR9)V5dlr(`&z>s^Uo&DFBc3Do?0`%2ND-7h)EB^4s>j!FTIzP^$2@_KGx zL9hSW>}D7RMb*jweMt6iX9&(hVV(jLW|w)jG|ANM5De*1fnfb*O0k#rYQmzCs82}E znF0Am;V0LCUe1<{zZ&unOpZ*&M@MOzbFl^GiT_;`m%IG_)t+dJug9vdSyfLAY1NdE z`FPx2N93)70GO*sPnp(y`x*waqfW__d2Ub(MDe`^jVhK7(XeVva|3kG`@SDSHF?yspHvkVx?*iTtP(F zOf|HcFa8*mlIojKmpxT|<+?520}&k$*vyEaGg@Y}Z{aPSJhZpO__2>CSb=f+gLhl; zam;jSq+b$bn@Ejn_{6IPK*mNu(Xc54wRfc$u)`Co{((ogrDErB-n+$TOTWkuyij_p z*=*`yePFG^ZY8Q;pUQ1b!xa;|+6)I_iuBwAWkwW}qe(n#DAN^hlk01wKba0ND0klC zFV^A;K7l2;VYESemQ=F;6*|5bXY9y83rdyMdxx{CUz_QbB4P`{A1<-oggPjzDPhqj z!eRH%>>{2%?4ym>>Vs8vBLtJdNAA0^#j&VGGNLtI;Pk?WK#Pa3Al@{j2P*e1(@7)M zu6Wf3>OW79(47^W{lRtz`R7%}r{}%&9q-PnCH|qH2=V)eLhB{0tW6oDlzvFW&6YN2 z6r=ZdAK@XUvD2yxJ*#Z?s+m^jRV184{2nL)>Ir+>%6H8Om3YbYgi_sUre?z*rlTu- zX?gT_0Du>Bi1&4oF2IC8?8J6{lglD|ZjsqzhDgnVy!(i|s^|Bg`1XPZTV11x%3pL# zm$fI`PgPkXvXo(i+%?vtSI7bg$`&$!_sYI-5Na~{wNOevLBjODTH!U5z`WP*u9QF67O$7}aoiRa(I`Y7 z2YQUQFB+yEz?(MaOqj%b2XDl@O%}qRH%-4+BzZ8<=ygmX_>w%I*|^{P?LA41IH5J8-)cY`{6?sI_Wkh=8 zN6C67-6d9zgS)oIu^^#~g895tE)`#K66f{!_aBo_gQu)*_j=?OeW$e{0^Zq zYQvXdc6&7MZkY&pH+`{r!(T(H)jj*Iq6_ZG;%}mtdmGVfhwt~rpwAgm)f zt;^NZ*?gH~ANsfZFI_JhPW?=!*B;!Llc}UST)Pgq9}8rS@ci|OE1BnLci>(%njxJ; znd2n;>}O@R2)B!Bzv1u~ciYXga2woCu-uUt-K9fIiQQ^?M=Pkv@b9A#U%{({s%q4wnn5oB5w!EP8ktxko*+{oiFp0jXrG?HwD^bPtSSn|(o0>}j~g0%E9?DtyWj&I?HXP;&VaP5KS51D`R_Eaf|aX? z2S;kVqF-7~lm2t!_5b&rIXPKC=LI-K`To>$#AbZyBI>NHA!Te=!YPqr;|m_NQf}7} z$@I%CVaR1t@G6|JiO^nwG1>zDZ1dQG53O~988eGFDXo@`>KdN^vhJqkUrPX;(;@#i zh2lTeivM^{i3T>ACdz2=6K)YLr}nu914#)|bg(gFM~wJG3>Q?2?q7j{@fll#J~-nrcw zzfnc4g$2K7)fCKT{Zw`cF}l%0NWFO;zZRPL7{9a9Hpj*>n=L;l9RFtXN}uT2oixhJ zX^&E_WM;iB`?3KUif$}hPcV;@N&&=j*Lo9!$bnL_n5otxK*Jj}y*I;7bVv)? z>24)`uT0=g4_<9}-dVg#%&kK`;|W)4T%yF*SO?Wu$A9H~WxNA4%CBP1n_`C z+U~&Z@C$VgO(VJmxDvS9iaNLt@h2$Z{f#Gm*5Lh@w+i4v^L(_qNs9O6NqTW?-$*Y;S71crsd+nlD{ zpFDY6XJrti|5}42dN*C~T6RY(-FJMuQG0bL=zy)1g zdwWeAbN7vVbA3sSxl%ZHu$?pJ7>frLT>h#XF7N-cJ+s#tzK8inMmn)d{{ph95Ub{k zQdQ=4-fgl7NxG7v^i7EYbkFAee#L}0UaoEViAOHKll@Tm9?b>Wa3zyKz8REI2}g)A z-F@#jc!ZFnS)Otp^w6HjA&MT@za~=#oXw@^{hyvj7)tRPwxgO=-p+I8j>`AEH3h^5 zcZ0QmAXFxkJ~rB*(!n?j3^#s<0L43vtQj;QZYbkQetcJ!9)6{=wiKKK9hEo}N67$J z65&iPZH@SRtP+`@VDIp!zo=VYWF(zHh=%LR&`=SO7x4~6khuP(OFt-EynSytROu2& zKC{y7$N%etE7|c2!9~UdiOc0nWsK%8Papb_iI=EJ?(f$js}tRC!zFS*4Vrg>_Ot%Q zu2D;ovScFFA@}OBuo$TgAPa=c_#l4nLxQ(gHc?;m0$f&IxL}c56SGY&W!CLQK@GO&D*zl}3C{lj>YjyG+*@rdD z$5i4zt`mBcnb{7jCGUU55B|S--3E;7@702%TOwRSBGSEZl!ytPBAbI;I`;J}M(e={r zs|u1KSKjlNews3@Ngh2EN_kSR&PPq*XK;dWdS7!0=S@iIxQx#TDF9jHkt_PY51+{h zcLWYvCKty<-o7pITWU@A0S{Zo%_|X}eHs8?<%CY@x#c0BI~^&FSqhCM1N2yZ8%k;Q zD=sQyXFB1zJN+)Ht?zHmMV6)a*deo(xf#mLhtA9rn=aq?@#R@^7xPh>I7|<*?TgF) zUYQVx%W1lqGSRvMlP==&?+--{E(UCqPm%I=)OE?ee2O&hjF+6li5Ek=s>TVk1@<9k zol21t%k-DL4{!7bm-om}Zanfvmk2YqIiY-foWgMZ^FQ+K4E!E1JPWIAl>sgyzEq_3Wn+cSZV&Q^TIz7o z(NIwCm?B;fum11a)c>oWiC9uC)X|hV#Ask1K7fiE|Kd53ATkRPe9~Z(CK8ZwpOUa2 z=?w7y!5nFYfyOQKp8yj*6%z~;z-;qxn_BN|iz%2C$KOa(j(R{7rH7^LkL)S$+BKc& zd_^h&K8MAD8?x3sbFyazIIwk5j##C*CCh=82NvR_Io~L`$meSJ$U*TO^MR^i18LOO zpNq$E&Att`GtF(y)qf~V#xC69TppTxnNw?^(G`XOEoo8?${qgZNWh}+ckKWZ7(3Oh13T~mrKT`mCj-Sa49o~B~=WMX!&w|&f{oyHyoFqc@{ z-B794=oD~Sgl2CYhMID^s1(274Ob1yhNmvWz6U3^%a`F32aI^XkG=oN|01PP!yPqxuZ61Fprt)IcYdb>~doSS?R3r{bonH8!!Fl{u~1Y#n|SKsVnedt#Xcv36l@HvdpWD?xkI z#rJr`na;0*M;hI(g*+1xI!vXomXA^q{y3AJi{&)vY~uj2YGqdV<}+9U>mU2+^J?=W zKKgzmLp5!x^zveALj&-g&kW(9pF3*)_BbdyToHfH`~K;e!h>(O_kDD^fHlhZ_>M1T zHR`JEz}@~k?!MBtX7*Fx_{DEUM#F53suqkSg7U0cMSpR)3qP-)$Lkb5iSU0E;?Qb^V9XUQ3Ld} zjWK)Ns0x|i-#z=ZDIpBp#-uXdyT@cwpcx#9Fiqro<*2`w@>G=4Oqc!sHU+}IC(imt z2YIJQvyG^q4ypul}(smzw>?cwng*Wrfif=XHbn{b4w$R$Z`<} zV2VQjQ4q|^9~VZ5X^q=9kz>R2pqEST?&&$qgS?F^(Nr6jV-@Q6xwX2O9!%xTvRMV` zja$4gp%xp=>dfir^fYZV89BU(FPZD+zWGDcWd2JDyW+4^QdHc|Qf{Ct`#~{oR$ue~M#oO8-N{eSqKtExlS8`=0G+`FDz_)Zk6vdd~3CYy^@yAOPrp8GeAvTQ-z zBijt#T7=w#7?Wx>Jh6;A?vfg+PCFhOej0OQnVgy^zYMH{C6?2cyvK)kU5sG7YP0v# zGfB8}5IJ4w2#$ny-|l1+i2}O3gXn3<^;d*+UfMr2Rd7CI`4-1abEdENI{duw1Hy-v zpAR;GUtkY=|F!CiA5@cb{qp#L+`)EG9skFy^naSO{-6D>x(3?QDw8Co)7Vt>+moZW zSS_~B1fKa;!YYyCd}|PnF&&#bUcKcy)ycJu^Oybeay)ux1WtJVooSUJM1+j$NOPc1 zsrBjPBp(k8W;zwSvP$bhaLIqZT}@GnYuh_o zZRZBBk4+BFQpv7DHIcX>9%J6Y+mh+c;@^93z1h8v$cvlBzPxS>8Q*pS|N-A~P*oHC$RArdj7+X8=d-MBg6*gZv&R1XIvaPXA7L$!}r> zIMybx!NDr2eD{J+v=7;tQ!&KDK{j}Tp};H`JBTb+yaDcl9Yt_?Q+y1~*PDI4^@kE{ z6ta9tn}R(op$=s)Fe8pAp2M$7OZjmBHo(KO> z+~7rn-Vs%=2+DaV4dIex7vi{0yM7vjW@Mi>;5;Hz5L2g^V>Bcfdq+e40IRpYhFHGo z#|)v3yIfU89@tvUzOcjktIqq+wm9My!>+;5Bf#DnPcL^L{$hy<(WjKBT4jG`8C(eW zLriuxIyMff!t88V{-O9JKOK$j?cu(IB&UL-7Di3?xN61c;?&GGO7wEZg7I+IY!~94 z7&tOpN&Ym5c&d4Iq`~V!gJo!$zL5K!z*I%v+&?Rny9V2ud(q%TKTmz8xOU~Ly+pgR zd7E3F9_@khN@$o9+ujqIs6Yf)>)0BL~zL}3?!npqDq^#qZOK5Vu~#%s+e3d)zgrj3(Q zw~!5QB|P1pR+BkQER?G1|Bbizj%u>))_sGZCSNtNnWko#;a z<>~gWhTncjr=jx0O?2Kn!7Is;vGmGa7#O1o~>%d|apM8#-AgfF%T7Rwg85dhOw zbcGtEQW#liu{oObMm<{US@QfR2RyoWWQMt26hCqd$Xc-M&%chsI8d{Gv3{+oBzEML=aS{ecg{<@=fjl zd+Y<*ex7;5jT}0FU+01(@B@%#%q(5k$r&=zyG;BF;fN=|txi;qF@nA6^;NA8`Vkbd z9^`M9`HM?~q{=Dgk4;+)w~%A# zx&Tz)g*`{*T3L%kUFak0H3w=d?M2kMK_r5ca~^!n0r&-C%pQY=yV#KdUo z**7|Cg+9ocf(a^J$x`w!P-W2^&Pc}O{k;-DkKGuDqEQt_-1-sjpUv3kRq>Y}%SC_5 zfiuu6Mlrnc(#hA~KQnkcWT3DWYp4;gR9h6S6JqiV07Y=s7FB>~1ohIBtrw3W{n1Z~(@l;_`XZZVTkCbx0yhZGM=Bji2WKs_F!D|~8RDfJ=2fRwB z$dc*olb00f=T(F9>)`NeuN~_tTA7q{aGGbm&{#)j=(z_}1-&+U_Em+!wj{o504QOo^v#$aAU1+YcAUFT74lUGb<9oaET!Fd2Uw*^kitv< z7D!C?NFXE2pK`z0aL*{5gD&uT>HX~=h9QOH;g-76c{j#ZQJu-Hf?F=7R}Y-;6WWjR zM;KZROaP3>gpJ0-k>A$Ifa(B-=LlrpVZix;Q?jdrAyUC zaU&fb1VMp!d%Fedl4wS{KP6U;V2m=`rC=BV3jvf+G_%^^6wg*l1u5adKLhAiL_5S| zBRBd;x9^`X^#8A~bl(sJ5uGyT_ZTN2BADgdAQ#Go|FhREE(#C1v=QQ^nX>LzVm8JJ z$+uZw1!b=_L+ARsANZq5R3asFytaKg8zr{7Qv<(7E>2!w_Nv=&YQY4soPtN&n1ATE z1JdUYV}KvR=r7RmG9Z8LfH?kh$>Ri^V*KSGf6n`QJ#&jiwbASGDw1+v+m?7&nq2JqHnM6NfJ-{E0?3O*6wi=wSyFAiLQwh z;pj1)??5ZV{@)w={xj+OKYqpt1sHhVnd~uh+v%?5JF8Cijg1Lv9O`*@zxRcJSb2Y3 zjuu%HG3R4KdZ$a1n)B z{ygU7Wl9txY{D|E8{C=Z)bMU|ua@*5y^d0d42QkAc8#oAnmzRtRriwcwNuU`PBK99 zLX#7pZIcKmYR`N)hKzhhtA5D%LEt#yk9g5qrzkAm2joWlB4WIG675vH?Yv($ndvA~ ze!hZ&A|cf>JA+t{8L(j$j-d9<$e|{k%cRmrGs_OX)S_`3*q_>QvaF zoqPjRGyQ0eQ2|tz77G@Q{%dg|c0MmVC~hco)lI=wj6ZA)jTe_sKVASXWB>oQLx$!h zoSz#I+D4gz#O~Nh=)6GCrjv5_KSxVPX3M&k{NsrNYe*H`FrnsWeJZu*Q6QX&tyaq%B|MTO@mg>9cDzg|5bVAq!r*h+;&m-MUYXEo7d9KYUi zRP{dS-tU`F3aGeJJ0Yd@l}1D@az}2l%#Sv!s9lF5O+r@v!+NZ{Ys0y4UmfhXYiHpd z%@jsk(qA9~c(EYP$LFxNq*PDOimu)3y4$lsW|4bs!w_fvPrgK+%H;<{u8xk^vci_`^hP8$hU*bPL+E{ z>&LA}%V!3@l|QrHR4EH24}p(qAK+UXDEcFYK^t$U>hmdn5u?1rpx}`M$Y)LA zY-H)|_N;blk&R&Xw_}Q?P@@febA&Nb`AVfBMB$$s)PMLYG6)xkj{|i#oMJ``64&BV zuyMf63#3Z=%q2*Kzm-u(-1VAj<0jMqBdRBOBr-4a89`|IR8mAp$q4Tkov2KWYNh$o zuhbKB^jlS!PqxEar+>3+rR>#~@N@3p0;3`|dw+qVp)AB(IK!@rN`Ju6i-G1YG4s30EJIC{}zP?p``miwQL%F0fF{iIJC-by))FHXWFNKO#yrF2nwIixC z8Pc^C+-IdbM7K!=pCI~VHQWPgmz$6750%WT`k@f~S2%oVJg1{iy?WS|h&;2LLmT0h zg?cxsZ7FK^tEf3%&}!IozwioG--K2!RYN)=2{bsmP7?E1s@d(QJ~Z~80~sW*H64w; z2)7V``^?nZQW`0ll41}zvY19N9EB}n_~wrROLbd5$@f28?*D|0 z`L7;_Fe8?8;Ox3rfFZ+*G?&ZbJ67g*0ZuR*L3Z0mN@GUVNr@WC&4tXj{a~gqHF1eIh`q5eNTGG6sNwhDJrVHSARSUUl*CdAv z0WfbJORJ-z;2%Y8ici?)Wq{eccsNz$T_|I|_x9I>jYahS-Yi(hVgyt%Jl|R{ChPHN z#_%lhlCDiO-G=4 zyS@qzDt_hS*C|4#gZu=0HGdLeXK((kD){GN`%2^8SaP>l_gJnkpG~hh?0Df&$HUca zNn3;1D^;sVav?iMh3ioTTd(fup7rzS*+RTIV=o9C)0-6xH1gmP{zw6U&U)E-P0>$t zQqtoF@1d8thEB*;1<^H;d~@rM zbjPjVkf+=EY-Q07mJ4n_R&lKLo+=R(j zID0ys*_}@8qLS(p)K{)}Hf1^*as8Tp=EBp(b#si!UKqnEJn6PFY}MQncd_OUWHgEW zEOBemDqPr3V^ffElFsu0XG-4x-BOisulqHv`l%Pn`SjZacJ5eX2Ha#vh*e?p3`kKw z7@85>K+jk;2wYf{1b=vO_WY*M$XErvGF=F|M4$8Hj@gsbIR|># zt^ALH2UQ)LP;}h^Gx65au~*u0FoDw6Cml)T&ldEo*iQP^m|~ac#c>_6nemDK;yB?1 zUF5PSXz*O9)a5hLGjq+z3+7|#X0>+wr(Ww%`s2Qesg1z0-gGQbN#sMy zTbbJ48+y1#6D%=AT(UzAuzjG^2y`*D7%6n=^F#~v`iI44zRCtfpa#%+SOp$2K zr@F6Hww#uRGh|tdsA>ZyS&A@$IzMwpvsJv?fy#L`!+Ii&hozvhpJ%YRw`%RGwVAWFi_; z;agM}pti$WQGg7qs9kQ?4t}i!J-)SO1K{#piQ83<$jl*UVSmkvW0$@0BVi&(b?Dy8 z_j@B$+Sm8B+8#1I__7dt1D=wC6%Va8U*a!W5m_JixZ`>E^+z)**@ssiQVIu4oJQ}q zuofa-5iGQ-1?jO3%6HHXJmLVIjH%*>C)DML%I6*~&Ztytg7_^X7W)DDlmK+YFIxgq zQv>XD*Ai2$6U-&A=Y7v%dZd90EBialo7D!<0YIS`17o{rAzg*Je~GsO_sPMNi#a^T zd`^u!H-V+^s@YYOv)=ED+xw}Gw_D!kG)6pJ@r;One!X0=V|iMr6vlxo1hn}zZ9O7L zjKggtu4vGQiO}h(nWthX*U$UcP!n%=e2iz)^81es!+=Y^|=y@yq@8G`+9!mjzgRE#Ho{ zfU&wn2Ki$+!5Y^31S_3YX60~c>Cr-Q1NKLR3IIvChwcwTgtT!5d_PMWE+|)5gSa%y z0?wXCkP4q>@wWi5eLqrn^v}*O{kP&DxE?{4TpPCa#?>mGL{>>bF?`^@{l7pG+klk~ z*levbtsLqJX1F|Kz(_*B)pjS#b>|Bt#@T&dv7rQ=t;7%WB&_3)7qy`5{^un63o896 zNjl2UwNbrZQGC2#X+Pb6*<({u5O7m);g{W0{ict9gJ~7Z;`4w1I3v_f z?}B#s;4q<*P|BxDg^kz3DF$eG9@HrQ4{!q*^`r3kZgHngQr=YvEdEtzH^5jzed#`bt+kH6uHp4Lz z$0meMNgifB=6yLuQW0#8Qmwi*u%=NhWO>hiOZVDHEBs)3g)UTlZTg6gZTo~0Haikk z#}54G7nj5Z4rq*`-#M<#zo_tPUum%xkRB;9=@}a6`*)JCg) zZUCP!7V#w40<=Ge1I1hM%KN)O1j;kc*Kpg1;DvbIy=dT%a=OfRr!||rYvFMcD_PYJ zw5$74Q*X6T)5ngVYrD4mB0JjU==@j(&@AuG1TDwMEN|Oz_Li&7NyPvLz_hYy^6xKn zfnZl+BZPG*@q~?x`NSAEB!p0RFBm)>QB$RAKP#^6jRp}fVSr#fAPUD~Qi+Z* z@i}!EK}gvWrt0xzi1fB~$koW|f_M%JZE2ox{|XGE4;48yAyHjBXPzNVVrbyg`Mk!M z8{UG8R{Xz1E^T_I)+PXl-;o7@-FmvmGsMpXyVbHy4>1@Y)={7eZ=Am8aaYFK*zB2Y zgfS&b>VE%L`>m5O_tWo#mxHDYTM;9~kp)@m7)CM6JWg>xlGVT=X?q{xP%~cFDjfaj z2}qfO3!B>JND5_?n|zN`vkaP`KPef{!6t?)uNDaA7tyBV>&oT48@&)D3F{9KT}ml4 z^^v`F082X5v4_w1(f-!`cdL?N@rOkjm;IE1&JO1TC$-?zg`1n689z*Cfr;)NI5@{(Vk3n+9k6 zrD9fr{YtuaNR3|~l4S#dtB2jkt$ExeAi6~*x_EE(9=uO72sc*5KC`<=+m#jiwfJ1g zAIRT4I|Ea8r<^+W#`+~=0Dm$uuD~@|`&q^KSmOn>mn|){D1NRNegn_^&Yk50kKy>Q zxF@tTFY-y$#(&!G_`4q|Bh71AckX7JkRqcmXl!1mq&4Zop&xPHYpYEYB_)Yv{BxG$ zl_B@Gn5x%5$NRXFR4WVSpUEcb{+N<@9V8ieSX%k}$oZp=bK2}p!ItS4iHP8M=7Y`W zl?qn5rm-XCrYe6<)aia_>~HOh&MF4_ta8pY(@EX=G|dd@L0wlC?qVu9-j0-2zxz2L zYb0m(KB~7FL*s9O?d!f`ghO2_odl)eHABHAu{hBHura z|LlZ4p>m#hF?TSEfO?+p;nt>mFdTJ}V{J?Xh(7+^=ogK;I~cq1ifYe~0x+_8oyC0e z*y$O_HOO-6@$9?$=7!#-TVRH7;kHm}N0lA##<{R4aFjy_B`O)ucoGrwc@tpg?i?=g z=+=$ZZu`v8WPK31eqTH{Hw1J>)oN-6mX8_o^zRuofbZD>keRT9rsNgGwTR8gz4 zQbrj6WUs;P{{wz^OJoK8Q-E}Brr3GC3&H@GoO>vJqZOIr0 zk2)75^3>N}y{*LZCH>EawK|g;Bt{;fI`Ju}6(HRG5eDNmwF?#+S3Mqo1CCE{fQZ*2 zPLeQ(J-bM&)uq#xh2HcRm*dZ~-&OcI%5stQ?TE^z6X`$iTaf{gz{*Nl-`e=wRK1Kc zTiTq;s3@DWo_iAD3SbLaS83ypfGiqaEb8a^a$1}?*PbcC3?O-yT;cK_=Lw&iufEKC zKK*6X0G7Bv1t`HN`Y$ql>fDxSZK{1AF4>hVK34m2&GXEd0*ceX%=F4!hl!R9#E(>1 zuKopjg02GYi=?}lx9lQTi`bX-vv9VOu=OD=9HT+-^2Y?`y!$D$sOT0}d8iSB=N*^rr^>()(* zn$I53vJd(S_X6+gUCH(Qus(`QidPx!|0miCl$$K6cL_Kh{0EAN{(td%lkO#)F+9ya|D)x;OL0M_e`Z&HHM>9Wf}ee{=YFg$ z+OXj|i1k#)_G~GP#O;_Z{Z2Z~zeYQ5#JS6MLw49^K$i7)+8gAa$>np!0ngk4tS*)F zJ$APz+O76U%#a6-N*1xcv!icOhE{&DaQY3nc+~90K zu3XLYgvY{-zMZ2d5sBv~v=c+GPwhB#p!!DPbwx7v8NRUO%>{v6`KNY1*Yh7_zvBqg zk^1e%+>O5S2I;cu!q7*1-DK|3QNP$i^WYCpLsO#P*h|zO`0eo{y6e#5K@|kKT=C9< zaO40$&nqKeY*H#x+^pmKO|n4ga|v~L37h`>_U>F;vdzF;YVA*;2M+0_W1Y1vuR49W zNB^{X)9;J3(DVh9@@?>*;BR;=S;b{pGlVb8A$+45d?36i*04dY)sdT5lR%t+aBbGu|}a-3gVkCF`T)evr^55R_ARf7>crSo1rss?piM z89oebML@xEbLp0$*2(l z(2;;lx6M=9D%?DMa<`|xb1fN<+uhe?r;X$(;c5-OiuNS{29wJogbp0X<}9>3Sb7N? z8EN~`EqBswu7C21SBUy$TUYPvO|reDqYs;!Y=;oJp5K#S(vqiu;$WoeY*Pj9;2%Sx zg5t%o&(p+l+npIEp|y_o_k+S!zq-n{V^25K3LQ}JW>lgYSI9YI}$LT)BLF0BP9aG(; zH!;f=8TU~I!DP5T64gf>sz(OrNRnxoATbd_Re!#i&Rw#%m~_{3nb!z3gjZrMfildUBGRO%(~yx=8gp&V=$Fva|@4Rike^T06}oW6K?#knl$r!nba zb?v##JL2m&ACaexaqe%Jc65QnOEItQHRD&ZiR40;)%&@Bv0cbr)I;oJ5VM)fsue4y z-}U@MXCgl5E)2Fu?~rvS&sb^QKAfkMSAokB+3;>y>ZL0#cr6F4D6Lw367}0iYIaw_ zr5zqvez4quHIqZ+o9GIz%rkKLYkp4-MJKz-tPe*>LNhvJZpfl!i`OCafv|k0thifT zUAO*-tLpVz-2Nj(vbW#@tw&M^iODg|5ce`2#+(%?pP8*UY-ydk*PN4i_cx3azc+Tx z?ltr^(m$vS#_NG2l(fQ}u;^QJcTlOfN&^z<2-LSPG%Du`1jbqeeb)J$?$J-c7^AO2+)kW;bNfejEJ}|aqHoYhy9wyM ziVAY0?rlH(#r)!4kJrSD=@PaBabz32n@jti-=$>FB6TqnPG4_CKj#vT?Z`>>ma!99 zB14TnENA|8b%HqT#Y<1Bcq1T~a?+|H)+R1i+Qma8=DIpFWp)(hJo@Wn0*Pdb}l33>&T&+Qp5$_^y{ z1v(_Nx;6Fz`DtjYGoGqK<4^8x;Lh0IUG3+jJ{g5WM&Bo?WmBkofGo)Wz}Fny(Rfuj zg~9Cmf}=Kw&&zV}y(A~3d)76>y~eS@cqr>@?Zr(LI5|!^Ju}$U!CMC{xh9o9F>R!zV zy(_A8vb-0GD@(IrY|)>+;`i`-8g6*{D_jxAJ!?o?s|e^+M!G#IUwz>aeCwcF%izuy_uP7YHZALLz#kpT1v?IRQH$`uQD8-<3G1dD)OF|LDAOfyA>%^d<3gELgo6acAqmN zf8L2cd%Np0oaE^)?j3yBwt$hZMwIzd`Z!s(bIbyrdF4rtUy0zTOLiUmLeP}OQlOEO zcfl z8Jd=(mbC>of65+jxT#5MN$Ro}+rCgX{1N>DudXUG`&nYm^Lb^4LlR8#E1-vE?lo_C zyE~xe#EF(1;JEmuXs9?$xrVl`rqjeK2@oM3EI;Swe-0fhzUgS$mQV0Jp!H4OOrQ;- zM_Kma4zLFPAKDVjdL@@`ng153P5ymwm7_W^p0G1rB(^p8+RVjQ6(+zam(~%sLt=!-lDps90)(tPaTg7VtbJFuUZ!>&nF5>Fk`Fk#<&n3%sZHIxMd#^i>L7MLg(0EML;X)x z%Rtue_@?v?;$1?pr)Zbd;Z&7YP=Ig<*P8F3l2W-Z(v`|ID!+-Yo2WM2RuO7u%(+-K#Nup`V9k56(?c>shKlI$DpELV^gHE7M`# zoczb@{rIQ)ojz9frq=A-ZIO7Nk`*dhC6ub>|m=|tx*v; zB%<%Td3oSc7+Tb|#cn0oq9ZL$_c!3NaPBT#41hFocDs&B1d1*9eJMU-p-AM2K9d4O z!r(A22^_EWB|=S*K*Uj5+yfCSho^Y=G%ts!mM^?rEkSR-kp?Du2B(O}In{^1tMw;FN%B*D2>2kY1uAC`CHqfcF54-98G ziJ^WCKk1cwG~w-L-d?#^JEwJn>$f_%Qsj{C*c=Z-(If1kk%9Al!QB~8jSpl_@+0q6 z5ue$Tq;SI++8OQO0HAmx-fH-RSoX;>dYt(?#>1a9r!*G4jS)#UGT)cVM@J?dKmm0k zk41-AHqAv#IX{IOT`Y{=%keq=`Cz6<`tR#%7jF_Hf~%lrgMqq%r{Y+KvO>Vx2SN|J ziI#5FQ`i(|>U=l?$~q}@VL_untFg2~W0dKcWt)zvBeW3ZB|Z?eXS9gRK2k0$p4AOp zQM|Njb!#zKBH2i5EdkRC(iuyB_TYTNY@}7jZ!CoGfq{n<7aoOUSeW-F4uLc+&qkB= z!x}lF17nxsjvsgaY zPTslS1Cd?0Ui8aH@rzE-t*K^EM-!#g`R&!ENF`=M!OF}bnAwqu>(1!f?+PgvrstG3 zVgbgS=`Z4Y+oT9tz{Rb^5y!LxaGAYO$I#oCs#GC6n) zHj&kWoP4vWP^Lqb`cgN0$;pxA;y?g%8mePk1$w|$n4Me86d4*so;(6}m!!V%D&`X>#GZ%3->p^0bJZ!19{s@H zEn-1aeG{*3T^iAC%4{&~aq{3DSFciGOY`#z$pJ#B!viox5mqHhs}Za~27+$(aj58> zEy4DT>48Arms-Ew^R&hj3$SYMr%Ns}lP}Wzq??Os-RrCtmw;Tk&X-tdgrO)h z?r_t+_P1N2f9Q}_@8HjV&@xHw=TYUlDxND1E02IY!!)!ZF-glQ$1f+qHba37qvfM5 zZ@81BFPpL0-cx+PXKjQXnK@UU5(5s&Ly&MOm0^K#H~^>DqmTa!1t$1!V{X^g{b2ry2jYu z-_t%=$ZF>VP|yO)mC1P(60Im(Y0)M32YS<5W|HVxM1T)r)))(iep|{eul!E9M5p(d zuD5l(iwitTlqu+Q$(>VnvxmEOjHDx4EXr2G+{^|y)i!^u@SY1`VTwLpTGQy58Z@Kvz*551gg&$?HZ}sCru4vx z$=qYd1ka|(KSs^@U_^K9E(KF!xhHRoyJc=E?yLTI2qgL|G7M4MI^8isMmXu*DV~Mt z;SaL~TbgU9CF?0QTB034+qGt_C@H5cS_=*;9oe;0`UKd8XZ18&%|jQJiprMe2ZD>8 zZweYWHzoZ3#r--jhf3DSi2SWi?Q)5r=!nRDG|OVv?vl=ej#qbCtwf;7Pw*G*nmJNG zgpMMNhOhN|-o~`oy^E`8WQ*IqnlZFHlA1ysxNk#BAY*OI7f4BJBn^BJN^{r!39!%o z9JPGV%qYyquXj}`^pQx}T@nvm?K0naR3Lib6S^-HPxQFRj`iL&h zcXwF_$4b9KAQ3fZiJ$zF_5lYQ*|@vKnaOC9aU&2ihDrMse8sXN5(@eL(k8ohVg8_p zrdM0dI$)D_NuzO0{}CDQ-(5GoE7~C2@y^v~kRC)hg()K@qvpD81_(xPJ5^B5DLbU% zLRsfx-Vt&w=i1Ka*~^Zd>5L5YuPOxl7(h9OC2|Ho{>%OBf4~p^S7e=;5Kayl1Hf^=D}nNljE8SK@bCZyxebnSeOWxF3s8JQ(ihe9biy+#-h%b_@}y-;S5r4utrbo>vBhQZt;itk?WPHk2n zI0}tI*g=0HR-ijV!T7T7Hu*8}Js)bwd-Hmfn^fgzzUBboZ-m(*)&-t7!DBH9%}*=mWTQ)OHn8W1qq)3grC<6=GLOAh3L+&>T2`y*u+b$ z?-g!8RCL)4mIs1$OA+=W5s3G*VjuA_9mgwAXXBCe>_2(H0i@>!{=fEOO$Pth5}>y%wo2dsHLOMiq)u_uD^#sja{MO&E?5*9uWeq*$vZ7p z1z_K-6h3Z9#|%677UVgd9ieA@MA(BL&yfPGo>mK0g#ikqSvmoYDcDumxYJR*=6zaEFB^7DQ`s&^e)M5nK zmhHZbx!Wr-62`HLR1;N>D@i?ec7QG|FZEvEk|R2+MFvlXFYUYat>^eJ<*{(|6iD36Y&0-8g*4FOL~8Ce-;n|H25w#)+O3%P`F8~zLtf+i*YrvC=kwQTaAv^ zzgJtysM$m<-6A;uG0n`o?`jZ->kQz&WF0Qn(K=Srs9*k1t9dTi=8pb6%0PWcNq5tn z=^>R8YQ=2iDV!$l7610ZlLd?$bwcl#&cxmr4##`Nc_6w+@&*`9qx0Ihu_n6ldwzj6 zBW;p8t|SgZv|hnN`68pymbvai2!x5lWJ^4(mVRaF%7&alu~F6d&d%eIM`S!ky>yCY z2YzNhmU>8{gy0o#y;V!R4$AGpmyz9@P$fe^Ez=F)_g5s6t=Ft_la-o3Kwh`ZDftny z6#O7{ChgjHHO~7pEhiR5i*^g%##unj)QK(|tnwzqL6{Z33yf>7@dM=*573Z&>@PLN zNo)?wpJz^}LXnLIg^5>oL*~!UIPL~G_RvGXandRAo*I@#rvE6jWyO>*-$E{12XCoB zzlB4;6{;URqUH#Y`s{Y)wR)jN$0two`ufv84n2zc)C*b>1D4=Y+1tH}!iP?^dY5vS zpNG6kpz;CzE3?)A`Qz$3S9C9hFh%1KQK$yBcGSBx19Sf{tZIVCDy2_$`UpZevBUU= z$d2o=t4T6&-(Ob3)i=|_C~;^k6lry;A-Qw4{4QpZrtuS^-I08UN@NvDaNCPX?pre_ z4P+~Nzn}^@5xK>27Dj)k#2MPK*NvjPEZ6s^0M9lf5gDW+qp1{ryW>KT6ImzH2XO{+ zk-AXTn9j^SrtR1UnW4;J5e<_|7UxMy&$*(N4rJ^oOSr)wVK%_)c#D$>S9n+)gNd}3 z9#gPlQ2W!Y)L_F|`$p@hLgt|GiNH%)4yx1jW3G(8FsuJngAMY|-Cu$O4%}6;@*(ncGw0oyx{*I4xL$30aF{WdG;S|O>LEi@^hq!k~85WHdBNtIZdIV4 zt;ZA(26MJNq2>sBPtLOJ;Hy|=0&zq{WK096s+eZXpM&L*_YF$IIFU~yVa%X)6)R-Al=N~ z3Zxf|#MC;(DL`>S-De(Qwzy{gq_ef$wpS~YiAj9>`IqDSc$Z($k0@LidE#u2_i>>T zn@h|v@Txjwea@i%sn;R@1Y*Od*?LQDPgc%7o9PqRv6=;5{8*U4jul)pYh!nude*08 zpBiV|ejac)x9t+41V`5eB||tZQEX;2q4Zp+w=K%n>RLW%ijJh+0mX&9)&z88x=rYO zqRROr_$1_NZVE|=c%8I3w(3?(z3E*vW10qd1YmOM@gY{`xnTSj!OCW*NzoM zwiAnwy}sqiWNtT<2!68YQTcea6(~0_-IY@iWh%45vtw;25j#7kPI9n#S!rXJnl~KF zW#9G@ON>X6(MN+&YJaciQ)tv+)wmm9Ya?Q}kB!;pR0y5hsg{({bYl7GORPLkJHq}r ztQ(+l{{?c?WiCgwc+i^@-aMqUt*TY=;aapUM~G{l9B*55p5Jto2{ie$v@&F3$ajQf z81%vhZC>pN5a)M#j)E?vpB|%M+jOAibU!xCpR97379aDtH|7_3v^WWCQh|m9EysZ_ z*I6;yr8Btq5%gP%p_HVjeF#0z$XKQF74_9<9{>%avpDg|^U>vsI%kV^5JT!Qfm4{M z|3dFl57*^qm$@0v{uiwEf2B?EkLR>KCakVv-a~5<-EO+em`?UhfKs<0+RY_Jh@#b~ zdG%m6xbS{+aDiXSL#v;BuiuaroU6c>7Fh_oSSg(NTkjxD^j{zbdtYGnS|NTD{X`2p zy&*j&pBvgm={q_Uz*+RC;QR@ETBfWV2E!8p0uzi+npJ^vg|$BEW51cH1h=fB<+p_| zt!?EOz=03wyw@m&x+*Y#&S$R4u~@L*IBl5D_xi}Eu&S_QDfs7d-~z~BtrPMyXc^UE z;i5}WBa#=)J4>&|Ss1^wUX<|jc<{&UC z2TGSE1wNxH9nDSN@6c4D3um@c`^uT?HyQ{=C_A(tVf2BQxmyW@)AIDxK?y~KzIK-Q*QoeNqL}@+r z*qIEG+V?koEwsNykQY)3LE8NplktF|G?^8rjO*(Hx`x}$&|a6dAfZ|-cz?II0LUZt z@zUM&VZ#R2*Pz)YA7%l7N3+9zF6XbcsuSU(t%?=DPC#jfFZT6#hMUw{+LoVkYmt$7 zz2XZrvt1aipa#Nn*~8Y~=BIqyrZsUJv~; zjQQTr&nG77=<+57E&JrV!)RUN$B8eox?ukng2+lkgawu|#)eLB3&BK~6!n3`f$1xE@)9VMI~Q+t-_H?HvY6+H=z9{bH1cEG z>Kq(7zVdAKVfP4Q`hcO^)*@P4QY&}Uw|3W`whRwgS{Ocblx`n0NfZx6XuM4b`oQWj z)(BxHjkST(9<|luJ~WsQV;-I^ZIYueUK0GyDPflhFK!3(tQ5w1 z`LM8joy5w$%l``$B#{Q}5#ChC3o?(#CDl8fW_=1m$wKPC+tk0{5g@C}AYe-22A z&J`Bqy`G?R#bvQ}i6C;)9#p@7#6mRrtV7Gie!(_Hb z)$zK!N9T6=Z`S`FrRlq#t@9!i;F5?A12}^P>?Zz78E&b2yTX6Wl+;tOX)rTHG2kii zt>!_02*b0~TCjf%!32o10^E{ ziqV$gFkSdTC9RPni;D=$?DHH!uRSOP@G)OYwp-a#+FlXwrZMSyfE(S&09GORr)~u8 zYfduK$#=)3`f|c9@3-xBQ=`bPNxhn{+VWcUWwxzgoxZmabBrxq|FC@NhQD9$(sdvC zU@+Ds0%+TWce&PJLiLq0i^1wemf?sqTY@Wnh>K=FENs*ANE*UakoKzjJM>G>lN1u& zkP>Ec@SDzM&m|_Q?N)H7n?r%>!S?LLK)%!Kp261deXmwGu0bpVr(d-kR~8*Z2<{j* zh?D$ZAZF-e0pNXwpG&0%Xw*erF>5~f&Ak~GG3z3%x1OZ7#VQ4M(U+;7M0pTd2run$ zHY+mWuv;(dazYa={*R^5?`4z1n?*O&}wD3i!V@-YGq2}Nao7YyEEO4pRQ%wG8>PDIIqPoXa$zt z+srs|)=J7s`+R(uH)60iaS|+}S^q;ahEr_7*X-w9pVOr?HMVg5Q!;~_661^c2?x>0 z67K2r!2DpR4$s|Sp$^YKLf>jZ(U>^(C>`~!iF-_a3}hUy*U-u?pKPB`9XIY|jD?P~ z^ygf4+mSHWn_Iqahz*;q$X9kGtLlkPr_vLe_;1nZ{M*coY?!EmzrF~FNU_0h=5IHS zOAcoCcZZ2I%YN()u5Ovq?SMvRICL&Wm@`Knwx}mQ5@`G?;I(Kua6VAU*<3TgBasvw zEMkI%L;_g_qJ#i!9CbkKR-n~n>d{u4?cI;ylS%)jKdku9xmDDk@fEF;ukju?9H+K( zx9_=g+4|k16Zaw;|88VPc~0tmi+Td|LazS3NyUvw83f!D9z2v%UF9~&tktkH0}E6< z9y%S*_}Cyo-WniUe{^gAAvhYts33u}Xm3Wv5TPafX}PBSwuuqzi6aZ~Qd_%yA$f@*{_wu6y5lxL_IaW4c_OWYV4&JA}1KNT?8V+;S4?J zuVBV$Sb;ddMVK(I^0R2#I|V6z_)w|k;~xG=G3NaDwzP>t%cZulH^G0T^m0J=C_z-a z1sZ(cPlQA`JUWqK+1Cl+64}rzg)9_?oSyCbxRW zUTZJrgHe4PVbol~(L6UANUj!{*KN2{BPQ0gZD2JR`_}ADzef3e)09Z$$M4CRoV=%d z8Sk4E#x?TMAIf4&^cUAP3lpDow{eca9CDzJfybF{Wg90|>6NaPt8@&}K{pWh0z=6- zq6tgbr9T)*r`!EHt1G+fCb(a3qz@bA*T2Lz^p{`QDrbEiQJ|UmH9beJSSHgGI2^Sy zLhXEp0_dZEh!7{2|BJnM4AP|87KPikr)_)Mwr$&X_cPPB?P=S#ZQI7QrfuDR_d)FQ z#rxf}&yD-@W@N-uPgPV_RW9br1=6;_M{{ISV7d3Lm1#UV2hK{yr?!lZY860Qw6-*3 z{`qmfR`J*Fn09t@7SGZ>H@7Um$kk@M{!{k=yL932hp@+VcaB@cyd3T@9)$1u1=;o4 zJ@5PvKc0m1Jm`n?8>ek5dEcKQT@N=xTQOtPBYPMnhkn}5C0^Okh>R`jqOo( zV~=880ibbp5~kJb;|NsT&!KeGi5a>uTYm_8&*R~|vYW>A#=c67^C%utBAT!##$DB5 zZ|6ke%H9QSVZAespO8GYsN^%Z8*UZDt!+OQlamFOEJdeQ2~6+#O{8&Z5}2T7+(^-= z6Fk434pa_bOHquTZ*M&xUTbfDp@p=*|Fw8#)C#&#&kHG(L?eVrWhew9u3B?I%P~s+ z-xjd_@4~kJ_WE1pd$KpM$7TNq=HdsLC)^@k&R1Mlh^KnF1wQfBQZc7CBGS63V;9Ft z7IBhlkJ^qwK&u3Iw@UfG{i^f zs!y`W=M5KJyrkyU=8wKb{~2;kr@${emEiZQa^Lgmod)x?m>G)sGCQ7hk??|N_y&F5lBtYQVa;8cyv)q>+^M)qBFB)GU|4RI{NWWe`>ZI__WUeXwYWK0I zN116n!*ALi#lbGNq_wN!r8z*HS)B{_y0}|qKdcp%6ddAc$X97zsDB#Ao1Fbno)}cv z5+{{cv7`scI=3H|l2n1kH<3`pXTTYE**IbMQ z^OMJbHzxC)ZWxO-h)k4Ti z1Nbz@w=k^K(n6LE&D25DRtk+K+Stb*gdUIm{LpVyfIWN6GqyI22#ePE(~AfHpTr1N z$2qECS$!RA9xw?%(p#&73pXdbewjJ~0FLN|nH{#Y%cw09d!paW%y@u+NE7C|WWwya z?Jx2B@e*WhU%8+36+VHalX~@^WEk=YLl+#pM{$7Ty{|7aY=-M2_AuYjv_2@eh83P1 zU)c-#B(-b?%REX|4pof*2uK`*RkzpR@aQ&sdDq26ZQ1ud{^}7Y;)KR z9i6FO<8W4`iF0`YAku8Br|ey&jgK`S+})??axHn=tM=Y`N%I{q=HKY-%Z4GpO1bWO zs6p-zRb0iUYpHJXq59LZa$jjZ(L0|6uXYQsas5Am_7KD9aWt>_3I^!%*#dQS~T*fEN~it-bya0?q&1d!7>>rr+bMym?Q)${2K@ zmJz^u>Rr`C-{CoN!u{+a>zbxP+$D`iK!D~1*Yta_3kP~~-+6pP)BZrVHQN4C^e;$u zU#o+%c>F~4*OnE~=k9SGk3zm7A4dyXyu^<8Ew6pq=!>3Gqyv=ZSYdV5`Zdbsh&U1HIv&rgxiXJneVKzcTd5xI-}*jYhRR#|?eMi7pd-td6Vp*-3Nf zhj*o^)ZSqqB0zg%YKz7An8;EF7#(C>&?IqtZAe&rd;ChaRp74Q9MVT2l0M$E{q64e zGK7SQHccL6m8W0(Z|vMJpK^cyH`A-i{@(qVRp}wOUJrIIicD96kI?n6@XZ+vzM~e% zENk);FYEnp-8*GJL~BSCpNOvch6ESo5<>_c=jqgbeZTexTohd%0`3d^GN+yI)veukUGx zcEG>VKZT_ad$}@4HqseXv}22X!G^sB17MXiTeUA#=7**NgfiIYx)zQ^$qJzYK!JV}0~^gn$_`6`11x{srAFI_1v z*=+2%8?j78j`)qVK~o2{$EX!YoB9)|a2uYF{)u59-#>lY-&6hzMskE0@qG>#$h;UL zud~gNhYpC19$!HsKNXw5VkeB>QTw@~8kBXO+|CrPwo0v;AtOie1_E;-gCRJTInNR_ z2vEM9{*%8Lk7C($w_-(6%y_dKID29tq+r=-m!4WigBNp|)V@^m9DAKn+lf-EuUC-;0p))s23ge1|V zNwfNqh>uT2LHOQCh;!q4qOEr(nfE_nP)pe3c$@nt8Ik1Is$^^<-3DyleKt$%_z=Cf z`Iy~xh4&EyIvDI*;L}~(Orj5vExvqx@X;s?td2Kt*8W`RNnWczq&`VsDM)mEzdnk{ z-yD9d03Xf<%=4cTZ&Jv;I!<~{Y+uRRe+5LKf-zj1KO|m@wL!W2 zk5x-QS$=H<)jfe;{kdka^W^v1$2p+hvq#=aTVUjzPWD4OcrazvStg0YcXoXBern!t z99Sbb-@MA#xR%{#Pu!xoMiW|>spsr91Fmu41kOZ!rJH&1LF_gd-~M*C=KkgWZ?TOr zeJwxObaAY0A=uFgD@TzT2BeB&upf^u2cg=wyn=0)V47!nwQ|zr_TrUDVxzWHOY4|( z2a^LtZT1Z<_B?q|#g8z|C=7#RU!g3Nu`I^`2vUHTy7OX!jjdj1V-l~kfpSioWeS-@ zfO%rz3J54(*5MNf=j+J?z#r527+ybzwcfiD>;!MUR%xJcIfG2#4IGW?*{dSuyy*{~gwm2cm!O`=WN@p03Fa-FAN zV#gHBpNw7gA1px6*JySkwnO-vQ~E7QVg#S!b`it4Y_M*YRU4wW_7wPoZn3kxJmG4PkblKqePT z*0qlZ!KW7c_IatP(c1%7nU@#tug0hKlJ8NkO#OzaB{wOG@#-f07X-|VfN3nWVDA8> z@8DnwzMP~F)zjAHmrs=P1FxRF#ZL^op3DcpU64sCJ0|hVq{h_(fEP7VpDS7ZXnxd7 z&&vq@2D?&#IS0R0&D__9HV&_%aD!vXm!ZPsrvl`1_m@YeO-uj*1j??b@-?Jbb7zp# znr+73pG&?h8SPYjZeN;1do=GYA54Brb}!fm!zc4H)`Dn*UqfAlO)AX+?8#_Z}qlUoXa@Y~3Wc%_6u+fVt0?lazJoB=2t^d^2 z77jNDk~n;4hapLnK#!_o59o|C^0jy`!xII>FY`T)j-S`l1MCEtA4IJv%%{v9ZMO9w z5->3nE7QO|f~y>pUb*%L$ydW@iUo>dxhO0OWna}CfgFJD&^^V#IT#v&)TDo;83U>O zvJ@BuVxi-J(fYri@j36Gq`$zWZ`nTgj&`^R+sgaluX-&0aI68!e}B5YaZ!)Hg+E6Q-nHb zt9{2B0@2cNf7Bdop!du-VpEKn-ymxX;c@N$Ho-bZ^WZn7V*^a6CRlk8DLFPKKkVRm z;-_blbFZ0o+ta0EsU0>Kbp}p{A=Ld=7GJ@hg&1_!`2=$XL@}N5QfXL3pp?MX&%{(F z9jy7cajCLzCpiarVri7XDWrgE6v;}eGkXR^!}|jVbi7$-0Qr_vp<9F2b9N7wtoeuf z6Q{F_y%i)BCpVmia_{#UocX3 z&Il@~+NmpqFUk@lYmci zp3UI9uVa?K)XsgrRQ1`)f39h66P@6F57>C=aiE7_)yXa5*@j z`sdm$KS4!%xK0^Y!bm<8_%5}t3Y}aYM;HjqkfZ?3oXKFVp%ONbsHR=@xf;2m*&rTO zpXabDeU3p)veEAnDn4F0;^Djio(V@3Q#2meFercnxre%ATLHZad9W%inZB!kgzFjA z$(HV2j~sm<(WF0QkO-sZ^!dxa4#-G&r5wFho(Vwj@UTo^7w7UCh9{TMX|1JDBgHPR z@{mMX3TIs$CCuvg4cUK(#pvsKnL7IppE`VnZ!`97!T)m-=1i7N-aoVG# zY(kqAvBNHz#YIvf0HnF7Dv}Z?fQ5-zDk9cJM(U8#2_nBDkKsa0c-B)o^%MBZ$TMiA zMn1CuXOZ`Sn&};-#nflt5d&(*+z(k!$X7o)Ug%6-$Dy9NO~wVNIw*uB46TzoAn z61EiWDDf^Zmfyw{@X&SJ1aos()uABh?lfDhNo;k@BNDTC|M(72LBzX}U!gHkXQoOYn2W zAf+tD2c>PRy3mP0Qx!{=2|`SjPW){Hx$#HJTQY*dSr*Lf zO}Vo-nMU6EO(D?Gf@ffju-+{)2#Ah~t}}d#cPEeyex4ceu~SHlel-t)a02BI0694e zl)@m8x zO<0?YX#6J0up8!atphzI;nfSRw}vudwgxO8$aM6d_Q2jHJr z6%4Ph&M4y#w5zSnkwR2u1yaMu5>kyX_1o`iT3!nYir!4h3U-dy$IbSqoM0N}RvVtb4)i(owhRZOLjAQ2L$ zT6&0tS>5-0>N$j9s$S02O>d2vqA?j*IAbXTlhXnP7@xtlWfxt)*-63o@|2asOsr&Z z_#5*Da#(<%u@P>x`u0=Kd~hv$QYMhry^2AIcd#l*Sl!Sxbp%;C7(7_DAKBw&O32mJ za8L@3a^MD?t7zbY&&(7&&>S8Y%W9RDF+NY4Z5iW>G1%gAM%`IOQsl6oE@H`Q7yNde zx`?zmd3{IILTR@`fZ?L?vq?OQo8xh=riE)#VU7dmbR?E`G0*Go5ed<8k;p5@>K{YnD$4Av>BJ_DYVIpt zBm*MrIl1YhOp;>gbwKKg-y10i3Qm@th7%vNKWB7V%+?7(V6QYeF=o|_+`3d$?g+|N zMXf0(nYvX80C)ST)-MNCE&!_gR<^hgDIXkJ+UK7qs(Y)+cx_8Gq8hqC@0U+FVm_!~ zh^|_W@mc~EUNk->d%^l?z;iur=n32aSxj(}HgjH&l`KHxiW5QP&DEbg2njOY5(ic; zB}`!Iodl&U;NdQabk-CbYb{dl3WIBk2_lY-+_1Rq^uBJh5m}>xH#?o!uapkbhx~S> z6Y_-2+Y#Y|P?fUJ|28kE#rXMUsG!};Mu3TfqyT;#Rc-o2&=^Y4OQCVgsjBp(RWABQ zZGMkQP}ptp_hkAP+5J12axniFLC?hcAD8}F(*LF4{p-qHrn;^*4il0m`xF1~Rt44a zq(3f5Fpj4kIB@TvwxC{=EDZ0jNzN}EKaZDEkQfasb)(G8#p}L*KD2iarA<%OeWPd^ z9iTe;)b~lh%$~@8ULW5+8~1kSxOC@Pojr)@&G1QOm^PtIy=A!F`CZQWxpf&0n1n7I zgx91{?g<1>tw9LhaL`QT2hdNDC-y-eAI~wZP!%6k6Kw3`-WbCVa0>J)K|c#?CJ1P0 zi|PmkD3u1TthNyZX#;I*owVVo0ud2d;rYtA6mmrID(0ae{cf!YV+(J<-gzA`9fF-0 z!JF4Wd4@O$ml3Ml0((fSZT9{u8`~~vKysY1W4zTy>F1>=Bk}0a!}dT5W$` zd)73?P)}Jn0sVkhZS zT1(r$w1W{l90WpCrokEejapq|ML$F(Kk9`ee?j~|Z0dLj*krn=9h95DaoG4_%ULYq zZxgCxg50I1iYdt#)VHD11C-iW$yELHW-%Bs0Wm;(e#3p&)pZkR5~~IY6ohX(bD&`Y zQ#W&<%@8GBmT*8yEN3_I0^DQ05E0QhiP$ZhvbRxV_HCIn8d2(PoN1rpZicykPd)#++#w`nXJY#=LXP9_sOK-``F}t?YQ2By z$(@ilh+LRljif(q`s->e>mP#zd~z;?5QF{{c6VoKG*K82%B1ulvBbX>Jd(!v`3(2# zGhVIA!13Ln^@yf?biW5)X79**x4&)a#e~csdhBojBx1hN^Y4s*2hnPI^M?$Gad`IP z$w-)vz&LUf>GbujrD1&F!)mY#-B)|8@ zTJ8fH){{U=#All$ZSKp|ZO&z&!5_YF=PN9wFMawO-+Sdm<>=gpY60Ju@h`?e_+-Z~ za@;~_zRUcCgaya2{Ci~l&y^V=A?tU}e?~@TroTZ(=D*aie;pYsHDs-EzmSpP+~=xw zrqp!R7%@m!>`E?A7--9r#lNz+er-j(gquZ$b#(oY!WSC)GZC;_`6*`S||OqlFs}kpq7AK>urv#;%{$7)!(*0h zPDgtl`hyKT(!S@(mJ!-%$Y2=mDFZW#0dQHN%?!ye!%6JpX>5;~5V44a0r~_SKFW)c zoff#~s^77(Q)WqBB;v=GEC6#mNa3{7b(?q)nBiO*;pfPdb0|~#RB&n>fyhjSqD)>* ziWsF|%!k&x1Vnu3XBi}!uP*7eo|GcbxspG=#sk}H?g!r<_>F1!N#;|9EYL2jdXJ*||c(x7?{!7W%>Z+=4EPT9GBsePhW9k??XV-tOrJ(k)ZV}?hKp?`#GBQ<3^lUM~VS$5B-pOfJQbEyEFlTa2xbK`7F$O`N_f$=Ev%ASseVS zG9x{?U0Oh)VHFNI+Yu5bCizWFC0j4yK;J)-z6mD4P5Y^xdJOnh z%y8=sG*}HF*1T98N<01<%f(Bw#N#m(h!)K^LoqcRqZMugS(aDy#~$49;a}w&Wq;zB z&MmaTfOalX6;-OGvqPS$ev2#3#|Uj?ie5eJvE)XdC&2(Ry*!zYBTf;pH>)qZ_$8Ig zvPN~xp!VvHV4mxCGsX^gqt4ON;=EuFK1oKGLbB56V;wUr-eu69oMbkBVjC@0bs_5Y z+Ujr6%Dv2^zC*$gXexjl7@2`PGo;d4=*#yF~dDA5c#Y@cUUk7@BWj@;l0qKNPtt$5a^u@B5RUAC1b(=Z%Owb zr1&3N7|Var!kAh9j&%Q0&Hi=LjZz%90%d~x%cSN^zffy4swYgzLK=h*3j6NcMHriS zG`C&tb|EV@7ifTFR`4x~G={*sYuE8oSA>4nHJ12gyLtjA$)LxdBURYS@ zGk6u%59=NBC<}kazCzP-@`XQrqem-0ZI|EdsV+@Gu`^sATYMMFt`C-=tf7WRYW8k} zUybqrIu-_r+X|@=M)a}|EGf)QMT@nhy#nnpCvgf6_mysXAWYtt4Ris|qH9rMX%;83 zTF;joFEqg7S5q0*Y1u(wijy0&6DK?#85ISbIABu?bRw&n$nZJn+NfKt#Z~L?r}sZK zSwceQ@Bd{j%KV=a{4XU}1>j&x$e_pL`>Z*jZKxrh5o;$(sNx%9rWQPNb5X?OX;nMqrzVz#y5JW5oAnE zyi8$YQAM3lE23cMosSwQ?O&bJtaJ&lB&kFd=^;VbCCiYKp`o2!}J>vo{T@;S7G^34LWKDeT)ENM4=KV!H=TJp{FFp*d6oERr1 zN-(bf(D7(d_VG=67wP>FdeveWR!X%MS4*!i)kzeyqIq2t8Vr8qjI@$kQ>ZHLh>ohK zXOZdu>WDTg*jfEC3N|YPw!w%8`1|zR`A^7Goxrreoc@U4P~LLo%!zaO#2os9k%p9Z zjH+xJQAf1C$`;*Vg#41){Z+(BT19VEM(By>f%nP)BBkc497=SMilUJi6TWkB1qiEg z(t{qbECb6#zk!J@LZ%5QCzMwf-#pl**7U07wT-1()-TkhJyo_hq|NIhd=qk!2QI` zirP~A_He28G7VYVGRWkYjZvWt%vTGSqROsCMORn(Y?S+eO39+FPPnBk&-&c>Jrt$f zGc3mScmU85!!lg zogyJnOV1Iz#4J`MM+@8eCGZbKsw7FAzWeLQ;9BJ`FT;8_wtIrX@L#n7_l7}D2+xV#hhqtg#@&r86c;sNtnV4YmZ^XBLr;jHe7Qe%3eP53@8u);GsQjmBR-}#tBx6X zJ1iZzS<8-gT%iOf3$UW;e&zG*923kknDplh5v6T>6VKWM=%XxBPw4?c{^!Ax<-v5d zhSt4JLFki2vjdaCI`F2DCO&o01D|VV?1f8j`)i@Jo0Fx6<0!j)4J6>;;Dh?Gr~A_H z(U(e=p(N18FrQR26okh8884Jql=UPa1;;mf5b4K9#7}1&#RLxgvHL?#^;>T!e3&0{ zLijOKfk5qM@)F;T3^idQwZfP$?Z4)bXF{HA8B!4!xC1eO!t*CM6{*o zh5Xb#x96*trPCPZl9Ec4E@!}@9!J*d-qH@)I?4R2&w91IjDX0DE*@(C*&4>S1pDEr zKyTVImr87M67-P0mrD?SbVwNmWum#kbB?~_8j5t&QFSWiqA??J0Bw?Tkpyg2{=^L} z$#ce5(J^Y*RYI*Q6Ch%^@>0r)w}K*lh;l%+c-MSNpGX|dph~kj)_&hwA+1S0F}_Zz z-0J4qwmkT8bi20TpL`*`ACQRm+?yBvMNZHBXUW3o7Loc>>H~rh!Ft1gK%j0aK!rv z*xMLb)a0$DiJt{Y%;xi*?4t0pL?gn>~zWf z;l%~{%EXnK%8slelbrhO0t_p6749l}wLkqisYP!qeTCz{F2Xb=K9vLz29cOVe%y7s)cXl;PlCJ3{W1=&f#t)>ou zqs1Yeo*iv~IypABfFF*{d4LjXdafk5%uG5!k_OubW8Ep%ad34N1Jodxn3>3L3it@k)twGyD z&NVsU31neX83=a4IOr);T@&$X5H9DOyCbzJ*SUhoI`w(HI_sMNIu~x@FGiNNa+gQf zgDxq^iG=7cxwOOlzgi!zfkY5RQ@b)^?|e`T{HMTC)`2z(%dhL1NMDpxEJaf$Gm$=p zGr9s3aV0cpW0om0hY?*FQ($FHDEGT73IN)pqF=~-F(Zl~y`8Ea{~xIK^1An$&}FYE zKqiW?a#>gEvLPF#B&bV6Qb4~jF5%2t?=CVVyq2vwqhsKLb{bO9_E z83~J-8oXFg2Q$=;hR9Kx9*Lj{ueO)e-_fs90c7AkmZgAB@=HW6BQ>V>p0Hd}~_ zDVO-2z|FlgWIgo-K?Vkux~spC9D+iU95D8 zr)2il6`<6$Ni!FY)9msW@xn9BSR9@}r~OL@b)}F>3SX@RIBOS050VLYxvft{XAdMu zW)K|r%HbK;kxf)@IHo4Ii_sI5CcrmvF}8zVsvgmV7@|)FEhlf4iEM)4LzD;71MhA8 z2O6|qNQZN>M<%;dMX8@jF$x0#^iC%ubJKx@kjRSn0}sYjQ0Q-%^!o@@v+sr8YzNhZ zJT|nqv*#jnQ&tb+nHzYytDBLpn9zcOq(c2KjJX^l(nfu6ez~;)6(k2-zIy~l`=GNe zF~fWc5CyER4!(CYU_y03aX$j%HF)Ff)sAe1NB4x9^01Jg3R&D;Vl`wcKJ_YmD$F2N zAmhLo3D;-RE3b>biCN}4oeBO>hD(Fn>zBc&o01)NlA!FQGKYi`ILTw%lieNvFqpMT z`YEe;0W_Pt&dGc(`v8_)QP*fdH~pakZQTCNKAX|89d<_|r#n1CzO|coqW)cXV;a(a z>c~%mMkKQEoq9kV1vHazBdi<1)5XD>Wcr4YEBHrF zKXunta>O=o6(-QOz!}l)kCG0?=ozt)J5$mzsSds0ufRck9{J)JKc13nu10`{2=Xiv zqAxHPggS67bC$3j5g;=!1u^Cbk@F@441zG$cStISo(^nG{H4_3E5#w7odpT6jU%ow zs;5hPY_LU#SiH88-T-{jh%g9*UtS!71oHukCj)MP=u|T!1D2IwVt#ftSzB{cJjLNbEefO0Y8` zZ;Pn=9eqZ^xo^dR#2iP$cf3{Hz$w;K&Zz=TFW5c@SDqTN5T8R; zj?jTxHIsXGl;|u}UsVGQoFN^n*Ii)5_kvUhOa=d>D)HkTEfJgK@S|(xgPz<}G6NPl zRiMien<0)zQLNta8mGoL_)9H=F%1NiR?-UTNbgk}YpR(7zxHS31Kv*489x;(9w!i^ zvh1exM*zA!?34o7iJP0x%4`e|C7~X=OgA_{&cf2}8r8as;3B6p3VXY6Ox!ZoO=Xk) zV*oroDhdxg@D!4;n}{AFrfQs{w@L-~pl2$cbYp!~?0qemeheXJLpV{L!k`{KEiSH% zSzJCmw-WH_IuJlGxrA^B0-tHhJM8yj3n0-BY&fGm*NzxF*qd?I{UP!B1BTu+Bw3j5f@v@oZpT*heuSojckgwkOHmRcLr*#_XHf%oTINAv zo*;z2H^@nSl4qWEWDh*8#!wGJif6((R8?G647huwVH7gD!B!0DOQu}@7u7|j8t4~z ze=x2a{E^KYl%Q>fc9MRC#)I|HdkwC-MsC7mS07Z;9kwVEp70#)27$H_KKU_6G!7gg zXYsBOfskWbB$1B;;C4wDJ6R3r&c_1qLszt~w$zVOjS6UM5e(TkJC1Gll^#V95NJS> z@9&V?I}tLb%#J(s%Z@#>5;48DnfaCPMgU{I`Hox~Fx=ik>$j|$rm0`tbEe@gTSCD3 zKE_%7#+%9CA0Kji8FC2797qwG>fdV=%K>r|0Cx9REdAD-KJy!TV4sMIL`Vk#LjSzQ zf~*28pf@EucFsl=M@Gx=8JD%MgI=vZKo^?8YLCvunwT%(i@?=-mo9@y#-PT}A#$W&;5x9cTJ_ATm;Q-_=d z#SK%>ku*DFtd2O;B9N7ow(^rm@d(az)!qeY*nMa%pdw`tcOb~d+;oXYTk(+wUPn@# z#0+jD^XNxf{92)D3A$U(^%tX2tp~yb(r9R>>SuKPh z8XO#qpKNr!Pu>ob?p$%*14kHwiqIGraqNKOH5r;Q9ZG`|u(#3y7EzuuhitUe3 zf|2TH;0;wFpa;vUN5P1}FZxa(1`u{P^wAB3NIF}NtkH9xY7fEy+JWv;>-#{CmN*}r z2i%|sdzM=^rM_f0)Ek$o8GB{DJZ6XQ`e<7KIMz zqg6bgKYDbJ&UA1K&S^>Xx8+|&wwMPS!_m8y^xIn z2|g|0sW`4~(p_l#;N@!y^!j6zuc_vDKg7@)KiIuXYyZBZ?0y_0$kDTTLNYV#++&Vg zolsRB0lyh;es|@j*fD%dWF!ak<%w#>7HT3g^6uZnBVzf$OFCg$$44_6jn$x}*dOzO zgf!V7{Iahq7P>|x4@HgX48f9G*I$)yX-~2h94Y4f+y&i19PN7Ua5fgZEmMnuqDN5% zer5#2IN5L26z3&b(am4VZ$_v<&lrUJl+ZQ{NfT;cbm$?k|8I zMa5R)M7fw10w1YyyiLmdRTuZ4W~_0!Ursy)FyFKAZ9 zyt#dAVR=bob?ked|G3edbUfPp?!o|}upv4}Rop1G^?nSj{7GZ+BR#9A_~aA!et08iN!|KbKTI&f-gPjq(^W3d^zy1xtC5GDDSx)CDFzWPkq zn=uDwcRLZ#A;1UHagSw!!)%!dlZ-2B58}VC{!?eGLv2HA;bNmF`bJRn#Bd<8>JLKzICPv~k zC;Zmh6g9(-bcwX9?&DZ&OXy8}-Gtn#v20}B%N;T%MAN8+LOzHfz**g&j^uiMtRdxF zfZ=l->S9f1sX;)A5FfX7gypzS)Lby2AL5Qd2#x5d628ezd(>kU3VR=R#DN|kV5U3k zSydo9g2MC~1+(c#?#9#)c@!K8;b-Oqjoq;}KX5jJkKg}YBkRPF(?cGTubG0{h2js< z!6+N;Y65^&GIKVNR*%kdIN_rA2g3Xv3$LvF{IdFwL0yk9!(Za9o`bh-R`Uo@O!CHI zYDOz+bNa)#Ty_ws5>Q*V$kJIwvS7OjEP0(8U;u&K8 z9=iIg&#qo+)Q9gi8Ch=|G|~)Vr5an!sKmU-B2HScRa9#>D_R=bRagPyOv*gXN>%8N zr+90A{2G?EUhf)m1hPhW5~#8?jJh=7wthFNw_vsx8|NfHiup=j50O5(;9A=W;Zv`9nt2FcJ!S(nO)zQ6?R;6 z+jsSUO_2?`LVA&Au!ZHg6}bx#c1d-i3*iQ+_vL3+@?;vwgF}lPyE{^`?>9g`{T3&|K8xI z6)(luV#-KSEdYIOg4L5>LP*C$;hmk}v+$RaS14oUvPL)qJ(1)damS54UM^kl#Tiab zA-C68;%lxlfL-OHOzG&X!A#GrUplucYCvI@3|r0xy}rU0wLGJ23grk6A_uY#+Nl5i zM2IF_L~(~GfFlE@H~iYBcp^!z{R~|l0G;^A)M^V2y=BFf&p4jeINWY=>ZbwdUSCASP<5jh5)t$tea_ico0G3rrC~aQTGFbuD04f zAyy2fzdBWjVqi}lr^fIh2(O4;{yH+~KIR$5d?Ym5Uoe<>OZ|{8e!3fSfL-$0ROU&R z;7QqjchJ16kGsiJc1tA>V>AyNupbVEHh%X(dzX%K1BMe<8MrojM~abDsv+O8C8I=d z57~$+q=0c_t8+6qIM*@D1>DMVu!FwQLC(NF3p4Puae%30xCteiG7@fmJwqEh&EP8; z$H9eG-qLOxy*`VlIEpaa=vjPEcWD%O8Kxb{mi43?=mVX{h80XgFMx!St#D_9yc_(f z#ol$jF77(_zgD5nxpWdrOL?gBZ}8N|1H+rmRow$}0=Mb3c%C-~5>j zyNC36axKLO&LZ=5!~yh$SvI|VC5s-GV5?2lodZEytMq@Vz-X@iR}ZSu>na%I-{Kg# zQuWkHCsl(03m6ATu@VCPOxz{{^u^WU9QUHHhR?#yfy)wMu$%s7p$Z_oUZ`(8w6*qm z49c!}d_sS??etPB!C$ML5v_Z=y(0I&KDlDD5W>9}AAd@JQ4y+-GNqd1o|e>Lp2G|J zFdF-+Py|(=(;`o!5jufSe(vMAWEtVjEa0t)A_p#rsb79~x z0t8L#Ye)NZO{@!pkxf!hLUUrS&1FdzIo{G=K)PP`A7=*3)gPC zD#;>$01v=phiapO$IZ{^-i392NjG(r3vIflML_1Ei7<@98VYzN=BRm2Kt)A7^^A=i9dH&ATweVq&6my*Ye7EY_E7? zGFxz@Bum=p_Mui4FXW}#1MB{RVcx93P`jz{LkUv!{)we7(z7S5vVEWfMVn|}qcmQH zpr&%%{eeAMDz`!=5AO`2v5C!C51gp(==)&o4=0TJT*UE68-3j;r_3j|Mm6j&vGgUK z-m_UcMQc#gRSN?+#YlfxaNi13@cV{mPg7zZDZ>1q=KIW~J7Ct=-yPkK$PTG&3&NsO z1|)3ak0*YYL3d{`w;F%;1y?~q@=>8lA(0L+vZ7H9S4Oesr#9spIo$q=1lXioTDBSE zhoWXvX>4V^PzrH6%cZ|@Yrxle{m8X7?CMTioLu56TMD9SR0iTNoxuN^FE zm#?Ol6ehmdNqhgo=InrVw6Q&~R~GKO=6H4%zM6W9vXgP%EmNqMZ9HSmbO(X)5M&#d z5b&8acpPhanirFWN=6@%7!y0#tCe|Cc}ehXifLpG?N2Kgh7{Ye?I8HVnrLMgC&Xb> zd3M{CfD!mE+t?_`f+VD3tCd%LIrr@Lf=!;4kM+5MGXY~`DJ#J8-*u~slQR@@B6;CF zJJYoCh?vKrA_RmlXzyt1s4|@iiF8EsmOh!8tmt_I<115P4U5==nXrO|I;x=vQxhr< z{n=aTz)e$3v=3>3Xoz%mt1pToCAbdL)H5GdTUw4jkQUj3V2&2uJT2d*9*bL6)C(t# z64D-t)VJSey=EWj;B#&G{_ns8P2XapTvraHS5_klLIx(gz254%M`M zt18QMCf;)mhAVGiMK@XW5E*L-R$0jW$pa+dDVDUzlCeDQz3`o4_tg7yCDe4X@|~WC zgHGa$%mfX;j~sWPcR|78ib;YztewEG35Os6wX~|=DPrKudUh;Jdt`p?=Ge*I51e^a zp6|M1aN-=gMkSz+tcz+?nsm6Z0A^h_Mnj6gu$u@S3c-8OTDqa^4{Mz2dxItS2~iQRjQEFBOn6%V`%x_epbITpv^(x_Iw4iOY&# zCQ%kM7Gk~PWmBnET!)VSS5aKVkHt|B-9m7^VrDE$GN4geT)dgiE*sdQdFWl8+&T|J z;Xzj0Jwir#?(>Q{f2l^svW9%Ej(b-YtopNlBl6n4_vJiZR5@_&7(prL=yHiF?Y zE+pOPnSy8M6&KdH!4pL6gjDtT(GUmD??4!h=Mo^5*vMte)>@pXdM%w2StxkUmrHf- z-%iXmW#3Llgm!p@ zat88_9Ub7$HHxRg-!+9h5p(d3AjgS0Ju#|a?HuQ5qMwLHpD$=qE>vVa7&7Ftp_w^f zO`!86MpyT`tlYDUzf`ZB90MYAJ7xisDMP>e)!ws#eqx%hg?=Dl#b$sent=OhyIJ3U zcH_DbGkg6Tnn5efoFRJ%7L6?Q!}->=P`kMn?}q2VRc{H$R?>dY&j*{jU-T5lpIy4u zE}qa(_#=?v_h0k=c)3opK!&=!H;9=Pq$S|F&K4soma)|~h=cNEd++D)YnY(1bF@KW zCTu?>REvbf9Q<n87rV3XtKSaqLGjYM?2fDUI`1dT7*>bRWqEbSMn}*-O|}2Z zW-N`zr(IsoX3KMql0yDq#L*YlGJ0nmf4+C3zqS8Zw8#Hb_4)W1Lh$p>J_9j!5%Sx| zs1I+K= zR#A`|(hb5GH3lkD(mh%lsS(lxq-zYxA)O;ecaGoQpYQLSowL8TJxR3jI z9=JbhtroNw|J!H;A~sFAX>aC4POKFy5;lXswdtBxxV+L@1hcf*HRdKCY1t(}nVX)V z1*+o)nI5t#Ia7J+hJ{8u_A;dY#}s|*_>}flYUuX>LH=%KteU5A)esIKgu&my%qdM2 z#6(sYt)q?DjY6B79b$8lk&^7$Ix0J4((wM__M^%Tk;BeA#Od;OYJSF}WvTijQ{=&0 zT`Ni?P6)|8Z)`{7ws@eK0%gZ5vnk{2OKfgrq@;Nr{f-Kbk3Ep80Xl$nWI4is*>d7v7QINx0SOoDP(kv|SQ~wq{y^B8YRr5|J&5 z2GF;7@-yiF!uK51$plm{{KWw5y?h!5C8q|W5sYoZsJOg9l~2xV;MYnAY?8^8ciO+W z)2w#RF#+ueW*2w&)@KgZ7;0)aMSer>cW}dljDM1@a%D$`He>fKUIOjUOm)2sn%A>~ z_ZOe*P9_N~lj$kWNedo7?gdQ&EKzrOZ1ef@9=@33NF%MAbp06^EleZ3el)BYEH3Rf z$*m|v^nj8Y|KHtXxW`R%(1aOEf3cvFLH>RKrD0dZ(I`EH>i=6cu)jk(zP4F3E$uW= z=SGt=S8Md==lLFQ?sN-76+8*NQ)G7uy1Ra0S?8_>B*PH=r;HM^DqE%z7^95v? z$GHZUoBkjWxYw0@<^2?G01UkW$4h^E{Pf#8N{1y)63pStx|@-~la#Tno~c+c=Bqu0yR;nnFU#O`E^VEMa*4JTmdo@kN!Ud!9Ds+PAY{d8R>)V}*1E4Jo)y)z0; zUUQljLywr z5|4f9T`m057XGWVULbo5yxo~55o0y=|^7?H?AaWHxC}#e> z#cnHYpt?ZV`tH@UijV5)s{C&as)ghIY$gh#kdxhN{dF15rLOE!><%~MZxQ$ZSTY~9 z5xv){Klp9&UqkChn=CDghn{%9vFkn^a2+!`cnQ+ImmNz|()3R>H`Si55t#Wjcith~ z0QgAY)Oj)q9cL2`jR%*!m)H6UqU%@=%K-RJg>A*PWeaSDJrFR|F?dME)cxXTMyR5 zAO)21{}hNF=1G24BJ>D8L-wn76MNn|c!k7n#Ypl0TOz=K9d}0mB2dWmO>Vch7LC7y zhaR15s^6fCO#$pkDK{vkNiZ;e=+5<5-`P5>XX^}+<@xe@vhI+pO(u36atI^ z(@%!~6IyuKJRtxt^)5c+flxdvbBg#6Ea6cneP6GuIs3Bda)}ehH#6o;jeU>&@qGFu zfe?3me#goqT^lH5%XIk;|INzbPm*M&DSTt{-b#_&);Qz7h{+q#pPNmGiY$oie zfKmeXCHv;o+~e)rpZWD%rvKhMK(!(` z)?g#V<(V~xdLWB9r56e&ENxsL_~8yIJe<8SmqtM=X;Lh>hGWcQW;6JHiFb2qO-w_h zj*AdW<*exCU%aGHl>AoAVk|E*5)C5$G-+sbH-DuJVan-zk?O1tdtW#*bvsOz{McZ_ z(3o9dL1t-O9pU!vyFy4Xcs+w06v0KUk)gK#_x6&6!e2ykgN5)!6POHrb(vgSqd_CN#QdLH@*KQ7)4>oRKt^j7PJwj|5D$ zqZTA4y6Mk4jal9?R}6pbre=N#uQVpUQgEyDLmrYDUq`uyT`tr2x;4DfwB3?!%+Q?t zEFt9(b=3Ikzlx4n<$zVs?_~(^`g?th4DRjEwjnHC^}*aKoDgVdtGrE!!ZNv9jw2|x z6YG`uWUw-H8<-yui*Jj7jBl;d00)RmnT!Mvi|vV7=SwGIwf z+5a+~3Vh>475?EjutK!`KNkIYI{`d+g?)3&2~z;+b!KH3>iVeIW;Jo%H+=g}Qn1ee z51M`m{MZYvg+f`g$)*yeMR-V;+k#8EyH6Fx+-)`(gF z$99XGde4@tE%TxCGhu$QNvF;K)fAf64glJX7q}f5g+{ZU&UIxg zxg6+rq#YmY?%`jQU32JAd5G88{appB!zmil&z_$vfXv2G-Ef&Un986E&A$g zyN_`srQ_>#>UwhB%XW^k8Wb$k0zs8*1X!)NGE;M5YUFZqziyGbZ(AN`lrngo+#aa} zJNq}gc-wHTB*USRFo+}@^=4`)9E%~P=mF{up=t~5SE;o%BM%PdsoYQBYkEB4kmKj% z7h{WsQ4zlmi&2DLuJZ1kxF5U)%s8bCCN%xN3w>|@7kRM@pB)`;_712M^MIYM{#-Fp zQv7{TGof#O0kz~yVH@5(N%a=y!_x+d^=W?vw6orwyAzl_%6h#aYAdj}YU4D2<>T%7 zn-faY+m!s#o8-SgFTi|vCoiP|c-64M+5*lCNI97y)a@Wkr}(6ZyhpS|BXL1@EaFF7^Z*_ozre zeuWE_MWPJaLT)B}R)%VVwydW#be_&yS>=hH?}NaZc32II*G1R5~lsk!O! zuP0a9iiZGwH!pL-zW{`IpxS!c7v+dldu6;sHShK{kQqAS7aoMuN0CVMbAf3vthe?fgmZ;u z+<-10u9fV;wHv99Fb&a_G*e{a93r!M$}) zwzV@8fCO$k(?Z>iLJ@zRwf!2EPQlTEJfYOt{cL`A`nO`@O`}|=^Uf|im!-(22<<;~ zn47rLuV|xVG-HDl7&e|st_;No-BKs9ks}`l+4@Q_ofgK z^~GF=EM@2s(9!v0meNqMmW)VX#PI#|YIL=LhBZU)tS~0quEgo_Iid-(Q2{k_*Kj@; z>Br)u)bGYf&8sQvA_;qQGM>Z>ZehGy7<}Yr9)4LiAnP@A7-N70D^(5#?qv}+pRqicuYn-@@SP!O zJR{^u%*@Li>7|J5*YQfm0-hgk$>&p--fH_M@qQj|l>#=?3w!V499;dM3?4iF<69y; zD;;tTE+3wPx#Sklu>ah@d6oh^u0AMnpbE@f6w*NRWsZlOtCfL(XLB3b3j{qEC8Ac4vx`sZ2A^OaNeQ!<7B5(a; zc2yp<2jZvmcu#)9C20M8Xr=cenz_Z{H`cNKz)68YkhOE1-rY7QWvZw>)Ty$qVt(D? zE8RvUW9mhJID?f;hS?437@dqk{;-W^ZCqi0QwjJXcd$ny;yPdi!dSju?tV)0j&!*O zG~|9K;xFUa=n>63QcJo=(39ht6+o74bVXyeJ?LVf6N$R`H-?knIZ@@qbeTr>$)*TS zbDPKjiOsdkIRgzFc3JEH^cTT&B|6w{`mq}8JGYm2ZuelQ!A0Y-}4K+o;%1 ztv3nMlN6&{0*m$V_HzusmBO^dIZ?qS+#bToonnh9UbDWD;s6t^A4Nn&pfU$Zr!b)k zU@F-_VR(MSgWa%cRz;7eynw^;e$l>)Ax-@i@P@lPFvZ8S_X)glPT+9eAPXd*d0Qx1 z0MW2qU!L-=P`f_UJno(FWy`@qZKE!HhAW0bUkn)mL>k#C;RMpMTKslllW2jBEa*d_L5mqwK3BJRwq`ZB=*vyxKRG{c5 zyC#jW`{ES}kHz)vtskPqROPha3hQUJ(`E|wONn~x!<^JGby)}FITcxy^Z zhV^Ni3P!$8QS{3QXy& zIW3P%TPh`FSG(MYMhLG=12$?u{cv)%r9GVfr5Kkc3wV81^4DrzFKZsRq^|6@e9>cJxJ29U77jy2@wV0wNF=@(&KUHRPIHyrQTW!(9Y3u z5U#UxAguqc@BKWFvzoWbYdGKlp!OBr?)G)t)a$v~cG73`P!ObSv$e&4#ldzjdi2A* z%@H~oWeRaYiSd3GsR8rVNW~t^_4r&#q+c_-DcdHnue1ao1VHAU)Z(fN5BCnawCS86-$M+yTuFejiSPEA8G@sqe^MxD#Xf^XvTU1wmrUIQi2Kn!AUTEv} zVtKg}!)C3&3gJ7S`Gk^ z-aadGWhl0b`-DuFfvZN)Pv&!rymp4py4hHvQ7+!W2ppXn+~U^u-25`HYO!#5q{7kBd09KxSX;Kgd*6B4^I=Me zzj_HfcQT@*dEVE|yJ(H)54I%rH#1U?<_5ThiGv0=`cuN#Ksnz?&|)Gjd-F?kw`Kyr zEL|61lWSm14^iQ_LjWk{5B8O`;SydBSAx|JCIS+BKK&&sz1p$Frlovo0T~XGnxT*g zXsu6iMo0vnWHJg26bd#=Idsn%Y3(6DeufN`#UJRqMKPMMieZ}4*XimV>UsUdoB-M` z3@pw1RmzoP&3+?K0=t#&mu+{Qbi#Euep-C1PcAcsf_6)0Y77@Lo9q0QK25avwxtXK zO{Hxxb5#kukxVArfYY8ncLw$H662;uOEb4ywrs&odecgQwHIY5SdQAxs$1KW&U2GH z2;mW*tDP)1uH>EUC3Yz{$m;P)D8egqvdfX?-DrZR;Z4UNkiFXKxnRwb!V387KcCct z)`4?Vt2$G=Zxy0@jm98Ucrur5IGfg;be>%d(LK8-7 zj#cSM>$hjz#h3iZK{(B~$p-97A$;!UJWDXt>$K!hwc7Z%Pe|6 z&Qf)7nf@&oh(qK)mGBjs)P2%Lfo~n9nDpdIR=?7)ycVG@g)yX!^1ARaJbO_(@#Lb< zfc``sx){s=EY=#qqknM9UHD22UxFD`6bgzbu4AGf&|H(n)8JO3>_VN-=lM5EZ;&NI z-AAp!(_J~<-ac!ce~P<7Hkl#4*V~CxPSa~|=b-ZBbJ85bXJyu32K!Mk(SYNc;pri-HP)zu32`^2DH6$uQ1m5W7QOGX zEZ6H_KC!7WoKHn;qqeI2T8TO(9Yy-~W@>lM;*IOj^1#B+;M}V1^)AX`@Lh@|-@82E+@jv<_p7EkeVWQai zDSn$g-g&l7cdPx%Z|3){&u-z!=vQ3lR{aVB5GO~z0>8r1ZS&q+^Ab&xT0?F1KWPj|Lr zT5{S)pOc;m4~(e;__>kGTRPCe7T%{~ck}q-mxD9#>@C;XHd$p5`aodE5ysf5)^c0l z+vaq1J*)@*ym#o{2Uv(AP0r`#rAwMO*q*0$C0wZvs{B6e$2ZXv#cXD3%E3c1buFde zSjL$=DIrWERHY`1dZ!+k$(meM_=?*=4E`PcuSmgQMl&Sl>IoWK@ z^?a0*_p{E(w+mI8^~9)5h~4Zpga(rwlWnHtikTA|bB#&!vFa+mTg2JJZtBr`#Zx|f zMxxjjaXBE@dOINB=J$#W3%Dqc1*wap;+%H01yOJFgTE~>XBwULc#mamNHO~`^-j{~ z{;^sR_Q_p;@e^bg0Q4|0p=N?pDy3IRC_uVf&%wPl=<2^h3n^7x3b%h!6ZId78JA1z zWeZ7#!O%QBJu6%~cle^&=_beNEMiej_-^Ev@twIE(xWC8v%>kGNod-ac7Gwd87(en zBRp;JthP__SAWi=Z!SAgP{??F_DvyngcVj7H zv16@@rZ6-^frgpkSA%}m)OAHbRr9jbrI*hNwm0kIpa89V-D+XlW?m;~&RQX-|9P|e zDd%%TdclwT8+kEGxbu~OfB=7poMzy0ZXEP*wZGiBcI$7>OKoj3xk<{$qJMgOi7h!6 zcXrBQvH}97CiSjD#=keFs;pkUy4S_c&5gLgqz|RbghJlEi#L9Bh=5i7y!YCKmQB%5 zk~=77wL1rvEM&6$*w-Djj&d0*B#$S#RZ~~*R4+HF&l0!!(FNgs%Vy+(go(X*;?G1! z$J4*Dy82z4+kvQ>lcOqs*Lo~Axblo`i5+2Hoopo52G<7S zuH8xe*+Kz()cQW5{H33sEd?a;vjq06V_C?FQ$ z|43~gH+LIQ`|`+^0xx#iRM}^f*yH8$odbt#Dt!WTb|O!eZU)p>D%{mm-=huQ8yLPf zFfcHjOk8L&G&AY!8OK{?&S%V@=wNzy3a=|{u5N-wOfVLz2-oit^D_9}{@(DOxbz5^ zZ>6Qer~NS3LF)&fpfIC+oAq%SH6;f)!L=#6MQ(OwnhG6(A_N7V8_hHaPRl@P+P3IU zE{6G`7{eidi=Hva$_HQ8#IR<`;g@8L)W8%ErQNBM&fBcxQQ;o%i=osS*Sir%89-^j zo=mYn8-*#p-zc&ei2X9WJ*04w+|AiqYT4QGkdp}Ph`@49_VT45f7XhZt>}JJ3*&P~ zMD+WY9pC;Ma&-D|ipThRe@91`Zs(WmfxW(g$LPEY!7D_zZv~ICpUH$5xbTWgZ#N+#*H$mj3?gEere;mv&ng%|*FMfZA6 z$Q64p{M*rm%Feg5JyjH7#wT-L*0JMymKlkP&0mlqsxYhfz#&J*_{dNiG56ki?@ZUm z$D4TX&I*gz1zMQ3_$hL6l{QsBY)zulH|zA#&G5Z`Z*6Pa1c1*hehNoBSS>627D5*o zfH!N(d!ARl`es=HRUBNQW|2klggwhrPLs2ZpmltpyUf%j`PgzVfw7ZGNlE3vmdhxa zd5&O(Bcuc%lj3k$C4pC`uj@}2zAGnfoH+htYsJ5DkLewC!6%${$BGVlJOc{5@y ztj)LT%kx3y9?4z&Q&e73@(%eV{J8|GxZy*oLC!Mnw7%`@z1Kn9FS#exJFv7#y#;N! zODwar^Owk2R-3M5qehQ4s~E+}0H1YhAlYGHM}t`x#C@X9u>I!ISb&Q+xqXO@-AGf znd#_yU%gIjkipE`+$R9pOWOPdXxM$wG^oAQ@HuApYo_VZeFC^v6B|$5ShWL9OL9Sq zPD8!71=EFQFGY>5uAY`oh7@S46#lzD3*B;dw1qInL|Bw6ZPfoPPWx46Q&RHm6P3l3 zijJ@92Puf9*$3YbjG(j0Z8d+%mY^}23Eaw0Rd&lPr`%Q+tZ5!sz7VS~}3Gha}hBfIb&vEWQ zLiJ+7K?;YNYHK+07iTN6+c-jrD_q8OP2ja5G`Ec<<7n{P=%zVw;IzYhy3@-*$|(7G ztJg^qR5`82hs=qCtoD%!2M83{Wf5!}9+wKY@_s4!cha>1DX47&WTwM=#kiWU2E%^O z(soV=Su_$dupb`-c9xixKiPDEpvh24`wRTVbzb);59MOd?m*LhIs8IB0J;pli!^&&lkbF2^a!+1gh0foZlPU`WI~CRdF(3I4mEy)Ik($ zZfs0ul^ePabMrgh9B(u!LhXGpG)zfZNIC>`>*tYgE0n1My|?xc>SvU$MreiuuRO2X z&6@Z^GOUYSCfepy*i?v-5mYlv!H-xdgTGp-+_`^%S2nHq1hwyv>+3yNfuoggj>n#| z@r2ybB+Kq#g(UoZLra)#`8EDYY#_%v5vg%7O#NwHr zb3A>zadWnCyRLjI=QJspNW}9+-bnc3(Juuf0FHJ!F8s}WtrPkM`<;@>U;0Jr>`>3m z(SrPL?z=e-pCy)FRDGyg(-^WF&N36oQc?erQ;DGC{=j?7v&QxHHNgh=XLU_YM@LB} zcb!dD`2AMoUg*TYMY_~_#-AD)tnmx<=53bM{zo61aqYRV-6KGb?-X_6YFBNZqO|`h zDj9v*eXUg$m0?bzmxzWz9iFiJT7O}hx$bO;|xm+OPF za`$qqTPS}%94NPGqCCH8GuII*vDO@fP2&|UC27q`Qc2r!-P=gP{IX&pJ59JSZkY?y zLs$4M3uL)lA^}fmjd{G2J_TPm8HumRzG`X9^~C)cXdH8G&}-TREM4x48HPqa`+WG6 zMfPy^4qBmzvnl)jW`O6w)|tLq_MSe3yl+=I$LAPS^AXs4dM_Hy-$LHr@f;9_2Ez`Q zdrFc(nuXfW4l+Js#5SYX^JmzsDkxaJ9r_wNa;zTSrfVT` z&=-l`X)SQ7x5<>@u8^Z=&&Z(1clbF^$sNNNG@oR1E`!a~D;_rVBT>&%)4*=;rsq
  • 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 bHh~^*uG<@2sG&LYD(+=cQihGOb!huH@Z&L$ literal 0 HcmV?d00001 diff --git a/test/stress/stress2/doc/stress.pdf b/test/stress/stress2/doc/stress.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8c82924129a7953bd559f1a118b65955843731c4 GIT binary patch literal 39840 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 KPF)@k=YIg=hx1VY literal 0 HcmV?d00001 diff --git a/test/stress/stress2/hydra1.netperf.freebsd.org b/test/stress/stress2/hydra1.netperf.freebsd.org new file mode 100644 index 0000000000..a212dc92b2 --- /dev/null +++ b/test/stress/stress2/hydra1.netperf.freebsd.org @@ -0,0 +1,13 @@ +# $FreeBSD$ + +# Configuration needed for the hydra1 test box + +export RUNDIR=/var/tmp/stressX + +export BLASTHOST=192.168.5.105 # orangutan + +export DISKIMAGE=/var/tmp/diskimage # Location of 1G disk image +export MNTPOINT=/mnt # Disk image mount point +export TESTUSER=test # Name of non root test user +export MDSTART=5 # Start of free md units +INCARNATIONS=150 diff --git a/test/stress/stress2/hydra2.netperf.freebsd.org b/test/stress/stress2/hydra2.netperf.freebsd.org new file mode 100644 index 0000000000..ccdf18ae1c --- /dev/null +++ b/test/stress/stress2/hydra2.netperf.freebsd.org @@ -0,0 +1,13 @@ +# $FreeBSD$ + +# Configuration needed for the hydra1 test box + +export RUNDIR=/m2/stressX + +export BLASTHOST=192.168.5.105 # orangutan + +export DISKIMAGE=/m2/tmp/diskimage # Location of 1G disk image +export MNTPOINT=/mnt # Disk image mount point +export TESTUSER=test # Name of non root test user +export MDSTART=5 # Start of free md units +INCARNATIONS=125 diff --git a/test/stress/stress2/include/stress.h b/test/stress/stress2/include/stress.h new file mode 100644 index 0000000000..cf93d0ca47 --- /dev/null +++ b/test/stress/stress2/include/stress.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2008 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$ + */ + +#ifndef _STRESS_H_ +#define _STRESS_H_ +extern int setup(int); +extern int test(void); +extern void cleanup(void); +extern void options(int, char **); +extern int random_int(int, int); +/*extern void limits(void);*/ + +typedef struct { + int argc; + char **argv; + int run_time; + int load; + char *wd; + char *cd; + int verbose; + int incarnations; + int hog; + int nodelay; + int kill; + int kblocks; + int inodes; +} opt_t; + +extern opt_t *op; + +extern volatile int done_testing; +extern char *home; +extern void rmval(void); +extern void putval(unsigned long); +extern unsigned long getval(void); +extern void getdf(int64_t *, int64_t *); +extern void reservedf(int64_t, int64_t); +extern void show_status(void); +extern int64_t swap(void); +extern unsigned long usermem(void); +#endif diff --git a/test/stress/stress2/io.cfg b/test/stress/stress2/io.cfg new file mode 100644 index 0000000000..d14b31f710 --- /dev/null +++ b/test/stress/stress2/io.cfg @@ -0,0 +1,11 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +# Only run these three test programs for VFS tests + +export TESTPROGS="testcases/swap/swap testcases/creat/creat testcases/mkdir/mkdir testcases/rw/rw" +export swapLOAD=10 diff --git a/test/stress/stress2/jeff.cfg b/test/stress/stress2/jeff.cfg new file mode 100644 index 0000000000..2290c7acd7 --- /dev/null +++ b/test/stress/stress2/jeff.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +# Only run these two test programs for VFS tests + +export TESTPROGS="testcases/creat/creat testcases/mkdir/mkdir" diff --git a/test/stress/stress2/lib/Makefile b/test/stress/stress2/lib/Makefile new file mode 100644 index 0000000000..945dd8384f --- /dev/null +++ b/test/stress/stress2/lib/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +LIB=stress +SRCS=main.c options.c random_int.c resources.c + +.include "../testcases/Makefile.inc" + +.include diff --git a/test/stress/stress2/lib/main.c b/test/stress/stress2/lib/main.c new file mode 100644 index 0000000000..7f7fda2508 --- /dev/null +++ b/test/stress/stress2/lib/main.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Main program for all test programs */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char const rcsid[] = "$Name: $ $FreeBSD$"; + +volatile int done_testing; +static int cleanupcalled = 0; +char *home; + +static pid_t *r; + +void +handler(int i) +{ + int j; + + done_testing = 1; + for (j = 0; j < op->incarnations; j++) { + if (op->verbose > 2) + printf("handler: kill -HUP %d\n", r[j]); + if (r[j] != 0 && kill(r[j], SIGHUP) == -1) + if (errno != ESRCH) + warn("kill(%d, SIGHUP), %s:%d", r[j], __FILE__, __LINE__); + } + if (op->kill == 1) { + sleep(5); + /* test programs may have blocked for the SIGHUP, so try harder */ + for (j = 0; j < op->incarnations; j++) { + if (op->verbose > 2) + printf("handler: kill -KILL %d\n", r[j]); + if (r[j] != 0) + (void) kill(r[j], SIGKILL); + } + } +} + +void +run_test_handler(int i) +{ + + done_testing = 1; +} + +void +exit_handler(int i) +{ + + exit(1); +} + +void +callcleanup(void) +{ + if (cleanupcalled == 0) + cleanup(); + cleanupcalled = 1; +} + +static void +run_tests(int i) +{ + time_t start; + + signal(SIGHUP, run_test_handler); + signal(SIGINT, exit_handler); + atexit(callcleanup); + setup(i); + if ((strcmp(getprogname(), "run") != 0) && (op->nodelay == 0)) + sleep(random_int(1,10)); + start = time(NULL); + while (done_testing == 0 && + (time(NULL) - start) < op->run_time) { + test(); + } + callcleanup(); + exit(EXIT_SUCCESS); +} + +static void +run_incarnations(void) +{ + int i; + int s; + + signal(SIGHUP, handler); + for (i = 0; i < op->incarnations && done_testing == 0; i++) { + if ((r[i] = fork()) == 0) { + run_tests(i); + } + if (r[i] < 0) { + warn("fork(), %s:%d", __FILE__, __LINE__); + r[i] = 0; + break; + } + } + for (i = 0; i < op->incarnations; i++) + if (r[i] != 0 && waitpid(r[i], &s, 0) == -1) + warn("waitpid(%d), %s:%d", r[i], __FILE__, __LINE__); + + exit(EXIT_SUCCESS); +} + +static int +run_test(void) +{ + pid_t p; + time_t start; + int status = 0; + + if (random_int(1,100) > op->load) + return (status); + + show_status(); + + start = time(NULL); + done_testing = 0; + fflush(stdout); + rmval(); + p = fork(); + if (p == 0) + run_incarnations(); + if (p < 0) + err(1, "fork() in %s:%d", __FILE__, __LINE__); + while (done_testing != 1 && + (time(NULL) - start) < op->run_time) + sleep(1); + if (kill(p, SIGHUP) == -1) + warn("kill(%d, SIGHUP), %s:%d", p, __FILE__, __LINE__); + + if (waitpid(p, &status, 0) == -1) + err(1, "waitpid(%d), %s:%d", p, __FILE__, __LINE__); + + return (status); +} + +int +main(int argc, char **argv) +{ + struct stat sb; + int status = 0; + + options(argc, argv); + + umask(0); + if (stat(op->wd, &sb) == -1) { + if (mkdir(op->wd, 0770) == -1) + if (errno != EEXIST) + err(1, "mkdir(%s) %s:%d", op->wd, __FILE__, __LINE__); + } + if (stat(op->cd, &sb) == -1) { + if (mkdir(op->cd, 0770) == -1) + if (errno != EEXIST) + err(1, "mkdir(%s) %s:%d", op->cd, __FILE__, __LINE__); + } + if ((home = getcwd(NULL, 0)) == NULL) + err(1, "getcwd(), %s:%d", __FILE__, __LINE__); + if (chdir(op->wd) == -1) + err(1, "chdir(%s) %s:%d", op->wd, __FILE__, __LINE__); + + r = (pid_t *)calloc(1, op->incarnations * sizeof(pid_t)); + + status = run_test(); + + return (status); +} diff --git a/test/stress/stress2/lib/options.c b/test/stress/stress2/lib/options.c new file mode 100644 index 0000000000..ce37227a81 --- /dev/null +++ b/test/stress/stress2/lib/options.c @@ -0,0 +1,262 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +opt_t opt; +opt_t *op; + +static char path[64]; + +static void +usage(char *where) +{ + char *help; + + if (where != NULL) + printf("Error in \"%s\"\n", where); + fprintf(stderr, "Usage: %s [-t | -l | -i | -d | -h | -k | -v]\n", getprogname()); + help = " t : time to run test\n" + " l : load factor 0 - 100%\n" + " i : max # of parallel incarnations\n" + " d : working directory\n" + " h : hog resources\n" + " k : terminate with SIGHUP + SIGKILL\n" + " n : no startup delay\n" + " v : verbose\n"; + printf(help); + exit(EX_USAGE); +} + +static int +time2sec(const char *string) +{ + int r, s = 0; + char modifier; + r = sscanf(string, "%d%c", &s, &modifier); + if (r == 2) + switch(modifier) { + case 's': break; + case 'm': s = s * 60; break; + case 'h': s = s * 60 * 60; break; + case 'd': s = s * 60 * 60 * 24; break; + default: + usage("-t"); + } + else + usage("-t"); + return (s); +} + +static char *gete(char *name) +{ + char *cp; + char help[128]; + + snprintf(help, sizeof(help), "%s%s", getprogname(), name); + cp = getenv(help); + if (cp == NULL) + cp = getenv(name); + return (cp); +} + +static void +environment(void) +{ + char *cp; + + if ((cp = gete("INCARNATIONS")) != NULL) { + if (sscanf(cp, "%d", &op->incarnations) != 1) + usage("INCARNATIONS"); + } + if ((cp = gete("LOAD")) != NULL) { + if (sscanf(cp, "%d", &op->load) != 1) + usage("LOAD"); + } + if ((cp = gete("RUNTIME")) != NULL) { + op->run_time = time2sec(cp); + } + if ((cp = gete("RUNDIR")) != NULL) { + op->wd = cp; + } + if ((cp = gete("CTRLDIR")) != NULL) { + op->cd = cp; + } + if ((cp = gete("HOG")) != NULL) { + op->hog = 1; + } + if ((cp = gete("KILL")) != NULL) { + op->kill = 1; + } + if ((cp = gete("NODELAY")) != NULL) { + op->nodelay = 1; + } + if ((cp = gete("VERBOSE")) != NULL) { + if (sscanf(cp, "%d", &op->verbose) != 1) + usage("VERBOSE"); + } + if ((cp = gete("KBLOCKS")) != NULL) { + if (sscanf(cp, "%d", &op->kblocks) != 1) + usage("KBLOCKS"); + } + if ((cp = gete("INODES")) != NULL) { + if (sscanf(cp, "%d", &op->inodes) != 1) + usage("INODES"); + } +} + +void +options(int argc, char **argv) +{ + int ch; + + op = &opt; + + op->run_time = 60; + op->load = 100; + op->wd = "/tmp/stressX"; + op->cd = "/tmp/stressX.control"; + op->incarnations = 1; + op->hog = 0; + op->kill = 0; + op->nodelay = 0; + op->verbose = 0; + op->kblocks = 0; + op->inodes = 0; + + environment(); + + while ((ch = getopt(argc, argv, "t:l:i:d:hknv")) != -1) + switch(ch) { + case 't': /* run time */ + op->run_time = time2sec(optarg); + break; + case 'l': /* load factor in pct */ + if (sscanf(optarg, "%d", &op->load) != 1) + usage("-l"); + break; + case 'i': /* max incarnations */ + if (sscanf(optarg, "%d", &op->incarnations) != 1) + usage("-i"); + break; + case 'd': /* working directory */ + op->wd = strdup(optarg); + break; + case 'h': /* hog flag */ + op->hog += 1; + break; + case 'k': /* kill flag */ + op->kill = 1; + break; + case 'n': /* no delay flag */ + op->nodelay = 1; + break; + case 'v': /* verbose flag */ + op->verbose += 1; + break; + default: + usage(NULL); + } + op->argc = argc -= optind; + op->argv = argv += optind; + + if (op->incarnations < 1) + op->incarnations = 1; + if (op->hog == 0) + op->incarnations = random_int(1, op->incarnations); + if (op->run_time < 15) + op->run_time = 15; + if (op->load < 0 || op->load > 100) + op->load = 100; +} + +void +show_status(void) +{ + char buf[80]; + int days; + time_t t; + + if (op->verbose > 0) { + t = op->run_time; + days = t / (60 * 60 * 24); + t = t % (60 * 60 * 24); + strftime(buf, sizeof(buf), "%T", gmtime(&t)); + printf("%8s: run time %2d+%s, incarnations %3d, load %3d, verbose %d\n", + getprogname(), days, buf, op->incarnations, op->load, + op->verbose); + } +} + +void +rmval(void) +{ + if (snprintf(path, sizeof(path), "%s/%s.conf", op->cd, getprogname()) < 0) + err(1, "snprintf path"); + (void) unlink(path); +} + +void +putval(unsigned long v) +{ + char buf[64]; + + rmval(); + snprintf(buf, sizeof(buf), "%lu", v); + if (symlink(buf, path) < 0) + err(1, "symlink(%s, %s)", path, buf); +} + +unsigned long +getval(void) +{ + int i, n; + unsigned long val; + char buf[64]; + + if ((n = readlink(path, buf, sizeof(buf) -1)) < 0) { + for (i = 0; i < 60; i++) { + sleep(1); + if ((n = readlink(path, buf, sizeof(buf) -1)) > 0) + break; + } + if (n < 0) + err(1, "readlink(%s). %s:%d", path, __FILE__, __LINE__); + } + buf[n] = '\0'; + if (sscanf(buf, "%ld", &val) != 1) + err(1, "sscanf(%s)", buf); + return val; +} diff --git a/test/stress/stress2/lib/random_int.c b/test/stress/stress2/lib/random_int.c new file mode 100644 index 0000000000..9d82782850 --- /dev/null +++ b/test/stress/stress2/lib/random_int.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include + +int +random_int(int mi, int ma) +{ + return (arc4random() % (ma - mi + 1) + mi); +} + +#ifdef TEST +#include +int +main() +{ + int i, j, min, max, r; + min = 100; + max = 1; + for (i = 0; i < 10000; i++) { + j += (r = random_int(1,100)); + if (max < r) + max = r; + if (min > r) + min = r; + } + printf("Average is %d, min = %d, max = %d\n", j / 10000, min, max); + return (0); +} +#endif diff --git a/test/stress/stress2/lib/resources.c b/test/stress/stress2/lib/resources.c new file mode 100644 index 0000000000..c4c638cdac --- /dev/null +++ b/test/stress/stress2/lib/resources.c @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Get various resource limits for the tests */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static int lockfd; +static int dffd; +static int flags; +static char lockpath[128]; +static char dfpath[128]; + +static int64_t +inodes(void) +{ + char path[MAXPATHLEN+1]; + struct statfs buf; + + if (op->inodes != 0) + return (op->inodes); + if (getcwd(path, sizeof(path)) == NULL) + err(1, "getcwd()"); + + if (statfs(path, &buf) < 0) + err(1, "statfs(%s)", path); + if (!strcmp(buf.f_fstypename, "msdosfs")) + buf.f_ffree = 9999; + flags = buf.f_flags & MNT_VISFLAGMASK; + if (op->verbose > 2) + printf("Free inodes on %s (%s): %jd\n", path, buf.f_mntonname, + (intmax_t)buf.f_ffree); + return (buf.f_ffree); +} + +static int64_t +df(void) +{ + char path[MAXPATHLEN+1]; + struct statfs buf; + + if (op->kblocks != 0) + return (op->kblocks * (uint64_t)1024); + + if (getcwd(path, sizeof(path)) == NULL) + err(1, "getcwd()"); + + if (statfs(path, &buf) < 0) + err(1, "statfs(%s)", path); + if (buf.f_bavail > buf.f_blocks || buf.f_bavail < 0) { + warnx("Corrupt statfs(%s). f_bavail = %jd!", path, + (intmax_t)buf.f_bavail); + buf.f_bavail = 100; + } + if (op->verbose > 2) + printf("Free space on %s: %jd Mb\n", path, + (intmax_t)(buf.f_bavail * buf.f_bsize / 1024 / 1024)); + return (buf.f_bavail * buf.f_bsize); +} + + +int64_t +swap(void) +{ +#error "please put the amount of free swap (in bytes) in sz" /* REMOVE HERE! */ + /* + * Currently, DragonFly has no way of determining free swap as non-root + * + * Please remove the #error line above this comment and modify the + * line below it with the amount of free swap you have (in bytes). + */ + int64_t sz = 1073741824; /* EDIT HERE! */ + + if (op->verbose > 2) + printf("Total free swap space %jd Mb\n", + (intmax_t)(sz / 1024 / 1024)); + + return (sz); +} + +unsigned long +usermem(void) +{ + unsigned long mem; + size_t nlen = sizeof(mem); + + if (sysctlbyname("hw.usermem", &mem, &nlen, NULL, 0) == -1) + err(1, "sysctlbyname() %s:%d", __FILE__, __LINE__); + + if (op->verbose > 2) + printf("Total free user memory %lu Mb\n", + mem / 1024 / 1024); + + return (mem); +} + +void cleanupdf() +{ + unlink(dfpath); +} + +void +getdf(int64_t *block, int64_t *inode) +{ + int i, j; + char buf[128]; + + snprintf(lockpath, sizeof(lockpath), "%s/lock", op->cd); + for (j = 0; j < 10; j++) { + for (i = 0; i < 10000; i++) { + if ((lockfd = open(lockpath, + O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0644)) != -1) + break; + usleep(10000); /* sleep 1/100 sec */ + } + if (lockfd != -1) + break; + fprintf(stderr, "%s. Removing stale %s\n", getprogname(), lockpath); + unlink(lockpath); + } + if (lockfd == -1) + errx(1, "%s. Can not create %s\n", getprogname(), lockpath); + snprintf(dfpath, sizeof(dfpath), "%s/df", op->cd); + if ((dffd = open(dfpath, O_RDWR, 0644)) == -1) { + if ((dffd = open(dfpath, + O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { + unlink(lockpath); + err(1, "creat(%s) %s:%d", dfpath, __FILE__, __LINE__); + } + atexit(cleanupdf); + *block = df(); + *inode = inodes(); + snprintf(buf, sizeof(buf), "%jd %jd", *block, *inode); + + if (write(dffd, buf, strlen(buf) + 1) != strlen(buf) +1) + err(1, "write df. %s:%d", __FILE__, __LINE__); + } else { + if (read(dffd, buf, sizeof(buf)) < 1) { + system("ls -l /tmp/stressX.control"); + unlink(lockpath); + err(1, "read df. %s:%d", __FILE__, __LINE__); + } + sscanf(buf, "%jd %jd", block, inode); + } + close(dffd); +} + + +void +reservedf(int64_t blks, int64_t inos) +{ + char buf[128]; + int64_t blocks, inodes; + + if ((dffd = open(dfpath, O_RDWR, 0644)) == -1) { + warn("open(%s) %s:%d. %s", dfpath, __FILE__, __LINE__, getprogname()); + goto err; + } + if (read(dffd, buf, sizeof(buf)) < 1) { + warn("read df. %s:%d", __FILE__, __LINE__); + goto err; + } + sscanf(buf, "%jd %jd", &blocks, &inodes); + + if (op->verbose > 2) + printf("%-8s: reservefd(%9jdK, %6jd) out of (%9jdK, %6jd)\n", + getprogname(), blks/1024, inos, blocks/1024, inodes); + blocks -= blks; + inodes -= inos; + + snprintf(buf, sizeof(buf), "%jd %jd", blocks, inodes); + if (blocks < 0 || inodes < 0) + printf("******************************** %s: %s\n", getprogname(), buf); + if (lseek(dffd, 0, 0) == -1) + err(1, "lseek. %s:%d", __FILE__, __LINE__); + if (write(dffd, buf, strlen(buf) + 1) != strlen(buf) +1) + warn("write df. %s:%d", __FILE__, __LINE__); +err: + close(dffd); + close(lockfd); + if (unlink(lockpath) == -1) + err(1, "unlink(%s)", lockpath); +} + +/* The UFS2 soft update lag problem causes a lot of confusion, so for now add the err() function here */ + +static void +vpr(int code, const char *fmt, va_list ap) +{ + char path[MAXPATHLEN+1]; + char siz[5], ino[5]; + int64_t s, i; + + s = df(); + i = inodes(); + + if (errno == ENOSPC && (flags & MNT_SOFTDEP) && (flags & MNT_QUOTA) == 0 && + s > 100 && i > 100) { + if (getcwd(path, sizeof(path)) == NULL) + err(1, "getcwd()"); + + humanize_number(siz, sizeof(siz), s, "", + HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + humanize_number(ino, sizeof(ino), i, "", + HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + + printf("A syscall has failed with ENOSPC even though free disk " + "space for %s is reported as %s and %s inodes.\n", + path, siz, ino); + } + + + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); +} + +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + int code = errno; + + va_start(ap, fmt); + vpr(code, fmt, ap); + va_end(ap); + exit(eval); +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + int code = errno; + + va_start(ap, fmt); + vpr(code, fmt, ap); + va_end(ap); +} diff --git a/test/stress/stress2/link.cfg b/test/stress/stress2/link.cfg new file mode 100644 index 0000000000..59c1f30b94 --- /dev/null +++ b/test/stress/stress2/link.cfg @@ -0,0 +1,11 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/link/link testcases/swap/swap" +export linkHOG=1 +export linkLOAD=100 +export linkINCARNATIONS=100 diff --git a/test/stress/stress2/load.cfg b/test/stress/stress2/load.cfg new file mode 100644 index 0000000000..d4d70161a7 --- /dev/null +++ b/test/stress/stress2/load.cfg @@ -0,0 +1,18 @@ +# Just a test of the EXCLUDETESTS feature + +# Default values +. ./default.cfg + +###export TESTPROGS="" # Remove comments for test +###export HOG=1 # Remove comments for test + +###export LOAD=100 # Remove comments for test +###export swapLOAD=100 # Remove comments for test +###export rwLOAD=100 # Remove comments for test +###export mkdirLOAD=100 # Remove comments for test +###export creatLOAD=100 # Remove comments for test +###export symlinkLOAD=100 # Remove comments for test +###export swapLOAD=100 # Remove comments for test +###export linkLOAD=100 # Remove comments for test + +EXCLUDETESTS="sysctl|swap|tcp|udp|syscall|mmap|socket|thr|thr1|thr2|shm|badcode" diff --git a/test/stress/stress2/lockf.cfg b/test/stress/stress2/lockf.cfg new file mode 100644 index 0000000000..ded73eef97 --- /dev/null +++ b/test/stress/stress2/lockf.cfg @@ -0,0 +1,11 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/lockf2/lockf2 testcases/lockf/lockf testcases/swap/swap" +export lockf2HOG=1 +export lockf2LOAD=100 +export lockf2INCARNATIONS=100 diff --git a/test/stress/stress2/marcus.cfg b/test/stress/stress2/marcus.cfg new file mode 100644 index 0000000000..dcd93e4b0e --- /dev/null +++ b/test/stress/stress2/marcus.cfg @@ -0,0 +1,25 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +# Test configuration for the vop_stdvptocnp implementation + +export LOAD=80 +export symlinkLOAD=80 +export TESTPROGS=" +testcases/lockf2/lockf2 +testcases/symlink/symlink +testcases/openat/openat +testcases/rw/rw +testcases/fts/fts +testcases/link/link +testcases/lockf/lockf +testcases/creat/creat +testcases/mkdir/mkdir +testcases/rename/rename +testcases/swap/swap +testcases/mkfifo/mkfifo +" diff --git a/test/stress/stress2/misc/README b/test/stress/stress2/misc/README new file mode 100644 index 0000000000..d87e594a38 --- /dev/null +++ b/test/stress/stress2/misc/README @@ -0,0 +1,6 @@ +$FreeBSD$ + +This directory contains various test scenarios. Most are regression +tests for problems fixed. + +The script "all.sh" will run all the test scenarios for ever. diff --git a/test/stress/stress2/misc/all.sh b/test/stress/stress2/misc/all.sh new file mode 100755 index 0000000000..c8cdd96276 --- /dev/null +++ b/test/stress/stress2/misc/all.sh @@ -0,0 +1,139 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Run all the scripts in stress2/misc + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +# Start of list Run Known problems Verified + +# altbufferflushes.sh Y +# alternativeFlushPath.sh Y +# backingstore.sh Y +# cdevsw.sh N +# core.sh N No problems seen +# crossmp.sh Y +# crossmp2.sh N panic: sx lock still held 20071101 +# devfs.sh Y +# devfs2.sh Y 20070503 +# fdescfs.sh Y +# fpclone.sh N No problem seen +# fpclone2.sh N No problem seen +# fs.sh Y +# fullpath.sh Y 20081212 +# fuzz.sh N 20080413 +# inversion.sh N Problem not seen lately +# isofs.sh Y +# kevent.sh Y panic: KN_INFLUX set when not suppose to be 20080501 +# kevent2.sh Y +# kevent3.sh Y +# kevent4.sh Y +# kevent5.sh Y +# kinfo.sh Y +# kinfo2.sh Y +# libMicro.sh Y +# lockf.sh Y Page fault in nfs_advlock 20080413 +# lookup_shared.sh N The default, now +# mac.sh Y +# md.sh N Waiting for fix 20071208 +# md2.sh N Waiting for fix 20071208 +# mmap.sh N Waiting for fix 20080222 +# mount.sh N Known problem 20070505 +# mount2.sh Y +# mountro.sh N Waiting for commit 20080725 +# mountro2.sh N Waiting for commit 20080725 +# mountro3.sh N Waiting for commit 20080725 +# msdos.sh Y +# newfs.sh Y Problem not seen lately 20080513 +# newfs2.sh Y +# newfs3.sh N panic: lockmgr: locking against myself 20070505 +# newfs4.sh N Livelock 20080725 +# nfs.sh Y +# nfs2.sh N panic: wrong diroffset 20080801 +# nfs3.sh Y +# nfs4.sh Y +# nfs5.sh N Page fault in ufs/ffs/ffs_vfsops.c:1501 20080913 +# nfs6.sh N Page fault in ffs_fhtovp+0x18 20080913 +# nfsrename.sh Y +# nullfs.sh N panic: xdrmbuf_create with NULL mbuf chain 20081122 +# pthread.sh Y panic: spin lock held too long 20081109 +# quota1.sh Y +# quota10.sh N Deadlock 20081212 +# quota2.sh Y +# quota3.sh Y +# quota4.sh N Known backing store problem 20070703 +# quota5.sh Y +# quota6.sh N Known problem with snapshots and no disk space +# quota7.sh Y 20070505 +# quota8.sh Y 20070505 +# quota9.sh N 20070505 +# recursiveflushes.sh Y +# revoke.sh Y +# snap.sh N Waiting for snap3.sh fix +# snap2-1.sh Y +# snap2.sh Y +# snap3.sh N Reported as kostik033.html +# snap4.sh Y +# snap5-1.sh Y +# snap5.sh Y +# snap6.sh Y +# snap7.sh N Waiting for snap3.sh fix 20070508 +# snapbackup.sh N WIP +# softupdate.sh Y +# statfs.sh Y +# symlink.sh Y +# syscall.sh Y +# ucom.sh N +# umount.sh Y +# umountf.sh Y +# umountf2.sh N Waiting for commit of fix +# umountf3.sh N Deadlock. Waiting for commit of fix 20081212 +# umountf4.sh Y Page fault in ufs/ufs/ufs_dirhash.c:204 20081003 +# unionfs.sh N Page fault 20070503 +# unionfs2.sh N Reported as cons224 20070504 +# unionfs3.sh N Page fault in vfs_statfs 20070504 + +# End of list + +list=`sed -n '/^# Start of list/,/^# End of list/p' < $0 | awk '$3 ~ /Y/ {print $2}'` +[ $# -ne 0 ] && list=$* + + +rm -f /tmp/misc.log +while true; do +# Shuffle the list + list=`perl -e 'print splice(@ARGV,rand(@ARGV),1), " " while @ARGV;' $list` + for i in $list; do + ./cleanup.sh + echo "`date '+%Y%m%d %T'` all: $i" | tee /dev/tty >> /tmp/misc.log + logger "Starting test all: $i" + ./$i + done +done diff --git a/test/stress/stress2/misc/altbufferflushes.sh b/test/stress/stress2/misc/altbufferflushes.sh new file mode 100755 index 0000000000..7d5c41b7a5 --- /dev/null +++ b/test/stress/stress2/misc/altbufferflushes.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test. This script caused this panic: + +# panic: lockmgr: locking against myself +# cpuid = 2 +# KDB: enter: panic +# [thread pid 2526 tid 100070 ] +# Stopped at kdb_enter+0x2b: nop +# db> bt +# Tracing pid 2526 tid 100070 td 0xc46f8360 +# kdb_enter(c094247f) at kdb_enter+0x2b +# panic(c09402b6,c46f8360,0,12,c06af5d9,...) at panic+0x14b +# _lockmgr(d864a748,202122,c479f788,c46f8360,c094b01c,12d) at _lockmgr+0x41a +# getblk(c479f6b8,5d51940,0,4000,0,...) at getblk+0x13c +# breadn(c479f6b8,5d51940,0,4000,0,...) at breadn+0x2f +# bread(c479f6b8,5d51940,0,4000,0,e6d13544,c4743eac,0,c095a185,56d) at bread+0x20 +# ffs_alloccg(c47408c4,104,1754628,0,4000,c4743eac,1,c095a185,4d8) at ffs_alloccg+0x11d +# ffs_hashalloc(c47408c4,104,1754628,0,4000,...) at ffs_hashalloc+0x45 +# ffs_alloc(c47408c4,3f2cd,0,1754628,0,4000,c42fd400,e6d13674) at ffs_alloc+0x1a5 +# ffs_balloc_ufs2(c4735d70,fcb34000,0,4000,c42fd400,...) at ffs_balloc_ufs2+0x1619 +# ffs_copyonwrite(c479f6b8,d84e3d08) at ffs_copyonwrite+0x3d3 +# ffs_geom_strategy(c479f7c0,d84e3d08) at ffs_geom_strategy+0xbd +# bufwrite(d84e3d08,4000,d84e3d08,e6d137e4,c070b7a9,...) at bufwrite+0x17a +# ffs_bufwrite(d84e3d08) at ffs_bufwrite+0x282 +# vfs_bio_awrite(d84e3d08) at vfs_bio_awrite+0x235 +# bdwrite(d864a6e8,c4743eac,0,c095a185,57c,...) at bdwrite+0x237 +# ffs_alloccg(c4b54a50,104,1754628,0,4000,c4743eac,1,c095a185,4d8) at ffs_alloccg+0x1f6 +# ffs_hashalloc(c4b54a50,104,1754628,0,4000,...) at ffs_hashalloc+0x45 +# ffs_alloc(c4b54a50,1b00c,0,1754628,0,4000,c4b22a80,e6d139ac) at ffs_alloc+0x1a5 +# ffs_balloc_ufs2(c4e72158,6c030000,0,4000,c4b22a80,...) at ffs_balloc_ufs2+0x1619 +# ffs_write(e6d13b98) at ffs_write+0x2ac +# VOP_WRITE_APV(c0a00e80,e6d13b98) at VOP_WRITE_APV+0x132 +# vn_write(c46c65a0,e6d13c60,c4b22a80,0,c46f8360) at vn_write+0x1f6 +# dofilewrite(c46f8360,4,c46c65a0,e6d13c60,ffffffff,...) at dofilewrite+0x77 +# kern_writev(c46f8360,4,e6d13c60,8430000,d0000,...) at kern_writev+0x36 +# write(c46f8360,e6d13d00) at write+0x45 +# syscall(e6d13d38) at syscall+0x256 + + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +persist () { + false + while [ $? -ne 0 ]; do + $1 > /dev/null 2>&1 + sleep 1 + done +} + +diskfree=`df -k /var/tmp | tail -1 | awk '{print $4}'` +[ $((diskfree / 1024 / 1024)) -lt 5 ] && echo "Not enough disk space" && exit 1 + +rm -f /var/.snap/pho /var/tmp/big.? +trap "rm -f /var/.snap/pho /var/tmp/big.?" 0 +persist 'mksnap_ffs /var /var/.snap/pho' +sysctl vfs.dirtybufthresh=10 > /dev/null 2>&1 + +cd /var/tmp +for j in `jot 10`; do + old=`sysctl vfs.altbufferflushes | awk '{print $NF}'` + for i in `jot 4`; do + echo "`date '+%T'` Create big.$i" + dd if=/dev/zero of=big.$i bs=1m count=4k 2>&1 | egrep -v "records|transferred" + done + sleep 1 + rm -rf /var/tmp/big.? + new=`sysctl vfs.altbufferflushes | awk '{print $NF}'` + [ $new -ne $old ] && echo "vfs.altbufferflushes changed from $old to $new." +done +rm -f /var/.snap/pho diff --git a/test/stress/stress2/misc/alternativeFlushPath.sh b/test/stress/stress2/misc/alternativeFlushPath.sh new file mode 100755 index 0000000000..444c5d4ed3 --- /dev/null +++ b/test/stress/stress2/misc/alternativeFlushPath.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Alternate buffer flush path test (Not verified) +# Apply this patch to amplyfy the problem: +# +# diff -r1.520 vfs_bio.c +# 894c894 +# < if (bo->bo_dirty.bv_cnt > dirtybufthresh + 10) { +# --- +# > if (bo->bo_dirty.bv_cnt > dirtybufthresh /*+ 10*/) { + +odir=`pwd` +dir=/var/tmp/alternativeFlushPath + +find $dir -type f | xargs rm +[ ! -d $dir ] && mkdir -p $dir +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/alternativeFlushPath.c +cc -o alternativeFlushPath -Wall alternativeFlushPath.c -lthr +rm -f alternativeFlushPath.c + +for j in `jot 10`; do + ./alternativeFlushPath& +done +for j in `jot 20`; do + wait +done +sysctl -a | grep dirtybuf + +rm alternativeFlushPath + +exit + +EOF +#include +#include +#include +#include +#include +#include +#include +#include + +int +main() +{ + char name[80]; + int i, j, k; + pid_t mypid; + int *fd; + struct rlimit rlp; + + + if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) + err(1, "getrlimit(RLIMIT_NOFILE)"); + rlp.rlim_cur /= 10; + mypid = getpid(); + fd = malloc(rlp.rlim_cur * sizeof(int)); + + for (k = 0; k < 100; k++) { + for (i = 0, j = 0; i < (rlp.rlim_cur - 10); i++, j++) { + sprintf(name, "f%05d.%05d", mypid, i); + if ((fd[i] = open(name, O_CREAT|O_WRONLY, 0666)) == -1) { + warn("open(%s)", name); + break; + } + } + for (i = 0; i < j; i++) { + sprintf(name, "f%05d.%05d", mypid, i); + if (unlink(name) == -1) + warn("unlink(%s)", name); + } + for (i = 0; i < j; i++) { + if (close(fd[i]) == -1) + warn("close(%d)", i); + } + } + + exit(0); +} diff --git a/test/stress/stress2/misc/backingstore.sh b/test/stress/stress2/misc/backingstore.sh new file mode 100755 index 0000000000..493a3f3bec --- /dev/null +++ b/test/stress/stress2/misc/backingstore.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test sparse backing store + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +export here=`pwd` + +m=$mdstart + +mount | grep "${mntpoint}" | grep -q md$m && umount ${mntpoint}$m +mdconfig -l | grep -q md$m && mdconfig -d -u $m + +dede $D$m 100m 1 || exit 1 + +mdconfig -a -t vnode -f $D$m -u $m + +bsdlabel -w md$m auto +newfs md${m}${part} > /dev/null 2>&1 +mount $opt /dev/md${m}${part} ${mntpoint}$m + +n=$m +m=$((m + 1)) + +mount | grep "${mntpoint}" | grep -q md$m && umount ${mntpoint}$m +mdconfig -l | grep -q md$m && mdconfig -d -u $m + +truncate -s 500M ${mntpoint}$n/diskimage +mdconfig -a -t vnode -f ${mntpoint}$n/diskimage -u $m + +bsdlabel -w md$m auto +newfs md${m}${part} > /dev/null 2>&1 +mount $opt /dev/md${m}${part} ${mntpoint}$m + +export RUNDIR=${mntpoint}$m/stressX +../testcases/rw/rw -t 5m -i 200 -h -n + +while mount | grep -q ${mntpoint}$m; do + flag=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") + umount $flag ${mntpoint}$m > /dev/null 2>&1 +done +mdconfig -l | grep -q md$m && mdconfig -d -u $m + +m=$((m - 1)) +while mount | grep -q ${mntpoint}$m; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && \ + echo "-f" || echo "") ${mntpoint}$m > /dev/null 2>&1 +done +mdconfig -l | grep -q md$m && mdconfig -d -u $m +rm -f $D diff --git a/test/stress/stress2/misc/backingstore2.sh b/test/stress/stress2/misc/backingstore2.sh new file mode 100755 index 0000000000..fbc2684597 --- /dev/null +++ b/test/stress/stress2/misc/backingstore2.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test unmount of a device that is already gone + +# Leaves /mnt6 unmountable and leads to a "panic: 1 vncache entries remaining" +# during shut down. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +export here=`pwd` + +m1=$mdstart +m2=$((m1 + 1)) +mount | grep "${mntpoint}" | grep -q md$m2 && umount ${mntpoint}$m2 +mdconfig -l | grep -q md$m2 && mdconfig -d -u $m2 +mount | grep "${mntpoint}" | grep -q md$m1 && umount ${mntpoint}$m1 +mdconfig -l | grep -q md$m1 && mdconfig -d -u $m1 + +dede $D$m1 100m 1 || exit 1 + +mdconfig -a -t vnode -f $D$m1 -u $m1 + +bsdlabel -w md$m1 auto +newfs md${m1}${part} > /dev/null 2>&1 +mount /dev/md${m1}${part} ${mntpoint}$m1 + + +truncate -s 500M ${mntpoint}$m1/diskimage +mdconfig -a -t vnode -f ${mntpoint}$m1/diskimage -u $m2 + +bsdlabel -w md$m2 auto +newfs md${m2}${part} > /dev/null 2>&1 +mount /dev/md${m2}${part} ${mntpoint}$m2 + +# Reversed umount sequence: +umount -f /dev/md${m1}${part} +umount -f /dev/md${m2}${part} + +mount | grep "${mntpoint}" | grep -q md$m2 && umount ${mntpoint}$m2 +mdconfig -l | grep -q md$m2 && mdconfig -d -u $m2 +mount | grep "${mntpoint}" | grep -q md$m1 && umount ${mntpoint}$m1 +mdconfig -l | grep -q md$m1 && mdconfig -d -u $m1 diff --git a/test/stress/stress2/misc/backingstore3.sh b/test/stress/stress2/misc/backingstore3.sh new file mode 100755 index 0000000000..d65c1ead64 --- /dev/null +++ b/test/stress/stress2/misc/backingstore3.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test unmount of a device that is already gone + +# Caused "panic: bundirty: buffer 0xdafaf2c4 still on queue 1" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +export here=`pwd` + +m1=$mdstart +m2=$((m1 + 1)) +mount | grep "${mntpoint}" | grep -q md$m2 && umount ${mntpoint}$m2 +mdconfig -l | grep -q md$m2 && mdconfig -d -u $m2 +mount | grep "${mntpoint}" | grep -q md$m1 && umount ${mntpoint}$m1 +mdconfig -l | grep -q md$m1 && mdconfig -d -u $m1 + +dede $D$m1 25m 1 || exit 1 + +mdconfig -a -t vnode -f $D$m1 -u $m1 + +bsdlabel -w md$m1 auto +newfs md${m1}${part} > /dev/null 2>&1 +mount /dev/md${m1}${part} ${mntpoint}$m1 + + +truncate -s 500M ${mntpoint}$m1/diskimage +mdconfig -a -t vnode -f ${mntpoint}$m1/diskimage -u $m2 + +bsdlabel -w md$m2 auto +newfs md${m2}${part} > /dev/null 2>&1 +mount /dev/md${m2}${part} ${mntpoint}$m2 + +dd if=/dev/zero of=${mntpoint}$m2/file bs=1m > /dev/null 2>&1 + +# Reversed umount sequence: +umount -f /dev/md${m1}${part} +umount -f /dev/md${m2}${part} + +mount | grep "${mntpoint}" | grep -q md$m2 && umount ${mntpoint}$m2 +mdconfig -l | grep -q md$m2 && mdconfig -d -u $m2 +mount | grep "${mntpoint}" | grep -q md$m1 && umount ${mntpoint}$m1 +mdconfig -l | grep -q md$m1 && mdconfig -d -u $m1 diff --git a/test/stress/stress2/misc/cdevsw.sh b/test/stress/stress2/misc/cdevsw.sh new file mode 100755 index 0000000000..b300daa3ed --- /dev/null +++ b/test/stress/stress2/misc/cdevsw.sh @@ -0,0 +1,220 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by kib@freebsd.org + +# Test of patch for Giant trick in cdevsw + +exit # Test moved to fpclone*.sh + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +dir=$RUNDIR/tclone +[ ! -d $dir ] && mkdir -p $dir + +cd $dir +cat > Makefile < +EOF + +sed '1,/^EOF2/d' < $odir/$0 > tclone.c +make +kldload $dir/tclone.ko + +cd $odir +dd if=/dev/tclone bs=1m count=5k > /dev/null 2>&1 & + +export runRUNTIME=2m +cd /home/pho/stress2; ./run.sh pty.cfg + +kldstat +kldunload $dir/tclone.ko +rm -rf $dir +exit + +EOF2 +/* $FreeBSD$ */ + +#include +#include +#include +#include +#include +#include +#include + +static d_open_t tclone_open; +static d_close_t tclone_close; +static d_read_t tclone_read; + +static struct cdevsw tclone_cdevsw = { + .d_open = tclone_open, + .d_close = tclone_close, + .d_read = tclone_read, + .d_name = "tclone", + .d_version = D_VERSION, + .d_flags = D_TRACKCLOSE|D_NEEDGIANT +}; + +static eventhandler_tag tclone_ehtag; +static struct clonedevs *tclone_clones; + +MALLOC_DEFINE(M_TCLONESC, "tclone memory", "tclone memory"); + +struct tclone_sc +{ + int pos; +}; + +static void +tclone_clone(void *arg, struct ucred *cred, + char *name, int namelen, struct cdev **dev) +{ + int i, clone; + + if (*dev != NULL) + return; + if (strcmp(name, "tclone") != 0) + return; + + clone = 0; + do { + i = clone_create(&tclone_clones, &tclone_cdevsw, + &clone, dev, 0); + if (i == 0) + clone++; + } while ((clone <= CLONE_UNITMASK) && (i == 0)); + + if ((i != 0) && (clone <= CLONE_UNITMASK)) { + *dev = make_dev_credf(MAKEDEV_REF, + &tclone_cdevsw, unit2minor(clone), + cred, UID_ROOT, GID_WHEEL, 0666, + "tclone.%u", clone); + if (*dev != NULL) { + (*dev)->si_flags |= SI_CHEAPCLONE; + (*dev)->si_drv1 = (void *)1; + } + } +} + +static int +tclone_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td) +{ + int status; + + if (!dev->si_drv2) { + /* only allow one open() of this file */ + dev->si_drv2 = malloc(sizeof(struct tclone_sc), M_TCLONESC, + M_WAITOK | M_ZERO); + status = 0; + } else + status = EBUSY; + + if (status == 0) { + /* XXX Fix me? (clear of SI_CHEAPCLONE) */ + dev->si_flags &= ~SI_CHEAPCLONE; + } + + return (status); +} + +static int +tclone_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td) +{ + void *x; + + x = dev->si_drv2; + dev->si_drv2 = &tclone_cdevsw; + if (x != &tclone_cdevsw) + free(x, M_TCLONESC); + destroy_dev_sched(dev); + return (0); +} + +static char rdata[] = "tclone sample data string\n"; + +static int +tclone_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct tclone_sc *sc; + int rv, amnt; + + sc = dev->si_drv2; + rv = 0; + while (uio->uio_resid > 0) { + amnt = MIN(uio->uio_resid, sizeof(rdata) - sc->pos); + rv = uiomove(rdata + sc->pos, amnt, uio); + if (rv != 0) + break; + sc->pos += amnt; + sc->pos %= sizeof(rdata); + } + return (rv); +} + +static int +tclone_modevent(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + clone_setup(&tclone_clones); + tclone_ehtag = EVENTHANDLER_REGISTER(dev_clone, + tclone_clone, 0, 0); + if (tclone_ehtag == NULL) + return ENOMEM; + return(0); + + case MOD_UNLOAD: + EVENTHANDLER_DEREGISTER(dev_clone, tclone_ehtag); + drain_dev_clone_events(); + clone_cleanup(&tclone_clones); + destroy_dev_drain(&tclone_cdevsw); + return (0); + default: + break; + } + + return (0); +} + +moduledata_t tclone_mdata = { + "tclone", + tclone_modevent, + NULL +}; + +DECLARE_MODULE(tclone, tclone_mdata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +MODULE_VERSION(tclone, 1); diff --git a/test/stress/stress2/misc/cleanup.sh b/test/stress/stress2/misc/cleanup.sh new file mode 100755 index 0000000000..66858d4594 --- /dev/null +++ b/test/stress/stress2/misc/cleanup.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +[ ! -z "$mntpoint" ] && rm -rf ${mntpoint}*/* +rm -f /tmp/.snap/pho* /var/.snap/pho* +rm -rf /tmp/stressX.control + +mount | grep -wq $mntpoint && umount $mntpoint +m=$mdstart +for i in `jot 15`; do + while mount | grep -q ${mntpoint}$m; do + rm -rf ${mntpoint}$m + umount -f ${mntpoint}$m > /dev/null 2>&1 + done + mdconfig -l | grep -q md$m && mdconfig -d -u $m + m=$((m + 1)) +done diff --git a/test/stress/stress2/misc/core.sh b/test/stress/stress2/misc/core.sh new file mode 100755 index 0000000000..87af822ce6 --- /dev/null +++ b/test/stress/stress2/misc/core.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test multiple (parallel) core dumps + +. ../default.cfg + +odir=`pwd` + +cd /tmp +rm -f core +sed '1,/^EOF/d' < $odir/$0 > core.c +cc -o core -Wall core.c +rm -f core.c +cd $RUNDIR + +for i in `jot 2`; do + for j in `jot 4`; do + /tmp/core & + done + for j in `jot 4`; do + wait + done +done +rm -f core +exit +EOF +#include +#include +#include +#include +#include +#include +#include + +#define SIZ 10*1024*1024 + +int +main(int argc, char **argv) +{ + char *cp = 0; + + if ((cp = malloc(SIZ)) == NULL) + err(1, "Could not malloc 10Mb!"); + + memset(cp, 1, SIZ); + +// printf("sleep %d\n", (120 - (time(NULL) % 120))); fflush(stdout); + sleep(120 - (time(NULL) % 120)); + raise(SIGSEGV); +// printf(".\n"); + + return (0); +} diff --git a/test/stress/stress2/misc/crossmp.sh b/test/stress/stress2/misc/crossmp.sh new file mode 100755 index 0000000000..d5bc951a20 --- /dev/null +++ b/test/stress/stress2/misc/crossmp.sh @@ -0,0 +1,88 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Copy of crossmp.sh, but with SU enabled. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point +D=$diskimage + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + mdconfig -l | grep -q md$m && mdconfig -d -u $m + + dede $D$m 1m 1 + mdconfig -a -t vnode -f $D$m -u $m + bsdlabel -w md$m auto + newfs md${m}${part} > /dev/null 2>&1 + done + + # start the parallel tests + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done + + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + mdconfig -d -u $m + rm -f $D$m + done + +else + if [ $1 = find ]; then + for i in `jot 1024`; do + find ${mntpoint}* -type f > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + mount /dev/md${m}${part} ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + opt=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + fi +fi diff --git a/test/stress/stress2/misc/crossmp2.sh b/test/stress/stress2/misc/crossmp2.sh new file mode 100755 index 0000000000..961c6d6d5d --- /dev/null +++ b/test/stress/stress2/misc/crossmp2.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Panic in getdirentries+0x21a +# Run with stress: disk.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=10 # Number of parallel scripts + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + [ ! -d ${mntpoint}$i ] && mkdir ${mntpoint}$i + mount | grep -qw "${mntpoint}$i" && umount ${mntpoint}$i + done + + # start the parallel tests + for i in `jot $mounts`; do + ./$0 $i & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done +else + if [ $1 = find ]; then + for i in `jot 64`; do + find ${mntpoint}* -maxdepth 1 -type f > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 64`; do + m=$1 + mount -t nfs -o tcp -o nfsv3 -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp ${mntpoint}$m + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + n=0 + while mount | grep -qw ${mntpoint}$m; do + umount $opt ${mntpoint}$m > /dev/null 2>&1 + n=$((n + 1)) + [ $n -gt 99 ] && umount -f ${mntpoint}$m > /dev/null 2>&1 + [ $n -gt 100 ] && exit + done + done + fi +fi diff --git a/test/stress/stress2/misc/datamove.sh b/test/stress/stress2/misc/datamove.sh new file mode 100755 index 0000000000..da2fb2001a --- /dev/null +++ b/test/stress/stress2/misc/datamove.sh @@ -0,0 +1,208 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# There is a well-known problem in FreeBSD, caused by allowing page faults +# while doing filesystem data move to or from userspace during read(2) and +# write(2). The issue is that if the userspace address being read or write +# from/to is backed by the mapping of the same file we are doing i/o to, +# we deadlock. + +# Test scenario by ups + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > dl.c +cc -o dl -Wall dl.c +rm -f dl.c + +n=5 +old=`sysctl vm.old_msync | awk '{print $NF}'` +sysctl vm.old_msync=1 +for i in `jot $n`; do + mkdir -p /tmp/dl.dir.$i + cd /tmp/dl.dir.$i + /tmp/dl & +done +cd /tmp +for i in `jot $n`; do + wait +done +for i in `jot $n`; do + rm -rf /tmp/dl.dir.$i +done +sysctl vm.old_msync=$old + +rm -rf /tmp/dl +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include + + +int prepareFile(char* filename,int* fdp); +int mapBuffer(char** bufferp,int fd1,int fd2); +int startIO(int fd,char *buffer); + +int pagesize; + +#define FILESIZE (32*1024) +char wbuffer[FILESIZE]; + +/* Create a FILESIZE sized file - then remove file data from the cache*/ +int prepareFile(char* filename,int* fdp) +{ + int fd; + int len; + int status; + void *addr; + + fd = open(filename,O_CREAT | O_TRUNC | O_RDWR,S_IRWXU); + if (fd == -1) + { + perror("Creating file"); + return fd; + } + + len = write(fd,wbuffer,FILESIZE); + if (len < 0) + { + perror("Write failed"); + return 1; + } + + status = fsync(fd); + if (status != 0) + { + perror("fsync failed"); + return 1; + } + + addr = mmap(NULL,FILESIZE, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) + { + perror("Mmap failed"); + return 1; + } + + status = msync(addr,FILESIZE,MS_INVALIDATE | MS_SYNC); + if (status != 0) + { + perror("Msync failed"); + return 1; + } + + munmap(addr,FILESIZE); + + *fdp = fd; + return 0; +} + + +/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ +int mapBuffer(char** bufferp,int fd1,int fd2) +{ + void* addr; + char *buffer; + + addr = mmap(NULL,pagesize*2, PROT_READ | PROT_WRITE , MAP_SHARED, fd1, 0); + if (addr == MAP_FAILED) + { + perror("Mmap failed"); + return 1; + } + + buffer = addr; + addr = mmap(buffer + pagesize,pagesize, PROT_READ | PROT_WRITE , MAP_FIXED | +MAP_SHARED, fd2, 0); + + if (addr == MAP_FAILED) + { + perror("Mmap2 failed"); + return 1; + } + *bufferp = buffer; + return 0; +} + + +int startIO(int fd,char *buffer) +{ + ssize_t len; + len = write(fd,buffer,2*pagesize); + if (len == -1) + { + perror("write failed"); + return 1; + } + return 0; +} + + +int main(int argc,char *argv[],char *envp[]) +{ + + int fdA,fdB,fdDelayA,fdDelayB; + int status; + char *bufferA,*bufferB; + pid_t pid; + + pagesize = getpagesize(); + + if ((prepareFile("A",&fdA)) + || (prepareFile("B",&fdB)) + || (prepareFile("DelayA",&fdDelayA)) + || (prepareFile("DelayB",&fdDelayB)) + || (mapBuffer(&bufferA,fdDelayA,fdB)) + || (mapBuffer(&bufferB,fdDelayB,fdA))) + exit(1); + + pid = fork(); + + if (pid == 0) + { + status = startIO(fdA,bufferA); + exit(status); + } + + if (pid == -1) + { + exit(1); + } + status = startIO(fdB,bufferB); + exit(status); + +} diff --git a/test/stress/stress2/misc/datamove2.sh b/test/stress/stress2/misc/datamove2.sh new file mode 100755 index 0000000000..ad321cc8fd --- /dev/null +++ b/test/stress/stress2/misc/datamove2.sh @@ -0,0 +1,210 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Variation of the datamove.sh scenario by not using "sysctl vm.old_msync=1" + +# Deadlock seen + +# Test scenario by ups + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > dl.c +cc -o dl -Wall dl.c +rm -f dl.c + +for i in `jot 3`; do + $here/../testcases/swap/swap -t 10m -i 200 -h & + /tmp/dl + ps | grep swap | grep -v swap | awk '{print $1}' | xargs kill +done +rm -rf /tmp/dl +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int prepareFile(char *filename, int *fdp); +int mapBuffer (char **bufferp, int fd1, int fd2); +int startIO (int fd, char *buffer); + +int pagesize; + +#define FILESIZE (32*1024) +char wbuffer [FILESIZE]; + +/* Create a FILESIZE sized file - then remove file data from the cache */ +int +prepareFile(char *filename, int *fdp) +{ + int fd; + int len; + int status; + void *addr; + + fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); + if (fd == -1) { + perror("Creating file"); + return fd; + } + len = write(fd, wbuffer, FILESIZE); + if (len < 0) { + perror("Write failed"); + return 1; + } + status = fsync(fd); + if (status != 0) { + perror("fsync failed"); + return 1; + } + addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + perror("Mmap failed"); + return 1; + } + status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC); + if (status != 0) { + perror("Msync failed"); + return 1; + } + if (munmap(addr, FILESIZE) == -1) { + perror("munmap failed"); + return 1; + } + + *fdp = fd; + return 0; +} + + +/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ +int +mapBuffer(char **bufferp, int fd1, int fd2) +{ + void *addr; + char *buffer; + + addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); + if (addr == MAP_FAILED) { + perror("Mmap failed"); + return 1; + } + buffer = addr; + addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | + MAP_SHARED, fd2, 0); + + if (addr == MAP_FAILED) { + perror("Mmap2 failed"); + return 1; + } + *bufferp = buffer; + return 0; +} + +void +unmapBuffer(char *bufferp) +{ + if (munmap(bufferp, pagesize * 2) == -1) + err(1, "unmap 1. buffer"); + if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1) + err(1, "unmap 2. buffer"); +} + +int +startIO(int fd, char *buffer) +{ + ssize_t len; + + len = write(fd, buffer, 2 * pagesize); + if (len == -1) { + perror("write failed"); + return 1; + } + return 0; +} + + +int +main(int argc, char *argv[], char *envp[]) +{ + + int fdA, fdB, fdDelayA, fdDelayB; + int status; + int i; + char *bufferA, *bufferB; + pid_t pid; + + pagesize = getpagesize(); + + for (i = 0; i < 1000; i++) { + if ((prepareFile("A", &fdA)) + || (prepareFile("B", &fdB)) + || (prepareFile("DelayA", &fdDelayA)) + || (prepareFile("DelayB", &fdDelayB)) + || (mapBuffer(&bufferA, fdDelayA, fdB)) + || (mapBuffer(&bufferB, fdDelayB, fdA))) + exit(1); + + pid = fork(); + + if (pid == 0) { + status = startIO(fdA, bufferA); + exit(status); + } + if (pid == -1) { + perror("fork"); + exit(1); + } + status = startIO(fdB, bufferB); + if (wait(&status) == -1) + err(1, "wait"); + + close(fdA); + close(fdB); + close(fdDelayA); + close(fdDelayB); + unmapBuffer(bufferA); + unmapBuffer(bufferB); + unlink("A"); + unlink("B"); + unlink("DelayA"); + unlink("DelayB"); + } + exit(status); + +} diff --git a/test/stress/stress2/misc/datamove3.sh b/test/stress/stress2/misc/datamove3.sh new file mode 100755 index 0000000000..0afb42d9e4 --- /dev/null +++ b/test/stress/stress2/misc/datamove3.sh @@ -0,0 +1,219 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Threaded variation of datamove.sh + +# Based on a test scenario by ups and suggestions by kib + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > dl.c +cc -o dl -Wall dl.c -lpthread +rm -f dl.c + +n=5 +old=`sysctl vm.old_msync | awk '{print $NF}'` +sysctl vm.old_msync=1 +for i in `jot $n`; do + mkdir -p /tmp/dl.dir.$i + cd /tmp/dl.dir.$i + /tmp/dl & +done +cd /tmp +for i in `jot $n`; do + wait +done +for i in `jot $n`; do + rm -rf /tmp/dl.dir.$i +done +sysctl vm.old_msync=$old + +rm -rf /tmp/dl +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct args { + char *bp; + int fd1; + int fd2; +} a[2]; + +int prepareFile(char *, int *); +void * mapBuffer(void *); +int startIO(int, char *); + +int pagesize; + +#define FILESIZE (32*1024) +char wbuffer [FILESIZE]; + +/* Create a FILESIZE sized file - then remove file data from the cache */ +int +prepareFile(char *filename, int *fdp) +{ + int fd; + int len; + int status; + void *addr; + + fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); + if (fd == -1) { + perror("Creating file"); + return fd; + } + len = write(fd, wbuffer, FILESIZE); + if (len < 0) { + perror("Write failed"); + return 1; + } + status = fsync(fd); + if (status != 0) { + perror("fsync failed"); + return 1; + } + addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + perror("Mmap failed"); + return 1; + } + status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC); + if (status != 0) { + perror("Msync failed"); + return 1; + } + munmap(addr, FILESIZE); + + *fdp = fd; + return 0; +} + + +/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ +void * +mapBuffer(void *ar) +{ + void *addr; + char *buffer; + int i; + + i = (int )ar; + addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, a[i].fd1, 0); + if (addr == MAP_FAILED) { + err(1, "Mmap failed"); + } + buffer = addr; + addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | + MAP_SHARED, a[i].fd2, 0); + + if (addr == MAP_FAILED) { + err(1, "Mmap2 failed"); + } + a[i].bp = buffer; + sleep(1); + return (NULL); +} + + +int +startIO(int fd, char *buffer) +{ + ssize_t len; + + len = write(fd, buffer, 2 * pagesize); + if (len == -1) { + warn("startIO(%d, %p): write failed", fd, buffer); + return 1; + } + return 0; +} + + + +int +main(int argc, char *argv[], char *envp[]) +{ + + int fdA, fdB, fdDelayA, fdDelayB; + int r, status; + char *bufferA, *bufferB; + pid_t pid; + pthread_t threads[2]; + + pagesize = getpagesize(); + + if ((prepareFile("A", &fdA)) + || (prepareFile("B", &fdB)) + || (prepareFile("DelayA", &fdDelayA)) + || (prepareFile("DelayB", &fdDelayB))) + exit(1); + + a[0].fd1 = fdDelayA; + a[0].fd2 = fdB; + + a[1].fd1 = fdDelayB; + a[1].fd2 = fdA; + + if ((r = pthread_create(&threads[0], NULL, mapBuffer, (void *)0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + if ((r = pthread_create(&threads[1], NULL, mapBuffer, (void *)1)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + while (a[0].bp == NULL || a[1].bp == NULL) + pthread_yield(); + + bufferA = a[0].bp; + bufferB = a[1].bp; + + pid = fork(); + + if (pid == 0) { + status = startIO(fdA, bufferA); + exit(status); + } + if (pid == -1) { + exit(1); + } + status = startIO(fdB, bufferB); + exit(status); + +} diff --git a/test/stress/stress2/misc/devfs.sh b/test/stress/stress2/misc/devfs.sh new file mode 100755 index 0000000000..8f3382803b --- /dev/null +++ b/test/stress/stress2/misc/devfs.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +mounts=10 # Number of parallel scripts +D=/usr/tmp/diskimage + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + [ ! -d ${mntpoint}$i ] && mkdir ${mntpoint}$i + mount | grep -q "${mntpoint}$i" && umount ${mntpoint}$i + done + + # start the parallel tests + for i in `jot $mounts`; do + ./$0 $i & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done +else + if [ $1 = find ]; then + for i in `jot 64`; do + find ${mntpoint}* -maxdepth 1 -type f > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 64`; do + m=$1 + mount -t devfs none ${mntpoint}$m + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + while mount | grep -q ${mntpoint}$m; do + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + fi +fi diff --git a/test/stress/stress2/misc/devfs2.sh b/test/stress/stress2/misc/devfs2.sh new file mode 100755 index 0000000000..b9b23b9e4d --- /dev/null +++ b/test/stress/stress2/misc/devfs2.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Stopped at devfs_open+0x23f: pushl 0x14(%ebx) +# db> where +# Tracing pid 46017 tid 100350 td 0xc4c08510 +# devfs_open(e6d06a10) at devfs_open+0x23f +# VOP_OPEN_APV(c09edda0,e6d06a10) at VOP_OPEN_APV+0x9b +# vn_open_cred(e6d06b78,e6d06c78,0,c4883900,3,...) at vn_open_cred+0x41e +# vn_open(e6d06b78,e6d06c78,0,3) at vn_open+0x1e +# kern_open(c4c08510,8048887,0,1,0,...) at kern_open+0xb7 +# open(c4c08510,e6d06d00) at open+0x18 +# syscall(e6d06d38) at syscall+0x252 + +# Test scenario by kib@freebsd.org + +odir=`pwd` +dir=/tmp + +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/devfs2.c +cc -o devfs2 -Wall devfs2.c -lthr +rm -f devfs2.c + +./devfs2 + +rm devfs2 + +exit + +EOF +#include +#include +#include +#include +#include +#include +#include +#include + +void * +thr1(void *arg) +{ + int fd; + int i; + + for (i = 0; i < 1024; i++) { + if ((fd = open("/dev/zero", O_RDONLY)) == -1) + perror("open /dev/zero"); + close(fd); + } + return (0); +} + +void * +thr2(void *arg) +{ + int i; + for (i = 0; i < 1024; i++) + close(3); + return (0); +} + +int +main() +{ + pthread_t threads[2]; + int i; + int r; + + if ((r = pthread_create(&threads[0], NULL, thr1, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + if ((r = pthread_create(&threads[1], NULL, thr2, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + for (i = 0; i < 2; i++) + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + + return (0); +} diff --git a/test/stress/stress2/misc/extattr.sh b/test/stress/stress2/misc/extattr.sh new file mode 100755 index 0000000000..37dcc70755 --- /dev/null +++ b/test/stress/stress2/misc/extattr.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Regression test of extattr on a UFS2 FS using ACLs +# Caused a "Duplicate free" panic. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > extattr.c +cc -o extattr -Wall extattr.c +rm -f extattr.c +cd $odir + +mount | grep "${mntpoint}" | grep -q md${mdstart}${part} && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 20m -u $mdstart +bsdlabel -w md$mdstart auto + +newfs -O 2 md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} $mntpoint + +mkdir -p ${mntpoint}/.attribute/system +cd ${mntpoint}/.attribute/system + +extattrctl initattr -p . 388 posix1e.acl_access +extattrctl initattr -p . 388 posix1e.acl_default +cd / +umount /mnt +tunefs -a enable /dev/md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint +mount | grep md${mdstart}${part} + +touch $mntpoint/acl-test +setfacl -b $mntpoint/acl-test +setfacl -m user:nobody:rw-,group:wheel:rw- $mntpoint/acl-test + +for i in `jot 5`; do + /tmp/extattr $mntpoint/acl-test & +done +for i in `jot 5`; do + wait +done + +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/extattr +exit +EOF +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i; + struct stat sb; + + for (i = 0; i < 100000; i++) + if (lstat(argv[1], &sb) == -1) + err(1, "lstat(%s)", argv[1]); + return (0); +} diff --git a/test/stress/stress2/misc/extattrctl.sh b/test/stress/stress2/misc/extattrctl.sh new file mode 100755 index 0000000000..98a522b0cc --- /dev/null +++ b/test/stress/stress2/misc/extattrctl.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Regression test of extattrctl and ACLs on UFS1 FS +# Kernel must be compiled with options UFS_EXTATTR and UFS_EXTATTR_AUTOSTART + +# Scenario by rwatson@ from: +# +# Newsgroups: lucky.freebsd.current +# Subject: Re: setfacl requirements? +# Date: Thu, 5 Dec 2002 15:50:02 +0000 (UTC) + + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +sysctl -a | ! grep -q ufs_extattr && echo "Missing options UFS_EXTATTR" && exit 1 + +mount | grep "${mntpoint}" | grep -q md${mdstart}${part} && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 20m -u $mdstart +bsdlabel -w md$mdstart auto + +newfs -O 1 md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} $mntpoint + +mkdir -p ${mntpoint}/.attribute/system +cd ${mntpoint}/.attribute/system + +extattrctl initattr -p . 388 posix1e.acl_access +extattrctl initattr -p . 388 posix1e.acl_default +cd / +umount /mnt +tunefs -a enable /dev/md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint +mount | grep md${mdstart}${part} + +touch $mntpoint/acl-test +setfacl -b $mntpoint/acl-test +setfacl -m user:nobody:rw-,group:wheel:rw- $mntpoint/acl-test +getfacl $mntpoint/acl-test +ls -l $mntpoint/acl-test + +umount $mntpoint +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/fdescfs.sh b/test/stress/stress2/misc/fdescfs.sh new file mode 100755 index 0000000000..a01ab93a10 --- /dev/null +++ b/test/stress/stress2/misc/fdescfs.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point +D=$diskimage + +if [ $# -eq 0 ]; then + # start the parallel tests + for i in `jot $mounts`; do + ./$0 $i & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done +else + if [ $1 = find ]; then + exec 6< /dev/zero + exec 7< /dev/zero + exec 8< /dev/zero + exec 9< /dev/zero + for i in `jot 128`; do + ls -l ${mntpoint}* > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 128`; do +# mount -t fdescfs null ${mntpoint}$1 # This causes mound to complain + mount_fdescfs null ${mntpoint}$1 + while mount | grep -wq ${mntpoint}$1; do + umount -f ${mntpoint}$1 > /dev/null 2>&1 + done + done + fi +fi diff --git a/test/stress/stress2/misc/fpclone.sh b/test/stress/stress2/misc/fpclone.sh new file mode 100755 index 0000000000..907f5a0e46 --- /dev/null +++ b/test/stress/stress2/misc/fpclone.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by kib@freebsd.org + +# Test of + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +dir=$RUNDIR/fpclone +[ ! -d $dir ] && mkdir -p $dir + +cd $dir +cat > Makefile < +EOF + +sed '1,/^EOF2/d' < $odir/$0 > fpclone.c +make +kldload $dir/fpclone.ko + +cd $odir +for i in `jot 10`; do + dd if=/dev/fpclone bs=1m count=10 > /dev/null 2>&1 & +done + +export runRUNTIME=2m +cd /home/pho/stress2; ./run.sh pty.cfg + +for i in `jot 10`; do + wait +done +kldstat +dd if=/dev/fpclone bs=1m count=1k > /dev/null 2>&1 & +kldunload $dir/fpclone.ko +rm -rf $dir +exit + +EOF2 +/* $FreeBSD$ */ + +#include +#include +#include +#include +#include +#include +#include + +typedef void (*cdevpriv_dtr_t)(void *data); +int devfs_get_cdevpriv(void **datap); +int devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t dtr); +void devfs_clear_cdevpriv(void); +void devfs_fpdrop(struct file *fp); /* XXX This is not public KPI */ + + +static d_open_t fpclone_open; +static d_close_t fpclone_close; +static d_read_t fpclone_read; + +static struct cdevsw fpclone_cdevsw = { + .d_open = fpclone_open, + .d_close = fpclone_close, + .d_read = fpclone_read, + .d_name = "fpclone", + .d_version = D_VERSION, + .d_flags = D_TRACKCLOSE +}; + +MALLOC_DEFINE(M_FPCLONESC, "fpclone memory", "fpclone memory"); + +struct fpclone_sc +{ + int pos; +}; + +static struct cdev *fpclone_dev; +static struct mtx me; + +static void +fpclone_cdevpriv_dtr(void *data) +{ + free(data, M_FPCLONESC); +} + +static int +fpclone_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td) +{ + struct fpclone_sc *sc; + int error; + + sc = malloc(sizeof(struct fpclone_sc), M_FPCLONESC, + M_WAITOK | M_ZERO); + error = devfs_set_cdevpriv(sc, fpclone_cdevpriv_dtr); + if (error) + fpclone_cdevpriv_dtr(sc); + return (error); +} + +static int +fpclone_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td) +{ + + devfs_clear_cdevpriv(); + return (0); +} + +static char rdata[] = "fpclone sample data string\n"; + +static int +fpclone_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct fpclone_sc *sc; + int rv, amnt, svpos, error; + + error = devfs_get_cdevpriv((void **)&sc); + if (error) + return (error); + + rv = 0; + while (uio->uio_resid > 0) { + svpos = sc->pos; + amnt = MIN(uio->uio_resid, sizeof(rdata) - svpos); + rv = uiomove(rdata + svpos, amnt, uio); + if (rv != 0) + break; + mtx_lock(&me); + sc->pos += amnt; + sc->pos %= sizeof(rdata); + mtx_unlock(&me); + } + return (rv); +} + +static int +fpclone_modevent(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + mtx_init(&me, "fp_ref", NULL, MTX_DEF); + fpclone_dev = make_dev(&fpclone_cdevsw, 0, 0, 0, 0666, + "fpclone"); + return(0); + + case MOD_UNLOAD: + destroy_dev(fpclone_dev); + mtx_destroy(&me); + return (0); + + default: + break; + } + + return (0); +} + +moduledata_t fpclone_mdata = { + "fpclone", + fpclone_modevent, + NULL +}; + +DECLARE_MODULE(fpclone, fpclone_mdata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +MODULE_VERSION(fpclone, 1); diff --git a/test/stress/stress2/misc/fpclone2.sh b/test/stress/stress2/misc/fpclone2.sh new file mode 100755 index 0000000000..cbbc79c22d --- /dev/null +++ b/test/stress/stress2/misc/fpclone2.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by kib@freebsd.org + +# Test of + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +dir=$RUNDIR/fpclone +[ ! -d $dir ] && mkdir -p $dir + +cd $dir +cat > Makefile < +EOF + +sed '1,/^EOF2/d' < $odir/fpclone.sh > fpclone.c +make +kldload $dir/fpclone.ko + +sed '1,/^EOF2/d' < $odir/$0 > fpclone2.c +cc -o fpclone2 -Wall fpclone2.c +rm -f fpclone2.c + +cd $odir +for i in `jot 10`; do + $dir/fpclone2 & +done + +for i in `jot 10`; do + wait +done +kldstat +kldunload $dir/fpclone.ko +rm -rf $dir fpclone2 +exit + +EOF2 +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int fd; + int i; + char buf[80]; + + for (i = 0; i < 10000; i++) { + if ((fd = open("/dev/fpclone", O_RDONLY)) == -1) + err(1, "open(/dev/fpclone"); + if (read(fd, buf, sizeof(buf)) <= 0) + err(1, "read"); + if (dup2(fd, 10) == -1) + err(1, "dup"); + if (dup2(fd, 11) == -1) + err(1, "dup"); + if (dup2(fd, 12) == -1) + err(1, "dup"); + if (close(fd) == -1) + err(1, "close(%d)", fd); + if (close(10) == -1) + err(1, "close(%d)", 10); + if (close(11) == -1) + err(1, "close(%d)", 11); + if (close(12) == -1) + err(1, "close(%d)", 12); + } + if ((fd = open("/dev/fpclone", O_WRONLY)) == -1) + err(1, "open(/dev/fpclone"); + if (write(fd, "xxx", 3) == -1 && errno != ENODEV) + err(1, "write"); + if (close(fd) == -1) + err(1, "close(%d)", fd); + + return (0); +} diff --git a/test/stress/stress2/misc/fpu.sh b/test/stress/stress2/misc/fpu.sh new file mode 100755 index 0000000000..e69ac61213 --- /dev/null +++ b/test/stress/stress2/misc/fpu.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# Regression test for FPU changes in r208833 + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > fpu.c +cc -o fpu -Wall -O2 fpu.c +rm -f fpu.c +[ -d $RUNDIR ] || mkdir -p $RUNDIR +cd $RUNDIR + +r=`/tmp/fpu` +[ "$r" = "-0.000000017, 0.000000000, 0.000000000" ] || echo $r + +cd $here +rm -f /tmp/fpu + +exit 0 +EOF +#include +#include +#include +#include +#include +#include + +void +handler(int i) +{ +} + +void +test() +{ + float val = 0; + double lval = 0; + long double llval = 0; + int i, j; + + for (i = 0; i < 100000; i++) { + for (j = 0; j < 100000; j++) { + val = val + 0.00001; + lval = lval + 0.00001; + llval = llval + 0.00001; + } + for (j = 0; j < 100000; j++) { + val = val - 0.00001; + lval = lval - 0.00001; + llval = llval - 0.00001; + } + } + printf("%.9f, %.9f, %.9Lf\n", val, lval, llval); + exit(0); + +} + +int +main() +{ + pid_t pid; + int i; + + signal(SIGHUP, handler); + + if ((pid = fork()) == 0) + test(); + + for (i = 0; i < 10000; i++) + kill(pid, SIGHUP); + + wait(NULL); + + return (0); +} diff --git a/test/stress/stress2/misc/fragments.sh b/test/stress/stress2/misc/fragments.sh new file mode 100755 index 0000000000..743633f8bf --- /dev/null +++ b/test/stress/stress2/misc/fragments.sh @@ -0,0 +1,266 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# Scenario that causes "panic: brelse: free buffer onto another queue???" +# Idea for scenario by kib@. Fixed in r203818 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +here=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $here/$0 > fragments.c +rm -f /tmp/fragments +cc -o fragments -Wall -Wextra -O2 -g fragments.c +rm -f fragments.c +cd $here + +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f ${mntpoint} +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md$mdstart auto +newfs -U -m 0 md${mdstart}${part} > /dev/null 2>&1 +mount /dev/md${mdstart}${part} /mnt +chmod 777 /mnt + +cd /mnt +su ${testuser} -c "/tmp/fragments" +cd $here + +umount /mnt +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f ${mntpoint} +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +rm -f /tmp/fragments +exit +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOOPS 50000 +#define PARALLEL 8 + +static pid_t pid; +static char *buf; + +void +cleanup(int n) +{ + int i, j, start; + int nb = 0; + char file[128]; + struct statfs sbuf; + struct stat sb; + + if (n == -1) { + for (i = 0; i < LOOPS; i++) { + sprintf(file,"t%05d", i); + unlink(file); + } + return; + } + + start = arc4random() % n; + for (i = 0; i < LOOPS; i++) { + j = (start + i) % LOOPS; + sprintf(file,"t%05d", j); + if (stat(file, &sb) != 0) + continue; + + if (sb.st_size == 0) { + unlink(file); + continue; + } + if (truncate(file, 0) == 0) { + nb++; + continue; + } + if (nb > 10) + break; + } + + + for (i = 0; i < 10; i++) { + if (statfs(".", &sbuf) < 0) + err(1, "statfs(%s)", "."); + + if (sbuf.f_bfree > 8) + return; + } + + for (i = 0; i < LOOPS; i++) { + j = (start + i) % LOOPS; + sprintf(file,"t%05d", j); + if (unlink(file) == 0) { + return; + } + } +} + +void +fragments(void) +{ + int i, len; + char file[128]; + int fd; + + for (i = 0;; i++) { + sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i); + + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { + if (errno != ENOSPC) + warn("open(%s)", file); + break; + } + + len = 2 * 1024; + if (write(fd, buf, len) != len) { + } + + close(fd); + } +} + +void +blocks(void) +{ + int i, len; + char file[128]; + int fd; + + for (i = 0;; i++) { + sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i); + + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { + if (errno != ENOSPC) + warn("open(%s)", file); + break; + } + + len = 16 * 1024; + if (write(fd, buf, len) != len) { + } + + close(fd); + } +} + +void +setup(void) +{ + int i; + char file[128]; + + for (i = 0; i < 300; i++) { + sprintf(file,"d%d", i); + if (mkdir(file, 0700) == -1) + warn("mkdir(%s)", file); + } + + blocks(); + fragments(); + + for (i = 0;i < 8; i++) { + sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i); + unlink(file); + unlink(file); + } + for (i = 0;i < 1; i++) { + sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i); + unlink(file); + } + +} + +int +test(void) +{ + int i, len, n; + char file[128]; + int fd; + + for (i = 0; i < LOOPS; i++) { + sprintf(file,"t%05d", i); + + if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) { + continue; + } +// n = arc4random() % (12 + 1); + n = 0; + len = (arc4random() % (16 * 1024) + 1) + n * 16; + while (len > 0) { + if (write(fd, buf, len) == len) + break; + len = len / 2; + usleep(1000); + } + close(fd); + if (len == 0) { + cleanup(i); + } + } + + exit(0); + + return (0); +} + +int +main() +{ + int i, j, status; + + pid = getpid(); + if ((buf = malloc(12 * 16 * 1024)) == NULL) + err(1, "malloc()"); + + setup(); + for (j = 0; j < 50; j++) { + for (i = 0; i < PARALLEL; i++) { + if (fork() == 0) + test(); + } + for (i = 0; i < PARALLEL; i++) + wait(&status); + cleanup(-1); + } + return (0); +} diff --git a/test/stress/stress2/misc/fs.sh b/test/stress/stress2/misc/fs.sh new file mode 100755 index 0000000000..1425e611b9 --- /dev/null +++ b/test/stress/stress2/misc/fs.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Caused panic: ffs_truncate3 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +ftest () { # fstype, soft update, disk full + echo "newfs -O $1 `[ $2 -eq 1 ] && echo \"-U\"` md${mdstart}${part}" + newfs -O $1 `[ $2 -eq 1 ] && echo "-U"` md${mdstart}${part} > /dev/null + mount /dev/md${mdstart}${part} ${mntpoint} + + export RUNDIR=${mntpoint}/stressX + disk=$(($3 + 1)) # 1 or 2 + set `df -ik ${mntpoint} | tail -1 | awk '{print $4,$7}'` + export KBLOCKS=$(($1 * disk)) + export INODES=$(($2 * disk)) + + for i in `jot 10`; do + (cd ../testcases/rw;./rw -t 2m -i 20) + done + + while mount | grep -q ${mntpoint}; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") ${mntpoint} > /dev/null 2>&1 + done +} + + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t swap -s 20m -u ${mdstart} +bsdlabel -w md${mdstart} auto + +ftest 1 0 0 # ufs1 +ftest 1 0 1 # ufs1, disk full +ftest 2 0 0 # ufs2 +ftest 2 0 1 # ufs2, disk full +ftest 2 1 0 # ufs2 + soft update +ftest 2 1 1 # ufs2 + soft update, disk full + +mdconfig -d -u ${mdstart} diff --git a/test/stress/stress2/misc/fullpath.sh b/test/stress/stress2/misc/fullpath.sh new file mode 100755 index 0000000000..8c07e94865 --- /dev/null +++ b/test/stress/stress2/misc/fullpath.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by marcus@freebsd.org + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > fullpath.c +cc -o fullpath -Wall fullpath.c +rm -f fullpath.c +cd /proc + +for i in `jot 5`; do + /tmp/fullpath & +done + +for i in `jot 30`; do + for j in `jot 25`; do + pid=`perl -e 'print splice(@ARGV,rand(@ARGV),1), " ";' $(echo [0-9]*)` +# echo $pid + procstat -f $pid > /dev/null 2>&1 + procstat -f $pid > /dev/null 2>&1 + procstat -f $pid > /dev/null 2>&1 + procstat -f $pid > /dev/null 2>&1 + procstat -f $pid > /dev/null 2>&1 + done +done + +for i in `jot 5`; do + wait +done + +rm -f /tmp/fullpath +exit +EOF + +#include +#include +#include +#include +#include +#include +#include + +char buf[4096]; + +void +handler(int i) { + exit(0); +} + +int +test(void) { + pid_t r; + int status; + + for (;;) { + r = fork(); + if (r == 0) { + bzero(buf, sizeof(buf)); + exit(0); /*child dies */ + } + if (r < 0) { + perror("fork"); + exit(2); + } + wait(&status); + } + return 0; +} + +int main(int argc, char **argv) +{ + int i; + + i = 0; + signal(SIGALRM, handler); + alarm(60); + + + return test(); +} diff --git a/test/stress/stress2/misc/fuzz.sh b/test/stress/stress2/misc/fuzz.sh new file mode 100755 index 0000000000..b86281c9af --- /dev/null +++ b/test/stress/stress2/misc/fuzz.sh @@ -0,0 +1,180 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Stress test UFS2 file systems by introducing single bit errors in the FS +# fsck fould fix the FS no matter how damaged, but f.x. this panic has been seen: +# +# panic(c0912b65,dfe96000,0,c09e4060,ef48c778,...) at panic+0x14b +# vm_fault(c1868000,dfe96000,1,0) at vm_fault+0x1e0 +# trap_pfault(ef48c894,0,dfe96000) at trap_pfault+0x137 +# trap(dfe90008,ef480028,c0690028,d0560000,dfe96000,...) at trap+0x341 +# calltrap() at calltrap+0x5 +# --- trap 0xc, eip = 0xc08785a6, esp = 0xef48c8d4, ebp = 0xef48c958 --- +# generic_bcopy(c81cd570,d0508000,c5ead600,c87b81c0,0,...) at generic_bcopy+0x1a +# ffs_mount(d0508000,c5ead600,0,c09b0860,c5ecfc3c,...) at ffs_mount+0xa14 +# vfs_domount(c5ead600,cd8c7280,ccb75080,0,...) at vfs_domount+0x687 +# vfs_donmount(c5ead600,0,ef48cc04) at vfs_donmount+0x2ef +# kernel_mount(c5660960,0,bfbfec86,0,fffffffe,...) at kernel_mount+0x6d +# ffs_cmount(c5660960,bfbfde50,0,c5ead600,c09b0860,...) at ffs_cmount+0x5d +# mount(c5ead600,ef48cd04) at mount+0x156 +# syscall(3b,3b,3b,804abcf,bfbfe8e4,...) at syscall+0x22f + + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage + +tst() { + rm -f $D + truncate -s 2M $D + mdconfig -a -t vnode -f $D -u $mdstart + bsdlabel -w md$mdstart auto + newfs -b 8192 -f 1024 -U /dev/md${mdstart}${part} > /dev/null 2>&1 + mount /dev/md${mdstart}${part} $mntpoint + cp /etc/passwd /etc/group /etc/hosts $mntpoint + cp -r /usr/include/ufs $mntpoint + umount $mntpoint + + for i in `jot 50`; do + ./fuzz -n 50 $D + if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then + if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then + if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then + echo "fsck is giving up in loop $i!" + break + fi + fi + fi + sync;sync;sync + if mount /dev/md${mdstart}${part} $mntpoint; then + ls -l $mntpoint > /dev/null + find $mntpoint -exec dd if={} of=/dev/null bs=1m count=3 \; > /dev/null 2>&1 + umount $mntpoint + else + echo "Giving up at loop $i" + break + fi + done + mdconfig -d -u ${mdstart} + rm -f $D +} + +odir=`pwd` +dir=/tmp + +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/fuzz.c +cc -o fuzz -Wall fuzz.c +rm -f fuzz.c + +for j in `jot 10`; do + date '+%T' + tst +done +rm -f fuzz + +exit + +EOF +#include +#include +#include +#include +#include +#include + +void +usage(void) +{ + fprintf(stderr, "%s {-n \n", getprogname()); + exit(1); +} + +long +random_long(long mi, long ma) +{ + return (arc4random() % (ma - mi + 1) + mi); +} + +int +main(int argc, char **argv) +{ + int ch, fd, i, times = 1, verbose = 0; + long pos; + unsigned char bit, buf, mask, old; + struct stat sb; + + while ((ch = getopt(argc, argv, "n:v")) != -1) + switch(ch) { + case 'n': /* Bits to alter */ + if (sscanf(optarg, "%d", ×) != 1) + usage(); + break; + case 'v': /* verbose flag */ + verbose += 1; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc == 0) + usage(); + + + if ((fd = open(argv[0], O_RDWR)) == -1) + err(1, "open(%s)", argv[0]); + if (fstat(fd, &sb) == -1) + err(1, "stat(%s)", argv[0]); + + for (i = 0; i < times; i++) { + pos = random_long(0, sb.st_size - 1); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "fseek(%d, %ld)", fd, pos); + if (read(fd, &buf, 1) != 1) + err(1, "read(%d)", fd); + bit = random_long(0,7); + mask = ~(1 << bit); + old = buf; + buf = (buf & mask) | (~buf & ~mask); + if (verbose > 0) + printf("Change %2x to %2x at %4ld by flipping bit %d\n", + old, buf, pos, bit); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "fseek(%d, %ld)", fd, pos); + if (write(fd, &buf, 1) != 1) + err(1, "write(%d)", fd); + } + close(fd); + return (0); +} diff --git a/test/stress/stress2/misc/inversion.sh b/test/stress/stress2/misc/inversion.sh new file mode 100755 index 0000000000..5bb7a57041 --- /dev/null +++ b/test/stress/stress2/misc/inversion.sh @@ -0,0 +1,91 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Provokes a deadlock by lower priority process holding a lock and +# never beeing run + +dir=/tmp +N=5 # Number of CPUs + 1 +M=25 # Number of lower priority jobs + +odir=`pwd` +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/inversion.c +cc -o inversion -Wall inversion.c +rm -f inversion.c + +for i in `jot $N`; do + ./inversion 3700& +done + +while pgrep inversion > /dev/null; do + date '+%T' + ( + for i in `jot $M`; do + nice -n 20 lockf -s -t 0 .lock pwd > /dev/null & + done + for i in `jot $M`; do + wait + done + ) +done + +for i in `jot $N`; do + wait +done +rm -f inversion +exit + +EOF +#include +#include +#include + +void +handler(int i) +{ + exit(0); +} + +int +main(int argc, char **argv) +{ + + int t; + if (argc == 2) + t = atoi(argv[1]); + else + t = 60; + signal(SIGALRM, handler); + alarm(t); + for (;;) + ; + return (0); +} diff --git a/test/stress/stress2/misc/isofs.sh b/test/stress/stress2/misc/isofs.sh new file mode 100755 index 0000000000..c51b1c43ee --- /dev/null +++ b/test/stress/stress2/misc/isofs.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 not be root!" && exit 1 + +[ -z "`type mkisofs 2>/dev/null`" ] && echo "mkisofs not found" && exit 1 + +. ../default.cfg + +D=`dirname $diskimage`/dir +I=`dirname $diskimage`/dir.iso +export here=`pwd` +cd /tmp + +cc -o fstool $here/../tools/fstool.c + +rm -rf $D $I +mkdir $D + +(cd $D; /tmp/fstool -n 10 -l -f 512) + +mkisofs -o $I -r $D > /dev/null 2>&1 + +mdconfig -a -t vnode -f $I -u ${mdstart} +mount -t cd9660 /dev/md${mdstart} $mntpoint + +for i in `jot 64`; do + find /$mntpoint -type f > /dev/null 2>&1 & +done +for i in `jot 64`; do + wait +done + +umount ${mntpoint} +mdconfig -d -u ${mdstart} + +rm -rf $D $I fstool diff --git a/test/stress/stress2/misc/jail.sh b/test/stress/stress2/misc/jail.sh new file mode 100755 index 0000000000..8798d7480f --- /dev/null +++ b/test/stress/stress2/misc/jail.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test for problem found with the syscall.sh test + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > jail.c +cc -o jail -Wall jail.c +rm -f jail.c +cd $RUNDIR +/tmp/jail +rm -f /tmp/jail +exit +EOF +#include +#include +#include + +int +main() +{ + struct jail j; + + j.version = 2; + j.path = (char *)0xa000000; + j.hostname = (char *)1; + j.jailname = (char *)0; + j.ip4s = 0; + j.ip6s = 0; + j.ip4 = (struct in_addr *)0x58000000; + j.ip6 = (struct in6_addr *)0x33000001; + + if (jail(&j) == -1) + err(1, "jail()"); + + return (0); +} diff --git a/test/stress/stress2/misc/jail2.sh b/test/stress/stress2/misc/jail2.sh new file mode 100755 index 0000000000..94500b42c0 --- /dev/null +++ b/test/stress/stress2/misc/jail2.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test for problem found with the syscall.sh test + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > jail2.c +cc -o jail2 -Wall jail2.c +rm -f jail2.c +cd $odir +/tmp/jail2 +rm -f /tmp/jail2 +exit +EOF +#include +#include +#include + +int +main() +{ + struct jail j; + + /* + version = 0x2, + path = 0x0, + hostname = 0x0, + jailname = 0x50000000

    , + ip4s = 0xf7000004, + ip6s = 0x1, + ip4 = 0x0, + ip6 = 0x0 + */ + j.version = 2; + j.path = 0; + j.hostname = 0; + j.jailname = (char *)0x50000000; + j.ip4s = 0xf7000004; + j.ip6s = 1; + j.ip4 = 0; + j.ip6 = 0; + + if (jail(&j) == -1) + err(1, "jail()"); + + return (0); +} diff --git a/test/stress/stress2/misc/jail3.sh b/test/stress/stress2/misc/jail3.sh new file mode 100755 index 0000000000..eb7115d2fe --- /dev/null +++ b/test/stress/stress2/misc/jail3.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test for problem found with the syscall.sh test + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > jail3.c +cc -o jail3 -Wall jail3.c +rm -f jail3.c +cd $odir +/tmp/jail3 +rm -f /tmp/jail3 +exit +EOF +#include +#include +#include + +int +main() +{ + struct jail j; + + /* + version = 0x0, + path = 0x2809cd61
    , + hostname = 0x2809b650
    , + jailname = 0x0, + ip4s = 0x1, + ip6s = 0x0, + ip4 = 0x0, + ip6 = 0x0 + */ + j.version = 0; + j.path = (char *)0x2809cd61; + j.hostname = (char *)0x2809b650; + j.jailname = 0; + j.ip4s = 1; + j.ip6s = 0; + j.ip4 = 0; + j.ip6 = 0; + + if (jail(&j) == -1) + err(1, "jail()"); + + return (0); +} diff --git a/test/stress/stress2/misc/jail4.sh b/test/stress/stress2/misc/jail4.sh new file mode 100755 index 0000000000..48c56efb39 --- /dev/null +++ b/test/stress/stress2/misc/jail4.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test for problem found with the syscall.sh test + +# "panic: kern_jail: too many iovecs (28)" seen. + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > jail4.c +cc -o jail4 -Wall jail4.c +rm -f jail4.c +cd $odir +/tmp/jail4 +rm -f /tmp/jail4 +exit +EOF +#include +#include +#include + +int +main() +{ + struct jail j; + + /* + version = 0x2, + path = 0x28190cb1
    , + hostname = 0x28167b90
    , + jailname = 0x28198700
    , + ip4s = 0x0, + ip6s = 0x0, + ip4 = 0x0, + ip6 = 0x0} + */ + j.version = 2; + j.path = (char *)0x28190cb1; + j.hostname = (char *)0x28167b90; + j.jailname = (char *)0x28198700; + j.ip4s = 0; + j.ip6s = 0; + j.ip4 = 0; + j.ip6 = 0; + + if (jail(&j) == -1) + err(1, "jail()"); + + return (0); +} diff --git a/test/stress/stress2/misc/kevent.sh b/test/stress/stress2/misc/kevent.sh new file mode 100755 index 0000000000..deeb0787e6 --- /dev/null +++ b/test/stress/stress2/misc/kevent.sh @@ -0,0 +1,173 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: KN_INFLUX set when not suppose to be + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kevent.c +cc -o kevent -Wall kevent.c -pthread +rm -f kevent.c +cd $RUNDIR + +for i in `jot 10`; do + for j in `jot 12`; do + /tmp/kevent > /dev/null 2>&1 & + done + for j in `jot 12`; do + wait + done +done +exit +EOF +#include +#include +#include +#include +#include +#include +#include +#include + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static int waiting; + +static int fd1[2]; +static int fd2[2]; +static int fd3[2]; + +void * +thr1(void *arg) +{ + int n; + int kq = -1; + struct kevent ev[3]; + + if ((kq = kqueue()) < 0) + err(1, "kqueue(). %s:%d", __FILE__, __LINE__); + + n = 0; + EV_SET(&ev[n], fd1[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + EV_SET(&ev[n], fd2[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + EV_SET(&ev[n], fd3[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + + if (kevent(kq, ev, n, NULL, 0, NULL) < 0) + err(1, "kevent(). %s:%d", __FILE__, __LINE__); + + if (pthread_mutex_lock(&mutex) == -1) + err(1, "pthread_mutex_lock"); + waiting = 0; + if (pthread_cond_signal(&cond) == -1) + err(1, "pthread_cond_signal"); + if (pthread_mutex_unlock(&mutex) == -1) + err(1, "pthread_mutex_unlock"); + + n = 0; + EV_SET(&ev[n], fd1[1], EVFILT_WRITE, + EV_DELETE, 0, 0, 0); + n++; + if (kevent(kq, ev, n, NULL, 0, NULL) < 0) + err(1, "kevent(). %s:%d", __FILE__, __LINE__); + close(kq); + +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + return (0); +} + +void * +thr2(void *arg) +{ + if (pthread_mutex_lock(&mutex) == -1) + err(1, "pthread_mutex_lock"); + while (waiting == 1) { + if (pthread_cond_wait(&cond, &mutex) == -1) + err(1, "pthread_cond_wait"); + } + if (pthread_mutex_unlock(&mutex) == -1) + err(1, "pthread_mutex_unlock"); +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + close(fd3[0]); + close(fd3[1]); + return (0); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[2]; + int r; + int i; + + for (i = 0; i < 1000; i++) { + waiting = 1; +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + if (pipe(fd1) == -1) + err(1, "pipe()"); + if (pipe(fd2) == -1) + err(1, "pipe()"); + if (pipe(fd3) == -1) + err(1, "pipe()"); + + if (pthread_mutex_init(&mutex, 0) == -1) + err(1, "pthread_mutex_init"); + if (pthread_cond_init(&cond, NULL) == -1) + err(1, "pthread_cond_init"); + + if ((r = pthread_create(&threads[0], NULL, thr1, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + if ((r = pthread_create(&threads[1], NULL, thr2, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + if (pthread_join(threads[0], NULL) != 0) + err(1, "pthread_join(%d)", 0); + if (pthread_join(threads[1], NULL) != 0) + err(1, "pthread_join(%d)", 1); + if (pthread_mutex_destroy(&mutex) == -1) + err(1, "pthread_mutex_destroy"); + if (pthread_cond_destroy(&cond) == -1) + err(1, "pthread_condattr_destroy"); + } + + return (0); +} diff --git a/test/stress/stress2/misc/kevent2.sh b/test/stress/stress2/misc/kevent2.sh new file mode 100755 index 0000000000..1d448ca91d --- /dev/null +++ b/test/stress/stress2/misc/kevent2.sh @@ -0,0 +1,175 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kevent.c +cc -o kevent -Wall kevent.c -pthread +rm -f kevent.c +cd $RUNDIR + +for i in `jot 10`; do + for j in `jot 12`; do + /tmp/kevent > /dev/null 2>&1 & + done + for j in `jot 12`; do + wait + done +done +exit +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static int waiting; + +static int fd1[2]; +static int fd2[2]; +static int fd3[2]; + +void * +thr1(void *arg) +{ + int n; + int kq = -1; + struct kevent ev[3]; + struct timespec ts; + + if ((kq = kqueue()) < 0) + err(1, "kqueue(). %s:%d", __FILE__, __LINE__); + + n = 0; + EV_SET(&ev[n], fd1[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + EV_SET(&ev[n], fd2[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + EV_SET(&ev[n], fd3[1], EVFILT_WRITE, + EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); + n++; + + if (kevent(kq, ev, n, NULL, 0, NULL) < 0) + err(1, "kevent(). %s:%d", __FILE__, __LINE__); + + if (pthread_mutex_lock(&mutex) == -1) + err(1, "pthread_mutex_lock"); + waiting = 0; + if (pthread_cond_signal(&cond) == -1) + err(1, "pthread_cond_signal"); + if (pthread_mutex_unlock(&mutex) == -1) + err(1, "pthread_mutex_unlock"); + + n = 0; + EV_SET(&ev[n], fd1[1], EVFILT_WRITE, + EV_DELETE, 0, 0, 0); + n++; + ts.tv_sec = 0; + ts.tv_nsec = 0; + if (kevent(kq, ev, n, NULL, 0, &ts) < 0) + err(1, "kevent(). %s:%d", __FILE__, __LINE__); + close(kq); + +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + close(fd1[1]); + close(fd2[1]); + close(fd3[1]); + return (0); +} + +void * +thr2(void *arg) +{ + if (pthread_mutex_lock(&mutex) == -1) + err(1, "pthread_mutex_lock"); + while (waiting == 1) { + if (pthread_cond_wait(&cond, &mutex) == -1) + err(1, "pthread_cond_wait"); + } + if (pthread_mutex_unlock(&mutex) == -1) + err(1, "pthread_mutex_unlock"); +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + close(fd1[0]); + close(fd2[0]); + close(fd3[0]); + return (0); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[2]; + int r; + int i; + + for (i = 0; i < 1000; i++) { + waiting = 1; +// printf("%s:%d\n", __FILE__, __LINE__); fflush(stdout); + if (pipe(fd1) == -1) + err(1, "pipe()"); + if (pipe(fd2) == -1) + err(1, "pipe()"); + if (pipe(fd3) == -1) + err(1, "pipe()"); + + if (pthread_mutex_init(&mutex, 0) == -1) + err(1, "pthread_mutex_init"); + if (pthread_cond_init(&cond, NULL) == -1) + err(1, "pthread_cond_init"); + + if ((r = pthread_create(&threads[0], NULL, thr1, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + if ((r = pthread_create(&threads[1], NULL, thr2, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + if (pthread_join(threads[0], NULL) != 0) + err(1, "pthread_join(%d)", 0); + if (pthread_join(threads[1], NULL) != 0) + err(1, "pthread_join(%d)", 1); + if (pthread_mutex_destroy(&mutex) == -1) + err(1, "pthread_mutex_destroy"); + if (pthread_cond_destroy(&cond) == -1) + err(1, "pthread_condattr_destroy"); + } + + return (0); +} diff --git a/test/stress/stress2/misc/kevent3.sh b/test/stress/stress2/misc/kevent3.sh new file mode 100755 index 0000000000..4cc7d378a0 --- /dev/null +++ b/test/stress/stress2/misc/kevent3.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kevent.c +cc -o kevent -Wall kevent.c -pthread +rm -f kevent.c +cd $RUNDIR + +for i in `jot 64`; do + for j in `jot 12`; do + /tmp/kevent > /dev/null 2>&1 & + done + for j in `jot 12`; do + wait + done +done +exit +EOF +/* + * Obtained from: + * http://projects.info-pull.com/mokb/MOKB-24-11-2006.html + */ +#include +#include +#include +#include +#include + +int main(void) +{ + struct kevent ke; + int kq; + kq = kqueue(); + EV_SET(&ke, getpid(), EVFILT_PROC, EV_ADD, + NOTE_EXIT|NOTE_EXEC|NOTE_TRACK, 0, NULL); + kevent(kq, &ke, 1, NULL, 0, NULL); + if (fork() != 0) + kevent(kq, NULL, 0, &ke, 1, NULL); + return (0); +} diff --git a/test/stress/stress2/misc/kevent4.sh b/test/stress/stress2/misc/kevent4.sh new file mode 100755 index 0000000000..e782783de3 --- /dev/null +++ b/test/stress/stress2/misc/kevent4.sh @@ -0,0 +1,202 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# +# Test scenario by kib@ + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kevent.c +cc -o kevent -Wall kevent.c -pthread +rm -f kevent.c + +cd $odir/.. +export runRUNTIME=3m +./run.sh & +rpid=$! + +cd $RUNDIR +/tmp/kevent $rpid & + +sleep 120 +kill $rpid +kill $! +rm -f /tmp/kevent + +exit +EOF +// $FreeBSD$ + +#include +#include +#include +#include +#include +#include +#include +#ifndef true +# define true 1 +#endif + +int kq; + +void +err(const char *msg, int err_no) +{ + fprintf(stderr, "%s: %s\n", msg, strerror(err_no)); + exit(1); +} + +void +init_kq() +{ + kq = kqueue(); + if (kq == -1) + err("kqueue", errno); +} + +void +add_watch(pid_t pid) +{ + struct kevent kev; + bzero(&kev, sizeof(kev)); + kev.ident = pid; + kev.flags = EV_ADD | EV_ENABLE; + kev.filter = EVFILT_PROC; + kev.fflags = NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK; + + while (true) { + int res = kevent(kq, &kev, 1, NULL, 0, NULL); + if (res == -1) { + if (errno == EINTR) + continue; + if (errno == ESRCH) + break; + + int err_no = errno; + char msg[64]; + snprintf(msg, sizeof(msg), + "kevent - add watch for pid %u", pid); + err(msg, err_no); + } + else + break; + } +} + +void +del_watch(pid_t pid) +{ + struct kevent kev; + bzero(&kev, sizeof(kev)); + kev.ident = pid; + kev.flags = EV_DELETE; + kev.filter = EVFILT_PROC; + + while (true) { + int res = kevent(kq, &kev, 1, NULL, 0, NULL); + if (res == -1) { + if (errno == EINTR) + continue; + if (errno == ESRCH) + break; + + int err_no = errno; + char msg[64]; + snprintf(msg, sizeof(msg), + "kevent - del watch for pid %u", pid); + err(msg, err_no); + } + else + break; + } +} + +void polling() +{ + struct kevent kev[10]; + pid_t pid; + int i; + + while (true) { + bzero(&kev, sizeof(kev)); + int res = kevent(kq, NULL, 0, kev, + sizeof(kev) / sizeof(kev[0]), NULL); + if (res == -1) { + if (errno == EINTR) + continue; + + if (errno == ESRCH) + continue; + + err("kevent", errno); + } + + for (i = 0; i < res; i++) { + pid = kev[i].ident; + if (kev[i].fflags & NOTE_CHILD) { + add_watch(pid); + printf("%u - new process, parent %u\n", pid, kev[i].data); + } + if (kev[i].fflags & NOTE_FORK) { + printf("%u forked\n", pid); + } + if (kev[i].fflags & NOTE_EXEC) { + printf("%u called exec\n", pid); + } + if (kev[i].fflags & NOTE_EXIT) { + printf("%u exited\n", pid); +// del_watch(pid); + } + if (kev[i].fflags & NOTE_TRACK) { + printf("%u forked - track\n", pid); + } + if (kev[i].fflags & NOTE_TRACKERR) { + fprintf(stderr, "%u - track error\n", pid); + } + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "pid ?\n"); + return (2); + } + pid_t parent = atoi(argv[1]); + + init_kq(); + add_watch(parent); + polling(); + + return (0); +} diff --git a/test/stress/stress2/misc/kevent5.sh b/test/stress/stress2/misc/kevent5.sh new file mode 100755 index 0000000000..d3ff75af13 --- /dev/null +++ b/test/stress/stress2/misc/kevent5.sh @@ -0,0 +1,161 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# +# Test EVFILT_VNODE. Found page fault in knlist_add+0x39 +# +# Test scenario by kib@ + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kevent.c +cc -o kevent -Wall kevent.c +rm -f kevent.c + +cd $RUNDIR/.. +/tmp/kevent xxx yyy + +rm -f /tmp/kevent + +exit +EOF +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static char *file1, *file2; + +#define N 1000 + + +void +test(test) { + int kq = -1; + int n; + struct kevent ev[2]; + int fd; + + if ((fd = open(file1, O_RDONLY, 0)) == -1) + err(1, "open(%s)(2)", file1); + + if ((kq = kqueue()) < 0) + err(1, "kqueue()"); + + n = 0; + EV_SET(&ev[n], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE, 0, 0); + n++; + + if (kevent(kq, ev, n, NULL, 0, NULL) < 0) + err(1, "kevent()"); + + memset(&ev, 0, sizeof(ev)); + n = kevent(kq, NULL, 0, ev, 1, NULL); +// printf("Event 1\n"); + close(fd); + close(kq); + +/* Once the rendezvous file is gone create a new kevent */ + + if ((fd = open(file2, O_RDONLY, 0)) == -1) + err(1, "open(%s)(2)", file2); + + if ((kq = kqueue()) < 0) + err(1, "kqueue()"); + + n = 0; + EV_SET(&ev[n], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE, 0, 0); + n++; + + if (kevent(kq, ev, n, NULL, 0, NULL) < 0) + err(1, "kevent()"); + + memset(&ev, 0, sizeof(ev)); + n = kevent(kq, NULL, 0, ev, 1, NULL); +// printf("Event 2\n"); + close(fd); + close(kq); +} + +int +main(int argc, char **argv) { + int i, j; + int fd; + int status; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return (1); + } + file1 = argv[1]; + file2 = argv[2]; + + for (j = 0; j < 100; j++) { + if ((fd = open(file1, O_CREAT | O_TRUNC | O_RDWR, 0660)) == -1) + err(1, "open(%s)", file1); + close(fd); + if ((fd = open(file2, O_CREAT | O_TRUNC | O_RDWR, 0660)) == -1) + err(1, "open(%s)", file2); + close(fd); + + for (i = 0; i < N; i++) { + if (fork() == 0) { + test(); + return (0); + } + } + + sleep(1); + if (unlink(file1) == -1) + err(1, "unlink(%s). %s:%d\n", file1, __FILE__, __LINE__); + sleep(1); + if (unlink(file2) == -1) + err(1, "unlink(%s). %s:%d\n", file2, __FILE__, __LINE__); + + for (i = 0; i < N; i++) { + if (wait(&status) == -1) + err(1, "wait(), %s:%d", __FILE__, __LINE__); + } + } + + return (0); +} diff --git a/test/stress/stress2/misc/kinfo.sh b/test/stress/stress2/misc/kinfo.sh new file mode 100755 index 0000000000..2f33255635 --- /dev/null +++ b/test/stress/stress2/misc/kinfo.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by marcus@freebsd.org + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kinfo.c +cc -o kinfo -Wall kinfo.c -lutil +rm -f kinfo.c + +mount | grep -q procfs || mount -t procfs procfs /procfs +for i in `jot 30`; do + for j in `jot 5`; do + /tmp/kinfo & + done + + for j in `jot 5`; do + wait + done +done + +rm -f /tmp/kinfo +exit +EOF + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char buf[8096]; + +void +handler(int i) { + exit(0); +} + +/* Stir /dev/proc */ +int +churning(void) { + pid_t r; + int fd, status; + + for (;;) { + r = fork(); + if (r == 0) { + if ((fd = open("/proc/curproc/mem", O_RDONLY)) == -1) + err(1, "open(/proc/curproc/mem)"); + bzero(buf, sizeof(buf)); + exit(0); + } + if (r < 0) { + perror("fork"); + exit(2); + } + wait(&status); + } +} + +/* Get files for each proc */ +void +list(void) +{ + struct kinfo_file *freep; + struct kinfo_vmentry *freep_vm; + long i; + int cnt, name[4]; + struct kinfo_proc *kipp; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_PROC; + + len = 0; + if (sysctl(name, 3, NULL, &len, NULL, 0) < 0) + err(-1, "sysctl: kern.proc.all"); + + kipp = malloc(len); + if (kipp == NULL) + err(1, "malloc"); + + if (sysctl(name, 3, kipp, &len, NULL, 0) < 0) { + free(kipp); +// warn("sysctl: kern.proc.all"); + return; + } + + for (i = 0; i < len / sizeof(*kipp); i++) { + + /* The test starts here */ + freep = kinfo_getfile(kipp[i].ki_pid, &cnt); + free(freep); + + freep_vm = kinfo_getvmmap(kipp[i].ki_pid, &cnt); + free(freep_vm); + /* End test */ + } + free(kipp); +} + +int +main(int argc, char **argv) +{ + pid_t r; + signal(SIGALRM, handler); + alarm(60); + + if ((r = fork()) == 0) { + alarm(60); + for (;;) + churning(); + } + if (r < 0) { + perror("fork"); + exit(2); + } + + for (;;) + list(); + + return (0); +} diff --git a/test/stress/stress2/misc/kinfo2.sh b/test/stress/stress2/misc/kinfo2.sh new file mode 100755 index 0000000000..941b41364b --- /dev/null +++ b/test/stress/stress2/misc/kinfo2.sh @@ -0,0 +1,176 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by marcus@freebsd.org + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kinfo.c +cc -o kinfo -Wall kinfo.c -lutil +rm -f kinfo.c + +mount | grep -q procfs || mount -t procfs procfs /procfs +for i in `jot 30`; do + for j in `jot 5`; do + /tmp/kinfo & + done + + for j in `jot 5`; do + wait + done +done + +rm -f /tmp/kinfo +exit +EOF + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char buf[8096]; + +void +handler(int i) { + exit(0); +} + +/* Stir /dev/proc */ +int +churning(void) { + pid_t r; + int fd, status; + + for (;;) { + r = fork(); + if (r == 0) { + if ((fd = open("/proc/curproc/mem", O_RDONLY)) == -1) + err(1, "open(/proc/curproc/mem)"); + bzero(buf, sizeof(buf)); + exit(0); + } + if (r < 0) { + perror("fork"); + exit(2); + } + wait(&status); + } +} + +/* Get files for each proc */ +void +list(void) +{ + int cnt, fd, n; + int space = sizeof(buf); + long base; + struct dirent *dp; + struct kinfo_file *freep; + struct kinfo_vmentry *freep_vm; + char *bp = buf; + pid_t pid; + long l; + char *dummy; + + if ((fd = open("/proc", O_RDONLY)) == -1) + err(1, "open(%s)", "/proc"); + + do { + if ((n = getdirentries(fd, bp, space, &base)) == -1) + err(1, "getdirentries"); + space = space - n; + bp = bp + n; + } while (n != 0); + close(fd); + + bp = buf; + dp = (struct dirent *)bp; + for (;;) { +#if 0 + printf("name: %-10s, inode %7d, type %2d, namelen %d, d_reclen %d\n", + dp->d_name, dp->d_fileno, dp->d_type, dp->d_namlen, + dp->d_reclen); fflush(stdout); +#endif + + if (dp->d_type == DT_DIR && + (dp->d_name[0] >= '0' && dp->d_name[0] <= '9')) { + l = strtol(dp->d_name, &dummy, 10); + pid = l; + + /* The tests start here */ + freep = kinfo_getfile(pid, &cnt); + free(freep); + + freep_vm = kinfo_getvmmap(pid, &cnt); + free(freep_vm); + /* End test */ + } + + bp = bp + dp->d_reclen; + dp = (struct dirent *)bp; + if (dp->d_reclen <= 0) + break; + } +} + +int +main(int argc, char **argv) +{ + pid_t r; + signal(SIGALRM, handler); + alarm(60); + + if ((r = fork()) == 0) { + alarm(60); + for (;;) + churning(); + } + if (r < 0) { + perror("fork"); + exit(2); + } + + for (;;) + list(); + + return (0); +} diff --git a/test/stress/stress2/misc/kinfo3.sh b/test/stress/stress2/misc/kinfo3.sh new file mode 100755 index 0000000000..a8d4d3c571 --- /dev/null +++ b/test/stress/stress2/misc/kinfo3.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by marcus@freebsd.org and kib@freebsd.org + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > kinfo.c +cc -o kinfo -Wall kinfo.c -lutil -pthread +rm -f kinfo.c + +mount | grep -q procfs || mount -t procfs procfs /procfs +for i in `jot 30`; do + for j in `jot 5`; do + /tmp/kinfo & + done + + for j in `jot 5`; do + wait + done +done + +rm -f /tmp/kinfo +exit +EOF + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char buf[8096]; + +void +handler(int i) { + exit(0); +} + +void * +thr(void *arg) +{ + int fd; + if ((fd = open("/proc/curproc/mem", O_RDONLY)) == -1) + err(1, "open(/proc/curproc/mem)"); + close(fd); + return (0); +} + + +/* Stir /dev/proc */ +int +churning(void) { + int i; + pid_t r; + int status; + pthread_t threads[5]; + + + for (;;) { + r = fork(); + if (r == 0) { + for (i = 0; i < 5; i++) { + if ((r = pthread_create(&threads[i], NULL, thr, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + } + for (i = 0; i < 5; i++) { + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", 0); + } + + bzero(buf, sizeof(buf)); + exit(0); + } + if (r < 0) { + perror("fork"); + exit(2); + } + wait(&status); + } +} + +/* Get files for each proc */ +void +list(void) +{ + struct kinfo_file *freep, *kif; + struct kinfo_vmentry *freep_vm; + long i, j; + int cnt, name[4]; + struct kinfo_proc *kipp; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_PROC; + + len = 0; + if (sysctl(name, 3, NULL, &len, NULL, 0) < 0) + err(-1, "sysctl: kern.proc.all"); + + kipp = malloc(len); + if (kipp == NULL) + err(1, "malloc"); + + if (sysctl(name, 3, kipp, &len, NULL, 0) < 0) { + free(kipp); +// warn("sysctl: kern.proc.all"); + return; + } + + for (i = 0; i < len / sizeof(*kipp); i++) { + + /* The test starts here */ + freep = kinfo_getfile(kipp[i].ki_pid, &cnt); + for (j = 0; j < cnt && freep; j++) { + kif = &freep[j]; +// printf("%d : %s\n", kif->kf_fd, kif->kf_path); + } + free(freep); + + freep_vm = kinfo_getvmmap(kipp[i].ki_pid, &cnt); + free(freep_vm); + /* End test */ + } + free(kipp); +} + +int +main(int argc, char **argv) +{ + pid_t r; + signal(SIGALRM, handler); + alarm(30); + + if ((r = fork()) == 0) { + alarm(30); + for (;;) + churning(); + } + if (r < 0) { + perror("fork"); + exit(2); + } + + for (;;) + list(); + + return (0); +} diff --git a/test/stress/stress2/misc/ldt.sh b/test/stress/stress2/misc/ldt.sh new file mode 100755 index 0000000000..e6910e2be8 --- /dev/null +++ b/test/stress/stress2/misc/ldt.sh @@ -0,0 +1,369 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test the amd64 implementation of: +# 1. Per-process private ldt and corresponding i386 arch syscalls. +# 2. Per-process private io permission bitmap and corresponding +# i386 arch syscalls. +# 3. Sigcontext + +# The tests must be compiled on i386 and run on amd64 + +# All tests by kib@ + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cd /tmp +if [ "`uname -p`" = "i386" ]; then + cat > ldt.c < +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char stack[64 * 1024]; + +char a[1]; + +int +s2ds(int sel) +{ + + return (LSEL(sel, SEL_UPL)); +} + +unsigned char +readbyte(int sel, int offset) +{ + unsigned char res; + + __asm__ volatile( + "\tpushl %%es\n" + "\tmovl %1,%%es\n" + "\tmovb %%es:(%2),%0\n" + "\tpopl %%es\n" + : "=r"(res) : "r"(s2ds(sel)), "r"(offset)); + + return (res); +} + +void +writebyte(int sel, int offset, unsigned char val) +{ + + __asm__ volatile( + "\tpushl %%es\n" + "\tmovl %0,%%es\n" + "\tmovb %2,%%es:(%1)\n" + "\tpopl %%es\n" + : : "r"(s2ds(sel)), "r"(offset), "r"(val) : "memory"); +} + +int +alloc_sel(char *base, size_t len, int type, int p) +{ + int sel; + union descriptor descs[1], descsk[1]; + uintptr_t pb; + + memset(descs, 0, sizeof(descs)); + if (len > PAGE_SIZE) { + len = roundup(len, PAGE_SIZE); + len /= PAGE_SIZE; + descs[0].sd.sd_lolimit = len & 0xffff; + descs[0].sd.sd_hilimit = (len >> 16) & 0xf; + descs[0].sd.sd_gran = 1; + } else { + descs[0].sd.sd_lolimit = len; + descs[0].sd.sd_hilimit = 0; + descs[0].sd.sd_gran = 0; + } + pb = (uintptr_t)base; + descs[0].sd.sd_lobase = pb & 0xffffff; + descs[0].sd.sd_hibase = (pb >> 24) & 0xff; + descs[0].sd.sd_type = type; + descs[0].sd.sd_dpl = SEL_UPL; + descs[0].sd.sd_p = p; + descs[0].sd.sd_def32 = 1; + + if ((sel = i386_set_ldt(LDT_AUTO_ALLOC, descs, 1)) == -1) + fprintf(stderr, "i386_set_ldt: %s\n", strerror(errno)); + else if (i386_get_ldt(sel, descsk, 1) == -1) { + fprintf(stderr, "i386_get_ldt: %s\n", strerror(errno)); + sel = -1; + } else if (memcmp(descs, descsk, sizeof(descs)) != 0) { + fprintf(stderr, "descs != descsk\n"); + sel = -1; + } else + fprintf(stderr, "selector %d\n", sel); + + return (sel); +} + +int +test1(int tnum, int sel) +{ + unsigned char ar; + + writebyte(sel, 0, '1'); + ar = readbyte(sel, 0); + if (ar == '1') + fprintf(stderr, "test %d.1 ok\n", tnum); + else + fprintf(stderr, "test%d.1 failed, ar %x\n", tnum, ar); + writebyte(sel, 0, '2'); + ar = readbyte(sel, 0); + if (ar == '2') + fprintf(stderr, "test %d.2 ok\n", tnum); + else + fprintf(stderr, "test%d.2 failed, ar %x\n", tnum, ar); + return (sel); +} + +int +test2_func(void *arg) +{ + int *sel; + + sel = arg; + test1(2, *sel); + rfork(0); + test1(3, *sel); + return (0); +} + +void +test2(int sel) +{ + pid_t r; + int status; + + r = rfork_thread(RFPROC | RFMEM, stack + sizeof(stack), + test2_func, &sel); + if (r == -1) { + fprintf(stderr, "rfork(RFPROC): %s\n", strerror(errno)); + return; + } else { + waitpid(r, &status, 0); + if (WIFSIGNALED(status)) { + fprintf(stderr, "test2: child terminated by %s\n", + strsignal(WTERMSIG(status))); + } + } +} + +int +main(int argc, char *argv[]) +{ + int sel; + + sel = alloc_sel(a, 1, SDT_MEMRWA, 1); + if (sel == -1) + return (1); + + test1(1, sel); + test2(sel); + return (0); +} +EOF + cc -o ldt_static_i386 -Wall -static ldt.c + rm ldt.c + + cat > ioperm.c < +#include +#include +#include +#include +#include + +static const unsigned int port_num = 0x130; + +unsigned char +inb(unsigned int port) +{ + unsigned char data; + + __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); + return (data); +} + +void +sigbus_handler(int signo) +{ + + fprintf(stderr, "Got SIGBUS\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + struct sigaction sa; + unsigned int length1; + int enable1; + + if (i386_get_ioperm(port_num, &length1, &enable1) == -1) { + fprintf(stderr, "get 1: %s\n", strerror(errno)); + return (1); + } + if (length1 != 0 && enable1 != 0) { + fprintf(stderr, "enable1: enabled\n"); + return (1); + } + if (i386_set_ioperm(port_num, 1, 1) == -1) { + fprintf(stderr, "set 1: %s\n", strerror(errno)); + return (1); + } + inb(port_num); + if (i386_set_ioperm(port_num, 1, 0) == -1) { + fprintf(stderr, "set 2: %s\n", strerror(errno)); + return (1); + } + if (i386_get_ioperm(port_num, &length1, &enable1) == -1) { + fprintf(stderr, "get 1: %s\n", strerror(errno)); + return (1); + } + if (enable1 != 0) { + fprintf(stderr, "enable2: enabled\n"); + return (1); + } + fprintf(stderr, "And now we should get SIGBUS\n"); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sigbus_handler; + if (sigaction(SIGBUS, &sa, NULL) == -1) { + fprintf(stderr, "sigaction(SIGBUS): %s\n", strerror(errno)); + return (1); + } + inb(port_num); + + return (0); +} +EOF + cc -o ioperm_static_i386 -Wall -static ioperm.c + rm ioperm.c + + cat > fault.c < +#include +#include +#include +#include +#include +#include +#include + +extern char *fault_instr; +int run; + +void +sigsegv_sigaction(int signo, siginfo_t *si, void *c) +{ + ucontext_t *uc; + mcontext_t *mc; + + uc = c; + mc = &uc->uc_mcontext; + printf("SIGSEGV run %d err %x ds %x ss %x es %x fs %x gs %x\n", + run, mc->mc_err, mc->mc_ds, mc->mc_ss, mc->mc_es, mc->mc_fs, + mc->mc_gs); + switch (run) { + case 0: + mc->mc_ds = 0x1111; + break; + case 1: + mc->mc_es = 0x1111; + break; + case 2: + mc->mc_fs = 0x1111; + break; + case 3: + mc->mc_gs = 0x1111; + break; + case 4: + mc->mc_ss = 0x1111; + break; + case 5: + _exit(11); + } + run++; +} + +void +fault(void) +{ + + __asm__ volatile(".globl\tfault_instr;fault_instr:\ttestl\t\$0,0\n"); +} + +int +main(int argc, char *argv[]) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = sigsegv_sigaction; + sa.sa_flags = SA_SIGINFO; + if (sigaction(SIGSEGV, &sa, NULL) == -1) { + fprintf(stderr, "sigaction: %s\n", strerror(errno)); + return (1); + } + if (sigaction(SIGBUS, &sa, NULL) == -1) { + fprintf(stderr, "sigaction: %s\n", strerror(errno)); + return (1); + } + + fault(); + + return (0); +} +EOF + cc -o fault_static_i386 -Wall -static fault.c + rm fault.c +fi + +if [ "`uname -p`" = "amd64" ]; then + [ -x ldt_static_i386 ] && ./ldt_static_i386 + [ -x ioperm_static_i386 ] && ./ioperm_static_i386 + [ -x fault_static_i386 ] && ./fault_static_i386 +fi diff --git a/test/stress/stress2/misc/ldt2.sh b/test/stress/stress2/misc/ldt2.sh new file mode 100755 index 0000000000..dfe3506821 --- /dev/null +++ b/test/stress/stress2/misc/ldt2.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# + +# Test the implementation of i386_get_ldt() and i386_set_ldt() for 32 bit +# processes on amd64 by running wine and mplayer with a 32 bit codec. + +# This is not a test script, but more of a howto document. + +[ `uname -p` != "amd64" ] && echo "Must run on amd64" && exit + +exit 0 + +This are notes of how to perform the test. + + +First of all you will need a i386 jail on amd64. This could be build like +this: + +cat > jailbuild.sh < mplayer.sh <:0 +while true;do + pos=100 + for i in `jot 5`; do + mplayer -vc rv40win -geometry $pos:$pos /root/samples/Real_Media.rm < \ + /dev/null > /dev/null 2>&1 & + pos=$((pos + 50)) + done + for i in `jot 5`; do + wait + done +done +EOF diff --git a/test/stress/stress2/misc/libMicro.sh b/test/stress/stress2/misc/libMicro.sh new file mode 100755 index 0000000000..17961a86e0 --- /dev/null +++ b/test/stress/stress2/misc/libMicro.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test using OpenSolaris libmicro-0.4.0.tar.gz benchmark +# Has shown page fault with the cascade_lockf test + +. ../default.cfg + +odir=`pwd` + +cd $RUNDIR +ftp http://www.opensolaris.org/os/project/libmicro/files/libmicro-0.4.0.tar.gz +[ ! -r libmicro-0.4.0.tar.gz ] && exit 1 +tar zxfv libmicro-0.4.0.tar.gz +cat > $RUNDIR/libMicro-0.4.0/Makefile.FreeBSD <<2EOF +CC= gcc + +CFLAGS= -pthread +CPPFLAGS= -DUSE_SEMOP -D_REENTRANT +MATHLIB= -lm + +ELIDED_BENCHMARKS= \ + cachetocache \ + atomic + + +include ../Makefile.com +2EOF + +cd libMicro-0.4.0 +gmake +ed bench <<3EOF +/ARCH +s/arch -k/uname -m/ +w +q +3EOF +./bench > output & +for i in `jot $((30 * 60))`; do + ps | grep -q bench || break + sleep 1 +done +ps | grep bin/connection | grep -v grep | awk '{print $1}' | xargs kill # hack +cd ..;rm -rf libMicro-0.4.0 diff --git a/test/stress/stress2/misc/lockf.sh b/test/stress/stress2/misc/lockf.sh new file mode 100755 index 0000000000..2acc762c93 --- /dev/null +++ b/test/stress/stress2/misc/lockf.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Page fault in nfs_advlock + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +trap "rm -f /tmp/$0.$$.*" 0 +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint + +for i in `jot 100`; do + mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint + + for j in `jot 50`; do +# sh -c "lockf -t 10 $mntpoint/$0.$$.$j sleep 3" & + lockf -t 10 $mntpoint/$0.$$.$j sleep 3 & + done + + while mount | grep -q ${mntpoint}; do + umount -f $mntpoint > /dev/null 2>&1 + done + for j in `jot 50`; do + wait + done +done diff --git a/test/stress/stress2/misc/lookup_shared.sh b/test/stress/stress2/misc/lookup_shared.sh new file mode 100755 index 0000000000..f18aea05f0 --- /dev/null +++ b/test/stress/stress2/misc/lookup_shared.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +saved=`sysctl vfs.lookup_shared | awk '{print $NF}'` + +export runRUNTIME=10m # Run tests for 10 minutes +for i in 1 0; do + sysctl vfs.lookup_shared=$i + (cd /home/pho/stress2; ./run.sh disk.cfg) +done + +sysctl vfs.lookup_shared=$saved diff --git a/test/stress/stress2/misc/mac.sh b/test/stress/stress2/misc/mac.sh new file mode 100755 index 0000000000..b85d476f63 --- /dev/null +++ b/test/stress/stress2/misc/mac.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +if sysctl security.mac.test 2>&1 | grep -q unknown; then + echo "Kernel must be configured with MAC and MAC_TEST!" + exit 1 +fi + +./crossmp.sh + +sysctl security.mac.test diff --git a/test/stress/stress2/misc/mac_chkexec.sh b/test/stress/stress2/misc/mac_chkexec.sh new file mode 100755 index 0000000000..b29315e4ad --- /dev/null +++ b/test/stress/stress2/misc/mac_chkexec.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Regression test for panic in second ls + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +sysctl -a | ! grep -q security.mac.chkexec && echo "chkexec.ko must be loaded" && exit 1 + +mount | grep "${mntpoint}" | grep -q md${mdstart}${part} && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 12m -u $mdstart +bsdlabel -w md$mdstart auto + +newfs md${mdstart}${part} > /dev/null +tunefs -l enable /dev/md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint + +cp /bin/ls $mntpoint +setfmac chkexec/md5:`md5 -q $mntpoint/ls` $mntpoint/ls +sysctl security.mac.chkexec.enforce=1 +$mntpoint/ls $mntpoint/ls +setfmac chkexec/none $mntpoint/ls +$mntpoint/ls $mntpoint/ls +sysctl security.mac.chkexec.enforce=0 + +umount $mntpoint +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/md.sh b/test/stress/stress2/misc/md.sh new file mode 100755 index 0000000000..26420fa3b8 --- /dev/null +++ b/test/stress/stress2/misc/md.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Caused panic: ffs_truncate3 +# The problem is caused by a full FS with Soft-updates disabled. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t swap -s 2m -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} ${mntpoint} + +export RUNDIR=${mntpoint}/stressX +export KBLOCKS=30000 # Exaggerate disk capacity +export INODES=8000 + +for i in `jot 500`; do + (cd ../testcases/rw;./rw -t 2m -i 20) +done + +while mount | grep -q ${mntpoint}; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") ${mntpoint} > /dev/null 2>&1 +done + +mdconfig -d -u ${mdstart} diff --git a/test/stress/stress2/misc/md2.sh b/test/stress/stress2/misc/md2.sh new file mode 100755 index 0000000000..dff6246c5c --- /dev/null +++ b/test/stress/stress2/misc/md2.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: ufs_dirbad: /mnt: bad dir ino 32899 at offset 16896: mangled entry + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "$mntpoint" | grep md${mdstart} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t malloc -s 256m -u ${mdstart} + +for i in 1 2; do + newfs -O$i -i1024 /dev/md${mdstart} > /dev/null 2>&1 + mount /dev/md${mdstart} ${mntpoint} + df -i $mntpoint + + export RUNDIR=$mntpoint/stressX + export runRUNTIME=10m + cd /home/pho/stress2; ./run.sh + + umount ${mntpoint} +done +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/md3.sh b/test/stress/stress2/misc/md3.sh new file mode 100755 index 0000000000..7deaab59d0 --- /dev/null +++ b/test/stress/stress2/misc/md3.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# +# $Id: nfs.sh,v 1.2 2008/02/25 16:31:43 pho Exp $ +# + +# Test scenario for deadlock fixed in r200447 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep -q "$mntpoint" && umount $mntpoint +mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1400m -u $mdstart +bsdlabel -w md${mdstart} auto + +newfs -U md5${part} > /dev/null +mount /dev/md5${part} /mnt + +# Stop FS "out of inodes" problem by only using 70% +set `df -ik /mnt | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 10 * 7)) +export INODES=$(($2 / 10 * 7)) + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=10m + +(cd /home/pho/stress2; ./run.sh marcus.cfg) + +umount $mntpoint +mount | grep -q "$mntpoint" && umount -f $mntpoint +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/mlockall.sh b/test/stress/stress2/misc/mlockall.sh new file mode 100755 index 0000000000..fed9ec1919 --- /dev/null +++ b/test/stress/stress2/misc/mlockall.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# "panic: swap_reserved < decr" seen. Fixed in r195329 + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > mlockall.c +cc -o mlockall -Wall mlockall.c +rm -f mlockall.c + +for i in `jot 10`; do + /tmp/mlockall & + sleep 1 + ps | grep /tmp/mlockall | grep -v grep | awk '{print $1}' | while read pid; do + kill -2 $pid + kill -9 $pid + done +done + +rm -f /tmp/mlockall +exit +EOF +#include +#include +#include +#include +#include +#include + +void +child(void) +{ + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) + err(1, "mlockall(MCL_CURRENT | MCL_FUTURE)"); + fork(); + sleep(60); +} + +int +main(int argc, char **argv) +{ + int status; + + if (fork() == 0) + child(); + wait(&status); + + return (0); +} diff --git a/test/stress/stress2/misc/mmap.sh b/test/stress/stress2/misc/mmap.sh new file mode 100755 index 0000000000..bccdf117ba --- /dev/null +++ b/test/stress/stress2/misc/mmap.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# +# $FreeBSD$ +# + +# Test scenario by Michiel Boland + +# panic: pmap_remove_all: page 0xc491f000 is fictitious + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > mmap.c +cc -o mmap -Wall mmap.c +rm -f mmap.c + +./mmap +rm -f ./mmap +exit + +EOF +#include +#include +#include +#include +#include + +static const off_t map_address = 0xa0000; +static const size_t map_size = 0x1000; + +static int testit(int fd) +{ + void *p; + int rv; + + p = mmap(NULL, 2 * map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + map_address); + if (p == MAP_FAILED) { + perror("mmap"); + return -1; + } + rv = *(char *) p; + if (munmap(p, map_size) == -1) { + perror("munmap"); + return -1; + } + return rv; +} + +int main(void) +{ + int fd, rv; + + fd = open("/dev/mem", O_RDWR); + if (fd == -1) { + perror("open"); + return 1; + } + rv = testit(fd); + close(fd); + return rv; +} diff --git a/test/stress/stress2/misc/mmap2.sh b/test/stress/stress2/misc/mmap2.sh new file mode 100755 index 0000000000..7ece8ab053 --- /dev/null +++ b/test/stress/stress2/misc/mmap2.sh @@ -0,0 +1,176 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Stress mmap by having at most 100 threads mapping random areas within +# a 100 Mb range. + +# Test scenario by kib@ + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > mmap2.c +cc -o mmap2 -Wall mmap2.c -lpthread +rm -f mmap2.c + +for i in `jot 10`; do + ./mmap2 +done +rm -f ./mmap2 +exit + +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define THREADS 100 +#define STARTADDR 0x50000000U +#define ADRSPACE 0x06400000U /* 100 Mb */ + +static void +work(int nr) +{ + int fd, m; + void *p; + size_t left, len; + char path[128]; + + p = (void *)STARTADDR + trunc_page(arc4random() % ADRSPACE); + left = ADRSPACE - (size_t)p + STARTADDR; + len = trunc_page(arc4random() % left) + PAGE_SIZE; + fd = -1; + + if (arc4random() % 100 < 90) + sprintf(path, "/tmp/mmap.%06d.%04d", getpid(), nr); + else + sprintf(path, "/dev/zero"); + if (arc4random() % 2 == 0) { + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) + err(1,"open()"); + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + if (arc4random() % 2 == 0) { + if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + if (errno == ENOMEM) + return; + err(1, "mmap()"); + } + } else { + if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == + MAP_FAILED) { + if (errno == ENOMEM) + return; + err(1, "mmap()"); + } + } + if (fd > 0 && strcmp(path, "/dev/zero")) + if (unlink(path) == -1) + err(1, "unlink(%s)", path); + } else { + if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)) == MAP_FAILED) { + if (errno == ENOMEM) + return; + err(1, "mmap()"); + } + strcpy(path, "anon"); + } +#if 0 + printf("nr = %d, %-14s, start = %p, end = %p, len = 0x%08x, (%5d pages)\n", + nr, path, p, p + len, len, len>>PAGE_SHIFT); +#endif + + *(int *)p = 1; + + if (arc4random() % 2 == 0) { + m = arc4random() % 10; + if (madvise(p, len, m) == -1) + warn("madvise(%p, %d, %d)", p, len, m); + } + if (arc4random() %2 == 0) + if (mprotect(p, trunc_page(arc4random() % len), PROT_READ) == -1 ) + err(1, "mprotect failed with error:"); + if (arc4random() % 2 == 0) { + if (arc4random() %2 == 0) { + if (msync(p, 0, MS_SYNC) == -1) + err(1, "msync(%p)", p); + } else { + if (msync(p, 0, MS_INVALIDATE) == -1) + err(1, "msync(%p)", p); + } + } + if (munmap(p, len) == -1) + err(1, "munmap(%p)", p); + close(fd); +} + +void * +thr(void *arg) +{ + int i; + + for (i = 0; i < 512; i++) { + work(*(int *)arg); + } + return (0); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[THREADS]; + int nr[THREADS]; + int i, n, r; + +// printf("Address start 0x%x, address end 0x%x, pages %d\n", +// STARTADDR, STARTADDR + ADRSPACE, ADRSPACE>>PAGE_SHIFT); + n = arc4random() % THREADS + 1; + for (i = 0; i < n; i++) { + nr[i] = i; + if ((r = pthread_create(&threads[i], NULL, thr, (void *)&nr[i])) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + } + + for (i = 0; i < n; i++) { + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + } + + return (0); +} diff --git a/test/stress/stress2/misc/mmap3.sh b/test/stress/stress2/misc/mmap3.sh new file mode 100755 index 0000000000..cb7c7c35fc --- /dev/null +++ b/test/stress/stress2/misc/mmap3.sh @@ -0,0 +1,159 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Variation of mmap2.sh with focus on random arguments for mprotect() + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > mmap3.c +cc -o mmap3 -Wall mmap3.c -lpthread +rm -f mmap3.c + +for i in `jot 20`; do + ./mmap3 +done +for i in `jot 100`; do + ./mmap3 random +done +rm -f mmap3 mmap3.core /tmp/mmap.0* +exit + +EOF +/* + Stress mmap by having max 18 threads mapping random areas within + a 100 Mb range. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define THREADS 100 +#define STARTADDR 0x50000000U +#define ADRSPACE 0x06400000U /* 100 Mb */ + +static int +ra; + +void +trash(void *p) +{ + mprotect(p, 0x570e3d38, 0x2c8fd54f); + + if (ra) { + madvise((void *)arc4random(), arc4random(), arc4random()); + mprotect((void *)arc4random(), arc4random(), arc4random()); + msync((void *)arc4random(), arc4random(), arc4random()); + } + +} + +void +work(int nr) +{ + int fd, m; + void *p; + size_t len; + char path[128]; + + p = (void *)STARTADDR; + len = ADRSPACE; + + sprintf(path, "/tmp/mmap.%06d.%04d", getpid(), nr); + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) + err(1,"open()"); + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + if (errno == ENOMEM) + return; + err(1, "mmap()"); + } + if (unlink(path) == -1) + err(1, "unlink(%s)", path); + + trash(p); + + m = arc4random() % 10; + if (madvise(p, len, m) == -1) + warn("madvise(%p, %d, %d)", p, len, m); + if (mprotect(p, trunc_page(arc4random() % len), PROT_READ) == -1 ) + err(1, "mprotect failed with error:"); + if (msync(p, 0, MS_SYNC) == -1) + err(1, "msync(%p)", p); + if (munmap(p, len) == -1) + err(1, "munmap(%p)", p); + close(fd); +} + +void * +thr(void *arg) +{ + int i; + + for (i = 0; i < 512; i++) { + work(*(int *)arg); + } + return (0); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[THREADS]; + int nr[THREADS]; + int i, n, r; + + n = arc4random() % 14 + 5; + ra = argc != 1; +// printf("Address start 0x%x, address end 0x%x, pages %d, n %d\n", +// STARTADDR, STARTADDR + ADRSPACE, ADRSPACE>>PAGE_SHIFT, n); + for (i = 0; i < n; i++) { + nr[i] = i; + if ((r = pthread_create(&threads[i], NULL, thr, (void *)&nr[i])) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + } + + for (i = 0; i < n; i++) { + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + } + + return (0); +} diff --git a/test/stress/stress2/misc/mmap4.sh b/test/stress/stress2/misc/mmap4.sh new file mode 100755 index 0000000000..fc35d23b8d --- /dev/null +++ b/test/stress/stress2/misc/mmap4.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# Test overcommit of the file system capacity +# Causes panic: 1 vncache entries remaining + +# Scanario by kib@ + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > mmap4.c +cc -o mmap4 -Wall -O2 mmap4.c +rm -f mmap4.c + +mount | grep -q "$mntpoint" && umount $mntpoint +mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 40m -u $mdstart +bsdlabel -w md${mdstart} auto + +newfs -U md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} $mntpoint + +/tmp/mmap4 /$mntpoint/file +ls -lh $mntpoint +df -h + +cd $here +rm -f /tmp/mmap4 + +while mount | grep -q $mntpoint; do + sync;sync;sync + sleep 1 + umount $mntpoint +done + +mdconfig -d -u $mdstart +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STARTADDR 0x0U +#define ADRSPACE 0x06400000U /* 100 Mb */ + +int +main(int argc, char **argv) +{ + int fd, ps; + void *p; + size_t len; + char *c, *path; + + p = (void *)STARTADDR; + len = ADRSPACE; + + path = argv[1]; + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) + err(1,"open()"); + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + if (errno == ENOMEM) + return (1); + err(1, "mmap(1)"); + } + + c = p; + ps = getpagesize(); + for (c = p; (void *)c < p + len; c += ps) { + *c = 1; + } + + close(fd); + + return (0); +} diff --git a/test/stress/stress2/misc/mount.sh b/test/stress/stress2/misc/mount.sh new file mode 100755 index 0000000000..1057623caf --- /dev/null +++ b/test/stress/stress2/misc/mount.sh @@ -0,0 +1,76 @@ +#!/bin/sh +# +# Copyright (c) 2008 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$ +# + +# Mount regression test + +# panic: vm_fault: fault on nofault entry, addr: deadc000 +# cpuid = 1 +# KDB: enter: panic +# [thread pid 69453 tid 100388 ] +# Stopped at kdb_enter+0x2b: nop +# db> where +# Tracing pid 69453 tid 100388 td 0xc4b5c1b0 +# kdb_enter(c091d9db) at kdb_enter+0x2b +# panic(c0938fa0,deadc000,e6b44834,c06c650e,c0a57d20,...) at panic+0x14b +# vm_fault(c1869000,deadc000,1,0) at vm_fault+0x1e0 +# trap_pfault(e6b4499c,0,deadc112) at trap_pfault+0x137 +# trap(8,c0910028,28,deadc0de,deadc0de,...) at trap+0x3f5 +# calltrap() at calltrap+0x5 +# --- trap 0xc, eip = 0xc0667def, esp = 0xe6b449dc, ebp = 0xe6b44a00 --- +# g_io_request(c66d6bdc,c4a1d840,d7c99940,d7c99940,e6b44a34,...) at g_io_request+0x5f +# g_vfs_strategy(c40624c4,d7c99940,d7c99940,0,c4e16dec,...) at g_vfs_strategy+0x49 +# ffs_geom_strategy(c40624c4,d7c99940,4ba0,0,c09dad00,...) at ffs_geom_strategy+0x141 +# ufs_strategy(e6b44a7c) at ufs_strategy+0xb5 +# VOP_STRATEGY_APV(c09da7c0,e6b44a7c) at VOP_STRATEGY_APV+0x95 +# bufstrategy(c50d2be0,d7c99940) at bufstrategy+0x55 +# breadn(c50d2b2c,0,0,1000,0,...) at breadn+0xf7 +# bread(c50d2b2c,0,0,1000,0,...) at bread+0x20 +# ffs_read(e6b44bb0) at ffs_read+0x23f +# VOP_READ_APV(c09da7c0,e6b44bb0) at VOP_READ_APV+0x7e +# ufs_readdir(e6b44c38) at ufs_readdir+0xd1 +# VOP_READDIR_APV(c09da7c0,e6b44c38) at VOP_READDIR_APV+0x7e +# getdirentries(c4b5c1b0,e6b44d04) at getdirentries+0x13f +# syscall(3b,3b,3b,8240160,1,...) at syscall+0x256 + + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +mount | grep /tmp && umount -f /tmp + +# The test: + +mount -r /tmp +mount -r /tmp +umount /tmp + +ls -lR /tmp > /dev/null # panic + +# End of test + +mount /tmp diff --git a/test/stress/stress2/misc/mount2.sh b/test/stress/stress2/misc/mount2.sh new file mode 100755 index 0000000000..2e76c9f806 --- /dev/null +++ b/test/stress/stress2/misc/mount2.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Stress test by performing parallel calls to mount and umount. Alternate +# between forced and non-forced unmounts + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +D=$diskimage + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "${mntpoint}" | grep -q md$m && umount ${mntpoint}$m + mdconfig -l | grep -q md$m && mdconfig -d -u $m + + dd if=/dev/zero of=$D$m bs=1m count=1 > /dev/null 2>&1 + mdconfig -a -t vnode -f $D$m -u $m + bsdlabel -w md$m auto + newfs md${m}${part} > /dev/null 2>&1 + done + + # start the parallel tests + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + done + + + for i in `jot $mounts`; do + wait + done + + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + mdconfig -d -u $m + rm -f $D$m + done + +else + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + mount /dev/md${m}${part} ${mntpoint}$m + while mount | grep -q ${mntpoint}$m; do + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done +fi diff --git a/test/stress/stress2/misc/mountro.sh b/test/stress/stress2/misc/mountro.sh new file mode 100755 index 0000000000..6184bbe685 --- /dev/null +++ b/test/stress/stress2/misc/mountro.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=$diskimage +dede $D 1m 128 || exit + +mount | grep "$mntpoint" | grep -q /md && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t vnode -f $D -u $mdstart + +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null 2>&1 +mount /dev/md${mdstart}${part} $mntpoint + +mkdir ${mntpoint}/stressX +chmod 777 ${mntpoint}/stressX + +export RUNDIR=${mntpoint}/stressX +export runRUNTIME=4m +(cd /home/pho/stress2; ./run.sh disk.cfg) & +sleep 30 + +for i in `jot 10`; do + mount $mntpoint -u -o ro > /dev/null 2>&1 + sleep 3 + mount $mntpoint -u -o rw > /dev/null 2>&1 + sleep 3 +done +df -i $mntpoint + +umount -f $mntpoint > /dev/null 2>&1 +mdconfig -d -u $mdstart +rm -f $D +kill `ps | grep run.sh | grep -v grep | awk '{print $1}'` diff --git a/test/stress/stress2/misc/mountro2.sh b/test/stress/stress2/misc/mountro2.sh new file mode 100755 index 0000000000..54b33f4760 --- /dev/null +++ b/test/stress/stress2/misc/mountro2.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by Matthew D. Fuller + + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=$diskimage +dede $D 1m 20 || exit + +mount | grep "$mntpoint" | grep -q /md && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t vnode -f $D -u $mdstart + +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null 2>&1 +mount /dev/md${mdstart}${part} $mntpoint + +mtree -deU -f /etc/mtree/BSD.usr.dist -p $mntpoint/ >> /dev/null +sync ; sync ; sync + +rm -rf $mntpoint/* +mount -u -o ro $mntpoint + +umount -f $mntpoint > /dev/null 2>&1 +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/mountro3.sh b/test/stress/stress2/misc/mountro3.sh new file mode 100755 index 0000000000..dd41d15600 --- /dev/null +++ b/test/stress/stress2/misc/mountro3.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by barbara +# kern/121809: unable to umount + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 64 || exit 1 + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null 2>&1 + +mount /dev/md${mdstart}${part} $mntpoint +touch $mntpoint/file +umount $mntpoint + +mount /dev/md${mdstart}${part} $mntpoint +rm $mntpoint/file +mount -u -o ro $mntpoint # Should fail with "Device busy" + +umount $mntpoint +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/msdos.sh b/test/stress/stress2/misc/msdos.sh new file mode 100755 index 0000000000..d03c612b65 --- /dev/null +++ b/test/stress/stress2/misc/msdos.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# +# Copyright (c) 2008-2010 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 + +# LOR seen. Fixed by r204467. + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md${mdstart} auto +newfs_msdos /dev/md${mdstart}a > /dev/null +mount -t msdosfs /dev/md${mdstart}a $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd ..; ./run.sh disk.cfg) + +while mount | grep "$mntpoint" | grep -q md$mdstart; do + umount $mntpoint || sleep 1 +done +fsck -t msdosfs -y /dev/md${mdstart}a +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/msdos2.sh b/test/stress/stress2/misc/msdos2.sh new file mode 100755 index 0000000000..aea34534b2 --- /dev/null +++ b/test/stress/stress2/misc/msdos2.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# panic: __lockmgr_args: recursing on non recursive lockmgr devfs @ ../../../kern/vfs_subr.c:2204 +# Scenario by kib@ + +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint +mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md${mdstart} auto +newfs_msdos /dev/md${mdstart}a > /dev/null +mount -t msdosfs /dev/md${mdstart}a $mntpoint + +u=$((mdstart + 1)) +mdconfig -l | grep -q $u && mdconfig -d -u $u +mdconfig -a -t swap -s 1g -u $u +bsdlabel -w md${u} auto +newfs_msdos /dev/md${u}a > /dev/null +mount -u /dev/md${u}a $mntpoint > /dev/null 2>&1 # panic + +ls $mntpoint > /dev/null + +while mount | grep "$mntpoint" | grep -q md$mdstart; do + umount $mntpoint || sleep 1 +done +mdconfig -d -u $mdstart +mdconfig -d -u $u diff --git a/test/stress/stress2/misc/msdos3.sh b/test/stress/stress2/misc/msdos3.sh new file mode 100755 index 0000000000..bc3cd52af9 --- /dev/null +++ b/test/stress/stress2/misc/msdos3.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# Page fault seen +# Scenario by kib@ + +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint +mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md${mdstart} auto +newfs_msdos /dev/md${mdstart}a > /dev/null + +mount -t msdosfs /dev/md${mdstart}a $mntpoint +mount -t msdosfs /dev/md${mdstart}a $mntpoint + +ls $mntpoint > /dev/null + +while mount | grep "$mntpoint" | grep -q md$mdstart; do + umount $mntpoint || sleep 1 +done +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/msdos4.sh b/test/stress/stress2/misc/msdos4.sh new file mode 100755 index 0000000000..9b1b19f29a --- /dev/null +++ b/test/stress/stress2/misc/msdos4.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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 + +# "panic: leaf should be empty" seen + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q md$mdstart && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md${mdstart} auto +newfs_msdos /dev/md${mdstart}a > /dev/null +mount -t msdosfs /dev/md${mdstart}a $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=20m +export TESTPROGS=' +testcases/lockf2/lockf2 +testcases/openat/openat +testcases/rw/rw +testcases/fts/fts +testcases/lockf/lockf +testcases/creat/creat +testcases/mkdir/mkdir +testcases/rename/rename +testcases/swap/swap +' + +(cd ..; ./run.sh) + +while mount | grep "$mntpoint" | grep -q md$mdstart; do + umount $mntpoint || sleep 1 +done +fsck -t msdosfs -y /dev/md${mdstart}a +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/namecache.sh b/test/stress/stress2/misc/namecache.sh new file mode 100755 index 0000000000..644d39598e --- /dev/null +++ b/test/stress/stress2/misc/namecache.sh @@ -0,0 +1,212 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test case for vfs.lookup_shared=1 that shows possible name cache +# inconsistency: + +# $ ls -l /tmp/file.05015? +# ls: /tmp/file.050150: No such file or directory +# $ fsdb -r /dev/ad4s1e +# ** /dev/ad4s1e (NO WRITE) +# Examining file system `/dev/ad4s1e' +# Last Mounted on /tmp +# current inode: directory +# I=2 MODE=41777 SIZE=5120 +# BTIME=May 7 05:54:47 2006 [0 nsec] +# MTIME=Apr 2 11:27:36 2009 [0 nsec] +# CTIME=Apr 2 11:27:36 2009 [0 nsec] +# ATIME=Apr 2 12:00:30 2009 [0 nsec] +# OWNER=root GRP=wheel LINKCNT=35 FLAGS=0 BLKCNT=c GEN=65f71df4 +# fsdb (inum: 2)> lookup file.050150 +# component `file.050150': current inode: regular file +# I=198 MODE=100600 SIZE=0 +# BTIME=Apr 2 11:24:33 2009 [0 nsec] +# MTIME=Apr 2 11:24:33 2009 [0 nsec] +# CTIME=Apr 2 11:24:33 2009 [0 nsec] +# ATIME=Apr 2 11:24:33 2009 [0 nsec] +# OWNER=pho GRP=wheel LINKCNT=1 FLAGS=0 BLKCNT=0 GEN=1deaab3a +# fsdb (inum: 198)> quit +# $ + +# Consistency is restored by a umount + mount of the FS + +# Observations: +# No problems seen with vfs.lookup_shared=0. +# Does not fail in a "private" subdirectory + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > namecache.c +cc -o namecache -Wall namecache.c +rm -f namecache.c + +#dir=/tmp/namecache.dir # No problems seen +dir=/tmp +[ -d $dir ] || mkdir -p $dir +cd $dir + +for i in `jot 30`; do + for j in `jot 10`; do + /tmp/namecache & + done + + for j in `jot 10`; do + wait + done +done + +if ls -l ${dir}/file.0* 2>&1 | egrep "file.0[0-9]" | grep -q "No such file"; then + echo "ls -l ${dir}/file.0*" + ls -l ${dir}/file.0* +fi + +rm -f /tmp/namecache # /${dir}/file.0* +exit +EOF +/* Test scenario for possible name cache problem */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char path[MAXPATHLEN+1]; +static char buf[64 * 1024]; + +void +pm(void) +{ + int fd, n; + int space = sizeof(buf); + struct stat statb; + long base; + struct dirent *dp; + char *bp = buf; + + if ((fd = open(".", O_RDONLY)) == -1) + err(1, "open(%s)", "."); + + do { + if ((n = getdirentries(fd, bp, space, &base)) == -1) + err(1, "getdirentries"); + space = space - n; + bp = bp + n; + } while (n != 0); + close(fd); + + bp = buf; + dp = (struct dirent *)bp; + for (;;) { + if (strcmp(path, dp->d_name) == 0) { + + if (stat(dp->d_name, &statb) == -1) { + warn("stat(%s)", dp->d_name); + printf("name: %-10s, inode %7d, type %2d, namelen %d, d_reclen %d\n", + dp->d_name, dp->d_fileno, dp->d_type, dp->d_namlen, + dp->d_reclen); + fflush(stdout); + } else { + printf("stat(%s) succeeded!\n", path); + fflush(stdout); + } + + } + bp = bp + dp->d_reclen; + dp = (struct dirent *)bp; + if (dp->d_reclen <= 0) + break; + } +} + +static void +reader(void) { + int fd; + + if ((fd = open(path, O_RDWR, 0600)) < 0) { + warn("open(%s). %s:%d", path, __FILE__, __LINE__); + pm(); + exit(1); + } + close(fd); + return; +} + +static void +writer(void) { + int fd; + + if ((fd = open(path, O_RDWR, 0600)) < 0) { + warn("open(%s). %s:%d", path, __FILE__, __LINE__); + pm(); + exit(1); + } + close(fd); + return; +} + +int +main(int argc, char **argv) +{ + pid_t pid; + int fd, i, status; + + for (i = 0; i < 10000; i++) { + if (sprintf(path, "file.0%d", getpid()) < 0) + err(1, "sprintf()"); + if ((fd = open(path, O_CREAT | O_RDWR, 0600)) == -1) + err(1, "open(%s)", path); + close(fd); + + if ((pid = fork()) == 0) { + writer(); + exit(EXIT_SUCCESS); + + } else if (pid > 0) { + reader(); + if (waitpid(pid, &status, 0) == -1) + warn("waitpid(%d)", pid); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + + if (unlink(path) == -1) + err(1, "unlink(%s). %s:%d", path, __FILE__, __LINE__); + } + return (0); +} diff --git a/test/stress/stress2/misc/nbufkv.sh b/test/stress/stress2/misc/nbufkv.sh new file mode 100755 index 0000000000..6a65c3792f --- /dev/null +++ b/test/stress/stress2/misc/nbufkv.sh @@ -0,0 +1,136 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test scenario with a 20G files on two UFS2 FSs with 64k/64k +# Test program will hang (deadlock) in "nbufkv" + +# Test scenario by John-Mark Gurney + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > nbufkv.c +cc -o nbufkv -Wall nbufkv.c +rm -f nbufkv.c +cd $odir + +u1=$mdstart +u2=$((u1 + 1)) +d1=/tmp/diskimage1 +d2=/tmp/diskimage2 +[ -d mp1 ] || mkdir mp1 +[ -d mp2 ] || mkdir mp2 +truncate -s 20g $d1 +truncate -s 20g $d2 + +mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part +mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 + +mdconfig -a -t vnode -f $d1 -u $u1 +bsdlabel -w md$u1 auto +newfs -b 65536 -f 65536 -O2 md${u1}${part} > /dev/null + +mdconfig -a -t vnode -f $d2 -u $u2 +bsdlabel -w md$u2 auto +newfs -b 65536 -f 65536 -O2 md${u2}${part} > /dev/null + +mount /dev/md${u1}$part mp1 +mount /dev/md${u2}$part mp2 + +/tmp/nbufkv `pwd`/mp1 & +/tmp/nbufkv `pwd`/mp2 & +wait;wait + +umount /dev/md${u2}$part +umount /dev/md${u1}$part + +mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part +mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part + +mdconfig -d -u $u2 +mdconfig -d -u $u1 + +rm -rf mp1 mp2 $d1 $d2 /tmp/nbufkv +exit +EOF +#include +#include +#include +#include +#include +#include +#include + +void +work(int fd, size_t n) +{ + int i; + + for (i = 0; i < 128 * 1024; i++) { + n = n - PAGE_SIZE; + if (lseek(fd, n , SEEK_SET) == -1) + err(1, "lseek()"); + if (write(fd, "1", 1) != 1) + err(1, "write()"); + } + +} + +int +main(int argc, char **argv) +{ + + int fd; + off_t len; + char path[128]; + + len = 20; + len = len * 1024 * 1024 * 1024; + + sprintf(path, "%s/nbufkv.%06d", argv[1], getpid()); + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0640)) == -1) + err(1,"open()"); + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + + work(fd, len); + + close(fd); + if (unlink(path) == -1) + err(1, "unlink(%s)", path); + + return (0); +} diff --git a/test/stress/stress2/misc/newfs.sh b/test/stress/stress2/misc/newfs.sh new file mode 100755 index 0000000000..64276392ca --- /dev/null +++ b/test/stress/stress2/misc/newfs.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +size=1 # Gb +[ `df -k $(dirname $diskimage) | tail -1 | awk '{print $4'}` -lt $((size * 1024 * 1024)) ] && \ + echo "Not enough disk space." && exit 1 +truncate -s ${size}G $diskimage + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $diskimage -u ${mdstart} +bsdlabel -w md${mdstart} auto + + +for opt in "-O1" "-O2" "-O2 -U"; do + blocksize=4096 + while [ $blocksize -le 65536 ]; do + for i in 8 4 2 1; do + fragsize=$((blocksize / i)) + echo "newfs $opt -b $blocksize -f $fragsize md${mdstart}${part}" + newfs $opt -b $blocksize -f $fragsize md${mdstart}${part} > /dev/null + mount /dev/md${mdstart}${part} $mntpoint + export RUNDIR=$mntpoint/stressX + export runRUNTIME=4m + (cd /home/pho/stress2; ./run.sh disk.cfg) + while mount | grep "$mntpoint" | grep -q md${mdstart}${part}; do + umount $mntpoint > /dev/null 2>&1 + done + done + blocksize=$((blocksize * 2)) + done +done +mdconfig -d -u ${mdstart} +rm -f $diskimage diff --git a/test/stress/stress2/misc/newfs2.sh b/test/stress/stress2/misc/newfs2.sh new file mode 100755 index 0000000000..58b5f2d863 --- /dev/null +++ b/test/stress/stress2/misc/newfs2.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# phk has seen freezes with this newfs option: "-b 32768 -f 4096 -O2" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +size=$((32 * 1024 * 1024)) + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +while [ $size -le $((900 * 1024 * 1024)) ]; do + echo "Testing with $((size / 1024 / 1024)) Mb" + truncate -s $size $diskimage + mdconfig -a -t vnode -f $diskimage -u ${mdstart} + disklabel -r -w md${mdstart} auto + newfs -b 32768 -f 4096 -O2 md${mdstart}${part} > /dev/null 2>&1 + mount /dev/md${mdstart}${part} $mntpoint + df -i $mntpoint + export RUNDIR=$mntpoint/stressX + export runRUNTIME=10m # Run tests for 10 minutes + (cd /home/pho/stress2; ./run.sh disk.cfg) + while mount | grep "$mntpoint" | grep -q md${mdstart}${part}; do + umount $mntpoint > /dev/null 2>&1 + done + mdconfig -d -u ${mdstart} + size=$((size + 32 * 1024 * 1024)) +done +rm -f $diskimage diff --git a/test/stress/stress2/misc/newfs3.sh b/test/stress/stress2/misc/newfs3.sh new file mode 100755 index 0000000000..78d785df75 --- /dev/null +++ b/test/stress/stress2/misc/newfs3.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# phk has seen freezes with this newfs option: "-b 32768 -f 4096 -O2" +# +# Deadlocks seen with this test and: +# newfs -b 4096 -f 4096 -O2 md0c on a 128 Mb FS +# newfs -b 4096 -f 1024 -O2 md0c on a 64 Mb FS +# 20070505 newfs -b 4096 -f 4096 -O2 md0c on a 32 Mb FS: panic: lockmgr: locking against myself + + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +size=$((32 * 1024 * 1024)) +opt="-O2" # newfs option. Eg. -U + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +while [ $size -le $((128 * 1024 * 1024)) ]; do + truncate -s $size $diskimage + mdconfig -a -t vnode -f $diskimage -u ${mdstart} + disklabel -r -w md${mdstart} auto + blocksize=4096 + while [ $blocksize -le 65536 ]; do + for i in 1 2 4 8; do + fragsize=$((blocksize / i)) + echo "newfs -b $blocksize -f $fragsize $opt md${mdstart}${part} on a $((size / 1024 / 1024)) Mb FS" + newfs -b $blocksize -f $fragsize $opt md${mdstart}${part} > /dev/null 2>&1 + mount /dev/md${mdstart}${part} $mntpoint + export RUNDIR=$mntpoint/stressX + export runRUNTIME=5m + (cd /home/pho/stress2; ./run.sh disk.cfg) + while mount | grep "$mntpoint" | grep -q md${mdstart}${part}; do + umount $mntpoint > /dev/null 2>&1 + done + done + blocksize=$((blocksize * 2)) + done + mdconfig -d -u ${mdstart} + size=$((size + 32 * 1024 * 1024)) +done +rm -f $diskimage diff --git a/test/stress/stress2/misc/newfs4.sh b/test/stress/stress2/misc/newfs4.sh new file mode 100755 index 0000000000..e2a22b8795 --- /dev/null +++ b/test/stress/stress2/misc/newfs4.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + + +. ../default.cfg + +# Deadlock problems. Test scenario by Lev Serebryakov +# newfs -O2 -U -b 65536 +# The io programs will get stuck in nbufkv wait state. + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > io.c +cc -o io -Wall io.c +rm -f io.c +cd $odir + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md$mdstart > /dev/null && mdconfig -d -u $mdstart + +size=9 # Gb +[ `df -k $(dirname $diskimage) | tail -1 | awk '{print $4'}` -lt $((size * 1024 * 1024)) ] && \ + echo "Not enough disk space." && exit 1 +truncate -s ${size}G $diskimage + +blocksize="-b 65536" +opt="-O2 -U" +mdconfig -a -t vnode -f $diskimage -u $mdstart +bsdlabel -w md$mdstart auto +newfs $blocksize $opt md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} $mntpoint + +cd $mntpoint +truncate -s 2g f1 +truncate -s 2g f2 +truncate -s 2g f3 +truncate -s 2g f4 +/tmp/io f1 & +/tmp/io f2 & +/tmp/io f3 & +/tmp/io f4 & +wait;wait;wait;wait + +while mount | grep "$mntpoint" | grep -q md${mdstart}${part}; do + umount -f $mntpoint > /dev/null 2>&1 +done + +mdconfig -d -u $mdstart +rm -f $diskimage +rm -f $RUNDIR/fsx.$$.* +rm -f /tmp/io +exit + +EOF +#include +#include +#include +#include +#include +#include +#include + +/* Perform random IO operations on a file */ + +int +main(int argc, char **argv) +{ + struct stat sb; + char buf[256]; + off_t bp, maxb; + int fd; + long i; + + if (argc != 2) { + fprintf(stderr, "Usage %s: file\n", argv[0]); + return (1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &sb) == -1) + err(1, "fstatf(stdin)"); + maxb = sb.st_size - sizeof(buf); + + for (i = 0; i < 10000; i++) { + bp = arc4random(); + bp = (bp << 31 | arc4random()) % maxb; +// printf("%jd\n", bp); + + if (lseek(fd, bp, 0) == -1) + err(1, "lseek()"); + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "write()"); + } + close(fd); + + return (0); +} diff --git a/test/stress/stress2/misc/nfs.sh b/test/stress/stress2/misc/nfs.sh new file mode 100755 index 0000000000..37d26b65dd --- /dev/null +++ b/test/stress/stress2/misc/nfs.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# No problems seen with this test + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q nfs && umount $mntpoint +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=10m # Run tests for 10 minutes + +(cd /home/pho/stress2; ./run.sh disk.cfg) + +while mount | grep "$mntpoint" | grep -q nfs; do + umount $mntpoint +done diff --git a/test/stress/stress2/misc/nfs2.sh b/test/stress/stress2/misc/nfs2.sh new file mode 100755 index 0000000000..512e88ab30 --- /dev/null +++ b/test/stress/stress2/misc/nfs2.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test msdos over nfs. "panic: wrong diroffset" seen. +# This needs to be in /etc/exports: /mnt -maproot=root 127.0.0.1 + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=$diskimage +dede $D 1m 128 || exit + +mount | grep "${mntpoint}2" | grep nfs > /dev/null && umount -f ${mntpoint}2 +mount | grep "$mntpoint" | grep /md > /dev/null && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t vnode -f $D -u $mdstart + +bsdlabel -w md${mdstart} auto +newfs_msdos -F 16 -b 8192 /dev/md${mdstart}a > /dev/null +mount -t msdosfs -o rw /dev/md${mdstart}a $mntpoint + +mkdir ${mntpoint}/stressX +chmod 777 ${mntpoint}/stressX + +[ ! -d ${mntpoint}2 ] && mkdir ${mntpoint}2 +chmod 777 ${mntpoint}2 + +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:$mntpoint $mntpoint2 + +export INODES=9999 # No inodes on a msdos fs +export RUNDIR=${mntpoint}2/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd /home/pho/stress2; ./run.sh disk.cfg) + +umount -f ${mntpoint}2 > /dev/null 2>&1 +umount -f $mntpoint > /dev/null 2>&1 +mdconfig -d -u $mdstart +rm -f $D diff --git a/test/stress/stress2/misc/nfs3.sh b/test/stress/stress2/misc/nfs3.sh new file mode 100755 index 0000000000..a696d7eed0 --- /dev/null +++ b/test/stress/stress2/misc/nfs3.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: neg mount point vnode list size + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ ! -d $mntpoint ] && mkdir $mntpoint +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint +rm -rf $mntpoint/stressX/* +rm -rf /tmp/stressX.control + +export RUNDIR=$mntpoint/nfs/stressX +[ ! -d $RUNDIR ] && mkdir -p $RUNDIR +export runRUNTIME=1m +rm -rf /tmp/stressX.control/* + +cd .. +./run.sh -a & +cd - +sleep 50 + +while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 +done +kill -9 $! +../tools/killall.sh diff --git a/test/stress/stress2/misc/nfs4.sh b/test/stress/stress2/misc/nfs4.sh new file mode 100755 index 0000000000..c890bf43f4 --- /dev/null +++ b/test/stress/stress2/misc/nfs4.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: vm_fault: fault on nofault entry, from vfs_stdcheckexp+0x74 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ ! -d $mntpoint ] && mkdir $mntpoint +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint +rm -rf $mntpoint/stressX/* +rm -rf /tmp/stressX.control + +export RUNDIR=$mntpoint/nfs/stressX +[ ! -d $RUNDIR ] && mkdir -p $RUNDIR +export runRUNTIME=3m +rm -rf /tmp/stressX.control/* + +(cd ..; ./run.sh all.cfg) & +sleep 60 + +while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 +done +kill -9 $! +../tools/killall.sh diff --git a/test/stress/stress2/misc/nfs5.sh b/test/stress/stress2/misc/nfs5.sh new file mode 100755 index 0000000000..6baaf5f634 --- /dev/null +++ b/test/stress/stress2/misc/nfs5.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=$diskimage +dede $D 1m 128 || exit + +mount | grep "${mntpoint}2" | grep nfs > /dev/null && umount -f ${mntpoint}2 +mount | grep "$mntpoint" | grep /md > /dev/null && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t vnode -f $D -u $mdstart + +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint + +mkdir ${mntpoint}/stressX +chmod 777 ${mntpoint}/stressX + +[ ! -d ${mntpoint}2 ] && mkdir ${mntpoint}2 +chmod 777 ${mntpoint}2 + +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/$mntpoint $mntpoint2 + +export RUNDIR=${mntpoint}2/stressX +export runRUNTIME=4m +(cd /home/pho/stress2; ./run.sh disk.cfg) & +sleep 60 + +umount -f $mntpoint > /dev/null 2>&1 +umount -f ${mntpoint}2 > /dev/null 2>&1 + +mdconfig -d -u $mdstart +rm -f $D +kill `ps | grep run.sh | grep -v grep | awk '{print $1}'` diff --git a/test/stress/stress2/misc/nfs6.sh b/test/stress/stress2/misc/nfs6.sh new file mode 100755 index 0000000000..867960c753 --- /dev/null +++ b/test/stress/stress2/misc/nfs6.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: vn_finished_write: neg cnt + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=$diskimage +dede $D 1m 128 || exit + +mount | grep "${mntpoint}2" | grep nfs > /dev/null && umount -f ${mntpoint}2 +mount | grep "$mntpoint" | grep /md > /dev/null && umount -f ${mntpoint} +mdconfig -l | grep -q ${mdstart} && mdconfig -d -u $mdstart + +mdconfig -a -t vnode -f $D -u $mdstart + +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint + +mkdir ${mntpoint}/stressX +chmod 777 ${mntpoint}/stressX + +[ ! -d ${mntpoint}2 ] && mkdir ${mntpoint}2 +chmod 777 ${mntpoint}2 + +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:$mntpoint ${mntpoint}2 + +export RUNDIR=${mntpoint}2/stressX +export runRUNTIME=4m +(cd /home/pho/stress2; ./run.sh disk.cfg) & +sleep 60 + +for i in `jot 10`; do + umount -f $mntpoint > /dev/null 2>&1 + sleep 1 + mount /dev/md${mdstart}${part} $mntpoint + sleep 1 +done + +umount -f $mntpoint > /dev/null 2>&1 +umount -f ${mntpoint}2 > /dev/null 2>&1 + +mdconfig -d -u $mdstart +rm -f $D +kill `ps | grep run.sh | grep -v grep | awk '{print $1}'` diff --git a/test/stress/stress2/misc/nfs7.sh b/test/stress/stress2/misc/nfs7.sh new file mode 100755 index 0000000000..d9ac7eee84 --- /dev/null +++ b/test/stress/stress2/misc/nfs7.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# NFS test excluding lockd + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ ! -d $mntpoint ] && mkdir $mntpoint +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint +mount -t nfs -o nfsv3,tcp,nolockd -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint +rm -rf $mntpoint/stressX/* +rm -rf /tmp/stressX.control + +export RUNDIR=$mntpoint/nfs/stressX +[ ! -d $RUNDIR ] && mkdir -p $RUNDIR +export runRUNTIME=10m +rm -rf /tmp/stressX.control/* + +cd .. +./run.sh marcus.cfg +cd - + +umount $mntpoint +while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 +done diff --git a/test/stress/stress2/misc/nfs8.sh b/test/stress/stress2/misc/nfs8.sh new file mode 100755 index 0000000000..cda7692a55 --- /dev/null +++ b/test/stress/stress2/misc/nfs8.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test scenario for a lock cascade problem with sending SIGSTOP to processes +# accessing a NFS intr mount. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ ! -d $mntpoint ] && mkdir $mntpoint +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint +mount -t nfs -o nfsv3,tcp,nolockd -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint + +pids="" +for i in `jot 10`; do + find $mntpoint > /dev/null 2>&1 & + sleep 0.1 + kill -s STOP $! + pids="$pids $!" +done + +umount $mntpoint 2>&1 | grep -v "Device busy" +while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 +done + +kill -s CONT $pids +for i in `jot 10`; do + wait +done diff --git a/test/stress/stress2/misc/nfs9.sh b/test/stress/stress2/misc/nfs9.sh new file mode 100755 index 0000000000..7b0e973c75 --- /dev/null +++ b/test/stress/stress2/misc/nfs9.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Copy of nfs4.sh, where it was discovered that a missing killall.sh script +# turned up quite a few new panics. For example: + +# vfs_mount_destroy: nonzero writeopcount +# Lock nfs not locked @ kern/vfs_default.c:462 +# Assertion x == LK_SHARERS_LOCK(1) failed at kern/kern_lock.c:236 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ ! -d $mntpoint ] && mkdir $mntpoint +for i in `jot 10`; do + mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint + mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint + rm -rf $mntpoint/stressX/* + rm -rf /tmp/stressX.control + + export RUNDIR=$mntpoint/nfs/stressX + [ ! -d $RUNDIR ] && mkdir -p $RUNDIR + export runRUNTIME=3m + rm -rf /tmp/stressX.control/* + + (cd ..; ./run.sh all.cfg) & + sleep 60 + + while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 + done + kill -9 $! +done +../tools/killall.sh diff --git a/test/stress/stress2/misc/nfsrename.sh b/test/stress/stress2/misc/nfsrename.sh new file mode 100755 index 0000000000..ccadf95eac --- /dev/null +++ b/test/stress/stress2/misc/nfsrename.sh @@ -0,0 +1,215 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + + +. ../default.cfg + +# Test scenario by jhb@ + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > nfsrename.c +cc -o nfsrename -Wall nfsrename.c +rm -f nfsrename.c +cd $odir + +mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint +mount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint + + +#export RUNDIR=$mntpoint/stressX +#export runRUNTIME=2m +#(cd /home/pho/stress2; ./run.sh disk.cfg) & + +for i in `jot 10`; do + /tmp/nfsrename $mntpoint/nfsrename.$i & +done +for i in `jot 10`; do + wait +done +killall nfsrename +rm -f $mntpoint/nfsrename.* + +umount $mntpoint > /dev/null 2>&1 +while mount | grep "$mntpoint" | grep -q nfs; do + umount -f $mntpoint > /dev/null 2>&1 +done + +rm -f /tmp/nfsrename +exit + +EOF +/* + * Try to expose races with doing renames over NFS that require silly + * renames. This results in 2 different RENAME RPCs leaving a race + * window where the file may not exist. It also appears that FreeBSD + * with shared lookups in NFS can get confused and possibly reference + * the sillyrenamed file in lookup but the file is deleted by the time + * open gets to it. + */ + +#include +#include +#include +#include +#include +#include + +const char *filename; +const char *dir; + +static void +usage(void) +{ + + fprintf(stderr, "nfsrename: [-n children] file\n"); + exit(1); +} + +static void +read_file(void) +{ + FILE *fp; + char buffer[4096]; + + fp = fopen(filename, "r"); + if (fp == NULL) { + warn("fopen"); + return; + } + while (!feof(fp)) { + if (fread(buffer, sizeof(buffer), 1, fp) < sizeof(buffer)) + break; + } + if (ferror(fp)) + warnx("fread encountered an error"); + fclose(fp); +} + +static void +write_file(void) +{ + FILE *fp; + char path[1024]; + int fd; + + snprintf(path, sizeof(path), "%s/nfsrename.XXXXXX", dir); + fd = mkstemp(path); + if (fd < 0) { + warn("mkstemp"); + return; + } + + fp = fdopen(fd, "w"); + if (fp == NULL) { + warn("fopen:writer"); + close(fd); + unlink(path); + } + + fprintf(fp, "blah blah blah garbage %ld\n", random()); + fclose(fp); + if (rename(path, filename) < 0) { + warn("rename"); + unlink(path); + } +} + +static void +random_sleep(int base, int slop) +{ + long val; + + val = random() % slop; + usleep(base + val); +} + +static void +child(void) +{ + + for (;;) { + random_sleep(500, 50); + read_file(); + } + exit(0); +} + +int +main(int ac, char **av) +{ + long i, nchild; + char *cp; + int ch; + + nchild = 1; + while ((ch = getopt(ac, av, "n:")) != -1) { + switch (ch) { + case 'n': + nchild = strtol(optarg, &cp, 0); + if (*cp != '\0') + errx(1, "Invalid count %s", optarg); + break; + case '?': + default: + usage(); + } + } + ac -= optind; + av += optind; + + if (ac == 0) + errx(1, "Missing filename"); + else if (ac > 1) + errx(1, "Extra arguments"); + + filename = av[0]; + dir = dirname(filename); + srandomdev(); + write_file(); + + for (i = 0; i < nchild; i++) { + switch (fork()) { + case 0: + child(); + case -1: + err(1, "fork"); + } + } + + for (i = 0; i < 10000; i++) { + random_sleep(1500, 1000); + write_file(); + } + + return (0); +} diff --git a/test/stress/stress2/misc/nullfs.sh b/test/stress/stress2/misc/nullfs.sh new file mode 100755 index 0000000000..2fe3a1b81a --- /dev/null +++ b/test/stress/stress2/misc/nullfs.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Stress test by performing parallel calls to mount and umount. Alternate +# between forced and non-forced unmounts + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + [ ! -d ${mntpoint}$i ] && mkdir ${mntpoint}$i + mount | grep "$mntpoint" | grep -q ${mntpoint}$i && umount ${mntpoint}$i + done + + # start the parallel tests + for i in `jot $mounts`; do + ./$0 $i & + done + + + for i in `jot $mounts`; do + wait + done + + for i in `jot $mounts`; do + umount ${mntpoint}$i > /dev/null 2>&1 + done + +else + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + mount_nullfs /tmp ${mntpoint}$m > /dev/null 2>&1 + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + while mount | grep "$mntpoint" | grep -q ${mntpoint}$m; do + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done +fi diff --git a/test/stress/stress2/misc/nullfs2.sh b/test/stress/stress2/misc/nullfs2.sh new file mode 100755 index 0000000000..374eb05e9b --- /dev/null +++ b/test/stress/stress2/misc/nullfs2.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple nullfs test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ -d mp1 ] || mkdir mp1 + +mp=`pwd`/mp1 +mount | grep -q $mp && umount -f $mp + +mount -t nullfs `dirname $RUNDIR` $mp + +export RUNDIR=`pwd`/mp1/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +umount $mp 2>&1 | grep -v busy + +mount | grep -q $mp && umount -f $mp + +rm -rf mp1 diff --git a/test/stress/stress2/misc/nullfs3.sh b/test/stress/stress2/misc/nullfs3.sh new file mode 100755 index 0000000000..86c2060339 --- /dev/null +++ b/test/stress/stress2/misc/nullfs3.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test scenario by "Paul B. Mahol" + +# Caused: lock violation + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ -d mp1 ] || mkdir mp1 +[ -d $RUNDIR ] || mkdir $RUNDIR + +mp=`pwd`/mp1 +mount | grep -q $mp && umount -f $mp + +mount -t nullfs `dirname $RUNDIR` $mp + +cd $mp/stressX +whereis something +cd / + +umount $mp + +mount | grep -q $mp && umount -f $mp + +rm -rf $mp diff --git a/test/stress/stress2/misc/nullfs4.sh b/test/stress/stress2/misc/nullfs4.sh new file mode 100755 index 0000000000..7fa91b699c --- /dev/null +++ b/test/stress/stress2/misc/nullfs4.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test scenario by Anatoli Klassen + +# kern/94269: [nullfs] procfs shows wrong data if executable is running from +# nullfs + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep -q /proc || mount -t procfs procfs /proc +mount -t nullfs /bin $mntpoint + +r1=`/bin/ls -l /proc/curproc/file` +r2=`$mntpoint/ls -l /proc/curproc/file | sed "s#$mntpoint#/bin#"` +if [ "$r1" != "$r2" ]; then + echo "/bin/ls -l /proc/curproc/file" + echo $r1 + echo "$mntpoint/ls -l /proc/curproc/file" + echo $r2 +fi + +umount $mntpoint diff --git a/test/stress/stress2/misc/nullfs5.sh b/test/stress/stress2/misc/nullfs5.sh new file mode 100755 index 0000000000..fa68c6d3ba --- /dev/null +++ b/test/stress/stress2/misc/nullfs5.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Composit test: nullfs2.sh + kinfo.sh + +# Kernel page fault with the following non-sleepable locks held from +# nullfs/null_vnops.c:531 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d;s/60/600/' < $odir/kinfo.sh > kinfo.c +cc -o kinfo -Wall -g kinfo.c -lutil +rm -f kinfo.c +cd $odir + +mount | grep -q procfs || mount -t procfs procfs /procfs + +for j in `jot 5`; do + /tmp/kinfo & +done + +[ -d mp1 ] || mkdir mp1 + +mp=`pwd`/mp1 +mount | grep -q $mp && umount -f $mp + +mount -t nullfs `dirname $RUNDIR` $mp + +export RUNDIR=`pwd`/mp1/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +umount $mp 2>&1 | grep -v busy + +mount | grep -q $mp && umount -f $mp + +rm -rf mp1 + +for j in `jot 5`; do + wait +done +rm -f /tmp/kinfo diff --git a/test/stress/stress2/misc/nullfs6.sh b/test/stress/stress2/misc/nullfs6.sh new file mode 100755 index 0000000000..b5e1d4c764 --- /dev/null +++ b/test/stress/stress2/misc/nullfs6.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# Lock violation panic regression test +# Test scenario by Mikolaj Golub +# Fixed in r208773 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep nullfs | grep -q /tmp/1 && umount /tmp/1 + +rm -rf /tmp/1 /tmp/2 +mkdir /tmp/1 /tmp/2 +touch /tmp/1/test.file + +mount -t nullfs /tmp/1 /tmp/2 + +cp /tmp/1/test.file /tmp/2/test.file # scenario by kib +mv /tmp/1/test.file /tmp/2/ # panics with lock violation + +umount /tmp/1 +rm -rf /tmp/1 /tmp/2 diff --git a/test/stress/stress2/misc/pmc.sh b/test/stress/stress2/misc/pmc.sh new file mode 100755 index 0000000000..dbd83e3c28 --- /dev/null +++ b/test/stress/stress2/misc/pmc.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# +# Copyright (c) 2008-2009 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$ +# + +# Simple pmc test + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q hwpmc || kldload hwpmc + +for i in `jot 2`; do + pmcstat -P instructions -O /tmp/sample.out.$i find /var -name not.there & +done + +export runRUNTIME=5m +(cd /home/pho/stress2; ./run.sh vfs.cfg) + +for i in `jot 2`; do + wait +done diff --git a/test/stress/stress2/misc/procfs.sh b/test/stress/stress2/misc/procfs.sh new file mode 100755 index 0000000000..95491847c2 --- /dev/null +++ b/test/stress/stress2/misc/procfs.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + done + + # start the parallel tests + touch /tmp/$0 + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find $m & + done + + for i in `jot $mounts`; do + wait; wait + done +else + if [ $1 = find ]; then + while [ -r /tmp/$0 ]; do + ls -lR ${mntpoint}* + done + echo "Done 1 @ `date '+%T'`" + else + + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + mount -t procfs proc ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + opt=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + rm -f /tmp/$0 + echo "Done 2 @ `date '+%T'`" + fi +fi diff --git a/test/stress/stress2/misc/pthread.sh b/test/stress/stress2/misc/pthread.sh new file mode 100755 index 0000000000..7d35aa0101 --- /dev/null +++ b/test/stress/stress2/misc/pthread.sh @@ -0,0 +1,140 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# panic: spin lock held too long + +# Test program and scenario by Peter Wemm + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > pth.c +cc -o pth -Wall pth.c -pthread +rm -f pth.c +cd $odir + +for i in `jot 2000`; do + date + /tmp/pth +done + +rm -f /tmp/pth +exit +EOF +#include + +#include +#include +#include +#include +#include + +static pthread_t worker1_thr; +static pthread_t worker2_thr; + +static pthread_mutex_t worker_mtx; +static pthread_cond_t worker_go; +static pthread_cond_t worker_done; + +struct workitem { + struct workitem *next; + int a, b; +}; + +struct workitem *head; + +static void * +worker(void *arg) +{ + struct workitem *w; + + pthread_detach(pthread_self()); + fprintf(stderr, "WORKER: started %p\n", arg); fflush(stderr); + + for (;;) { + pthread_mutex_lock(&worker_mtx); + while (head == NULL) { + pthread_cond_wait(&worker_go, &worker_mtx); + } + w = head; + head = w->next; + pthread_mutex_unlock(&worker_mtx); + + fprintf(stderr, "WORKER(%p): got work a=%d b=%d\n", arg, w->a, w->b); fflush(stderr); + free(w); + pthread_cond_signal(&worker_done); + } +} + +void +work_add(int a, int b) +{ + struct workitem *w; + int dowake = 0; + + w = calloc(sizeof(*w), 1); + w->a = a; + w->b = b; + pthread_mutex_lock(&worker_mtx); + if (head == 0) + dowake = 1; + w->next = head; + head = w; + pthread_mutex_unlock(&worker_mtx); + if (dowake) + pthread_cond_signal(&worker_go); +} + +int +main() +{ + pthread_mutex_init(&worker_mtx, NULL); + pthread_cond_init(&worker_go, NULL); + pthread_cond_init(&worker_done, NULL); + + fprintf(stderr, "pthread create\n"); fflush(stderr); + pthread_create(&worker1_thr, NULL, worker, (void *)1); + pthread_create(&worker2_thr, NULL, worker, (void *)2); + + work_add(10, 15); + work_add(11, 22); + work_add(314, 159); + + pthread_mutex_lock(&worker_mtx); + while (head != NULL) { + pthread_cond_wait(&worker_done, &worker_mtx); + } + pthread_mutex_unlock(&worker_mtx); + + fprintf(stderr, "job complete\n"); fflush(stderr); + exit(0); +} diff --git a/test/stress/stress2/misc/quota1.sh b/test/stress/stress2/misc/quota1.sh new file mode 100755 index 0000000000..15368f22c8 --- /dev/null +++ b/test/stress/stress2/misc/quota1.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Causes this: panic: mutex Giant not owned at ../../../kern/vfs_subr.c:1968 +# with a kernel compiled with "options QUOTA" + +. ../default.cfg + +D=$diskimage +trap "rm -f $D" 0 +dede $D 1m 128 || exit 1 + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} ${mntpoint} +export RUNDIR=${mntpoint}/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd /home/pho/stress2; ./run.sh disk.cfg) +false +while mount | grep -q ${mntpoint}; do + umount ${mntpoint} > /dev/null 2>&1 +done +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/quota10.sh b/test/stress/stress2/misc/quota10.sh new file mode 100755 index 0000000000..2c67e85a8d --- /dev/null +++ b/test/stress/stress2/misc/quota10.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Hunt for deadlock that could occur running umount and quota at the same time + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point +D=$diskimage + +if [ $# -eq 0 ]; then + cp -p /etc/fstab /etc/fstab.save + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + mdconfig -l | grep -q md$m && mdconfig -d -u $m + + dede $D$m 1m 1 + mdconfig -a -t vnode -f $D$m -u $m + bsdlabel -w md$m auto + newfs md${m}${part} > /dev/null 2>&1 + echo "/dev/md${m}${part} ${mntpoint}$m ufs rw,userquota 2 2" >> /etc/fstab + mount ${mntpoint}$m + edquota -u -f ${mntpoint}$m -e ${mntpoint}$m:100000:110000:15000:16000 root + umount ${mntpoint}$m + done + sync;sync;sync + + # start the parallel tests + touch /tmp/$0 + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find $m & + done + + for i in `jot $mounts`; do + wait; wait + done + + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + mdconfig -d -u $m + rm -f $D$m + done + + mv /etc/fstab.save /etc/fstab + +else + if [ $1 = find ]; then + while [ -r /tmp/$0 ]; do + quotaon ${mntpoint}$2 + quotaoff ${mntpoint}$2 + done + echo "Done 1 @ `date '+%T'`" + else + + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + mount $opt /dev/md${m}${part} ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + opt=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + rm -f /tmp/$0 + echo "Done 2 @ `date '+%T'`" + fi +fi diff --git a/test/stress/stress2/misc/quota2.sh b/test/stress/stress2/misc/quota2.sh new file mode 100755 index 0000000000..8ecb185980 --- /dev/null +++ b/test/stress/stress2/misc/quota2.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +D=$diskimage +trap "rm -f $D" 0 +dede $D 1m 128 || exit 1 + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null +echo "/dev/md${mdstart}${part} ${mntpoint} ufs rw,userquota 2 2" >> /etc/fstab +mount ${mntpoint} +edquota -u -f ${mntpoint} -e ${mntpoint}:100000:110000:15000:16000 root +quotacheck ${mntpoint} +quotaon ${mntpoint} +quota root +df -i ${mntpoint} +sed -i -e "/md${mdstart}${part}/d" /etc/fstab # clean up before any panics +export RUNDIR=${mntpoint}/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd /home/pho/stress2; ./run.sh disk.cfg) +false +while [ $? -ne 0 ]; do + umount ${mntpoint} > /dev/null 2>&1 +done +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/quota3.sh b/test/stress/stress2/misc/quota3.sh new file mode 100755 index 0000000000..e821227fad --- /dev/null +++ b/test/stress/stress2/misc/quota3.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +. ../default.cfg + +D=$diskimage +trap "rm -f $D" 0 +dede $D 1m 1k || exit 1 + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null +echo "/dev/md${mdstart}${part} ${mntpoint} ufs rw,userquota 2 2" >> /etc/fstab +mount ${mntpoint} +edquota -u -f ${mntpoint} -e ${mntpoint}:850000:900000:130000:140000 root +quotacheck ${mntpoint} +quotaon ${mntpoint} +quota root +df -i ${mntpoint} +sed -i -e "/md${mdstart}${part}/d" /etc/fstab # clean up before any panics +mksnap_ffs ${mntpoint} ${mntpoint}/.snap/pho +export RUNDIR=${mntpoint}/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd /home/pho/stress2; ./run.sh disk.cfg) +false +while mount | grep -q ${mntpoint}; do + umount ${mntpoint} > /dev/null 2>&1 +done +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/quota4.sh b/test/stress/stress2/misc/quota4.sh new file mode 100755 index 0000000000..c962c5b691 --- /dev/null +++ b/test/stress/stress2/misc/quota4.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Has shown a deadlock after 7 hours of testing + +. ../default.cfg + +D=$diskimage +trap "rm -f $D" 0 +dede $D 1m 1k || exit 1 + +mount | grep "${mntpoint}" | grep md${mdstart}${part} > /dev/null && umount ${mntpoint} +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null +echo "/dev/md${mdstart}${part} ${mntpoint} ufs rw,userquota 2 2" >> /etc/fstab +mount ${mntpoint} +edquota -u -f ${mntpoint} -e ${mntpoint}:850000:900000:130000:140000 root > /dev/null 2>&1 +quotaon ${mntpoint} +sed -i -e "/md${mdstart}${part}/d" /etc/fstab # clean up before any panics +export RUNDIR=${mntpoint}/stressX +../testcases/rw/rw -t 2m -i 200 -h -n -v -v& +sleep 60 +false +while mount | grep -q ${mntpoint}; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") ${mntpoint} > /dev/null 2>&1 +done +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/quota5.sh b/test/stress/stress2/misc/quota5.sh new file mode 100755 index 0000000000..907875f219 --- /dev/null +++ b/test/stress/stress2/misc/quota5.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +if ! grep /tmp /etc/fstab | grep -q quota ; then + echo "/tmp must have quota enabled!" + exit 2 +fi +edquota -u -f /tmp -e /tmp:1500000:1400000:200000:180000 pho +edquota -g -f /tmp -e /tmp:1500000:1400000:200000:180000 pho +quotaon /tmp + +#su pho -c "export runRUNTIME=60m; cd /home/pho/stress2; ./run.sh disk.cfg" +su pho -c "export runRUNTIME=60m; cd /home/pho/stress2/testcases/mkdir; ./mkdir -t 1h -i 200 -v -v" + +quotaoff /tmp diff --git a/test/stress/stress2/misc/quota6.sh b/test/stress/stress2/misc/quota6.sh new file mode 100755 index 0000000000..a3c173bc22 --- /dev/null +++ b/test/stress/stress2/misc/quota6.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Deadlock in umount(1) while out of disk space + +D=/usr/tmp/diskimage +#truncate -s 1G $D +truncate -s 250M $D + +mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt +mdconfig -l | grep md0 > /dev/null && mdconfig -d -u 0 + +mdconfig -a -t vnode -f $D -u 0 +bsdlabel -w md0 auto +newfs -U md0c > /dev/null +echo "/dev/md0c /mnt ufs rw,userquota 2 2" >> /etc/fstab +mount /mnt +edquota -u -f /mnt -e /mnt:850000:900000:130000:140000 root > /dev/null 2>&1 +quotaon /mnt +sed -i -e '/md0c/d' /etc/fstab # clean up before any panics +export RUNDIR=/mnt/stressX +../testcases/rw/rw -t 10m -i 200 -h -n -v -v& +pid=$! +for i in `jot 5`; do + echo "`date '+%T'` mksnap_ffs /mnt /mnt/.snap/snap$i" + mksnap_ffs /mnt /mnt/.snap/snap$i +done +for i in `jot 5`; do + rm -f /mnt/.snap/snap1 +done +kill $pid +false +while mount | grep -q /mnt; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") /mnt > /dev/null 2>&1 +done +mdconfig -d -u 0 +rm -f $D diff --git a/test/stress/stress2/misc/quota7.sh b/test/stress/stress2/misc/quota7.sh new file mode 100755 index 0000000000..5d91fbee54 --- /dev/null +++ b/test/stress/stress2/misc/quota7.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Quota / snapshot test scenario by Kris@ +# Causes spin in ffs_sync or panic in panic: vfs_allocate_syncvnode: insmntque failed + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +D=/var/tmp/diskimage +trap "rm -f $D" 0 +dd if=/dev/zero of=$D bs=1m count=1k + +mount | grep "/mnt" | grep -q md0 && umount -f /mnt +mdconfig -l | grep -q md0 && mdconfig -d -u 0 + +mdconfig -a -t vnode -f $D -u 0 +bsdlabel -w md0 auto +newfs -U md0c > /dev/null +echo "/dev/md0c /mnt ufs rw,userquota 2 2" >> /etc/fstab +mount /mnt +set `df -ik /mnt | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 21)) +export INODES=$(($2 / 21)) +export HOG=1 +export INCARNATIONS=40 + +export QK=$((KBLOCKS / 2)) +export QI=$((INODES / 2)) +edquota -u -f /mnt -e /mnt:$((QK - 50)):$QK:$((QI - 50 )):$QI pho +quotaon /mnt +sed -i -e '/md0c/d' /etc/fstab +export RUNDIR=/mnt/stressX +mkdir /mnt/stressX +chmod 777 /mnt/stressX +su pho -c "(cd ..;runRUNTIME=1h ./run.sh disk.cfg)"& # panic: vfs_allocate_syncvnode: insmntque failed +for i in `jot 20`; do + echo "`date '+%T'` mksnap_ffs /mnt /mnt/.snap/snap$i" + mksnap_ffs /mnt /mnt/.snap/snap$i + sleep 1 +done +i=$(($(date '+%S') % 20 + 1)) +echo "rm -f /mnt/.snap/snap$i" +rm -f /mnt/.snap/snap$i +wait + +while mount | grep -q /mnt; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") /mnt > /dev/null 2>&1 +done +mdconfig -d -u 0 +rm -f $D diff --git a/test/stress/stress2/misc/quota8.sh b/test/stress/stress2/misc/quota8.sh new file mode 100755 index 0000000000..cb03717e58 --- /dev/null +++ b/test/stress/stress2/misc/quota8.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Quota / snapshot test scenario by Kris@ +# Causes spin in ffs_sync or panic in panic: vfs_allocate_syncvnode: insmntque failed + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +trap "rm -f $D" 0 +dede $D 1m 1k || exit 1 + +mount | grep "${mntpoint}" | grep -q md${mdstart} && umount -f ${mntpoint} +mdconfig -l | grep -q md${mdstart} && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs -U md${mdstart}${part} > /dev/null +echo "/dev/md${mdstart}${part} ${mntpoint} ufs rw,userquota 2 2" >> /etc/fstab +mount ${mntpoint} +set `df -ik ${mntpoint} | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 21)) +export INODES=$(($2 / 21)) +export HOG=1 +export INCARNATIONS=40 + +export QK=$((KBLOCKS / 2)) +export QI=$((INODES / 2)) +edquota -u -f ${mntpoint} -e ${mntpoint}:$((QK - 50)):$QK:$((QI - 50 )):$QI ${testuser} +quotaon ${mntpoint} +sed -i -e "/md${mdstart}${part}/d" /etc/fstab +export RUNDIR=${mntpoint}/stressX +mkdir ${mntpoint}/stressX +chmod 777 ${mntpoint}/stressX +su ${testuser} -c 'sh -c "(cd ..;runRUNTIME=20m ./run.sh disk.cfg)"&' # Deadlock +for i in `jot 20`; do + echo "`date '+%T'` mksnap_ffs ${mntpoint} ${mntpoint}/.snap/snap$i" + mksnap_ffs ${mntpoint} ${mntpoint}/.snap/snap$i + sleep 1 +done +i=$(($(date '+%S') % 20 + 1)) +echo "rm -f ${mntpoint}/.snap/snap$i" +rm -f ${mntpoint}/.snap/snap$i +wait + +while mount | grep -q ${mntpoint}; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") ${mntpoint} > /dev/null 2>&1 +done +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/quota9.sh b/test/stress/stress2/misc/quota9.sh new file mode 100755 index 0000000000..3df67969fd --- /dev/null +++ b/test/stress/stress2/misc/quota9.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test if quotacheck reports actual usage + +. ../default.cfg + +export tmp=/tmp/$(basename $0).$$ +export D=$diskimage + +qc() { + quotacheck -v $1 > $tmp 2>&1 + grep -q fixed $tmp && cat $tmp +} + +if [ $# -eq 0 ]; then + trap "rm -f $D $tmp" 0 + [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + + dede $D 1m 50 || exit 1 + + mount | grep "${mntpoint}" | grep -q md${mdstart} && umount -f ${mntpoint} + mdconfig -l | grep -q md${mdstart} && mdconfig -d -u ${mdstart} + + mdconfig -a -t vnode -f $D -u ${mdstart} + bsdlabel -w md${mdstart} auto + newfs -U md${mdstart}${part} > /dev/null + echo "/dev/md${mdstart}${part} ${mntpoint} ufs rw,userquota 2 2" >> /etc/fstab + mount ${mntpoint} + mkdir ${mntpoint}/stressX + chown $testuser ${mntpoint}/stressX + set `df -ik ${mntpoint} | tail -1 | awk '{print $4,$7}'` + export KBLOCKS=$1 + export INODES=$2 + + export QK=$((KBLOCKS / 2)) + export QI=$((INODES / 2)) + edquota -u -f ${mntpoint} -e ${mntpoint}:$((QK - 50)):$QK:$((QI - 50 )):$QI ${testuser} > /dev/null 2>&1 + quotaon ${mntpoint} + +# quotaoff ${mntpoint};umount ${mntpoint}; mount ${mntpoint};quotaon ${mntpoint} +# df -i ${mntpoint} +# repquota -v ${mntpoint} + qc ${mntpoint} +# repquota -v ${mntpoint} +# echo "- Start test -" + + su ${testuser} $0 xxx + du -k /mnt/stressX + +# quotaoff ${mntpoint};umount ${mntpoint}; mount ${mntpoint};quotaon ${mntpoint} +# df -i ${mntpoint} +# repquota -v ${mntpoint} + qc ${mntpoint} +# repquota -v ${mntpoint} + + sed -i -e "/md${mdstart}${part}/d" /etc/fstab + while mount | grep -q ${mntpoint}; do + umount $([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f" || echo "") ${mntpoint} > /dev/null 2>&1 + done + mdconfig -d -u ${mdstart} + rm -f $D +else + for i in `jot 20`; do + dede ${mntpoint}/stressX/d$i 1m 1 + done +fi diff --git a/test/stress/stress2/misc/recursiveflushes.sh b/test/stress/stress2/misc/recursiveflushes.sh new file mode 100755 index 0000000000..5e89a23f20 --- /dev/null +++ b/test/stress/stress2/misc/recursiveflushes.sh @@ -0,0 +1,65 @@ +# $FreeBSD$ + +# +# Copyright (c) 2008 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$ +# + +# test recursive flushes in bdwrite(). + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +snap() { + for i in `jot 5`; do + mksnap_ffs $1 $2 + [ $? -eq 0 ] && break + done +} + +old=`sysctl vfs.recursiveflushes | awk '{print $NF}'` +cd /var/tmp +rm -f /var/.snap/pho.* +trap "rm -f /var/.snap/pho.*" 0 +snap /var /var/.snap/pho.1 +snap /var /var/.snap/pho.2 +snap /var /var/.snap/pho.3 +snap /var /var/.snap/pho.4 +snap /var /var/.snap/pho.5 + +for i in `jot 32`; do + # Create 32 Mb files + dd if=/dev/zero of=big.$i bs=16k count=2048 2>&1 | egrep -v "records|transferred"& +done +for i in `jot 32`; do + wait +done +for i in `jot 32`; do + rm -f big.$i +done + +rm -f /var/.snap/pho.* +new=`sysctl vfs.recursiveflushes | awk '{print $NF}'` +[ $old != $new ] && echo "vfs.recursiveflushes changed from $old to $new" diff --git a/test/stress/stress2/misc/rename.sh b/test/stress/stress2/misc/rename.sh new file mode 100755 index 0000000000..edf3769531 --- /dev/null +++ b/test/stress/stress2/misc/rename.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test race between ISDOTDOT lookups and directory removal/rename + +# With lookup_shared=1 rename() will fail from time to time with ENOENT and +# the following stat() will succed. + +# Test scenario by tegge + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > rename.c +cc -o rename -Wall rename.c +rm -f rename.c +cd $here + +rm -rf /tmp/rename.dir.* +for i in `jot 10`; do + for j in `jot 10`; do + /tmp/rename & + done + for j in `jot 10`; do + wait + done +done +rm -rf /tmp/rename.dir.* +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char dir1[128]; +static char dir2[128]; + +int +main(int argc, char **argv) +{ + int i, status; + struct stat sb; + pid_t p; + + sprintf(dir1, "/tmp/rename.dir.%d", getpid()); + sprintf(dir2, "/tmp/rename.dir.2.%d", getpid()); + if (mkdir(dir1, 0700) == -1) + err(1, "mkdir(%s)", dir1); + + if (chdir(dir1) == -1) + err(1, "chdir(%s)", dir1); + if ((p = fork()) == -1) + err(1, "fork()"); + if (p == 0) { + if (chdir("..") == -1) + err(1, "chdir(%s)", ".."); + for (i = 0; i < 100000; i++) { + if (rename(dir1, dir2) == -1) { + warn("rename(%s, %s)", dir1, dir2); + stat(dir1, &sb); + if (stat(dir1, &sb) == -1) + err(1, "stat(%s)", dir1); + else + errx(1, "stat(%s) succeeded!", dir1); + } + if (rename(dir2, dir1) == -1) { + warn("rename(%s, %s)", dir2, dir1); + stat(dir2, &sb); + if (stat(dir2, &sb) == -1) + err(1, "stat(%s)", dir2); + else + errx(1, "stat(%s) succeeded!", dir2); + } + } + exit(0); + } else { + for (i = 0; i < 100000; i++) { + if (stat("..", &sb) == -1) + err(1, "stat(..)"); + } + } + if (waitpid(p, &status, 0) == -1) + err(1, "waitpid()"); + if (rmdir(dir1) == -1) + err(1, "rmdir(%s)", dir1); + + return (0); +} diff --git a/test/stress/stress2/misc/rename2.sh b/test/stress/stress2/misc/rename2.sh new file mode 100755 index 0000000000..4f28714f90 --- /dev/null +++ b/test/stress/stress2/misc/rename2.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# With lookup_shared=1 rename() will fail from time to time with ENOENT and +# the following stat() will succeed. (Variation of rename.sh) + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > rename.c +cc -o rename -Wall rename.c +rm -f rename.c +cd $here + +rm -rf /tmp/rename.dir.* +for i in `jot 10`; do + for j in `jot 10`; do + /tmp/rename & + done + for j in `jot 10`; do + wait + done +done +rm -rf /tmp/rename.dir.* +exit 0 +EOF +#include +#include +#include +#include +#include +#include +#include +#include + +static char dir1[128]; +static char dir2[128]; + +int +main(int argc, char **argv) +{ + int i; + struct stat sb; + + sprintf(dir1, "/tmp/rename.dir.%d", getpid()); + sprintf(dir2, "/tmp/rename.dir.2.%d", getpid()); + if (mkdir(dir1, 0700) == -1) + err(1, "mkdir(%s)", dir1); + + if (chdir(dir1) == -1) + err(1, "chdir(%s)", dir1); + if (chdir("..") == -1) + err(1, "chdir(%s)", ".."); + + for (i = 0; i < 100000; i++) { + if (rename(dir1, dir2) == -1) { + warn("rename(%s, %s)", dir1, dir2); + if (stat(dir1, &sb) == -1) + err(1, "stat(%s)", dir1); + else + errx(1, "stat(%s) succeeded!", dir1); + } + if (rename(dir2, dir1) == -1) { + warn("rename(%s, %s)", dir2, dir1); + if (stat(dir2, &sb) == -1) + err(1, "stat(%s)", dir2); + else + errx(1, "stat(%s) succeeded!", dir2); + } + } + + if (rmdir(dir1) == -1) + err(1, "rmdir(%s)", dir1); + + return (0); +} diff --git a/test/stress/stress2/misc/rename3.sh b/test/stress/stress2/misc/rename3.sh new file mode 100755 index 0000000000..8a654e4eca --- /dev/null +++ b/test/stress/stress2/misc/rename3.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test vulnerability to transient failures when a directory closer +# to the root directory is renamed + +# Test scenario by Tor Egge + +root=/tmp +for i in `jot 10000`; do + rm -rf ${root}/a + mkdir -p ${root}/a/b/c/d/e/f/g + mkdir -p ${root}/a/b/c/d/e/f/z + cd ${root}/a/b/c/d/e/f + ( mv ${root}/a/b/c ${root}/a/c ) & + if ! mv z g/z; then + echo "FAILURE at loop $i" + break + fi + wait +done +rm -rf ${root}/a diff --git a/test/stress/stress2/misc/rename4.sh b/test/stress/stress2/misc/rename4.sh new file mode 100755 index 0000000000..8a8cb55086 --- /dev/null +++ b/test/stress/stress2/misc/rename4.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# lookup() does not return error when lookup of path ending on "/." is done +# for RENAME operation. + +# Tets scenario by Jim Meyering + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > rename4.c +cc -o rename4 -Wall rename4.c +rm -f rename4.c +cd $RUNDIR + +rm -rf 1 2 +mkdir 1 2 + +/tmp/rename4 1 2/. + +rm -rf 1 2 /tmp/rename4 +exit +EOF +#include +#include + +int +main(int argc, char **argv) +{ + if (rename(argv[1], argv[2]) == -1) + err(1, "rename(%s, %s)", argv[1], argv[2]); + + return (0); +} diff --git a/test/stress/stress2/misc/revoke.sh b/test/stress/stress2/misc/revoke.sh new file mode 100755 index 0000000000..626994d484 --- /dev/null +++ b/test/stress/stress2/misc/revoke.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test. Causes panic on 6.1 + +odir=`pwd` +dir=/tmp + +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/revoke.c +cc -o revoke -Wall revoke.c +rm -f revoke.c + +n=100 # Number of times to test +for i in `jot $n`; do + ./revoke /dev/ttyv9& + ./revoke /dev/ttyva& + ./revoke /dev/ttyvb& + ./revoke /dev/ttyvc& + for j in `jot 4`; do + wait + done +done + +#rm -f revoke + +exit +EOF +/* By Martin Blapp, */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/*#define TTY "/dev/ttyv9"*/ /* should be totally unused */ +#define CTTY "/dev/tty" + +int +main(int argc, char **argv) +{ + int ttyfd; + pid_t pid; + + if (argc != 2) { + fprintf(stderr, "Usage: %s /dev/ttyv?\n", argv[0]); + return 1; + } + + /* Get rid of my ctty. */ + printf("Parent starting: pid %d\n", getpid()); + pid = fork(); + if (pid < 0) { + err(1, "fork"); + exit(1); + } else if (pid > 0) { + int status; + /* parent */ + waitpid(pid, &status, 0); + exit(0); + } + /* child */ + printf("Child: pid %d\n", getpid()); + + if (setsid() < 0) { + err(1, "setsid"); + exit(1); + } + ttyfd = open(argv[1], O_RDWR); + if (ttyfd < 0) { + err(1, "open(%s)", argv[1]); + exit(1); + } + if (ioctl(ttyfd, TIOCSCTTY) < 0) { + err(1, "ioctl(TIOCSCTTY)"); + exit(1); + } + if (revoke(argv[1]) < 0) { + err(1, "revoke(%s)", argv[1]); + exit(1); + } + if (open(CTTY, O_RDWR) < 0) { + err(1, "open(%s)", CTTY); + exit(1); + } + return 0; +} diff --git a/test/stress/stress2/misc/sem.sh b/test/stress/stress2/misc/sem.sh new file mode 100755 index 0000000000..d6bc6c865d --- /dev/null +++ b/test/stress/stress2/misc/sem.sh @@ -0,0 +1,145 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Regression test for panic in semexit_myhook +# Test scenario by kib@ + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > sem.c +cc -o sem -Wall sem.c +rm -f sem.c + +cd $RUNDIR/.. +for i in `jot 5`; do + /tmp/sem& +done +for i in `jot 5`; do + wait +done + +rm -f /tmp/sem + +exit +EOF + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int semid = -1; +key_t semkey; +struct sembuf sop[2]; + +size_t pgsize; +pid_t pid; + +void +random_work(void) +{ + int i, n; + + n = (arc4random() % 5000) + 200; + for (i = 0; i < n; i++) + (void) getpid(); +} + +int +main() +{ + int i, j, seed, status; + + seed = getpid(); + semkey = ftok("/", seed); + + for (i = 0; i < 5000; i++) { + + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(2); + } + + if (pid == 0) { /* child */ + j = 0; + /* get sem */ + do { + sched_yield(); + semid = semget(semkey, 0, 0); + } while (semid == -1 && j++ < 10000); + if (semid == -1) + exit(1); + + /* + * Attempt to acquire the semaphore. + */ + sop[0].sem_num = 0; + sop[0].sem_op = -1; + sop[0].sem_flg = SEM_UNDO; + + semop(semid, sop, 1); + random_work(); + _exit(0); + + } else { /* parent */ + /* create sem */ + if ((semid = semget(semkey, 1, IPC_CREAT | 010640)) == -1) + err(1, "semget (%s:%d)", __FILE__, __LINE__); + usleep(2000); + + sop[0].sem_num = 0; + sop[0].sem_op = 1; + sop[0].sem_flg = 0; + if (semop(semid, sop, 1) == -1) + warn("init: semop (%s:%d)", __FILE__, __LINE__); + + random_work(); + if (semctl(semid, 0, IPC_RMID, 0) == -1 && errno != EINVAL) + warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); + + } + waitpid(pid, &status, 0); + } + return (0); +} diff --git a/test/stress/stress2/misc/sendfile.sh b/test/stress/stress2/misc/sendfile.sh new file mode 100755 index 0000000000..399edf7567 --- /dev/null +++ b/test/stress/stress2/misc/sendfile.sh @@ -0,0 +1,215 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test scenario for sendfile livelock seen on 7.2-STABLE for non SMP + +# Scenario by kib@ + +. ../default.cfg + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > sendfile.c +cc -o sendfile -Wall sendfile.c -pthread +rm -f sendfile.c +[ -d "$RUNDIR" ] || mkdir -p $RUNDIR +cd $RUNDIR + +in=/tmp/inputFile +out=/tmp/outputFile + +for i in 1 2 3 4 8 16 1k 2k 3k 4k 5k 1m 2m 3m 4m 5m ; do + rm -f $in $out + dd if=/dev/random of=$in bs=$i count=1 2>&1 | \ + egrep -v "records|transferred" + /tmp/sendfile $in $out 12345 + cmp $in $out || ls -l $in $out + rm -f $in $out +done +rm -f /tmp/sendfile +exit +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int port; +char *inputFile; +char *outputFile; +int bufsize = 4096; + +static void +reader(void) { + int tcpsock, msgsock; + int on; + socklen_t len; + struct sockaddr_in inetaddr, inetpeer; + int n, t, *buf, fd; + + on = 1; + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) + err(1, "bind(), %s:%d", __FILE__, __LINE__); + + if (listen(tcpsock, 5) < 0) + err(1, "listen(), %s:%d", __FILE__, __LINE__); + + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) + err(1, "accept(), %s:%d", __FILE__, __LINE__); + + t = 0; + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + + if ((fd = open(outputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) + err(1, "open(%s)", outputFile); + + for (;;) { + if ((n = read(msgsock, buf, bufsize)) < 0) + err(1, "read(), %s:%d", __FILE__, __LINE__); + t += n; + if (n == 0) break; + + if ((write(fd, buf, n)) != n) + err(1, "write"); + } + close(msgsock); + close(fd); + return; +} + +static void +writer(void) { + int tcpsock, on; + struct sockaddr_in inetaddr; + struct hostent *hostent; + struct stat statb; + int i, r, fd; + off_t off = 0; +#if 1 + size_t size; +#endif + + on = 1; + for (i = 1; i < 5; i++) { + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + +#if 1 /* livelock trigger */ + size = getpagesize() -4; + if (setsockopt(tcpsock, + SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) + err(1, "setsockopt(SO_SNDBUF), %s:%d", __FILE__, __LINE__); +#endif + + hostent = gethostbyname ("localhost"); + memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + r = connect(tcpsock, (struct sockaddr *) &inetaddr, + sizeof(inetaddr)); + if (r == 0) + break; + sleep(1); + close(tcpsock); + } + if (r < 0) + err(1, "connect(), %s:%d", __FILE__, __LINE__); + + if (stat(inputFile, &statb) != 0) + err(1, "stat(%s)", inputFile); + + if ((fd = open(inputFile, O_RDONLY)) == -1) + err(1, "open(%s)", inputFile); + + if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 0) == -1) + err(1, "sendfile"); + + return; +} + +int +main(int argc, char **argv) +{ + pid_t pid; + + if (argc != 4) { + fprintf(stderr, "Usage: %s 0) { + reader(); + kill(pid, SIGINT); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + + return (0); +} diff --git a/test/stress/stress2/misc/snap.sh b/test/stress/stress2/misc/snap.sh new file mode 100755 index 0000000000..863d914a8f --- /dev/null +++ b/test/stress/stress2/misc/snap.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +mount | grep "/dev/md0 on /mnt" > /dev/null && umount /mnt +rm -f /tmp/.snap/pho +trap "rm -f /tmp/.snap/pho" 0 + +for i in `jot 128`; do + mksnap_ffs /tmp /tmp/.snap/pho + mdconfig -a -t vnode -f /tmp/.snap/pho -u 0 -o readonly + mount -r /dev/md0 /mnt + + ls -l /mnt > /dev/null + + umount /mnt + mdconfig -d -u 0 + rm -f /tmp/.snap/pho +done + + +for i in `jot 128`; do + mksnap_ffs /tmp /tmp/.snap/pho + rm -f /tmp/.snap/pho +done diff --git a/test/stress/stress2/misc/snap2-1.sh b/test/stress/stress2/misc/snap2-1.sh new file mode 100755 index 0000000000..cf78136bcb --- /dev/null +++ b/test/stress/stress2/misc/snap2-1.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Regression test: Delete an active md device +# +# panic(c088cd33,deadc000,c0943aa0,0,c08753e1) at panic+0x14b +# vm_fault(c1060000,deadc000,1,0,c54de480) at vm_fault+0x1e0 +# trap_pfault(e76728b8,0,deadc112) at trap_pfault+0x137 +# trap(8,c0870028,28,deadc0de,deadc0de) at trap+0x355 +# calltrap() at calltrap+0x5 +# --- trap 0xc, eip = 0xc060bcfb, esp = 0xe76728f8, ebp = 0xe767291c --- +# g_io_request(c53ff7bc,c5051d40,d8c72408,c54ca110,e7672950) at g_io_request+0x5f + +rm -f /tmp/.snap/pho +[ -d /tmp/.snap ] || mkdir /tmp/.snap +trap "rm -f /tmp/.snap/pho" 0 +mount | grep "/mnt" | grep md0 > /dev/null && umount /mnt +mdconfig -l | grep -q md0 && mdconfig -d -u 0 + +mksnap_ffs /tmp /tmp/.snap/pho +mdconfig -a -t vnode -o readonly -f /tmp/.snap/pho -u 0 +mount -o ro /dev/md0 /mnt + +ls -lR /mnt > /dev/null 2>&1 & +mdconfig -d -u 0 > /dev/null 2>&1 + +umount -f /mnt +mdconfig -d -u 0 +rm -f /tmp/.snap/pho diff --git a/test/stress/stress2/misc/snap2.sh b/test/stress/stress2/misc/snap2.sh new file mode 100755 index 0000000000..302b8b1eb0 --- /dev/null +++ b/test/stress/stress2/misc/snap2.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Regression test: Delete an active md device +# +# panic(c088cd33,deadc000,c0943aa0,0,c08753e1) at panic+0x14b +# vm_fault(c1060000,deadc000,1,0,c54de480) at vm_fault+0x1e0 +# trap_pfault(e76728b8,0,deadc112) at trap_pfault+0x137 +# trap(8,c0870028,28,deadc0de,deadc0de) at trap+0x355 +# calltrap() at calltrap+0x5 +# --- trap 0xc, eip = 0xc060bcfb, esp = 0xe76728f8, ebp = 0xe767291c --- +# g_io_request(c53ff7bc,c5051d40,d8c72408,c54ca110,e7672950) at g_io_request+0x5f + +. ../default.cfg + +rm -f /tmp/.snap/pho +trap "rm -f /tmp/.snap/pho" 0 +mount | grep "${mntpoint}" | grep -q md${mdstart} && umount -f ${mntpoint} +mdconfig -l | grep -q md${mdstart} && mdconfig -d -u ${mdstart} + +mksnap_ffs /tmp /tmp/.snap/pho +mdconfig -a -t vnode -f /tmp/.snap/pho -u $mdstart -o readonly +mount -r /dev/md${mdstart} ${mntpoint} + +ls -lR > /dev/null 2>&1 & +mdconfig -d -u $mdstart > /dev/null 2>&1 + +umount ${mntpoint} > /dev/null 2>&1 +umount -f ${mntpoint} > /dev/null 2>&1 +mdconfig -d -u $mdstart +rm -f /tmp/.snap/pho diff --git a/test/stress/stress2/misc/snap3.sh b/test/stress/stress2/misc/snap3.sh new file mode 100755 index 0000000000..23d2991a60 --- /dev/null +++ b/test/stress/stress2/misc/snap3.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Test with two snapshots +# 20070506 Page fault in g_io_request+0x7f + +mount | grep "/dev/md0 on /mnt" > /dev/null && umount /mnt +rm -f /tmp/.snap/pho.1 +rm -f /tmp/.snap/pho.2 +trap "rm -f /tmp/.snap/pho.?" 0 +mount | grep "/mnt" | grep md5 > /dev/null && umount /mnt +mdconfig -l | grep -q md5 && mdconfig -d -u 5 +mdconfig -l | grep -q md6 && mdconfig -d -u 6 + +for i in `jot 64`; do + mksnap_ffs /tmp /tmp/.snap/pho.1 + mksnap_ffs /tmp /tmp/.snap/pho.2 + mdconfig -a -t vnode -f /tmp/.snap/pho.1 -u 5 -o readonly + mdconfig -a -t vnode -f /tmp/.snap/pho.2 -u 6 -o readonly + mount -o ro /dev/md5 /mnt + + sleep 3 + + umount /mnt + mdconfig -d -u 5 + mdconfig -d -u 6 + rm -f /tmp/.snap/pho.1 + rm -f /tmp/.snap/pho.2 +done diff --git a/test/stress/stress2/misc/snap4.sh b/test/stress/stress2/misc/snap4.sh new file mode 100755 index 0000000000..1c22d4117c --- /dev/null +++ b/test/stress/stress2/misc/snap4.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Test with snapshot file unlinked before unmount + +mount | grep "/dev/md0 on /mnt" > /dev/null && umount /mnt +mdconfig -l | grep -q md0 && mdconfig -d -u 0 +rm -f /tmp/.snap/pho +trap "rm -f /tmp/.snap/pho" 0 + +for i in `jot 64`; do + mksnap_ffs /tmp /tmp/.snap/pho + mdconfig -a -t vnode -f /tmp/.snap/pho -u 0 -o readonly + mount -o ro /dev/md0 /mnt + + ls -l /mnt > /dev/null + rm -f /tmp/.snap/pho + sleep 1 + + umount /mnt + mdconfig -d -u 0 + rm -f /tmp/.snap/pho +done diff --git a/test/stress/stress2/misc/snap5-1.sh b/test/stress/stress2/misc/snap5-1.sh new file mode 100755 index 0000000000..b74cbc9818 --- /dev/null +++ b/test/stress/stress2/misc/snap5-1.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +[ ! -d /mnt2 ] && mkdir /mnt2 + +trap "rm -f /tmp/.snap/pho" 0 +for i in `jot 64`; do + if mount | grep -q "/dev/md0 on /mnt2"; then + umount /mnt2 || exit 2 + fi + if mdconfig -l | grep -q md0; then + mdconfig -d -u 0 || exit 3 + fi + rm -f /tmp/.snap/pho + + date '+%T' + mksnap_ffs /tmp /tmp/.snap/pho || continue + mdconfig -a -t vnode -f /tmp/.snap/pho -u 0 -o readonly || exit 4 + mount -o ro /dev/md0 /mnt2 || exit 5 + + ls -l /mnt2 > /dev/null + r=`head -c4 /dev/urandom | od -N2 -tu4 | sed -ne '1s/ *$//;1s/.* //p'` + sleep $(( r % 120 )) +done +mount | grep -q "/dev/md0 on /mnt2" && umount /mnt2 +mdconfig -l | grep -q md0 && mdconfig -d -u 0 diff --git a/test/stress/stress2/misc/snap5.sh b/test/stress/stress2/misc/snap5.sh new file mode 100755 index 0000000000..1713ed000b --- /dev/null +++ b/test/stress/stress2/misc/snap5.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +[ ! -d /mnt2 ] && mkdir /mnt2 +mount | grep "/dev/md0 on /mnt2" > /dev/null && umount /mnt2 +mdconfig -l | grep md0 > /dev/null && mdconfig -d -u 0 +rm -f /tmp/.snap/pho +trap "rm -f /tmp/.snap/pho" 0 + +for i in `jot 64`; do + date '+%T' + mksnap_ffs /tmp /tmp/.snap/pho + mdconfig -a -t vnode -f /tmp/.snap/pho -u 0 -o readonly + mount -o ro /dev/md0 /mnt2 + + ls -l /mnt2 > /dev/null + r=`head -c4 /dev/urandom | od -N2 -tu4 | sed -ne '1s/ *$//;1s/.* //p'` + sleep $(( r % 120 )) + + umount /mnt2 + mdconfig -d -u 0 + rm -f /tmp/.snap/pho +done diff --git a/test/stress/stress2/misc/snap6.sh b/test/stress/stress2/misc/snap6.sh new file mode 100755 index 0000000000..c1bfdc304b --- /dev/null +++ b/test/stress/stress2/misc/snap6.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# Problem Report kern/92272 : [ffs] [hang] Filling a filesystem while creating +# a snapshot on it locks the system + +# John Kozubik + +# If a filesystem is completely full (approaching 110% in `df` output on +# most systems), mksnap_ffs will refuse to begin a snapshot for that reason. +# There seem to be no negative consequences. + +# However, if the filesystem is not quite completely full, mksnap_ffs will +# (correctly) begin creating the snapshot as expected. If, during the course +# of snapshot creation, the filesystem being snapshotted becomes full, +# mksnap_ffs will exit with an error exactly as it does if it is started on +# an already full filesystem. + +# However, several hours later, the system will lock up completely. It still +# responds to pings, and open connections to and from it remain in that +# state, but they cannot be used and new connections cannot be established. + +# *** This script does not provoke the problem. *** + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +root=/var + +rm -f $root/.snap/pho $root/big $root/big2 +trap "rm -f $root/.snap/pho $root/big $root/big2" 0 +free=`df $root | tail -1 | awk '{print $4}'` +dd if=/dev/zero of=$root/big bs=1m count=$(( free / 1024 - 90)) > /dev/null 2>&1 +df $root + +for i in `jot 1024`; do + date + nice -20 mksnap_ffs $root $root/.snap/pho & + dd if=/dev/zero of=$root/big2 bs=1m > /dev/null 2>&1 + wait + [ -f $root/.snap/pho ] && exit 0 + rm -f $root/.snap/pho $root/big2 +done +df $root + +rm -f $root/.snap/pho $root/big $root/big2 diff --git a/test/stress/stress2/misc/snap7.sh b/test/stress/stress2/misc/snap7.sh new file mode 100755 index 0000000000..8baa29bd3a --- /dev/null +++ b/test/stress/stress2/misc/snap7.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Test with unmount and paralless access to mountpoint +# 20070508 page fault in g_io_request+0xa6 + +mount | grep "/dev/md0 on /mnt" > /dev/null && umount /mnt +rm -f /tmp/.snap/pho.1 +trap "rm -f /tmp/.snap/pho.1" 0 +mount | grep "/mnt" | grep md0 > /dev/null && umount /mnt +mdconfig -l | grep -q md0 && mdconfig -d -u 0 + +for i in `jot 64`; do + mksnap_ffs /tmp /tmp/.snap/pho.1 + mdconfig -a -t vnode -f /tmp/.snap/pho.1 -u 0 -o readonly + sh -c "while true; do ls /mnt > /dev/null;done" & + for i in `jot 64`; do + mount -o ro /dev/md0 /mnt + umount /mnt + done + kill $! + mdconfig -d -u 0 + rm -f /tmp/.snap/pho.1 +done diff --git a/test/stress/stress2/misc/snap8.sh b/test/stress/stress2/misc/snap8.sh new file mode 100755 index 0000000000..aecb2f3026 --- /dev/null +++ b/test/stress/stress2/misc/snap8.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Deadlock seen when deleting the snapshots during an "ls" of the FS + +# Based on test scenario by John Kozubik +# kern/94769: [ufs] Multiple file deletions on multi-snapshotted filesystems +# causes hang + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep -q /dev/md${mdstart}$part && umount -f /dev/md${mdstart}$part +mdconfig -l | grep -q md${mdstart} && mdconfig -d -u $mdstart + + +parallel=20 +size=25 # Gb +[ `df -k $(dirname $diskimage) | tail -1 | awk '{print $4'}` -lt $((size * 1024 * 1024)) ] && \ + echo "Not enough disk space." && exit 1 +truncate -s ${size}G $diskimage + +mdconfig -a -t vnode -f $diskimage -u $mdstart +bsdlabel -w md$mdstart auto +newfs -O2 -U md${mdstart}${part} > /dev/null +mount /dev/md${mdstart}${part} $mntpoint + + +cc -o /tmp/fstool -Wall ../tools/fstool.c +for i in `jot $parallel`; do + (mkdir $mntpoint/test$i; cd $mntpoint/test$i; /tmp/fstool -l -f 50 -n 500 -s 8k) & +done +for i in `jot $parallel`; do + wait +done +rm -f /tmp/fstool + +mksnap_ffs $mntpoint $mntpoint/.snap/snap1 +mksnap_ffs $mntpoint $mntpoint/.snap/snap2 +mksnap_ffs $mntpoint $mntpoint/.snap/snap3 +mksnap_ffs $mntpoint $mntpoint/.snap/snap4 +mksnap_ffs $mntpoint $mntpoint/.snap/snap5 +mksnap_ffs $mntpoint $mntpoint/.snap/snap6 +mksnap_ffs $mntpoint $mntpoint/.snap/snap7 +mksnap_ffs $mntpoint $mntpoint/.snap/snap8 +mksnap_ffs $mntpoint $mntpoint/.snap/snap9 + +for i in `jot $parallel`; do + rm -rf $mntpoint/test$i & +done +for i in `jot $parallel`; do + wait +done + +rm -rf $mntpoint/.snap/snap? & + +for i in `jot 10`; do + ls -lsrt $mntpoint > /dev/null 2>&1 + sleep 2 +done +wait + +umount /dev/md${mdstart}$part + +mount | grep -q /dev/md${mdstart}$part && umount -f /dev/md${mdstart}$part +mdconfig -l | grep -q md${mdstart} && mdconfig -d -u $mdstart +rm -f $diskimage diff --git a/test/stress/stress2/misc/snapbackup.sh b/test/stress/stress2/misc/snapbackup.sh new file mode 100755 index 0000000000..8664084b03 --- /dev/null +++ b/test/stress/stress2/misc/snapbackup.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Maintain four snapshot backups of /tmp in /backup/snap? + +[ ! -d /backup ] && mkdir /backup + +for i in `mount | grep "/backup" | awk '{print $1}'`; do + num=`echo $i | sed 's/.*md//'` + false + while [ $? -ne 0 ]; do + umount $i + done + mdconfig -d -u $num +done +for i in `mdconfig -l | sed 's/md//g'`; do + [ $i -lt 1 -o $i -gt 4 ] && continue + mdconfig -d -u $i +done + +cd /tmp/.snap +[ -r snap4 ] && rm -f snap4 +[ -r snap3 ] && mv snap3 snap4 +[ -r snap2 ] && mv snap2 snap3 +[ -r snap1 ] && mv snap1 snap2 + +mksnap_ffs /tmp /tmp/.snap/snap1 + +for i in `ls /tmp/.snap/snap*`; do + name=`basename $i` + num=`echo $name | sed 's/snap//'` + mdconfig -a -t vnode -o readonly -f /tmp/.snap/snap${num} -u ${num} + [ ! -d /backup/snap${num} ] && mkdir /backup/snap${num} + mount -o ro /dev/md${num} /backup/snap${num} +done diff --git a/test/stress/stress2/misc/softupdate.sh b/test/stress/stress2/misc/softupdate.sh new file mode 100755 index 0000000000..ba821954e6 --- /dev/null +++ b/test/stress/stress2/misc/softupdate.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Like the symlink.sh test, this test shows the problem with Soft Update and +# incorrect statfs(2). + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +runRUNTIME=10m +runRUNTIME=1m +RUNDIR=${mntpoint}/stressX + +D=$diskimage +dede $D 1m 512 || exit 1 + +mount | grep "$mntpoint" | grep md${mdstart} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} + +for mode in "" "-U"; do + printf "newfs -O2 $mode /dev/md${mdstart}\n\n" + newfs -O2 $mode /dev/md${mdstart} > /dev/null 2>&1 + mount /dev/md${mdstart} ${mntpoint} + + for i in `jot 10`; do + (cd ..;./run.sh disk.cfg) + done + + umount -f ${mntpoint} +done +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/statfs.sh b/test/stress/stress2/misc/statfs.sh new file mode 100755 index 0000000000..825f65a10a --- /dev/null +++ b/test/stress/stress2/misc/statfs.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Regression test for statfs problems with deleting a large number of files + +# $ ./statfs.sh +# Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on +# /dev/ad0s1e 1982798 1782134 42042 98% 4965 254105 2% /tmp +# Free inodes on /tmp: 254105 +# Creating 100000 files... +# Deleting 100000 files... +# Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on +# /dev/ad0s1e 1982798 -284096 2108272 -16% 4965 254105 2% /tmp +# $ umount -f /tmp; mount /tmp +# $ df -i /tmp +# Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on +# /dev/ad0s1e 1982798 1784528 39648 98% 4965 254105 2% /tmp + + +odir=`pwd` +dir=/tmp + +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/statfs.c +cc -o statfs -Wall statfs.c +rm -f statfs.c + +df -i /tmp +./statfs +df -i /tmp + +exit +EOF +/* $FreeBSD$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int64_t +inodes(void) +{ + char path[MAXPATHLEN+1]; + struct statfs buf; + + sync(); + if (getcwd(path, sizeof(path)) == NULL) + err(1, "getcwd()"); + + if (statfs(path, &buf) < 0) + err(1, "statfs(%s)", path); + printf("Free inodes on %s: %jd\n", path, buf.f_ffree); + return (buf.f_ffree); +} + +int +main() +{ + int fd, i, j; + int64_t size; + pid_t pid; + char file[128]; + + size = inodes() - 1000; + + if (size > 100000) + size = 100000; + + printf("Creating %jd files...", size); fflush(stdout); + pid = getpid(); + for (j = 0; j < size; j++) { + sprintf(file,"p%06d.%05d", pid, j); + if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0666)) == -1) { + if (errno != EINTR) { + warn("creat(%s)", file); + printf("break out at %d, errno %d\n", j, errno); + break; + } + } + if (fd != -1 && close(fd) == -1) + err(2, "close(%d)", j); + + } + + printf("\nDeleting %jd files...", size); fflush(stdout); + for (i = --j; i >= 0; i--) { + sprintf(file,"p%06d.%05d", pid, i); + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + + } + printf("\n"); + return (0); +} diff --git a/test/stress/stress2/misc/suj.sh b/test/stress/stress2/misc/suj.sh new file mode 100755 index 0000000000..be0903d054 --- /dev/null +++ b/test/stress/stress2/misc/suj.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# +# Copyright (c) 2010 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$ +# + +# SUJ suspfs deadlock seen + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep $mntpoint | grep -q /dev/md && umount $mntpoint +mdconfig -a -t swap -s 1g -u $mdstart +bsdlabel -w md$mdstart auto +newfs -U md${mdstart}$part > /dev/null +tunefs -j enable /dev/md${mdstart}$part +mount /dev/md${mdstart}$part $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=20m +(cd ..; ./run.sh rw.cfg) + +while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 +done +mdconfig -d -u $mdstart diff --git a/test/stress/stress2/misc/symlink.sh b/test/stress/stress2/misc/symlink.sh new file mode 100755 index 0000000000..3976ad7e24 --- /dev/null +++ b/test/stress/stress2/misc/symlink.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Testing problem with premature disk full problem with symlinks + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 1024 || exit 1 + +odir=`pwd` +dir=$mntpoint + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > symlink.c +cc -o symlink -Wall symlink.c +rm -f symlink.c +cd $odir + +mount | grep "$mntpoint" | grep md${mdstart} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} + + +tst() { + cd $dir + df -ik $mntpoint + i=`df -ik $mntpoint | tail -1 | awk '{printf "%d\n", ($7 - 500)/2}'` + [ $i -gt 20000 ] && i=20000 + + for k in `jot 5`; do + for j in `jot 2`; do + /tmp/symlink $i & + done + for j in `jot 2`; do + wait + done + df -ik $mntpoint | tail -1 +# sleep 30 # With this enabled, soft update also works + done + cd $odir +} + +for i in "" "-U"; do + echo "newfs $i /dev/md${mdstart}" + newfs $i /dev/md${mdstart} > /dev/null 2>&1 + mount /dev/md${mdstart} ${mntpoint} + + tst + + umount -f ${mntpoint} +done +mdconfig -d -u $mdstart +exit +EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i, j; + int64_t size; + pid_t pid; + char file[128]; + + size = atol(argv[1]); + +// printf("Creating %jd symlinks...\n", size); fflush(stdout); + pid = getpid(); + for (j = 0; j < size; j++) { + sprintf(file,"p%05d.%05d", pid, j); + if (symlink("/mnt/not/there", file) == -1) { + if (errno != EINTR) { + warn("symlink(%s)", file); + printf("break out at %d, errno %d\n", j, errno); + break; + } + } + } + +// printf("Deleting %jd files...\n", size); fflush(stdout); + for (i = --j; i >= 0; i--) { + sprintf(file,"p%05d.%05d", pid, i); + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + + } + return (0); +} diff --git a/test/stress/stress2/misc/symlink2.sh b/test/stress/stress2/misc/symlink2.sh new file mode 100755 index 0000000000..698aa1d88f --- /dev/null +++ b/test/stress/stress2/misc/symlink2.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Testing problem with buffer cache inconsistancy + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 10 || exit 1 + +odir=`pwd` +dir=$mntpoint + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > symlink2.c +cc -o symlink2 -Wall symlink2.c +rm -f symlink2.c +cd $odir + +mount | grep "$mntpoint" | grep md${mdstart} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} + +for i in "" "-U"; do + echo "newfs $i /dev/md${mdstart}" + newfs $i /dev/md${mdstart} > /dev/null 2>&1 + mount /dev/md${mdstart} $mntpoint + mkdir ${mntpoint}/dir + + /tmp/symlink2 ${mntpoint}/dir/link + + ls -l ${mntpoint}/dir > /dev/null 2>&1 + if [ $? -ne 0 ]; then + set -x + ls -l ${mntpoint}/dir + umount $mntpoint + mount /dev/md${mdstart} $mntpoint + ls -l ${mntpoint}/dir + set +x + fi + + umount -f ${mntpoint} +done +mdconfig -d -u $mdstart +exit +EOF +#include +#include +#include +#include +#include +#include +#include + +static char *path; + +int +main(int argc, char **argv) +{ + int i, n; + pid_t p; + char buf[128]; + + path = argv[1]; + for (i = 0; i < 100; i++) { + if ((p = fork()) == 0) { + if ((n = readlink(path, buf, sizeof(buf) -1)) < 0) { + for (i = 0; i < 60; i++) { + sleep(1); + if ((n = readlink(path, buf, sizeof(buf) -1)) > 0) { + break; + } + } + } + if (n < 0) + err(1, "readlink(%s). %s:%d", path, __FILE__, __LINE__); + exit(0); + } + } + (void) unlink(path); + sleep(2); + if (symlink("1234", path) < 0) + err(1, "symlink(%s, %s)", path, "1234"); + + for (i = 0; i < 100; i++) { + if (wait(&n) == -1) + err(1, "wait(), %s:%d", __FILE__, __LINE__); + } + + return (0); +} diff --git a/test/stress/stress2/misc/syscall.sh b/test/stress/stress2/misc/syscall.sh new file mode 100755 index 0000000000..a5fd553b96 --- /dev/null +++ b/test/stress/stress2/misc/syscall.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# Copyright (c) 2008-2009 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$ +# + +# Test calls with random arguments, in reverse order + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q sysvmsg || kldload sysvmsg +kldstat -v | grep -q sysvsem || kldload sysvsem +kldstat -v | grep -q sysvshm || kldload sysvshm + +kldstat -v | grep -q aio || kldload aio +kldstat -v | grep -q mqueuefs || kldload mqueuefs + +syscall=`grep SYS_MAXSYSCALL /usr/include/sys/syscall.h | awk '{print $NF}'` + +n=$syscall +[ $# -eq 1 ] && n=$1 + +rm -f /tmp/syscall.log +while [ $n -gt 0 ]; do + echo "`date '+%T'` syscall $n" | tee /dev/tty >> /tmp/syscall.log + for i in `jot 5`; do + su ${testuser} -c "sh -c \"../testcases/syscall/syscall -t 30s -i 100 -h -l 100 -k $n\"" + done + n=$((n - 1)) + chflags -R 0 $RUNDIR + rm -rf $RUNDIR +done diff --git a/test/stress/stress2/misc/syscall2.sh b/test/stress/stress2/misc/syscall2.sh new file mode 100755 index 0000000000..054f64ed37 --- /dev/null +++ b/test/stress/stress2/misc/syscall2.sh @@ -0,0 +1,224 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test calls with random arguments, in reverse order +# Variation of the syscall test program. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > syscall2.c +cc -o syscall2 -Wall -I $odir/../include -L $odir/../lib syscall2.c -lstress -lutil +rm -f syscall2.c + +kldstat -v | grep -q sysvmsg || kldload sysvmsg +kldstat -v | grep -q sysvsem || kldload sysvsem +kldstat -v | grep -q sysvshm || kldload sysvshm + +kldstat -v | grep -q aio || kldload aio +kldstat -v | grep -q mqueuefs || kldload mqueuefs + +syscall=`grep SYS_MAXSYSCALL /usr/include/sys/syscall.h | awk '{print $NF}'` + +n=$syscall +[ $# -eq 1 ] && n=$1 + +rm -f /tmp/syscall2.log +while [ $n -gt 0 ]; do + echo "`date '+%T'` syscall $n" | tee /dev/tty >> /tmp/syscall2.log + for i in `jot 5`; do + su ${testuser} -c "sh -c \"/tmp/syscall2 -t 30s -i 100 -h -l 100 -k $n\"" + done + chflags -R 0 $RUNDIR + rm -rf $RUNDIR + n=$((n - 1)) +done +rm -f /tmp/syscall2 +exit +EOF + +/* Call random system calls with random arguments */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static int num; +static int starting_dir = 0; +uint32_t rb[7][10]; + +static int ignore[] = { + SYS_syscall, + SYS_exit, + SYS_fork, + 11, /* 11 is obsolete execv */ + SYS_unmount, + SYS_reboot, + SYS_vfork, + 109, /* 109 is old sigblock */ + 111, /* 111 is old sigsuspend */ + SYS_shutdown, + SYS___syscall, + SYS_rfork, + SYS_sigsuspend, + SYS_mac_syscall, + SYS_sigtimedwait, + SYS_sigwaitinfo, +}; + +int +setup(int nb) +{ + int i; + struct rlimit rl; + + umask(0); + sprintf(path,"%s.%05d", getprogname(), getpid()); + (void)mkdir(path, 0770); + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + if ((starting_dir = open(".", 0)) < 0) + err(1, "."); + + if (op->argc == 1) { + num = atoi(op->argv[0]); + for (i = 0; i < sizeof(ignore) / sizeof(ignore[0]); i++) + if (num == ignore[i]) { + printf("syscall %d is marked a no test!\n", num); + exit(1); + } + } else { + num = 0; + while (num == 0) { + num = random_int(0, SYS_MAXSYSCALL); + for (i = 0; i < sizeof(ignore) / sizeof(ignore[0]); i++) + if (num == ignore[i]) { + num = 0; + break; + } + } + } + if (op->verbose > 1) + printf("Testing syscall #%d, pid %d\n", num, getpid()); + + /* Multiple parallel core dump may panic the kernel with: + panic: kmem_malloc(184320): kmem_map too small: 84426752 total allocated + */ + rl.rlim_max = rl.rlim_cur = 0; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + warn("setrlimit"); + + setproctitle("#%d", num); + + return (0); +} + +void +cleanup(void) +{ + if (starting_dir != 0) { + if (fchdir(starting_dir) == -1) + err(1, "fchdir()"); + (void)system("find . -type d -exec chmod 777 {} \\;"); + (void)system("find . -type f -exec chmod 666 {} \\;"); + (void)system("find . -delete"); + + if (chdir("..") == -1) + err(1, "chdir(..)"); + if (rmdir(path) == -1) + err(1, "rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } + starting_dir = 0; +} + +void +rainit(void) +{ + int i, j; + + for (i = 0; i < 7; i++) { + for (j = 0; j < 10; j++) { + if (arc4random() % 100 > 20) + rb[i][j] = arc4random(); + else + rb[i][j] = (uint32_t) &rb[i][j]; + } + } +} + +uint32_t +ra(int i) +{ + uint32_t r; + + r = arc4random(); + if ((r & 1) == 0) + r = arc4random(); + else + r = (uint32_t) &rb[i][0]; + + return (r); +} + +int +test(void) +{ + int i; + unsigned int arg1, arg2, arg3, arg4, arg5, arg6, arg7; + + for (i = 0; i < 128; i++) { + rainit(); + arg1 = ra(0); + arg2 = ra(1); + arg3 = ra(2); + arg4 = ra(3); + arg5 = ra(4); + arg6 = ra(5); + arg7 = ra(6); + + if (op->verbose > 3) + printf("%2d : syscall(%3d, %x, %x, %x, %x, %x, %x, %x)\n", + i, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + return (0); +} diff --git a/test/stress/stress2/misc/tmpfs.sh b/test/stress/stress2/misc/tmpfs.sh new file mode 100755 index 0000000000..25c3deadb9 --- /dev/null +++ b/test/stress/stress2/misc/tmpfs.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# +# $Id: nfs.sh,v 1.2 2008/02/25 16:31:43 pho Exp $ +# + +# panic: tmpfs_alloc_vp: type 0xc866ce58 0, seen. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q tmpfs && umount $mntpoint +mount -t tmpfs tmpfs $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=10m # Run tests for 10 minutes + +(cd /home/pho/stress2; ./run.sh marcus.cfg) + +umount $mntpoint +mount | grep "$mntpoint" | grep -q tmpfs && umount -f $mntpoint diff --git a/test/stress/stress2/misc/tmpfs2.sh b/test/stress/stress2/misc/tmpfs2.sh new file mode 100755 index 0000000000..af696c9c2f --- /dev/null +++ b/test/stress/stress2/misc/tmpfs2.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# +# $Id: crossmp.sh,v 1.2 2008/02/25 16:31:43 pho Exp $ +# + +# panic: vfs_mount_destroy: nonzero writeopcount, seen. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$MDSTART # Use md unit numbers from this point +D=$DISKIMAGE + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + done + + # start the parallel tests + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done + +else + if [ $1 = find ]; then + for i in `jot 1024`; do + find ${mntpoint}* -type f > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 1024`; do + m=$1 + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + mount -t tmpfs tmpfs ${mntpoint}$m + cp -r /usr/include/machine/a* ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + opt=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + fi +fi diff --git a/test/stress/stress2/misc/tmpfs3.sh b/test/stress/stress2/misc/tmpfs3.sh new file mode 100755 index 0000000000..268a5e669c --- /dev/null +++ b/test/stress/stress2/misc/tmpfs3.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# +# $Id: nfs.sh,v 1.2 2008/02/25 16:31:43 pho Exp $ +# + +# panic: tmpfs_alloc_vp: type 0xc866ce58 0, seen. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q tmpfs && umount $mntpoint +mount -t tmpfs tmpfs $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=10m # Run tests for 10 minutes + +(cd /home/pho/stress2; ./run.sh vfs.cfg) + +umount $mntpoint +mount | grep "$mntpoint" | grep -q tmpfs && umount -f $mntpoint diff --git a/test/stress/stress2/misc/tmpfs4.sh b/test/stress/stress2/misc/tmpfs4.sh new file mode 100755 index 0000000000..2bff3dcba6 --- /dev/null +++ b/test/stress/stress2/misc/tmpfs4.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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. +# +# $Id: nfs.sh,v 1.2 2008/02/25 16:31:43 pho Exp $ +# + +# Regression test from kern/122038 by gprspb mail ru + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mount | grep "$mntpoint" | grep -q tmpfs && umount $mntpoint +mount -t tmpfs tmpfs $mntpoint + +for i in `jot 100`; do + mkdir -p /${mntpoint}/1/2 + cd /${mntpoint}/1/2 + rm -rf /${mntpoint}/1 + cd .. 2>&1 | grep -v "cd to" +done + + +umount $mntpoint 2>&1 | grep -v busy +mount | grep "$mntpoint" | grep -q tmpfs && umount -f $mntpoint diff --git a/test/stress/stress2/misc/truncate.sh b/test/stress/stress2/misc/truncate.sh new file mode 100755 index 0000000000..b60fc9ac27 --- /dev/null +++ b/test/stress/stress2/misc/truncate.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Test high water mark for freeblks + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > truncate.c +cc -o truncate -Wall -O2 truncate.c +rm -f truncate.c +[ -d $RUNDIR ] || mkdir -p $RUNDIR +cd $RUNDIR + +/tmp/truncate + +rm -f /tmp/truncate +exit 0 +EOF +#include +#include +#include +#include +#include +#include + +#define SIZ 512 +char buf[SIZ]; + +void +test(void) +{ + int fd[10], i, j; + char name[128]; + + for (j = 0; j < 10; j++) { + sprintf(name, "%05d.%05d", getpid(), j); + if ((fd[j] = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1) + err(1, name); + unlink(name); + } + + for (i = 0; i < 100000; i++) { + for (j = 0; j < 10; j++) { + if (write(fd[j], buf, 2) != 2) + err(1, "write"); + if (ftruncate(fd[j], 0) == -1) + err(1, "ftruncate"); + } + } + + exit(0); +} +int +main(int argc, char **argv) +{ + int i, status; + + for (i = 0; i < 20; i++) { + if (fork() == 0) + test(); + } + for (i = 0; i < 20; i++) + wait(&status); + + return (0); +} diff --git a/test/stress/stress2/misc/truncate2.sh b/test/stress/stress2/misc/truncate2.sh new file mode 100755 index 0000000000..51a8f61ec0 --- /dev/null +++ b/test/stress/stress2/misc/truncate2.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > truncate2.c +cc -o truncate2 -Wall -O2 truncate2.c +rm -f truncate2.c +[ -d $RUNDIR ] || mkdir -p $RUNDIR +cd $RUNDIR + +/tmp/truncate2 & + +sleep 1 +while ps | grep -v grep | egrep -q "truncate2$"; do + $here/../testcases/swap/swap -t 2m -i 20 +done + +rm -f /tmp/truncate2 +exit 0 +EOF +#include +#include +#include +#include +#include +#include + +#define SIZ 512 +char buf[SIZ]; + +void +test(void) +{ + int fd[10], i, j; + char name[128]; + off_t len; + + for (j = 0; j < 10; j++) { + sprintf(name, "%05d.%05d", getpid(), j); + fd[j] = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd[j] == -1) + err(1, name); + unlink(name); + } + + for (i = 0; i < 100; i++) { + for (j = 0; j < 10; j++) { + if (write(fd[j], buf, 2) != 2) + err(1, "write"); + len = arc4random() % 1024 * 1024; + if (ftruncate(fd[j], len) == -1) + err(1, "ftruncate"); + } + } + + exit(0); +} +int +main(int argc, char **argv) +{ + int i, status; + + for (i = 0; i < 20; i++) { + if (fork() == 0) + test(); + } + for (i = 0; i < 20; i++) + wait(&status); + + return (0); +} diff --git a/test/stress/stress2/misc/ucom.sh b/test/stress/stress2/misc/ucom.sh new file mode 100755 index 0000000000..4ea67748a1 --- /dev/null +++ b/test/stress/stress2/misc/ucom.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test disconnecting busy UCOM USB serial dongle + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +tst () { + for i in `jot 10`; do + [ -r /dev/cuaU0 ] && break + sleep 1 + done + echo $1 + (eval "$@")& + sleep 10 + ps | grep -qw $! && kill $! +} + +if [ $# -eq 0 ]; then + ( + while true; do + pstat -t > /dev/null + sleep 1 + done + ) & + pid=$! +fi + + +tst "cat < /dev/ttyU0" +tst "cat < /dev/cuaU0" + +tst "cu -l /dev/cuaU0" +tst "cu -l /dev/ttyU0" + +tst "stty -a -f /dev/ttyU0" +tst "stty -a < /dev/ttyU0" +tst "stty -f /dev/ttyU0 -a" +tst "tail -F /dev/ttyU0" +tst "tail /dev/ttyU0" + +[ ! -z "$pid" ] && kill $pid diff --git a/test/stress/stress2/misc/umount.sh b/test/stress/stress2/misc/umount.sh new file mode 100755 index 0000000000..b6e6ae8c97 --- /dev/null +++ b/test/stress/stress2/misc/umount.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test "umount" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 110 || exit 1 + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint +export RUNDIR=$mntpoint/stressX +export runRUNTIME=3m # Run tests for three minutes +(cd /home/pho/stress2; ./run.sh vfs.cfg) +umount $mntpoint +mdconfig -d -u ${mdstart} +rm -f $D diff --git a/test/stress/stress2/misc/umountf.sh b/test/stress/stress2/misc/umountf.sh new file mode 100755 index 0000000000..49f75cbb83 --- /dev/null +++ b/test/stress/stress2/misc/umountf.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test problems with "umount -f" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 110 || exit 1 + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs md${mdstart}${part} +mount /dev/md${mdstart}${part} $mntpoint + +export RUNDIR=$mntpoint/stressX +export runRUNTIME=2m +cd /home/pho/stress2; ./run.sh vfs.cfg & +pid=$! + +sleep 30 + +umount -f $mntpoint +mdconfig -d -u $mdstart +rm -f $D + +while ps | egrep "testcases|swap|mkdir|creat" | grep -vq grep; do + ps | egrep "testcases|swap|mkdir|creat" | grep -v grep | awk '{print $1}' | xargs kill + sleep 1 +done diff --git a/test/stress/stress2/misc/umountf2.sh b/test/stress/stress2/misc/umountf2.sh new file mode 100755 index 0000000000..7740068412 --- /dev/null +++ b/test/stress/stress2/misc/umountf2.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Test scenario by kris@freebsd.org + +# Test problems with "umount -f and fsx. Results in a "KDB: enter: watchdog timeout" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +fsxc=`find / -name fsx.c | tail -1` +[ -z "fsxc" ] && exit + +cc -o /tmp/fsx $fsxc + +. ../default.cfg + +D=$diskimage +dede $D 1m 1k || exit 1 + +mount | grep "$mntpoint" | grep md${mdstart}${part} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs md${mdstart}${part} > /dev/null 2>&1 +mount /dev/md${mdstart}${part} $mntpoint +df -ih $mntpoint +sleep 5 +for i in `jot 100`; do + /tmp/fsx -S $i -q ${mntpoint}/xxx$i & +done +sleep 30 +umount -f $mntpoint& +sleep 300 +killall fsx +sleep 5 +ls -l ${mntpoint} +mdconfig -d -u $mdstart +rm -f $D +ls -l $mntpoint diff --git a/test/stress/stress2/misc/umountf3.sh b/test/stress/stress2/misc/umountf3.sh new file mode 100755 index 0000000000..596ded0317 --- /dev/null +++ b/test/stress/stress2/misc/umountf3.sh @@ -0,0 +1,122 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Demonstrate livelock with "umount -f" seen both with UFS and MSDOS + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +D=$diskimage +dede $D 1m 1k || exit 1 + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > umountf3.c +cc -o umountf3 -Wall umountf3.c +rm -f umountf3.c +cd $odir + + +mount | grep "$mntpoint" | grep md${mdstart} > /dev/null && umount $mntpoint +mdconfig -l | grep md${mdstart} > /dev/null && mdconfig -d -u ${mdstart} + +mdconfig -a -t vnode -f $D -u ${mdstart} +bsdlabel -w md${mdstart} auto +newfs md${mdstart}${part} > /dev/null 2>&1 +mount /dev/md${mdstart}${part} $mntpoint +#newfs_msdos -F 32 -b 8192 /dev/md${mdstart}a +#mount -t msdosfs /dev/md${mdstart}a $mntpoint +export RUNDIR=$mntpoint/stressX +for i in `jot 25`; do + (cd /$mntpoint; /tmp/umountf3) & +done +sleep $((4 * 60)) +echo "umount -f $mntpoint" +umount -f $mntpoint +mdconfig -d -u $mdstart +rm -f $D /tmp/umountf3 +exit +EOF + +#include +#include +#include +#include +#include +#include +#include + +static unsigned long size = 1024 * 1024 * 2; + +int +main(int argc, char **argv) +{ + int buf[1024], index, to, n; + int fd; + char file[128]; + + + sprintf(file,"p%06d", getpid()); + if ((fd = open(file, O_CREAT | O_RDWR, 0666)) == -1) + err(1, "creat(%s)", file); + + to = sizeof(buf); + for (;;) { + index = 0; + while (index < size) { + if (index + to > size) + to = size - index; + index += to; + if (write(fd, buf, to) != to) + err(1, "write(%s), %s:%d", file, __FILE__, __LINE__); + } + + if (lseek(fd, 0, 0) == -1) + err(1, "lseek"); + index = 0; + while (index < size) { + if (index + to > size) + to = size - index; + if ((n = read(fd, buf, to)) != to) + err(1, "rw read(%d, %d, %d). %s.%d", n, to, index, __FILE__, __LINE__); + index += to; + } + if (lseek(fd, 0, 0) == -1) + err(1, "lseek"); + } + + if (close(fd) == -1) + err(1, "close(%s), %s:%d", file, __FILE__, __LINE__); + if (unlink(file) == -1) + err(1, "unlink(%s), %s:%d", file, __FILE__, __LINE__); + return (0); +} diff --git a/test/stress/stress2/misc/umountf4.sh b/test/stress/stress2/misc/umountf4.sh new file mode 100755 index 0000000000..d7c57ea77d --- /dev/null +++ b/test/stress/stress2/misc/umountf4.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Found: Fatal trap 12: page fault while in kernel mode + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point +D=$diskimage + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + mdconfig -l | grep -q md$m && mdconfig -d -u $m + + dede $D$m 1m 10 + mdconfig -a -t vnode -f $D$m -u $m + bsdlabel -w md$m auto + newfs md${m}${part} > /dev/null 2>&1 + done + + # start the parallel tests + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find & + done + + for i in `jot $mounts`; do + wait; wait + done + + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + mdconfig -d -u $m + rm -f $D$m + done + +else + if [ $1 = find ]; then + for i in `jot 100`; do + find ${mntpoint}* -type f > /dev/null 2>&1 + done + else + + # The test: Parallel mount and unmounts + for i in `jot 100`; do + m=$1 + opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` + mount $opt /dev/md${m}${part} ${mntpoint}$m + cp -r /usr/include/machine/a* ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + umount -f ${mntpoint}$m > /dev/null 2>&1 + done + done + fi +fi diff --git a/test/stress/stress2/misc/union.sh b/test/stress/stress2/misc/union.sh new file mode 100755 index 0000000000..c02dac6e6a --- /dev/null +++ b/test/stress/stress2/misc/union.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple union test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +u1=$mdstart +u2=$((u1 + 1)) +[ -d mp1 ] || mkdir mp1 + +mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part +mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 + +mdconfig -s 256m -u $u1 +bsdlabel -w md$u1 auto +newfs md${u1}${part} > /dev/null + +mdconfig -s 256m -u $u2 +bsdlabel -w md$u2 auto +newfs md${u2}${part} > /dev/null + +mount -o ro /dev/md${u1}$part mp1 +mount -o union /dev/md${u2}$part mp1 + +export RUNDIR=`pwd`/mp1/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +umount /dev/md${u2}$part +umount /dev/md${u1}$part + +mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part +mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part + +mdconfig -d -u $u2 +mdconfig -d -u $u1 + +rm -rf mp1 diff --git a/test/stress/stress2/misc/unionfs.sh b/test/stress/stress2/misc/unionfs.sh new file mode 100755 index 0000000000..68f7c5ebde --- /dev/null +++ b/test/stress/stress2/misc/unionfs.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Causes this: panic: mutex Giant not owned at ../../../kern/vfs_subr.c:1968 +# with a kernel compiled with "options QUOTA" + +D=/usr/tmp/diskimage +truncate -s 256M $D + +mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt +mdconfig -l | grep md0 > /dev/null && mdconfig -d -u 0 + +mdconfig -a -t vnode -f $D -u 0 +bsdlabel -w md0 auto +newfs -U md0c > /dev/null +mount /dev/md0c /mnt +mount -t unionfs -o noatime /mnt /tmp +export RUNDIR=/tmp/stressX +export runRUNTIME=10m # Run tests for 10 minutes +(cd /home/pho/stress2; ./run.sh disk.cfg) +mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt +mount | grep "/mnt" | grep md0c > /dev/null && umount -f /mnt +mdconfig -d -u 0 +rm -f $D diff --git a/test/stress/stress2/misc/unionfs2.sh b/test/stress/stress2/misc/unionfs2.sh new file mode 100755 index 0000000000..5960082d95 --- /dev/null +++ b/test/stress/stress2/misc/unionfs2.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +saved=`sysctl vfs.lookup_shared | awk '{print $NF}'` +for i in 1 0; do + sysctl vfs.lookup_shared=$i + [ -d /var/tmp/unionfs ] || mkdir -p /var/tmp/unionfs + mount_unionfs /var/tmp/unionfs /tmp/stressX + + export RUNDIR=/var/tmp/unionfs/stressX + export runRUNTIME=10m # Run tests for 10 minutes + (cd /home/pho/stress2; ./run.sh disk.cfg) + false + while mount | grep -q /unionfs; do + umount /tmp/stressX > /dev/null 2>&1 + done + rm -rf /var/tmp/unionfs +done +sysctl vfs.lookup_shared=$saved diff --git a/test/stress/stress2/misc/unionfs3.sh b/test/stress/stress2/misc/unionfs3.sh new file mode 100755 index 0000000000..f3cd77b492 --- /dev/null +++ b/test/stress/stress2/misc/unionfs3.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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 + +# Test with interchanged arguments to mount_unionfs +# Causes page fault in vfs_mount.c:1975 + +D=/usr/tmp/diskimage +truncate -s 256M $D + +mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt +mdconfig -l | grep md0 > /dev/null && mdconfig -d -u 0 + +mdconfig -a -t vnode -f $D -u 0 +bsdlabel -w md0 auto +newfs -U md0c > /dev/null +mount /dev/md0c /mnt +mount -t unionfs -o noatime /tmp /mnt +umount -f /tmp # panic +mount /tmp +mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt +mount | grep "/mnt" | grep md0c > /dev/null && umount -f /mnt +mdconfig -d -u 0 +rm -f $D diff --git a/test/stress/stress2/misc/zfs.sh b/test/stress/stress2/misc/zfs.sh new file mode 100755 index 0000000000..6c91fc2967 --- /dev/null +++ b/test/stress/stress2/misc/zfs.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple zfs raidz test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q zfs.ko || kldload zfs.ko + +u1=$mdstart +u2=$((u1 + 1)) +u3=$((u2 + 1)) + +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 +mdconfig -l | grep -q md${u3} && mdconfig -d -u $u3 + +mdconfig -s 512m -u $u1 +mdconfig -s 512m -u $u2 +mdconfig -s 512m -u $u3 + +zpool create tank raidz md$u1 md$u2 md$u3 +zfs create tank/test + +export RUNDIR=/tank/test/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +zfs destroy -r tank +zpool destroy tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 +mdconfig -d -u $u3 diff --git a/test/stress/stress2/misc/zfs2.sh b/test/stress/stress2/misc/zfs2.sh new file mode 100755 index 0000000000..82414e5d5c --- /dev/null +++ b/test/stress/stress2/misc/zfs2.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple zfs mirror test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q zfs.ko || kldload zfs.ko + +d1=${diskimage}.1 +d2=${diskimage}.2 + +dd if=/dev/zero of=$d1 bs=1m count=1k 2>&1 | egrep -v "records|transferred" +dd if=/dev/zero of=$d2 bs=1m count=1k 2>&1 | egrep -v "records|transferred" + +u1=$mdstart +u2=$((u1 + 1)) + +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 + +mdconfig -a -t vnode -f $d1 -u $u1 +mdconfig -a -t vnode -f $d2 -u $u2 + +zpool create tank mirror md$u1 md$u2 + +export RUNDIR=/tank/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +zfs destroy -r tank +zpool destroy tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 + +rm -rf $d1 $d2 diff --git a/test/stress/stress2/misc/zfs3.sh b/test/stress/stress2/misc/zfs3.sh new file mode 100755 index 0000000000..aac53df949 --- /dev/null +++ b/test/stress/stress2/misc/zfs3.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple zfs snapshot test scenario + +# page fault from fs/zfs/dbuf.c:1807 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q zfs.ko || kldload zfs.ko + +d1=${diskimage}.1 +d2=${diskimage}.2 + +dd if=/dev/zero of=$d1 bs=1m count=1k 2>&1 | egrep -v "records|transferred" +dd if=/dev/zero of=$d2 bs=1m count=1k 2>&1 | egrep -v "records|transferred" + +u1=$mdstart +u2=$((u1 + 1)) + +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 + +mdconfig -a -t vnode -f $d1 -u $u1 +mdconfig -a -t vnode -f $d2 -u $u2 + +zpool create tank md$u1 md$u2 +zfs create tank/test +zfs set quota=800m tank/test +zfs snapshot tank/test@snap1 + +export RUNDIR=/tank/test/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) + +zfs rollback tank/test@snap1 +zfs destroy tank/test@snap1 + +zfs destroy -r tank +zpool destroy tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 + +rm -rf $d1 $d2 diff --git a/test/stress/stress2/misc/zfs4.sh b/test/stress/stress2/misc/zfs4.sh new file mode 100755 index 0000000000..8d9848ba27 --- /dev/null +++ b/test/stress/stress2/misc/zfs4.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple zfs snapshot test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q zfs.ko || kldload zfs.ko + +d1=${diskimage}.1 +d2=${diskimage}.2 + +dd if=/dev/zero of=$d1 bs=1m count=1k 2>&1 | egrep -v "records|transferred" +dd if=/dev/zero of=$d2 bs=1m count=1k 2>&1 | egrep -v "records|transferred" + +u1=$mdstart +u2=$((u1 + 1)) + +mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1 +mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2 + +mdconfig -a -t vnode -f $d1 -u $u1 +mdconfig -a -t vnode -f $d2 -u $u2 + +zpool create tank md$u1 md$u2 +zfs create tank/test +zfs set quota=100m tank/test +zfs set snapdir=visible tank/test + +export RUNDIR=/tank/test/stressX +export runRUNTIME=10m +(cd ..; ./run.sh marcus.cfg) & + +for i in `jot 20`; do + zfs snapshot tank/test@snap$i +done +for i in `jot 20`; do + zfs destroy tank/test@snap$i +done +wait + +zfs destroy -r tank +zpool destroy tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 + +rm -rf $d1 $d2 diff --git a/test/stress/stress2/misc/zfs5.sh b/test/stress/stress2/misc/zfs5.sh new file mode 100755 index 0000000000..b3f5a15e17 --- /dev/null +++ b/test/stress/stress2/misc/zfs5.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# +# Copyright (c) 2009 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$ +# + +# Simple zfs test of vdev as a file and snapshot clones + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +kldstat -v | grep -q zfs.ko || kldload zfs.ko + +d1=${diskimage}.1 +d2=${diskimage}.2 + +dd if=/dev/zero of=$d1 bs=1m count=1k 2>&1 | egrep -v "records|transferred" +dd if=/dev/zero of=$d2 bs=1m count=1k 2>&1 | egrep -v "records|transferred" + +zpool create tank $d1 $d2 +zfs create tank/test +zfs set quota=100m tank/test + +export RUNDIR=/tank/test/stressX +export runRUNTIME=10m +(cd ..; ./run.sh vfs.cfg) & + +for i in `jot 20`; do + zfs snapshot tank/test@snap$i + zfs clone tank/test@snap$i tank/snap$i +done +for i in `jot 20`; do + zfs destroy tank/snap$i + zfs destroy tank/test@snap$i +done +wait + +zfs destroy -r tank +zpool destroy tank + +rm -rf $d1 $d2 diff --git a/test/stress/stress2/mkdir.cfg b/test/stress/stress2/mkdir.cfg new file mode 100644 index 0000000000..45d5153d85 --- /dev/null +++ b/test/stress/stress2/mkdir.cfg @@ -0,0 +1,11 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/mkdir/mkdir" +export mkdirNODELAY=1 +export mkdirLOAD=100 +export mkdirRUNTIME=2m diff --git a/test/stress/stress2/mkfifo.cfg b/test/stress/stress2/mkfifo.cfg new file mode 100644 index 0000000000..978bd1df2a --- /dev/null +++ b/test/stress/stress2/mkfifo.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/mkfifo/mkfifo testcases/swap/swap" +export mkfifoNODELAY=1 +export mkfifoLOAD=100 diff --git a/test/stress/stress2/norw.cfg b/test/stress/stress2/norw.cfg new file mode 100644 index 0000000000..969da9ef9c --- /dev/null +++ b/test/stress/stress2/norw.cfg @@ -0,0 +1,8 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export rwLOAD=0 diff --git a/test/stress/stress2/noswap.cfg b/test/stress/stress2/noswap.cfg new file mode 100644 index 0000000000..cb93966674 --- /dev/null +++ b/test/stress/stress2/noswap.cfg @@ -0,0 +1,8 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export swapLOAD=0 diff --git a/test/stress/stress2/orangutan.netperf.freebsd.org b/test/stress/stress2/orangutan.netperf.freebsd.org new file mode 100644 index 0000000000..ccbdbd65cb --- /dev/null +++ b/test/stress/stress2/orangutan.netperf.freebsd.org @@ -0,0 +1,17 @@ +# $FreeBSD$ + +# Configuration needed for the orangutan test box + +RUNDIR=/m2/stressX +KBLOCKS=`df -ik $RUNDIR | tail -1 | awk '{print $4}` +INODES=`df -ik $RUNDIR | tail -1 | awk '{print $7}` + +BLASTHOST=127.0.0.1 + +DISKIMAGE=/m2/diskimage # Location of 1G disk image +MNTPOINT=/m2 # Disk image mount point +TESTUSER=test # Name of non root test user +MDSTART=5 # Start of free md units + +TZ=Europe/Copenhagen; export TZ +SHELL=/bin/sh diff --git a/test/stress/stress2/pty.cfg b/test/stress/stress2/pty.cfg new file mode 100644 index 0000000000..a776e7ad39 --- /dev/null +++ b/test/stress/stress2/pty.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/pty/pty" +export ptyNODELAY=1 +export ptyLOAD=100 diff --git a/test/stress/stress2/run.sh b/test/stress/stress2/run.sh new file mode 100755 index 0000000000..3c53fb5f85 --- /dev/null +++ b/test/stress/stress2/run.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Run 1) with no argument: the default test cases +# 2) with the "-a" arguments all the *.cfg test variations +# 3) with one argument: that specific test case + +while getopts a name; do + case $name in + a) aflag=1;; + ?) printf "Usage: %s: [-a] [arg]\n" $0 + exit 2;; + esac +done +shift $(($OPTIND - 1)) + +. ./default.cfg +if [ ! -z "$aflag" ]; then + export runRUNTIME=5m + t1=`date '+%s'` + while true;do + for i in `ls *.cfg | grep -v default`; do + t2=`date '+%s'` +# e=` date -u -j -f '%s' '+%T' $((t2 - t1))` +# echo "`date '+%Y%m%d %T'` $i, elapsed $e" | tee /dev/tty >> /tmp/all.log + echo "`date '+%Y%m%d %T'` $i, elapsed $((t2 - t1))s" | tee /dev/tty >> /tmp/all.log + logger "Starting test $i" + $0 $i + done + [ "`id -un`" = pho ] && ipcs | \ + awk '$5 ~/pho/ && $6 ~/pho/ {print "-" $1,$2}' | xargs ipcrm + done +else + CONFIG=./default.cfg + if [ $# -eq 1 ]; then + [ ! -r $1 ] && echo "$0: $1 not found!" && exit 1 + CONFIG=$1 + fi + . $CONFIG + + [ -z "$RUNDIR" ] && echo "$0: RUNDIR is unset!" && exit 1 + [ `basename $RUNDIR` != stressX ] && \ + echo "$0: Basename of RUNDIR must be stressX!" && exit 2 + [ -d "$RUNDIR" ] && (cd $RUNDIR && find . -delete) + + [ -z "$EXCLUDETESTS" ] && EXCLUDETESTS=DuMmY + + [ -z "$TESTPROGS" ] && \ + TESTPROGS=`find testcases/ -perm -1 -type f | egrep -v "/run/|$EXCLUDETESTS"` + #LD_PRELOAD=/usr/local/lib/libefence.so.0 ./testcases/run/run $TESTPROGS + ./testcases/run/run $TESTPROGS +fi diff --git a/test/stress/stress2/rw.cfg b/test/stress/stress2/rw.cfg new file mode 100644 index 0000000000..8e5720c6fe --- /dev/null +++ b/test/stress/stress2/rw.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export TESTPROGS="testcases/rw/rw" +export rwNODELAY=1 +export rwLOAD=100 diff --git a/test/stress/stress2/syscall.cfg b/test/stress/stress2/syscall.cfg new file mode 100644 index 0000000000..5f45a80f8a --- /dev/null +++ b/test/stress/stress2/syscall.cfg @@ -0,0 +1,13 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export RUNTIME=15s +export TESTPROGS="testcases/swap/swap testcases/syscall/syscall" + +export syscallKILL=1 +export syscallNODELAY=1 +export syscallLOAD=100 diff --git a/test/stress/stress2/sysctl.cfg b/test/stress/stress2/sysctl.cfg new file mode 100644 index 0000000000..4030ff090d --- /dev/null +++ b/test/stress/stress2/sysctl.cfg @@ -0,0 +1,14 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +export RUNTIME=15s +export TESTPROGS="testcases/swap/swap testcases/sysctl/sysctl testcases/mmap/mmap" + +export sysctlKILL=1 +export sysctlNODELAY=1 +export sysctlLOAD=100 +export mmapLOAD=100 diff --git a/test/stress/stress2/testcases/Makefile b/test/stress/stress2/testcases/Makefile new file mode 100644 index 0000000000..8c537c36ac --- /dev/null +++ b/test/stress/stress2/testcases/Makefile @@ -0,0 +1,29 @@ +# $FreeBSD$ + +SUBDIR= \ +badcode \ +creat \ +fts \ +link \ +lockf \ +lockf2 \ +mkdir \ +mkfifo \ +mmap \ +openat \ +pty \ +rename \ +run \ +rw \ +shm \ +socket \ +swap \ +symlink \ +syscall \ +sysctl \ +tcp \ +thr1 \ +thr2 \ +udp + +.include diff --git a/test/stress/stress2/testcases/Makefile.inc b/test/stress/stress2/testcases/Makefile.inc new file mode 100644 index 0000000000..200a353c5d --- /dev/null +++ b/test/stress/stress2/testcases/Makefile.inc @@ -0,0 +1,8 @@ +# $FreeBSD$ + +NO_MAN= +NO_OBJ= noobj +LDADD+= -L../../lib -lstress -lutil +DPADD+= ../../lib/libstress.a +CFLAGS =-g -Wall -I../../include -I../include +NOMAN= sorry diff --git a/test/stress/stress2/testcases/README b/test/stress/stress2/testcases/README new file mode 100644 index 0000000000..2a025c17e7 --- /dev/null +++ b/test/stress/stress2/testcases/README @@ -0,0 +1,11 @@ +$FreeBSD$ + +All test programs must implement these three procedures: + +int setup(int nb) +void cleanup(void) +int test(void) + +The setup() procedure is called once before test() is called multiple times +until timeout. After timeout cleanup() is called. +test() should periodically test the global variable done_testing and return. diff --git a/test/stress/stress2/testcases/badcode/Makefile b/test/stress/stress2/testcases/badcode/Makefile new file mode 100644 index 0000000000..8abcbb90a7 --- /dev/null +++ b/test/stress/stress2/testcases/badcode/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= badcode + +.include diff --git a/test/stress/stress2/testcases/badcode/badcode.c b/test/stress/stress2/testcases/badcode/badcode.c new file mode 100644 index 0000000000..2974ffa783 --- /dev/null +++ b/test/stress/stress2/testcases/badcode/badcode.c @@ -0,0 +1,121 @@ +/* + * COPYRIGHT (c) 1990 BY * + * GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. * + * ALL RIGHTS RESERVED * + +Permission to use, copy, modify, distribute and sell this software +and its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all copies +and that both that copyright notice and this permission notice appear +in supporting documentation, and that the name of the author +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +This code is based on crashme.c + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define BUFS 64 + +char buf [BUFS]; +pid_t pid; + +void (*sub)(); + +void +proto(void) { + int i = 2; + printf("Hello, world (%d)\n", i); + return; +} + +void +alter(void) { /* Change one byte in the code */ + int i; + i = random() % BUFS; + buf[i] = random() & 0xff; +} + +void +hand(int i) { /* alarm handler */ + if (pid != 0) { + kill(pid, SIGHUP); + kill(pid, SIGKILL); + } + exit(1); +} + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + pid_t pid; + int i, status; + + for (i = 0; i < 512; i++) { + if (i % 10 == 0) + bcopy(proto, buf, BUFS); + alter(); + + if ((pid = fork()) == 0) { + signal(SIGALRM, hand); +#if 0 + signal(SIGILL, hand); + signal(SIGFPE, hand); + signal(SIGSEGV, hand); + signal(SIGBUS, hand); + signal(SIGURG, hand); + signal(SIGSYS, hand); + signal(SIGTRAP, hand); +#endif + alarm(2); + + (*sub)(); + + exit(EXIT_SUCCESS); + + } else if (pid > 0) { + signal(SIGALRM, hand); + alarm(3); + if (waitpid(pid, &status, 0) == -1) + warn("waitpid(%d)", pid); + alarm(0); + kill(pid, SIGINT); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + } + + return (0); +} diff --git a/test/stress/stress2/testcases/creat/Makefile b/test/stress/stress2/testcases/creat/Makefile new file mode 100644 index 0000000000..0cac1bdd78 --- /dev/null +++ b/test/stress/stress2/testcases/creat/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=creat + +.include diff --git a/test/stress/stress2/testcases/creat/creat.c b/test/stress/stress2/testcases/creat/creat.c new file mode 100644 index 0000000000..236eb87a7e --- /dev/null +++ b/test/stress/stress2/testcases/creat/creat.c @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static unsigned long size; + +int +setup(int nb) +{ + int pct; + int64_t in; + int64_t bl; + int64_t reserve_in; + int64_t reserve_bl; + + + umask(0); + path[0] = 0; + if (nb == 0) { + getdf(&bl, &in); + size = in / op->incarnations; + + pct = 90; + if (op->hog == 0) + pct = random_int(1, 90); + size = size / 100 * pct + 1; + + if (size > 20000) + size = 20000; /* arbitrary limit number of files pr. dir */ + if (size > 1000) + size = 1000; /* XXX Soft Update */ + + /* Resource requirements: */ + while (size > 0) { + reserve_in = 1 * size * op->incarnations + size; + reserve_bl = 29 * size * op->incarnations; +// printf("size = %lu, reserve(%jd, %jd)\n", size, reserve_bl/1024, reserve_in); + if (reserve_bl <= bl && reserve_in <= in) + break; + size--; + } + if (size == 0) + reserve_bl = reserve_in = 0; + + if (op->verbose > 1) + printf("creat(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + } else { + size = getval(); + } + + if (size == 0) + exit(1); + sprintf(path,"%s.%05d", getprogname(), getpid()); + if (mkdir(path, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path, __FILE__, __LINE__); + + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + + return (0); +} + +void +cleanup(void) +{ + (void)chdir(".."); + if (path[0] != 0 && rmdir(path) == -1) { + warn("rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } +} + +int +test(void) +{ + int fd, i, j; + pid_t pid; + char file[128]; + + pid = getpid(); + for (j = 0; j < size && done_testing == 0; j++) { + sprintf(file,"p%05d.%05d", pid, j); + if ((fd = creat(file, 0660)) == -1) { + if (errno != EINTR) { + warn("creat(%s). %s:%d", file, __FILE__, __LINE__); + break; + } + } + if (fd != -1 && close(fd) == -1) + err(2, "close(%d)", j); + + } + + for (i = --j; i >= 0; i--) { + sprintf(file,"p%05d.%05d", pid, i); + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + + } + + return (0); +} diff --git a/test/stress/stress2/testcases/fts/Makefile b/test/stress/stress2/testcases/fts/Makefile new file mode 100644 index 0000000000..9b29d27cd6 --- /dev/null +++ b/test/stress/stress2/testcases/fts/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= fts + +.include diff --git a/test/stress/stress2/testcases/fts/fts.c b/test/stress/stress2/testcases/fts/fts.c new file mode 100644 index 0000000000..80750cce2d --- /dev/null +++ b/test/stress/stress2/testcases/fts/fts.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Directory scan */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + + FTS *fts; + FTSENT *p; + int ftsoptions; + char *args[2]; + + ftsoptions = 0; + args[0] = "."; + args[1] = 0; + + if ((fts = fts_open(args, ftsoptions, NULL)) == NULL) + err(1, "fts_open"); + + while ((p = fts_read(fts)) != NULL) { + if (op->verbose > 1) + (void) printf("%s\n", p->fts_path); + switch (p->fts_info) { + case FTS_F: /* Ignore. */ + break; + case FTS_D: /* Ignore. */ + break; + case FTS_DP: + break; + case FTS_DC: /* Ignore. */ + break; + case FTS_SL: /* Ignore. */ + break; + case FTS_DNR: /* Warn, continue. */ + case FTS_ERR: + case FTS_NS: + case FTS_DEFAULT: + if (op->verbose > 1) + warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); + break; + default: + printf("%s: default, %d\n", getprogname(), p->fts_info); + break; + } + } + + if (errno != 0 && errno != ENOENT) + err(1, "fts_read"); + if (fts_close(fts) == -1) + err(1, "fts_close()"); + + return (0); +} diff --git a/test/stress/stress2/testcases/link/Makefile b/test/stress/stress2/testcases/link/Makefile new file mode 100644 index 0000000000..a466747f91 --- /dev/null +++ b/test/stress/stress2/testcases/link/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=link + +.include diff --git a/test/stress/stress2/testcases/link/link.c b/test/stress/stress2/testcases/link/link.c new file mode 100644 index 0000000000..fba4083045 --- /dev/null +++ b/test/stress/stress2/testcases/link/link.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static unsigned long size; + +int +setup(int nb) +{ + int pct; + int64_t in; + int64_t bl; + int64_t reserve_in; + int64_t reserve_bl; + + umask(0); + path[0] = 0; + if (nb == 0) { + getdf(&bl, &in); + size = in / op->incarnations; + + pct = 90; + if (op->hog == 0) + pct = random_int(1, 90); + size = size / 100 * pct + 1; + + if (size > 20000 && op->hog == 0) + size = 20000; /* arbitrary limit number of files pr. dir */ + if (size > LINK_MAX) + size = LINK_MAX; + + + /* Resource requirements: */ + reserve_in = 2 * op->incarnations + 1; + reserve_bl = 26 * size * op->incarnations; + if (reserve_bl > bl) + size = bl / 26 * op->incarnations; + if (reserve_in > in) + size = reserve_in = reserve_bl = 0; + + if (op->verbose > 1) + printf("link(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + } else { + size = getval(); + } + if (size == 0) + exit (1); + + sprintf(path,"%s.%05d", getprogname(), getpid()); + if (mkdir(path, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path, __FILE__, __LINE__); + + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + + return (0); +} + +void +cleanup(void) +{ + (void)chdir(".."); + if (path[0] != 0 && rmdir(path) == -1) + warn("rmdir(%s), %s:%d", path, __FILE__, __LINE__); +} + +int +test(void) +{ + int fd, i, j; + pid_t pid; + char file[128]; + char lfile[128]; + + pid = getpid(); + for (j = 0; j < size && done_testing == 0; j++) { + sprintf(file,"p%05d.%05d", pid, j); + if (j == 0) { + if ((fd = creat(file, 0660)) == -1) { + if (errno != EINTR) { + warn("creat(%s)", file); + break; + } + } + if (fd != -1 && close(fd) == -1) + err(2, "close(%d)", j); + strcpy(lfile, file); + } else { + if (link(lfile, file) == -1) { + if (errno != EINTR) { + warn("link(%s, %s)", lfile, file); + break; + } + } + } + + } + + for (i = --j; i >= 0; i--) { + sprintf(file,"p%05d.%05d", pid, i); + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + + } + + return (0); +} diff --git a/test/stress/stress2/testcases/lockf/Makefile b/test/stress/stress2/testcases/lockf/Makefile new file mode 100644 index 0000000000..7baff7cd77 --- /dev/null +++ b/test/stress/stress2/testcases/lockf/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= lockf + +.include diff --git a/test/stress/stress2/testcases/lockf/lockf.c b/test/stress/stress2/testcases/lockf/lockf.c new file mode 100644 index 0000000000..b261d66056 --- /dev/null +++ b/test/stress/stress2/testcases/lockf/lockf.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Test lockf(3) */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +char file[128]; +int fd; +pid_t pid; + +int +get(void) { + int sem; + if (lockf(fd, F_LOCK, 0) == -1) + err(1, "lockf(%s, F_LOCK)", file); + if (read(fd, &sem, sizeof(sem)) != sizeof(sem)) + err(1, "get: read(%d)", fd); + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek"); + if (lockf(fd, F_ULOCK, 0) == -1) + err(1, "lockf(%s, F_ULOCK)", file); + return (sem); +} + +void +incr(void) { + int sem; + if (lockf(fd, F_LOCK, 0) == -1) + err(1, "lockf(%s, F_LOCK)", file); + if (read(fd, &sem, sizeof(sem)) != sizeof(sem)) + err(1, "incr: read(%d)", fd); + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek"); + sem++; + if (write(fd, &sem, sizeof(sem)) != sizeof(sem)) + err(1, "incr: read"); + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek"); + if (lockf(fd, F_ULOCK, 0) == -1) + err(1, "lockf(%s, F_ULOCK)", file); +} +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + int i; + int sem = 0; + + sprintf(file, "lockf.0.%d", getpid()); + if ((fd = open(file,O_CREAT | O_TRUNC | O_RDWR, 0600)) == -1) + err(1, "creat(%s)", file); + if (write(fd, &sem, sizeof(sem)) != sizeof(sem)) + err(1, "write"); + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek"); + + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(2); + } + + if (pid == 0) { /* child */ + for (i = 0; i < 100; i++) { + while ((get() & 1) == 0) + ; + if (op->verbose > 2) + printf("Child %d, sem = %d\n", i, get()), + fflush(stdout); + incr(); + } + exit(0); + } else { /* parent */ + for (i = 0; i < 100; i++) { + while ((get() & 1) == 1) + ; + if (op->verbose > 2) + printf("Parent %d, sem = %d\n", i, get()), + fflush(stdout); + incr(); + } + } + close(fd); + waitpid(pid, &i, 0); + unlink(file); + + return (0); +} diff --git a/test/stress/stress2/testcases/lockf2/Makefile b/test/stress/stress2/testcases/lockf2/Makefile new file mode 100644 index 0000000000..dc43bcbc3f --- /dev/null +++ b/test/stress/stress2/testcases/lockf2/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= lockf2 + +.include diff --git a/test/stress/stress2/testcases/lockf2/lockf2.c b/test/stress/stress2/testcases/lockf2/lockf2.c new file mode 100644 index 0000000000..f3bf434d76 --- /dev/null +++ b/test/stress/stress2/testcases/lockf2/lockf2.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Test lockf(3) with overlapping ranges */ + +/* Provoked: + lock order reversal: + 1st 0xc50057a0 vnode interlock (vnode interlock) @ kern/kern_lockf.c:190 + 2nd 0xc14710e8 system map (system map) @ vm/vm_kern.c:296 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +char file[128]; +int fd; + +int +setup(int nb) +{ + int i; + char buf[1024]; + + sprintf(file, "lockf.%d", getpid()); + if ((fd = open(file,O_CREAT | O_TRUNC | O_RDWR, 0600)) == -1) + err(1, "creat(%s)", file); + bzero(buf, sizeof(buf)); + for (i = 0; i < 1024; i++) + if (write(fd, &buf, sizeof(buf)) != sizeof(buf)) + err(1, "write"); + close(fd); + return (0); +} + +void +cleanup(void) +{ + unlink(file); +} + +int +test(void) +{ + int i; + off_t pos; + off_t size; + + if ((fd = open(file, O_RDWR, 0600)) == -1) + err(1, "open(%s)", file); + + for (i = 0; i < 1024; i++) { + pos = random_int(0, 1024 * 1024 - 1); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek"); + size = random_int(1, 1024 * 1024 - pos); + if (size > 64) + size = 64; + if (lockf(fd, F_LOCK, size) == -1) + err(1, "lockf(%s, F_LOCK)", file); + size = random_int(1, size); + if (lockf(fd, F_ULOCK, size) == -1) + err(1, "lockf(%s, F_ULOCK)", file); + + } + close(fd); + + return (0); +} diff --git a/test/stress/stress2/testcases/mkdir/Makefile b/test/stress/stress2/testcases/mkdir/Makefile new file mode 100644 index 0000000000..4220ecf5c3 --- /dev/null +++ b/test/stress/stress2/testcases/mkdir/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=mkdir + +.include diff --git a/test/stress/stress2/testcases/mkdir/mkdir.c b/test/stress/stress2/testcases/mkdir/mkdir.c new file mode 100644 index 0000000000..d192f61891 --- /dev/null +++ b/test/stress/stress2/testcases/mkdir/mkdir.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static unsigned long size; + + +int +setup(int nb) +{ + int pct; + int64_t in; + int64_t bl; + int64_t reserve_in; + int64_t reserve_bl; + + if (nb == 0) { + getdf(&bl, &in); + size = in / op->incarnations; + + pct = 90; + if (op->hog == 0) + pct = random_int(1, 90); + size = size / 100 * pct + 1; + + size = size % 10000; /* arbitrary limit depth */ + size = size % 200; /* arbitrary limit depth */ /* XXX Soft Update */ + + /* Resource requirements: */ + while (size > 0) { + reserve_in = 1 * size * op->incarnations + 1; + reserve_bl = 2048 * size * op->incarnations; +// printf("---size = %lu, reserve(%jd, %jd)\n", size, reserve_bl/1024, reserve_in); + if (reserve_bl <= bl && reserve_in <= in) + break; + size--; + } + if (size == 0) + reserve_bl = reserve_in = 0; + + if (op->verbose > 1) + printf("mkdir(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + } else + size = getval(); + + return (0); +} + +void +cleanup(void) +{ +} + +void +mkDir(char *path, int level) { + char newPath[MAXPATHLEN + 1]; + + if (mkdir(path, 0770) == -1) { + warn("mkdir(%s), %s:%d", path, __FILE__, __LINE__); + size = level; + } else + chdir(path); + + if (done_testing == 1) + size = level; + + if (level < size) { + sprintf(newPath,"d%d", level+1); + mkDir(newPath, level+1); + } +} + +void +rmDir(char *path, int level) { + char newPath[MAXPATHLEN + 1]; + + if (level < size) { + sprintf(newPath,"d%d", level+1); + rmDir(newPath, level+1); + } + chdir (".."); + if (rmdir(path) == -1) { + err(1, "rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } +} + +int +test(void) +{ + char path[MAXPATHLEN + 1]; + + umask(0); + sprintf(path,"p%05d.d%d", getpid(), 1); + mkDir(path, 1); + rmDir(path, 1); + + return (0); +} diff --git a/test/stress/stress2/testcases/mkfifo/Makefile b/test/stress/stress2/testcases/mkfifo/Makefile new file mode 100644 index 0000000000..33ac79d413 --- /dev/null +++ b/test/stress/stress2/testcases/mkfifo/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= mkfifo +LDADD= -lutil + +.include diff --git a/test/stress/stress2/testcases/mkfifo/mkfifo.c b/test/stress/stress2/testcases/mkfifo/mkfifo.c new file mode 100644 index 0000000000..e7ead07ece --- /dev/null +++ b/test/stress/stress2/testcases/mkfifo/mkfifo.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[MAXPATHLEN+1]; +#define NB (1 * 1024 * 1024) + +int bufsize; + +static void +reader(void) { + int fd; + int i, n, *buf; + + if ((fd = open(path, O_RDWR, 0600)) < 0) { + unlink(path); + err(1, "open(%s)", path); + } + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + for (i = 0; i < NB; i+= bufsize) { + if ((n = read(fd, buf, bufsize)) < 0) + err(1, "read(), %s:%d", __FILE__, __LINE__); + if (n == 0) break; + } + close(fd); + free(buf); + return; +} + +static void +writer(void) { + int i, *buf; + int fd; + + if ((fd = open(path, O_RDWR, 0600)) < 0) { + unlink(path); + err(1, "open(%s)", path); + } + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + for (i = 0; i < bufsize / sizeof(int); i++) + buf[i] = i; + + for (i = 0; i < NB; i+= bufsize) { + if (write(fd, buf, bufsize) < 0) { + err(1, "write(%d), %s:%d", fd, + __FILE__, __LINE__); + } + } + close(fd); + free(buf); + return; +} + +int +setup(int nb) +{ + bufsize = 2 << random_int(2, 12); + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + pid_t pid; + int i, status; + + for (i = 0; i < 100; i++) { + if (sprintf(path, "fifo.%d.%d", getpid(), i) < 0) + err(1, "sprintf()"); + if (mkfifo(path, 0600) < 0) + err(1, "mkfifo(%s)", path); + } + for (i = 0; i < 100; i++) { + if (sprintf(path, "fifo.%d.%d", getpid(), i) < 0) + err(1, "sprintf()"); + if (unlink(path) < 0) + err(1, "unlink(%s)", path); + } + + + if (sprintf(path, "fifo.%d", getpid()) < 0) + err(1, "sprintf()"); + if (mkfifo(path, 0600) < 0) + err(1, "mkfifo(%s)", path); + + if ((pid = fork()) == 0) { + writer(); + exit(EXIT_SUCCESS); + + } else if (pid > 0) { + reader(); + kill(pid, SIGINT); + if (waitpid(pid, &status, 0) == -1) + warn("waitpid(%d)", pid); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + + unlink(path); + return (0); +} diff --git a/test/stress/stress2/testcases/mmap/Makefile b/test/stress/stress2/testcases/mmap/Makefile new file mode 100644 index 0000000000..8f132b60ea --- /dev/null +++ b/test/stress/stress2/testcases/mmap/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=mmap + +.include diff --git a/test/stress/stress2/testcases/mmap/mmap.c b/test/stress/stress2/testcases/mmap/mmap.c new file mode 100644 index 0000000000..2dfd437b8c --- /dev/null +++ b/test/stress/stress2/testcases/mmap/mmap.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; + +#define INPUTFILE "/bin/date" + +int +setup(int nb) +{ + umask(0); + + sprintf(path,"%s.%05d", getprogname(), getpid()); + if (mkdir(path, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path, __FILE__, __LINE__); + + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + + return (0); +} + +void +cleanup(void) +{ + (void)chdir(".."); + if (rmdir(path) == -1) { + warn("rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } + +} + +int +test(void) +{ + int i; + pid_t pid; + char file[128]; + int fdin, fdout; + char *src, *dst; + struct stat statbuf; + + pid = getpid(); + for (i = 0; i < 100 && done_testing == 0; i++) { + sprintf(file,"p%05d.%05d", pid, i); + + if ((fdin = open(INPUTFILE, O_RDONLY)) < 0) + err(1, INPUTFILE); + + if ((fdout = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) + err(1, "%s", file); + + if (fstat(fdin, &statbuf) < 0) + err(1, "fstat error"); + + if (lseek(fdout, statbuf.st_size - 1, SEEK_SET) == -1) + err(1, "lseek error"); + + /* write a dummy byte at the last location */ + if (write(fdout, "", 1) != 1) + err(1, "write error"); + + if ((src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0)) == + (caddr_t) - 1) + err(1, "mmap error for input"); + + if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fdout, 0)) == (caddr_t) - 1) + err(1, "mmap error for output"); + + memcpy(dst, src, statbuf.st_size); + + + if (munmap(src, statbuf.st_size) == -1) + err(1, "munmap"); + close(fdin); + + if (munmap(dst, statbuf.st_size) == -1) + err(1, "munmap"); + close(fdout); + + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + } + + + return (0); +} diff --git a/test/stress/stress2/testcases/openat/Makefile b/test/stress/stress2/testcases/openat/Makefile new file mode 100644 index 0000000000..8ed401edd5 --- /dev/null +++ b/test/stress/stress2/testcases/openat/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=openat + +.include diff --git a/test/stress/stress2/testcases/openat/doat.c b/test/stress/stress2/testcases/openat/doat.c new file mode 100644 index 0000000000..8337e0f9d4 --- /dev/null +++ b/test/stress/stress2/testcases/openat/doat.c @@ -0,0 +1,693 @@ +/*- + * Copyright (c) 2007 Roman Divacky + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +union param { + int i; + char *cp; + mode_t m; + dev_t d; + void *vp; + uid_t u; + gid_t g; + char **cpp; +}; + +struct testcase { + int result; + union param params[5]; // no *at syscall with more than 5 params +}; + +struct test { + int syscall; + int num_of_cases; + char *name; + struct testcase tests[10]; // no more than 10 tests + +}; + +struct test *tests; +#define NUM_OF_TESTS 15 + +char *absolute_path = NULL; +char *relative_path = "tmp/"; +char *not_dir_path = "/bin/date"; + +char *file = "foo"; +char *absolute_file = NULL; +char *relative_file = NULL; +char *symlinkf = "link"; +char *newlink = "nlink1"; +char *newlink2 = "nlink2"; +char *newlink3 = "nlink3"; +char *newdir = "newdir"; +char *fifo = "fifo"; +char *nod = "nod"; +char *newfile = "newfile"; +char *newslink = "nslink1"; + +bool dir_exist = false; +bool file_exist = false; +bool link_exist = false; + +int rel_fd, abs_fd, notd_fd, exec_fd; + +struct timeval times[2]; +struct stat buf; +char *pargv[2] = { "/bin/date", NULL }; +char cbuf[PATH_MAX]; + +void +setup() +{ + int i, error; + struct stat sb; + + tests = calloc(NUM_OF_TESTS, sizeof(struct test)); + if (tests == NULL) { + perror(""); + exit(0); + } + + absolute_path = getcwd(NULL, 0); + if (absolute_path == NULL) { + perror("getcwd"); + exit(0); + } + + absolute_path = realloc(absolute_path, strlen(absolute_path) + 5); + if (absolute_path == NULL) { + perror("realloc"); + exit(0); + } + + strcat(absolute_path, "/"); + strcat(absolute_path, relative_path); + + absolute_file = malloc(strlen(absolute_path) + 1 + strlen(file)); + bzero(absolute_file, strlen(absolute_path) + 1 + strlen(file)); + if (absolute_file == NULL) { + perror("malloc"); + exit(0); + } + strcpy(absolute_file, absolute_path); + absolute_file[strlen(absolute_file)] = '/'; + strcpy(absolute_file + strlen(absolute_path), file); + + printf("XX: %s\n", absolute_file); + + relative_file = malloc(strlen(relative_path) + 1 + strlen(file)); + bzero(relative_file, strlen(relative_path) + 1 + strlen(file)); + if (relative_file == NULL) { + perror("malloc"); + exit(0); + } + strcpy(relative_file, relative_path); + relative_file[strlen(relative_file)] = '/'; + strcpy(relative_file + strlen(relative_path), file); + + printf("YY: %s\n", relative_file); + + error = mkdir(relative_path, 0744); + dir_exist = (errno == EEXIST); + if (error && errno != EEXIST) { + perror("tmp"); + exit(0); + } + + error = stat("tmp/foo", &sb); + file_exist = (errno != ENOENT); + i = open("tmp/foo", O_RDONLY | O_CREAT, 0644); + if (i == -1) { + perror("foo"); + exit(0); + } + + rel_fd = open(relative_path, O_RDONLY); + if (rel_fd == -1) { + perror("relative path"); + exit(0); + } + + abs_fd = open(absolute_path, O_RDONLY); + if (abs_fd == -1) { + perror("absolute path"); + exit(0); + } + + notd_fd = open(not_dir_path, O_RDONLY); + if (notd_fd == -1) { + perror("not a directory"); + exit(0); + } + + exec_fd = open(not_dir_path, O_RDONLY); + if (exec_fd == -1) { + perror("not a directory"); + exit(0); + } + + error = symlink(absolute_file, symlinkf); + link_exist = (errno == EEXIST); + if (error && errno != EEXIST) { + perror("symlink"); + exit(0); + } + + // faccessat + tests[0].syscall = SYS_faccessat; + tests[0].num_of_cases = 6; + tests[0].name = "faccessat"; + tests[0].tests[0].result = EBADF; + tests[0].tests[0].params[0].i = 106; // invalid fd + tests[0].tests[0].params[1].cp = relative_path; + tests[0].tests[0].params[2].m = 0; + tests[0].tests[0].params[3].i = 0; + tests[0].tests[1].result = EBADF; + tests[0].tests[1].params[0].i = 106; // invalid fd + tests[0].tests[1].params[1].cp = relative_path; + tests[0].tests[1].params[2].m = 0; + tests[0].tests[1].params[3].i = AT_EACCESS; + tests[0].tests[2].result = EINVAL; + tests[0].tests[2].params[0].i = rel_fd; + tests[0].tests[2].params[1].cp = absolute_path; + tests[0].tests[2].params[2].m = 0; + tests[0].tests[2].params[3].i = 123; // invalid flag + tests[0].tests[3].result = ENOTDIR; + tests[0].tests[3].params[0].i = notd_fd; + tests[0].tests[3].params[1].cp = relative_file; + tests[0].tests[3].params[2].m = 0; + tests[0].tests[3].params[3].i = 0; + tests[0].tests[4].result = 0; + tests[0].tests[4].params[0].i = rel_fd; + tests[0].tests[4].params[1].cp = file; + tests[0].tests[4].params[2].m = 0; + tests[0].tests[4].params[3].i = 0; + tests[0].tests[5].result = 0; + tests[0].tests[5].params[0].i = rel_fd; + tests[0].tests[5].params[1].cp = file; + tests[0].tests[5].params[2].m = 0; + tests[0].tests[5].params[3].i = AT_EACCESS; + tests[0].tests[6].result = 0; + tests[0].tests[6].params[0].i = 106; // invalid fd + tests[0].tests[6].params[1].cp = absolute_path; + tests[0].tests[6].params[2].m = 0; + tests[0].tests[6].params[3].i = 0; + + // fchmodat + tests[1].syscall = SYS_fchmodat; + tests[1].num_of_cases = 6; + tests[1].name = "fchmodat"; + tests[1].tests[0].result = EBADF; + tests[1].tests[0].params[0].i = 106; // invalid fd + tests[1].tests[0].params[1].cp = relative_path; + tests[1].tests[0].params[2].m = 33190; + tests[1].tests[0].params[3].i = 0; + tests[1].tests[1].result = EINVAL; + tests[1].tests[1].params[0].i = rel_fd; + tests[1].tests[1].params[1].cp = absolute_path; + tests[1].tests[1].params[2].m = 33190; // mode 646 translated + tests[1].tests[1].params[3].i = 123; // invalid flag + tests[1].tests[2].result = ENOTDIR; + tests[1].tests[2].params[0].i = notd_fd; + tests[1].tests[2].params[1].cp = relative_file; + tests[1].tests[2].params[2].m = 33190; + tests[1].tests[2].params[3].i = 0; + tests[1].tests[3].result = 0; + tests[1].tests[3].params[0].i = notd_fd; + tests[1].tests[3].params[1].cp = absolute_file; + tests[1].tests[3].params[2].m = 33190; + tests[1].tests[3].params[3].i = 0; + tests[1].tests[4].result = 0; + tests[1].tests[4].params[0].i = AT_FDCWD; + tests[1].tests[4].params[1].cp = symlinkf; + tests[1].tests[4].params[2].m = 33190; + tests[1].tests[4].params[3].i = AT_SYMLINK_NOFOLLOW; + tests[1].tests[5].result = 0; + tests[1].tests[5].params[0].i = rel_fd; + tests[1].tests[5].params[1].cp = file; + tests[1].tests[5].params[2].m = 33190; + tests[1].tests[5].params[3].i = 0; + + // fchownat + tests[2].syscall = SYS_fchownat; + tests[2].num_of_cases = 6; + tests[2].name = "fchownat"; + tests[2].tests[0].result = EBADF; + tests[2].tests[0].params[0].i = 106; // invalid fd + tests[2].tests[0].params[1].cp = relative_file; + tests[2].tests[0].params[2].u = 65534; + tests[2].tests[0].params[3].g = 65534; + tests[2].tests[0].params[4].i = 0; + tests[2].tests[1].result = EINVAL; + tests[2].tests[1].params[0].i = rel_fd; + tests[2].tests[1].params[1].cp = file; + tests[2].tests[1].params[2].u = 65534; + tests[2].tests[1].params[3].g = 65534; + tests[2].tests[1].params[4].i = 123; // invalid flag + tests[2].tests[2].result = ENOTDIR; + tests[2].tests[2].params[0].i = notd_fd; + tests[2].tests[2].params[1].cp = relative_file; + tests[2].tests[2].params[2].u = 65534; + tests[2].tests[2].params[3].g = 65534; + tests[2].tests[2].params[4].i = 0; + tests[2].tests[3].result = 0; + tests[2].tests[3].params[0].i = notd_fd; + tests[2].tests[3].params[1].cp = absolute_file; + tests[2].tests[3].params[2].u = 65534; + tests[2].tests[3].params[3].g = 65534; + tests[2].tests[3].params[4].i = 0; + tests[2].tests[4].result = 0; + tests[2].tests[4].params[0].i = AT_FDCWD; + tests[2].tests[4].params[1].cp = symlinkf; + tests[2].tests[4].params[2].u = 65534; + tests[2].tests[4].params[3].g = 65534; + tests[2].tests[4].params[4].i = AT_SYMLINK_NOFOLLOW; + tests[2].tests[5].result = 0; + tests[2].tests[5].params[0].i = rel_fd; + tests[2].tests[5].params[1].cp = file; + tests[2].tests[5].params[2].u = 0; + tests[2].tests[5].params[3].g = 0; + tests[2].tests[5].params[4].i = 0; + + // fstatat + tests[3].syscall = SYS_fstatat; + tests[3].num_of_cases = 5; + tests[3].name = "fstatat"; + tests[3].tests[0].result = EBADF; + tests[3].tests[0].params[0].i = 106; // invalid fd + tests[3].tests[0].params[1].cp = relative_file; + tests[3].tests[0].params[2].vp = &buf; + tests[3].tests[0].params[3].i = 0; + tests[3].tests[1].result = EINVAL; + tests[3].tests[1].params[0].i = rel_fd; + tests[3].tests[1].params[1].cp = relative_file; + tests[3].tests[1].params[2].vp = &buf; + tests[3].tests[1].params[3].i = 123; // invalid flags + tests[3].tests[2].result = ENOTDIR; + tests[3].tests[2].params[0].i = notd_fd; + tests[3].tests[2].params[1].cp = relative_file; + tests[3].tests[2].params[2].vp = &buf; + tests[3].tests[2].params[3].i = 0; + tests[3].tests[2].result = 0; + tests[3].tests[2].params[0].i = rel_fd; + tests[3].tests[2].params[1].cp = file; + tests[3].tests[2].params[2].vp = &buf; + tests[3].tests[2].params[3].i = 0; + tests[3].tests[3].result = 0; + tests[3].tests[3].params[0].i = AT_FDCWD; + tests[3].tests[3].params[1].cp = symlinkf; + tests[3].tests[3].params[2].vp = &buf; + tests[3].tests[3].params[3].i = AT_SYMLINK_NOFOLLOW; + tests[3].tests[4].result = 0; + tests[3].tests[4].params[0].i = notd_fd; + tests[3].tests[4].params[1].cp = absolute_file; + tests[3].tests[4].params[2].vp = &buf; + tests[3].tests[4].params[3].i = 0; + + // futimesat + tests[4].syscall = SYS_futimesat; + tests[4].num_of_cases = 4; + tests[4].name = "futimesat"; + tests[4].tests[0].result = EBADF; + tests[4].tests[0].params[0].i = 106; // invalid fd + tests[4].tests[0].params[1].cp = relative_file; + tests[4].tests[0].params[2].vp = times; + tests[4].tests[1].result = ENOTDIR; + tests[4].tests[1].params[0].i = notd_fd; + tests[4].tests[1].params[1].cp = relative_file; + tests[4].tests[1].params[2].vp = times; + tests[4].tests[2].result = 0; + tests[4].tests[2].params[0].i = rel_fd; + tests[4].tests[2].params[1].cp = file; + tests[4].tests[2].params[2].vp = times; + tests[4].tests[3].result = 0; + tests[4].tests[3].params[0].i = notd_fd; + tests[4].tests[3].params[1].cp = absolute_file; + tests[4].tests[3].params[2].vp = times; + + // linkat + tests[5].syscall = SYS_linkat; + tests[5].num_of_cases = 7; + tests[5].name = "linkat"; + tests[5].tests[0].result = EBADF; + tests[5].tests[0].params[0].i = 106; // invalid fd + tests[5].tests[0].params[1].cp = relative_file; + tests[5].tests[0].params[2].i = AT_FDCWD; + tests[5].tests[0].params[3].cp = newlink; + tests[5].tests[0].params[4].i = 0; + tests[5].tests[1].result = EBADF; + tests[5].tests[1].params[0].i = AT_FDCWD; + tests[5].tests[1].params[1].cp = relative_file; + tests[5].tests[1].params[2].i = 106; // invalid fd + tests[5].tests[1].params[3].cp = newlink; + tests[5].tests[1].params[4].i = 0; + tests[5].tests[2].result = EINVAL; + tests[5].tests[2].params[0].i = rel_fd; + tests[5].tests[2].params[1].cp = relative_file; + tests[5].tests[2].params[2].i = AT_FDCWD; + tests[5].tests[2].params[3].cp = newlink; + tests[5].tests[2].params[4].i = 123; // invalid flag + tests[5].tests[3].result = ENOTDIR; + tests[5].tests[3].params[0].i = notd_fd; + tests[5].tests[3].params[1].cp = relative_file; + tests[5].tests[3].params[2].i = AT_FDCWD; + tests[5].tests[3].params[3].cp = newlink; + tests[5].tests[3].params[4].i = 0; + tests[5].tests[4].result = 0; + tests[5].tests[4].params[0].i = rel_fd; + tests[5].tests[4].params[1].cp = file; + tests[5].tests[4].params[2].i = rel_fd; + tests[5].tests[4].params[3].cp = newlink; + tests[5].tests[4].params[4].i = 0; + tests[5].tests[5].result = 0; + tests[5].tests[5].params[0].i = AT_FDCWD; + tests[5].tests[5].params[1].cp = symlinkf; + tests[5].tests[5].params[2].i = rel_fd; + tests[5].tests[5].params[3].cp = newlink2; + tests[5].tests[5].params[4].i = 0; + tests[5].tests[6].result = 0; + tests[5].tests[6].params[0].i = AT_FDCWD; + tests[5].tests[6].params[1].cp = symlinkf; + tests[5].tests[6].params[2].i = rel_fd; + tests[5].tests[6].params[3].cp = newlink3; + tests[5].tests[6].params[4].i = AT_SYMLINK_FOLLOW; + + // mkdirat + tests[6].syscall = SYS_mkdirat; + tests[6].num_of_cases = 3; + tests[6].name = "mkdirat"; + tests[6].tests[0].result = EBADF; + tests[6].tests[0].params[0].i = 106; // invalid fd + tests[6].tests[0].params[1].cp = relative_file; + tests[6].tests[0].params[2].m = 33190; + tests[6].tests[1].result = ENOTDIR; + tests[6].tests[1].params[0].i = notd_fd; + tests[6].tests[1].params[1].cp = relative_file; + tests[6].tests[1].params[2].m = 33190; + tests[6].tests[2].result = 0; + tests[6].tests[2].params[0].i = rel_fd; + tests[6].tests[2].params[1].cp = newdir; + tests[6].tests[2].params[2].m = 33190; + + // mkfifoat + tests[7].syscall = SYS_mkfifoat; + tests[7].num_of_cases = 3; + tests[7].name = "mkfifoat"; + tests[7].tests[0].result = EBADF; + tests[7].tests[0].params[0].i = 107; // invalid fd + tests[7].tests[0].params[1].cp = relative_file; + tests[7].tests[0].params[2].m = 33190; + tests[7].tests[1].result = ENOTDIR; + tests[7].tests[1].params[0].i = notd_fd; + tests[7].tests[1].params[1].cp = relative_file; + tests[7].tests[1].params[2].m = 33190; + tests[7].tests[2].result = 0; + tests[7].tests[2].params[0].i = rel_fd; + tests[7].tests[2].params[1].cp = fifo; + tests[7].tests[2].params[2].m = 33190; + + // mknodat + tests[8].syscall = SYS_mknodat; + tests[8].num_of_cases = 3; + tests[8].name = "mknodat"; + tests[8].tests[0].result = EBADF; + tests[8].tests[0].params[0].i = 108; // invalid fd + tests[8].tests[0].params[1].cp = relative_file; + tests[8].tests[0].params[2].m = 0666 | S_IFCHR; + tests[8].tests[0].params[3].d = 15; + tests[8].tests[1].result = ENOTDIR; + tests[8].tests[1].params[0].i = notd_fd; + tests[8].tests[1].params[1].cp = relative_file; + tests[8].tests[1].params[2].m = 0666 | S_IFCHR; + tests[8].tests[1].params[3].d = 15; + tests[8].tests[2].result = 0; + tests[8].tests[2].params[0].i = rel_fd; + tests[8].tests[2].params[1].cp = nod; + tests[8].tests[2].params[2].m = 0666 | S_IFCHR; + tests[8].tests[2].params[3].d = 2570; + + // openat + tests[9].syscall = SYS_openat; + tests[9].num_of_cases = 5; + tests[9].name = "openat"; + tests[9].tests[0].result = EBADF; + tests[9].tests[0].params[0].i = 106; // invalid fd + tests[9].tests[0].params[1].cp = relative_file; + tests[9].tests[0].params[2].i = O_RDONLY; + tests[9].tests[0].params[3].i = 0666; + tests[9].tests[1].result = ENOTDIR; + tests[9].tests[1].params[0].i = notd_fd; + tests[9].tests[1].params[1].cp = relative_file; + tests[9].tests[1].params[2].i = O_RDONLY; + tests[9].tests[1].params[3].i = 0666; + tests[9].tests[2].result = 7; // hardcoded fd + tests[9].tests[2].params[0].i = rel_fd; + tests[9].tests[2].params[1].cp = file; + tests[9].tests[2].params[2].i = O_RDONLY; + tests[9].tests[2].params[3].i = 0400; + tests[9].tests[3].result = 8; // hardcoded fd + tests[9].tests[3].params[0].i = notd_fd; + tests[9].tests[3].params[1].cp = absolute_file; + tests[9].tests[3].params[2].i = O_RDONLY; + tests[9].tests[3].params[3].i = 0400; + tests[9].tests[4].result = 9; // hardcoded fd + tests[9].tests[4].params[0].i = rel_fd; + tests[9].tests[4].params[1].cp = newfile; + tests[9].tests[4].params[2].i = O_RDONLY | O_CREAT; + tests[9].tests[4].params[3].i = 0666; + + // readlinkat + tests[10].syscall = SYS_readlinkat; + tests[10].num_of_cases = 3; + tests[10].name = "readlinkat"; + tests[10].tests[0].result = EBADF; + tests[10].tests[0].params[0].i = 106; // invalid fd + tests[10].tests[0].params[1].cp = relative_file; + tests[10].tests[0].params[2].vp = cbuf; + tests[10].tests[0].params[3].i = PATH_MAX; + tests[10].tests[1].result = ENOTDIR; + tests[10].tests[1].params[0].i = notd_fd; + tests[10].tests[1].params[1].cp = relative_file; + tests[10].tests[1].params[2].vp = cbuf; + tests[10].tests[1].params[3].i = PATH_MAX; + tests[10].tests[2].result = strlen(absolute_file); + tests[10].tests[2].params[0].i = AT_FDCWD; + tests[10].tests[2].params[1].cp = symlinkf; + tests[10].tests[2].params[2].vp = cbuf; + tests[10].tests[2].params[3].i = PATH_MAX; + + // renameat + tests[11].syscall = SYS_renameat; + tests[11].num_of_cases = 5; + tests[11].name = "renameat"; + tests[11].tests[0].result = EBADF; + tests[11].tests[0].params[0].i = 106; // invalid fd + tests[11].tests[0].params[1].cp = file; + tests[11].tests[0].params[2].i = rel_fd; + tests[11].tests[0].params[3].cp = file; + tests[11].tests[1].result = EBADF; + tests[11].tests[1].params[0].i = rel_fd; + tests[11].tests[1].params[1].cp = file; + tests[11].tests[1].params[2].i = 106; // invalid fd + tests[11].tests[1].params[3].cp = file; + tests[11].tests[2].result = ENOTDIR; + tests[11].tests[2].params[0].i = notd_fd; + tests[11].tests[2].params[1].cp = relative_file; + tests[11].tests[2].params[2].i = rel_fd; + tests[11].tests[2].params[3].cp = file; + tests[11].tests[3].result = ENOTDIR; + tests[11].tests[3].params[0].i = rel_fd; + tests[11].tests[3].params[1].cp = file; + tests[11].tests[3].params[2].i = notd_fd; + tests[11].tests[3].params[3].cp = relative_file; + tests[11].tests[4].result = 0; + tests[11].tests[4].params[0].i = rel_fd; + tests[11].tests[4].params[1].cp = newfile; + tests[11].tests[4].params[2].i = AT_FDCWD; + tests[11].tests[4].params[3].cp = newfile; + + // symlinkat + tests[12].syscall = SYS_symlinkat; + tests[12].num_of_cases = 3; + tests[12].name = "symlinkat"; + tests[12].tests[0].result = EBADF; + tests[12].tests[0].params[0].cp = file; + tests[12].tests[0].params[1].i = 106; // invalid fd + tests[12].tests[0].params[2].cp = file; + tests[12].tests[1].result = ENOTDIR; + tests[12].tests[1].params[0].cp = file; + tests[12].tests[1].params[1].i = notd_fd; + tests[12].tests[1].params[2].cp = relative_file; + tests[12].tests[2].result = 0; + tests[12].tests[2].params[0].cp = absolute_file; + tests[12].tests[2].params[1].i = rel_fd; + tests[12].tests[2].params[2].cp = newslink; + + + // unlinkat + tests[13].syscall = SYS_unlinkat; + tests[13].num_of_cases = 7; + tests[13].name = "unlinkat"; + tests[13].tests[0].result = EBADF; + tests[13].tests[0].params[0].i = 106; // invalid fd + tests[13].tests[0].params[1].cp = relative_file; + tests[13].tests[0].params[2].i = 0; + tests[13].tests[1].result = ENOTDIR; + tests[13].tests[1].params[0].i = notd_fd; + tests[13].tests[1].params[1].cp = relative_file; + tests[13].tests[1].params[2].i = 0; + tests[13].tests[2].result = EINVAL; + tests[13].tests[2].params[0].i = rel_fd; + tests[13].tests[2].params[1].cp = file; + tests[13].tests[2].params[2].i = 123; // invalid flag + tests[13].tests[3].result = ENOTDIR; + tests[13].tests[3].params[0].i = rel_fd; + tests[13].tests[3].params[1].cp = not_dir_path; + tests[13].tests[3].params[2].i = AT_REMOVEDIR; + tests[13].tests[4].result = ENOTEMPTY; + tests[13].tests[4].params[0].i = AT_FDCWD; + tests[13].tests[4].params[1].cp = relative_path; + tests[13].tests[4].params[2].i = AT_REMOVEDIR; + tests[13].tests[5].result = 0; + tests[13].tests[5].params[0].i = rel_fd; + tests[13].tests[5].params[1].cp = newdir; + tests[13].tests[5].params[2].i = AT_REMOVEDIR; + tests[13].tests[6].result = 0; + tests[13].tests[6].params[0].i = AT_FDCWD; + tests[13].tests[6].params[1].cp = newfile; + tests[13].tests[6].params[2].i = 0; + + + // fexecve + tests[14].syscall = SYS_fexecve; + tests[14].num_of_cases = 2; + tests[14].name = "fexecve"; + tests[14].tests[0].result = EBADF; + tests[14].tests[0].params[0].i = 106; // invalid fd + tests[14].tests[0].params[1].cpp = pargv; + tests[14].tests[0].params[2].cpp = NULL; + // This is EXPECTED to execve /bin/date, so dont expect OK output + tests[14].tests[1].result = 0; + tests[14].tests[1].params[0].i = exec_fd; + tests[14].tests[1].params[1].cpp = pargv; + tests[14].tests[1].params[2].cpp = NULL; +} + +void +cleanup() +{ + int error; + + close(notd_fd); + close(rel_fd); + close(abs_fd); + + if (!file_exist) { + error = unlink("tmp/foo"); + if (error) { + perror("unlink"); + exit(0); + } + } + if (!dir_exist) { + error = rmdir(absolute_path); + if (error) { + perror("rmdir"); + exit(0); + } + } + if (link_exist) { + error = unlink(symlinkf); + if (error) { + perror("unlink"); + exit(0); + } + } +} + +void +setup_once() +{ +} + +int +main(int argc, char *argv[]) +{ + int i,j; + int error; + + setup(); + + for (i = 0; i < NUM_OF_TESTS; i++) { + printf("\nTest: %s\n", tests[i].name); + for (j = 0; j < tests[i].num_of_cases; j++) { + error = syscall(tests[i].syscall, + tests[i].tests[j].params[0], + tests[i].tests[j].params[1], + tests[i].tests[j].params[2], + tests[i].tests[j].params[3], + tests[i].tests[j].params[4]); + if (error == 0) { + if (tests[i].tests[j].result == 0) + printf("#%i ... OK\n", j); + else { + printf("#%i ... BAD: ", j); + printf("expected %i, but got %i\n", tests[i].tests[j].result, error); + } + } else { + if (tests[i].tests[j].result == errno) + printf("#%i ... OK\n", j); + else { + if (error != tests[i].tests[j].result) { + printf("#%i ... BAD: ", j); + printf("expected %i, but got %i\n", tests[i].tests[j].result, error); + } else + printf("#%i ... OK\n", j); + } + } + + + } + } + +// cleanup(); + + + return (0); +} diff --git a/test/stress/stress2/testcases/openat/openat.c b/test/stress/stress2/testcases/openat/openat.c new file mode 100644 index 0000000000..482c42da2c --- /dev/null +++ b/test/stress/stress2/testcases/openat/openat.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path1[128]; +static char path2[] = "tmp"; + +static char rpath[128]; +static char apath[128]; + +static int fd; + +int +setup(int nb) +{ + umask(0); + + sprintf(path1,"%s.%05d", getprogname(), getpid()); + if (mkdir(path1, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path1, __FILE__, __LINE__); + if (chdir(path1) == -1) + err(1, "chdir(%s), %s:%d", path2, __FILE__, __LINE__); + + if (mkdir(path2, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path2, __FILE__, __LINE__); + if (chdir(path2) == -1) + err(1, "chdir(%s), %s:%d", path2, __FILE__, __LINE__); + if (getcwd(apath, sizeof(apath)) == NULL) + err(1, "getcwd(%s), %s:%d", path2, __FILE__, __LINE__); + + if (chdir("..") == -1) + err(1, "chdir(%s), %s:%d", path1, __FILE__, __LINE__); + + if ((fd = open(path2, O_RDONLY)) == -1) + err(1, "open(%s), %s:%d", path2, __FILE__, __LINE__); + + strcpy(rpath, "tmp"); + return (0); +} + +void +cleanup(void) +{ +#if 1 + if (rmdir(path2) == -1) + warn("rmdir(%s), %s:%d", path2, __FILE__, __LINE__); + (void)chdir(".."); + if (rmdir(path1) == -1) + warn("rmdir(%s), %s:%d", path1, __FILE__, __LINE__); +#endif +} + +static void +test_openat(void) +{ + int i; + pid_t pid; + char file[128]; + char p[128]; + int tfd; + + pid = getpid(); + for (i = 0; i < 100; i++) { + sprintf(file,"p%05d.%05d", pid, i); + if ((tfd = openat(fd, file, O_RDONLY|O_CREAT, 0660)) == -1) + err(1, "openat(%s), %s:%d", file, __FILE__, __LINE__); + close(tfd); + strcpy(p, "tmp/"); + strcat(p, file); + if (unlink(p) == -1) + err(1, "unlink(%s), %s:%d", p, __FILE__, __LINE__); + } +} + +static void +test_renameat(void) +{ + int i; + pid_t pid; + char file[128]; + char file2[128]; + int tfd; + + pid = getpid(); + for (i = 0; i < 100; i++) { + sprintf(file,"p%05d.%05d", pid, i); + if ((tfd = openat(fd, file, O_RDONLY|O_CREAT, 0660)) == -1) + err(1, "openat(%s), %s:%d", file, __FILE__, __LINE__); + close(tfd); + + sprintf(file2,"p%05d.%05d.togo", pid, i); + if (renameat(fd, file, fd, file2) == -1) + err(1, "renameat(%s)", file2); + + sprintf(file2,"tmp/p%05d.%05d.togo", pid, i); + if (unlink(file2) == -1) + err(1, "unlink(%s), %s:%d", file2, __FILE__, __LINE__); + } +} + +static void +test_unlinkat(void) +{ + int i; + pid_t pid; + char file[128]; + int tfd; + + pid = getpid(); + for (i = 0; i < 100; i++) { + sprintf(file,"p%05d.%05d", pid, i); + if ((tfd = openat(fd, file, O_RDONLY|O_CREAT, 0660)) == -1) + err(1, "openat(%s), %s:%d", file, __FILE__, __LINE__); + close(tfd); + if (unlinkat(fd, file, 0) == -1) + err(1, "unlinkat(%s), %s:%d", file, __FILE__, __LINE__); + } +} + +int +test(void) +{ + test_openat(); + test_renameat(); + test_unlinkat(); + + return (0); +} diff --git a/test/stress/stress2/testcases/pty/Makefile b/test/stress/stress2/testcases/pty/Makefile new file mode 100644 index 0000000000..cdae6dea2f --- /dev/null +++ b/test/stress/stress2/testcases/pty/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= pty +LDADD= -lutil + +.include diff --git a/test/stress/stress2/testcases/pty/pty.c b/test/stress/stress2/testcases/pty/pty.c new file mode 100644 index 0000000000..855d9fd7a7 --- /dev/null +++ b/test/stress/stress2/testcases/pty/pty.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Test PTYs */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define TXT "Hello, world!" + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + int i, master, slave; + int s[32], m[32]; + char buf[512], slname[1025]; + struct termios tios; + + for (i = 0; i < 32; i++) { + if (openpty(&m[i], &s[i], slname, NULL, NULL) == -1) + err(1, "openpty"); + } + for (i = 0; i < 32; i++) { + close(m[i]); + close(s[i]); + } + + for (i = 0; i < 1024; i++) { + if (openpty(&m[0], &s[0], slname, NULL, NULL) == -1) + err(1, "openpty"); + close(m[0]); + close(s[0]); + } + + for (i = 0; i < 10 && done_testing == 0; i++) { + if (openpty(&master, &slave, slname, NULL, NULL) == -1) + err(1, "openpty"); + if ((i & 1) == 0) { + if (close(master) == -1) + err(1, "close(master)"); + if (close(slave) == -1) + err(1, "close(%s)", slname); + } else { + if (close(slave) == -1) + err(1, "close(%s)", slname); + if (close(master) == -1) + err(1, "close(master)"); + } + } + + if (openpty(&master, &slave, slname, NULL, NULL) == -1) + err(1, "openpty"); + if (tcgetattr(slave, &tios) < 0) + err(1, "tcgetattr(%s)", slname); + cfmakeraw(&tios); + if (tcsetattr(slave, TCSAFLUSH, &tios) < 0) + err(1, "tcsetattr(%s)", slname); + + for (i = 0; i < 64 && done_testing == 0; i++) { + if (write(master, TXT, sizeof(TXT)) == -1) + err(1, "write"); + if (read(slave, buf, sizeof(TXT)) == -1) + err(1, "read(%s)", slname); + } + close(master); + close(slave); + return (0); +} diff --git a/test/stress/stress2/testcases/rename/Makefile b/test/stress/stress2/testcases/rename/Makefile new file mode 100644 index 0000000000..57e23f700e --- /dev/null +++ b/test/stress/stress2/testcases/rename/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=rename + +.include diff --git a/test/stress/stress2/testcases/rename/rename.c b/test/stress/stress2/testcases/rename/rename.c new file mode 100644 index 0000000000..fcd26b1618 --- /dev/null +++ b/test/stress/stress2/testcases/rename/rename.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static unsigned long size; + +int +setup(int nb) +{ + int64_t in; + int64_t bl; + int64_t reserve_in; + int64_t reserve_bl; + + umask(0); + + if (nb == 0) { + getdf(&bl, &in); + size = in / op->incarnations; + + if (size > 100) + size = 100; /* arbitrary limit number of files pr. dir */ + + /* Resource requirements: */ + while (size > 0) { + reserve_in = 1 * size * op->incarnations + 2 * op->incarnations; + reserve_bl = 100 * size * op->incarnations; +// printf("size = %lu, reserve(%jd, %jd)\n", size, reserve_bl/1024, reserve_in); + if (reserve_bl <= bl && reserve_in <= in) + break; + size--; + } + if (size == 0) + reserve_bl = reserve_in = 0; + + if (op->verbose > 1) + printf("rename(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + } else { + size = getval(); + } + + sprintf(path,"%s.%05d", getprogname(), getpid()); + if (mkdir(path, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path, __FILE__, __LINE__); + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + + return (0); +} + +void +cleanup(void) +{ + (void)system("rm -f p*"); + (void)chdir(".."); + if (rmdir(path) == -1) + warn("rmdir(%s), %s:%d", path, __FILE__, __LINE__); +} + +static void +test_rename(void) +{ + int i, j; + pid_t pid; + char file1[128]; + char file2[128]; + int tfd; + + pid = getpid(); + for (i = 0; i < size; i++) { + sprintf(file1,"p%05d.%05d", pid, i); + if ((tfd = open(file1, O_RDONLY|O_CREAT, 0660)) == -1) + err(1, "openat(%s), %s:%d", file1, __FILE__, __LINE__); + close(tfd); + } + for (j = 0; j < 100; j++) { + for (i = 0; i < size; i++) { + sprintf(file1,"p%05d.%05d", pid, i); + sprintf(file2,"p%05d.%05d.togo", pid, i); + if (rename(file1, file2) == -1) + err(1, "rename(%s, %s). %s:%d", file1, file2, + __FILE__, __LINE__); + } + for (i = 0; i < size; i++) { + sprintf(file1,"p%05d.%05d", pid, i); + sprintf(file2,"p%05d.%05d.togo", pid, i); + if (rename(file2, file1) == -1) + err(1, "rename(%s, %s). %s:%d", file2, file1, + __FILE__, __LINE__); + } + } + + for (i = 0; i < size; i++) { + sprintf(file1,"p%05d.%05d", pid, i); + if (unlink(file1) == -1) + err(1, "unlink(%s), %s:%d", file1, __FILE__, __LINE__); + } +} + +int +test(void) +{ + test_rename(); + + return (0); +} diff --git a/test/stress/stress2/testcases/run/Makefile b/test/stress/stress2/testcases/run/Makefile new file mode 100644 index 0000000000..49cd4ea3c7 --- /dev/null +++ b/test/stress/stress2/testcases/run/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=run + +.include diff --git a/test/stress/stress2/testcases/run/run.c b/test/stress/stress2/testcases/run/run.c new file mode 100644 index 0000000000..16543717bf --- /dev/null +++ b/test/stress/stress2/testcases/run/run.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Control program to run all the other test cases */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define MAXAV 10 +static char *av[MAXAV]; +static int loop = 1; + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +static char ** +mkargv(char *name) +{ + av[0] = name; + av[1] = 0; + return (av); +} + +static void +clean(void) +{ + char buf[132]; + + /* cleanup after the syscall test */ + snprintf(buf, sizeof(buf), + "cd %s; find . -type d -mtime -1 -exec chmod 777 {} \\;", op->wd); + (void)system(buf); + snprintf(buf, sizeof(buf), + "cd %s; find . -type f -mtime -1 -exec chmod 666 {} \\;", op->wd); + (void)system(buf); + snprintf(buf, sizeof(buf), + "cd %s; chflags \"nouappnd nouchg nouunlnk\" .", op->wd); + (void)system(buf); + snprintf(buf, sizeof(buf), + "cd %s; rm -rf syscall.[0-9]* fifo.[0-9]* creat.[0-9]* " + "p[0-9]*.d1 df lock", op->cd); + (void)system(buf); +} + +int +test(void) +{ + int i; + int s; + pid_t *r; + char fullpath[MAXPATHLEN+1]; + time_t t; + char ct[80]; + struct tm *tm; + + r = (pid_t *)malloc(op->argc * sizeof(pid_t)); + + (void)time(&t); + tm = localtime(&t); + (void) strftime(ct, sizeof(ct), "%T", tm); + printf("%s Loop #%d\n", ct, loop++); + + for (i = 0; i < op->argc; i++) { + if ((r[i] = fork()) == 0) { + snprintf(fullpath, sizeof(fullpath), "%s/%s", home, + op->argv[i]); + if (execv(fullpath, mkargv(basename(op->argv[i]))) == -1) + err(1, "execl(%s), %s:%d", fullpath, __FILE__, + __LINE__); + } + if (r[i] < 0) + err(1, "fork(), %s:%d", __FILE__, __LINE__); + } + for (i = 0; i < op->argc; i++) + if (r[i] != 0 && waitpid(r[i], &s, 0) == -1) + err(1, "waitpid(%d), %s:%d", r[i], __FILE__, __LINE__); + free(r); + + clean(); + + return (0); +} diff --git a/test/stress/stress2/testcases/rw/Makefile b/test/stress/stress2/testcases/rw/Makefile new file mode 100644 index 0000000000..597cda0ec4 --- /dev/null +++ b/test/stress/stress2/testcases/rw/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= rw + +.include diff --git a/test/stress/stress2/testcases/rw/rw.c b/test/stress/stress2/testcases/rw/rw.c new file mode 100644 index 0000000000..ed17a20166 --- /dev/null +++ b/test/stress/stress2/testcases/rw/rw.c @@ -0,0 +1,181 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Write and check read a file */ + +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static int starting_dir; +static unsigned long size; + +#define MAXSIZE 256 * 1024 + +int +setup(int nb) +{ + int64_t bl; + int64_t in; + int64_t reserve_in; + int64_t reserve_bl; + int pct; + + if (nb == 0) { + getdf(&bl, &in); + size = bl / op->incarnations / 1024; + + pct = 90; + if (op->hog == 0) + pct = random_int(1, 90); + size = size / 100 * pct + 1; + + if (size > MAXSIZE) + size = MAXSIZE; /* arbitrary limit size pr. incarnation */ + + /* Resource requirements: */ + while (size > 0) { + reserve_in = 2 * op->incarnations + 1; + reserve_bl = size * 1024 * op->incarnations + + (512 * 1024 * op->incarnations) + + 64 * 1024; +// printf("-- size = %lu, reserve(%jd, %jd)\n", size, reserve_bl/1024, reserve_in); + if (reserve_bl <= bl && reserve_in <= in) + break; + size = size - 1024; + } + if (size == 0) + reserve_bl = reserve_in = 0; + + if (op->verbose > 1) + printf("rw(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + size = size * 1024; + } else { + size = getval(); + size = size * 1024; + } + + umask(0); + sprintf(path,"%s.%05d", getprogname(), getpid()); + (void)mkdir(path, 0770); + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + if ((starting_dir = open(".", 0)) < 0) + err(1, "."); + + + return (0); +} + +void +cleanup(void) +{ + if (size == 0) + return; + if (fchdir(starting_dir) == -1) + err(1, "fchdir()"); + if (close(starting_dir) < 0) + err(1, "close(starting_dir:%d)", starting_dir); + + (void)system("find . -delete"); + + if (chdir("..") == -1) + err(1, "chdir(..)"); + if (rmdir(path) == -1) + err(1, "rmdir(%s), %s:%d", path, __FILE__, __LINE__); + size = 0; +} + +int +test(void) +{ + int buf[1024], index, to; +#ifdef TEST + int i; +#endif + int fd; + char file[128]; + + + sprintf(file,"p%05d", getpid()); + if ((fd = creat(file, 0660)) == -1) + err(1, "creat(%s)", file); + + to = sizeof(buf); + index = 0; + while (index < size) { + if (index + to > size) + to = size - index; +#ifdef TEST + for (i = 0; i < to; i++) + buf[i] = index + i; +#endif + index += to; + if (write(fd, buf, to) != to) + err(1, "write(%s), %s:%d", file, __FILE__, __LINE__); + } + if (close(fd) == -1) + err(1, "close(%s), %s:%d", file, __FILE__, __LINE__); + + if ((fd = open(file, O_RDONLY)) == -1) + err(1, "open(%s), %s:%d", file, __FILE__, __LINE__); + + index = 0; + while (index < size && done_testing == 0) { + if (index + to > size) + to = size - index; + if (read(fd, buf, to) != to) + err(1, "rw read. %s.%d", __FILE__, __LINE__); +#ifdef TEST + for (i = 0; i < to; i++) { + if (buf[i] != index + i) { + fprintf(stderr, + "%s, pid %d: expected %d @ %d, got %d\n", + getprogname(), getpid(), index+i, index+i, + buf[i]); + exit(EXIT_FAILURE); + } + } +#endif + index += to; + } + if (close(fd) == -1) + err(1, "close(%s), %s:%d", file, __FILE__, __LINE__); + if (unlink(file) == -1) + err(1, "unlink(%s), %s:%d", file, __FILE__, __LINE__); + return (0); +} diff --git a/test/stress/stress2/testcases/shm/Makefile b/test/stress/stress2/testcases/shm/Makefile new file mode 100644 index 0000000000..e30b93faba --- /dev/null +++ b/test/stress/stress2/testcases/shm/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= shm +LDADD= -lutil + +.include diff --git a/test/stress/stress2/testcases/shm/shm.c b/test/stress/stress2/testcases/shm/shm.c new file mode 100644 index 0000000000..3c6e1c9b45 --- /dev/null +++ b/test/stress/stress2/testcases/shm/shm.c @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Test shared memory */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +int shmid = -1; +key_t shmkey; +char *shm_buf; + +int semid = -1; +key_t semkey; +struct sembuf sop[2]; + +size_t pgsize; +pid_t pid; + +int +setup(int nb) +{ + int seed; + + pgsize = sysconf(_SC_PAGESIZE); + + seed = getpid(); +// printf("seed(%d) = %d\n", getpid(), seed); + shmkey = ftok("/tmp", seed); + if ((shmid = shmget(shmkey, 10 * pgsize, IPC_CREAT | IPC_EXCL | 0640)) == -1) { + if (errno == ENOSPC) { + fprintf(stderr, "Max number of semaphores reached.\n"); + exit(1); + } + err(1, "shmget (%s:%d)", __FILE__, __LINE__); + } + + shm_buf = 0; + if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1) + err(1, "sender: shmat (%s:%d)", __FILE__, __LINE__); + +// printf("seed(%d) = %d\n", getpid(), seed); + semkey = ftok("/var", seed); + if ((semid = semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0640)) == -1) { + if (errno == ENOSPC) { + fprintf(stderr, "Max number of semaphores reached.\n"); + exit(1); + } + err(1, "semget (%s:%d)", __FILE__, __LINE__); + } + /* Initialize the semaphore. */ + sop[0].sem_num = 0; + sop[0].sem_op = 0; /* This is the number of runs without queuing. */ + sop[0].sem_flg = 0; + sop[1].sem_num = 1; + sop[1].sem_op = 0; /* This is the number of runs without queuing. */ + sop[1].sem_flg = 0; + if (semop(semid, sop, 2) == -1) + err(1, "init: semop (%s:%d)", __FILE__, __LINE__); + return (0); +} + +void +cleanup(void) +{ + if (shmid != -1) + if (shmctl(shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) + warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); + if (semid != -1) + if (semctl(semid, 0, IPC_RMID, 0) == -1 && errno != EINVAL) + warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); +} + +static void +Wait(int i) { + sop[0].sem_num = i; + sop[0].sem_op = -1; + if (semop(semid, sop, 1) == -1) { + if (errno != EINTR && errno != EIDRM && errno != EINVAL) + warn("Wait: semop (%s:%d)", __FILE__, __LINE__); + done_testing = 1; + } +} + +static void +Sig(int i) { + sop[0].sem_num = i; + sop[0].sem_op = 1; + if (semop(semid, sop, 1) == -1) { + if (errno != EINTR && errno != EIDRM && errno != EINVAL) + warn("Sig: semop (%s:%d)", __FILE__, __LINE__); + done_testing = 1; + } +} + +int +test(void) +{ + int i = 0; + + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(2); + } + + if (pid == 0) { /* child */ + i = 0; + for (;;) { + Wait(1); + if (done_testing == 1) + break; + if (shm_buf[i] != (i % 128)) { + fprintf(stderr, + "child %d: expected %d, got %d\n", + getpid(), i % 128, shm_buf[i]); + break; + } + shm_buf[i] = 0; + i = (i + 1) % (10 * pgsize); + shm_buf[i] = (i % 128); + i = (i + 1) % (10 * pgsize); + Sig(0); + } + exit(0); + + } else { /* parent */ + i = 0; + for (;;) { + shm_buf[i] = (i % 128); + Sig(1); + i = (i + 1) % (10 * pgsize); + Wait(0); + if (done_testing == 1) + break; + if (shm_buf[i] != (i % 128)) { + fprintf(stderr, + "parent(%d): expected %d, got %d\n", + getpid(), i % 128, shm_buf[i]); + break; + } + shm_buf[i] = 0; + i = (i + 1) % (10 * pgsize); + } + kill(pid, SIGHUP); + kill(pid, SIGKILL); + } + return (0); +} diff --git a/test/stress/stress2/testcases/socket/Makefile b/test/stress/stress2/testcases/socket/Makefile new file mode 100644 index 0000000000..c31d950fdd --- /dev/null +++ b/test/stress/stress2/testcases/socket/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=socket + +.include diff --git a/test/stress/stress2/testcases/socket/socket.c b/test/stress/stress2/testcases/socket/socket.c new file mode 100644 index 0000000000..6a7dd9bdf9 --- /dev/null +++ b/test/stress/stress2/testcases/socket/socket.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define NB (400 * 1024 * 1024) + +int port; +int bufsize; +int sv[2]; + +static void +reader(void) { + int n, t, *buf; + + t = 0; + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + while (done_testing == 0) { + if ((n = read(sv[0], buf, bufsize)) < 0) + err(1, "read(), %s:%d", __FILE__, __LINE__); + t += n; + if (n == 0) break; + } + close(sv[0]); + return; +} + +static void +writer(void) { + int i, *buf, r; + + if (r < 0) + err(1, "connect(), %s:%d", __FILE__, __LINE__); + + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + for (i = 0; i < bufsize / sizeof(int); i++) + buf[i] = i; + + for (;;) { + for (i = 0; i < NB; i+= bufsize) { + if (write(sv[1], buf, bufsize) < 0) { + if (errno == EPIPE) + return; + err(1, "write(%d), %s:%d", sv[1], + __FILE__, __LINE__); + } + } + } + return; +} + +int +setup(int nb) +{ + port = 12340 + nb; + bufsize = 2 << random_int(2, 12); + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + pid_t pid; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) != 0) + err(1, "socketpair()"); + if ((pid = fork()) == 0) { + writer(); + exit(EXIT_SUCCESS); + + } else if (pid > 0) { + reader(); + kill(pid, SIGINT); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + + return (0); +} diff --git a/test/stress/stress2/testcases/swap/Makefile b/test/stress/stress2/testcases/swap/Makefile new file mode 100644 index 0000000000..509db0ded5 --- /dev/null +++ b/test/stress/stress2/testcases/swap/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=swap + +.include diff --git a/test/stress/stress2/testcases/swap/swap.c b/test/stress/stress2/testcases/swap/swap.c new file mode 100644 index 0000000000..77d2bef1e1 --- /dev/null +++ b/test/stress/stress2/testcases/swap/swap.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "stress.h" + +static unsigned long size; + +int +setup(int nb) +{ + int pct; + unsigned long mem; + int64_t swapinfo = 0; + struct rlimit rlp; + + if (nb == 0) { + mem = usermem(); + swapinfo = swap(); + if (swapinfo > mem) + swapinfo = mem; + + if (op->hog == 0) + pct = random_int(1, 10); + + if (op->hog == 1) + pct = random_int(10, 20); + + if (op->hog == 2) + pct = random_int(80, 90); + + if (op->hog >= 3) + pct = random_int(100, 110); + + if (swapinfo == 0) + size = mem / 100 * pct; + else + size = swapinfo / 100 * pct + mem; + + size = size / op->incarnations; + + if (getrlimit(RLIMIT_DATA, &rlp) < 0) + err(1,"getrlimit"); + rlp.rlim_cur -= 1024 * 1024; + + if (size > rlp.rlim_cur) + size = rlp.rlim_cur; + putval(size); + + + if (op->verbose > 1 && nb == 0) + printf("setup: pid %d, %d%%. Total %luMb\n", + getpid(), pct, size / 1024 / 1024 * op->incarnations); + } else + size = getval(); + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + char *c; + int i, page; + unsigned long oldsize = size; + time_t start; + + c = malloc(size); + while (c == NULL && done_testing == 0) { + size -= 1024 * 1024; + c = malloc(size); + } + if (op->verbose > 1 && size != oldsize) + printf("Malloc size changed from %ld Mb to %ld Mb\n", + oldsize / 1024 / 1024, size / 1024 / 1024); + page = getpagesize(); + start = time(NULL); /* Livelock workaround */ + while (done_testing == 0 && + (time(NULL) - start) < op->run_time) { + i = 0; + while (i < size && done_testing == 0) { + c[i] = 0; + i += page; + } +#if 0 + if (op->hog != 1) + usleep(1000); +#endif + } + free(c); + + return (0); +} diff --git a/test/stress/stress2/testcases/symlink/Makefile b/test/stress/stress2/testcases/symlink/Makefile new file mode 100644 index 0000000000..77fe9e8d2a --- /dev/null +++ b/test/stress/stress2/testcases/symlink/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=symlink + +.include diff --git a/test/stress/stress2/testcases/symlink/symlink.c b/test/stress/stress2/testcases/symlink/symlink.c new file mode 100644 index 0000000000..9d955ae265 --- /dev/null +++ b/test/stress/stress2/testcases/symlink/symlink.c @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static unsigned long size; + +int +setup(int nb) +{ + int pct; + int64_t in; + int64_t bl; + int64_t reserve_in; + int64_t reserve_bl; + + umask(0); + if (nb == 0) { + getdf(&bl, &in); + size = in / op->incarnations; + + pct = 90; + if (op->hog == 0) + pct = random_int(1, 90); + size = size / 100 * pct + 1; + + if (size > 20000) + size = 20000; /* arbitrary limit number of files pr. dir */ + + /* Resource requirements: */ + while (size > 0) { + reserve_in = 1 * size * op->incarnations; + reserve_bl = 36 * size * op->incarnations; +// printf("size = %lu, reserve(%jd, %jd)\n", size, reserve_bl/1024, reserve_in); + if (reserve_bl <= bl && reserve_in <= in) + break; + size--; + } + if (size == 0) + reserve_bl = reserve_in = 0; + + if (op->verbose > 1) + printf("symlink(size=%lu, incarnations=%d). Free(%jdk, %jd), reserve(%jdk, %jd)\n", + size, op->incarnations, bl/1024, in, reserve_bl/1024, reserve_in); + reservedf(reserve_bl, reserve_in); + putval(size); + } else { + size = getval(); + } + + sprintf(path,"%s.%05d", getprogname(), getpid()); + if (mkdir(path, 0770) < 0) + err(1, "mkdir(%s), %s:%d", path, __FILE__, __LINE__); + + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + + return (0); +} + +void +cleanup(void) +{ + (void)chdir(".."); + if (rmdir(path) == -1) { + warn("rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } +} + +int +test(void) +{ + int i, j, error = 0; + pid_t pid; + char file[128]; + + pid = getpid(); + for (j = 0; j < size && done_testing == 0; j++) { + sprintf(file,"p%05d.%05d", pid, j); + if (symlink("/tmp/not/there", file) == -1) { + if (errno != EINTR) { + warn("symlink(%s). %s.%d", file, __FILE__, __LINE__); + error = 1; +/* printf("break out at %d, errno %d\n", j, errno);*/ + exit(1); + break; + } + } + if (j % 4000) sleep(1); + } + + for (i = --j; i >= 0; i--) { + sprintf(file,"p%05d.%05d", pid, i); + if (unlink(file) == -1) + err(3, "unlink(%s)", file); + } + + if (error != 0) + exit(1); + + return (0); +} diff --git a/test/stress/stress2/testcases/syscall/Makefile b/test/stress/stress2/testcases/syscall/Makefile new file mode 100644 index 0000000000..91bb2e5af6 --- /dev/null +++ b/test/stress/stress2/testcases/syscall/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=syscall + +.include diff --git a/test/stress/stress2/testcases/syscall/syscall.c b/test/stress/stress2/testcases/syscall/syscall.c new file mode 100644 index 0000000000..0392654348 --- /dev/null +++ b/test/stress/stress2/testcases/syscall/syscall.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Call random system calls with random arguments */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static char path[128]; +static int num; +static int starting_dir = 0; + +static int ignore[] = { + SYS_syscall, + SYS_exit, + SYS_fork, + 11, /* 11 is obsolete execv */ + SYS_unmount, + SYS_reboot, + SYS_vfork, + 109, /* 109 is old sigblock */ + 111, /* 111 is old sigsuspend */ + SYS_shutdown, + SYS___syscall, + SYS_rfork, + SYS_sigsuspend, +// SYS_mac_syscall, + SYS_sigtimedwait, + SYS_sigwaitinfo, +}; + +int +setup(int nb) +{ + int i; + struct rlimit rl; + + umask(0); + sprintf(path,"%s.%05d", getprogname(), getpid()); + (void)mkdir(path, 0770); + if (chdir(path) == -1) + err(1, "chdir(%s), %s:%d", path, __FILE__, __LINE__); + if ((starting_dir = open(".", 0)) < 0) + err(1, "."); + + if (op->argc == 1) { + num = atoi(op->argv[0]); + for (i = 0; i < sizeof(ignore) / sizeof(ignore[0]); i++) + if (num == ignore[i]) { + printf("syscall %d is marked a no test!\n", num); + exit(1); + } + } else { + num = 0; + while (num == 0) { + num = random_int(0, SYS_MAXSYSCALL); + for (i = 0; i < sizeof(ignore) / sizeof(ignore[0]); i++) + if (num == ignore[i]) { + num = 0; + break; + } + } + } + if (op->verbose > 1) + printf("Testing syscall #%d, pid %d\n", num, getpid()); + + /* Multiple parallel core dump may panic the kernel with: + panic: kmem_malloc(184320): kmem_map too small: 84426752 total allocated + */ + rl.rlim_max = rl.rlim_cur = 0; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + warn("setrlimit"); + + setproctitle("#%d", num); + + return (0); +} + +void +cleanup(void) +{ + if (starting_dir != 0) { + if (fchdir(starting_dir) == -1) + err(1, "fchdir()"); + (void)system("find . -type d -exec chmod 777 {} \\;"); + (void)system("find . -type f -exec chmod 666 {} \\;"); + (void)system("find . -delete"); + + if (chdir("..") == -1) + err(1, "chdir(..)"); + if (rmdir(path) == -1) + err(1, "rmdir(%s), %s:%d", path, __FILE__, __LINE__); + } + starting_dir = 0; +} + +int +test(void) +{ + int i; + unsigned int arg1, arg2, arg3, arg4, arg5, arg6, arg7; + + for (i = 0; i < 128; i++) { + arg1 = arc4random(); + arg2 = arc4random(); + arg3 = arc4random(); + arg4 = arc4random(); + arg5 = arc4random(); + arg6 = arc4random(); + arg7 = arc4random(); + + if (op->verbose > 3) + printf("%2d : syscall(%3d, %x, %x, %x, %x, %x, %x, %x)\n", + i, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } +#if 0 + while (done_testing == 0) + sleep(1); +#endif + + return (0); +} diff --git a/test/stress/stress2/testcases/sysctl/Makefile b/test/stress/stress2/testcases/sysctl/Makefile new file mode 100644 index 0000000000..3785ed3d46 --- /dev/null +++ b/test/stress/stress2/testcases/sysctl/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= sysctl + +.include diff --git a/test/stress/stress2/testcases/sysctl/sysctl.c b/test/stress/stress2/testcases/sysctl/sysctl.c new file mode 100644 index 0000000000..231de58e4c --- /dev/null +++ b/test/stress/stress2/testcases/sysctl/sysctl.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +/* Call sysctl(8) and fstat(1) a few times */ + +#include +#include +#include +#include + +#include "stress.h" + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + + +int +test(void) +{ + int i; + + for (i = 0; i < 64 && done_testing == 0; i++) { + if (system("sysctl -a > /dev/null 2>&1") == -1) + err(1, "system(\"sysctl -a\"), %s:%d", __FILE__, __LINE__); + + if (system("fstat > /dev/null 2>&1") == -1) + err(1, "system(\"fstat\"), %s:%d", __FILE__, __LINE__); + sleep(1); + } + return (0); +} diff --git a/test/stress/stress2/testcases/tcp/Makefile b/test/stress/stress2/testcases/tcp/Makefile new file mode 100644 index 0000000000..941c2863c4 --- /dev/null +++ b/test/stress/stress2/testcases/tcp/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=tcp + +.include diff --git a/test/stress/stress2/testcases/tcp/tcp.c b/test/stress/stress2/testcases/tcp/tcp.c new file mode 100644 index 0000000000..92e006c665 --- /dev/null +++ b/test/stress/stress2/testcases/tcp/tcp.c @@ -0,0 +1,179 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define NB (400 * 1024 * 1024) + +int port; +int bufsize; + +static void +reader(void) { + int tcpsock, msgsock; + int on; + socklen_t len; + struct sockaddr_in inetaddr, inetpeer; + int n, t, *buf; + + on = 1; + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) + err(1, "bind(), %s:%d", __FILE__, __LINE__); + + if (listen(tcpsock, 5) < 0) + err(1, "listen(), %s:%d", __FILE__, __LINE__); + + if ((random_int(1,100) > 60) || (op->hog == 1)) { + usleep(random_int(1000000,1000000) * 60); + } + + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) + err(1, "accept(), %s:%d", __FILE__, __LINE__); + + t = 0; + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + while (done_testing == 0) { + if ((n = read(msgsock, buf, bufsize)) < 0) + err(1, "read(), %s:%d", __FILE__, __LINE__); + t += n; + if (n == 0) break; + } + close(msgsock); + return; +} + +static void +writer(void) { + int tcpsock, on; + struct sockaddr_in inetaddr; + struct hostent *hostent; + int i, *buf, r; + + on = 1; + for (i = 1; i < 5; i++) { + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + hostent = gethostbyname ("localhost"); + memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + r = connect(tcpsock, (struct sockaddr *) &inetaddr, + sizeof(inetaddr)); + if (r == 0) + break; + sleep(1); + close(tcpsock); + } + if (r < 0) + err(1, "connect(), %s:%d", __FILE__, __LINE__); + + if ((buf = malloc(bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + for (i = 0; i < bufsize / sizeof(int); i++) + buf[i] = i; + + for (;;) { + for (i = 0; i < NB; i+= bufsize) { + if (write(tcpsock, buf, bufsize) < 0) { + if (errno == EPIPE) + return; + err(1, "write(%d), %s:%d", tcpsock, + __FILE__, __LINE__); + } + } + } + return; +} + +int +setup(int nb) +{ + port = 12340 + nb; + bufsize = 2 << random_int(1, 12); + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + pid_t pid; + + if ((pid = fork()) == 0) { + writer(); + exit(EXIT_SUCCESS); + + } else if (pid > 0) { + reader(); + kill(pid, SIGINT); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + + return (0); +} diff --git a/test/stress/stress2/testcases/thr1/Makefile b/test/stress/stress2/testcases/thr1/Makefile new file mode 100644 index 0000000000..f9e5f5d39a --- /dev/null +++ b/test/stress/stress2/testcases/thr1/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= thr1 + +.include + +CFLAGS+= -pthread diff --git a/test/stress/stress2/testcases/thr1/thr1.c b/test/stress/stress2/testcases/thr1/thr1.c new file mode 100644 index 0000000000..d86b9f49bd --- /dev/null +++ b/test/stress/stress2/testcases/thr1/thr1.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define NTHREADS 256 + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +void * +thr_routine(void *arg) +{ + (void) getpid(); + return (0); +} + +int +test(void) +{ + pthread_t threads[NTHREADS]; + int i; + int r; + + for (i = 0; i < NTHREADS; i++) + if ((r = pthread_create(&threads[i], NULL, thr_routine, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + for (i = 0; i < NTHREADS; i++) + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + + return (0); +} diff --git a/test/stress/stress2/testcases/thr2/Makefile b/test/stress/stress2/testcases/thr2/Makefile new file mode 100644 index 0000000000..efa1aec14d --- /dev/null +++ b/test/stress/stress2/testcases/thr2/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= thr2 + +.include + +CFLAGS+= -pthread diff --git a/test/stress/stress2/testcases/thr2/thr2.c b/test/stress/stress2/testcases/thr2/thr2.c new file mode 100644 index 0000000000..052cbd5317 --- /dev/null +++ b/test/stress/stress2/testcases/thr2/thr2.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +#define NTHREADS 256 + +volatile int done = 0; + +int +setup(int nb) +{ + return (0); +} + +void +cleanup(void) +{ +} + +void * +thr1(void *arg) +{ + return (0); +} + +void * +thr2(void *arg) +{ + while (done == 0) + pthread_yield(); + return (0); +} + +int +test(void) +{ + pthread_t threads[NTHREADS]; + int i; + int r; + + for (i = 0; i < NTHREADS; i++) + if ((r = pthread_create(&threads[i], NULL, thr1, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + + for (i = 0; i < NTHREADS; i++) + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + + for (i = 0; i < NTHREADS; i++) + if ((r = pthread_create(&threads[i], NULL, thr2, 0)) != 0) + err(1, "pthread_create(): %s\n", strerror(r)); + done = 1; + + for (i = 0; i < NTHREADS; i++) + if (pthread_join(threads[i], NULL) != 0) + err(1, "pthread_join(%d)", i); + + return (0); +} diff --git a/test/stress/stress2/testcases/udp/Makefile b/test/stress/stress2/testcases/udp/Makefile new file mode 100644 index 0000000000..442ed66cca --- /dev/null +++ b/test/stress/stress2/testcases/udp/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG=udp + +.include diff --git a/test/stress/stress2/testcases/udp/udp.c b/test/stress/stress2/testcases/udp/udp.c new file mode 100644 index 0000000000..9a75b0ea1f --- /dev/null +++ b/test/stress/stress2/testcases/udp/udp.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +/*#include */ +#include +#include +#include +#include +#include +#include +#include + +#include "stress.h" + +static int bufsize; + +int +setup(int nb) +{ + bufsize = 2 << random_int(1, 12); + return (0); +} + +void +cleanup(void) +{ +} + +int +test(void) +{ + struct sockaddr_in sock_in; + struct hostent *host; + char *hostname; + int f, i, n; + int *buf; + + bzero((char *)&sock_in, sizeof(sock_in)); + sock_in.sin_family = AF_INET; + f = socket(AF_INET, SOCK_DGRAM, 0); + if (f < 0) + err(1, "socket"); + if (bind(f, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0) { + warn("bind"); + return (1); + } + if (getenv("BLASTHOST") == NULL) + hostname = "localhost"; + else + hostname = getenv("BLASTHOST"); + host = gethostbyname(hostname); + if (host) { + sock_in.sin_family = host->h_addrtype; + bcopy(host->h_addr, &sock_in.sin_addr, host->h_length); + } else { + sock_in.sin_family = AF_INET; + sock_in.sin_addr.s_addr = inet_addr(hostname); + if (sock_in.sin_addr.s_addr == -1) { + err(1, "host: %s", hostname); + } + } + sock_in.sin_port = htons(9); + + if (connect(f, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0) + err(1, "connect"); + + if ((buf = calloc(1, bufsize)) == NULL) + err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); + + if (op->verbose > 1) + printf("udp %s:9 with %d bytes\n", hostname, bufsize); + for (i = 0; i < 128 && done_testing == 0; i++) { + n = write(f, buf, bufsize); + if (n == -1 && errno == ENOBUFS) + continue; + if (n == -1 && errno == ECONNREFUSED) + break; + if (n == -1) + err(1, "write(%d) #%d", bufsize, i); + if (n == 0) break; + } + free(buf); + close(f); + return (0); +} diff --git a/test/stress/stress2/tools/df.sh b/test/stress/stress2/tools/df.sh new file mode 100755 index 0000000000..7389ec0580 --- /dev/null +++ b/test/stress/stress2/tools/df.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Trace the df of RUNDIR + +. ../default.cfg + +old=x +while true;do + d=`df -i $RUNDIR | tail -1` + p1=`echo $d | awk '{print $5}' | sed 's/\%//'` + p2=`echo $d | awk '{print $8}' | sed 's/\%//'` + [ $p1 -lt 80 -a $p2 -lt 80 -a $old != x ] && continue + [ "$old" != "$d" ] && echo `date '+%T'` $d + old=$d + sleep 30 +done diff --git a/test/stress/stress2/tools/freeze.sh b/test/stress/stress2/tools/freeze.sh new file mode 100755 index 0000000000..de37b67419 --- /dev/null +++ b/test/stress/stress2/tools/freeze.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Freeze detection script + +while true; do + t1=`date '+%s'` + sleep 60 + t2=`date '+%s'` + delta=$((t2 - $t1)) + if [ $delta -gt 120 ]; then + d1=`date -j -f '%s' '+%T' $t1` + d2=`date -j -f '%s' '+%T' $t2` + e=` date -u -j -f '%s' '+%T' $delta` + echo "Freeze from $d1 to $d2, $e elapsed." + fi +done diff --git a/test/stress/stress2/tools/freeze2.sh b/test/stress/stress2/tools/freeze2.sh new file mode 100755 index 0000000000..7225665b77 --- /dev/null +++ b/test/stress/stress2/tools/freeze2.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Freeze detection script + +while true; do + t1=`date '+%s'` + ls -l /var > /dev/null + sleep 30 + t2=`date '+%s'` + delta=$((t2 - $t1)) + if [ $delta -gt 120 ]; then + d1=`date -j -f '%s' '+%T' $t1` + d2=`date -j -f '%s' '+%T' $t2` + e=` date -u -j -f '%s' '+%T' $delta` + echo "Freeze from $d1 to $d2, $e elapsed." + fi +done diff --git a/test/stress/stress2/tools/fstool.c b/test/stress/stress2/tools/fstool.c new file mode 100644 index 0000000000..90eecebff7 --- /dev/null +++ b/test/stress/stress2/tools/fstool.c @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int files = 5; +static int fs = 1024; +static char *buffer; +static int max; + +void +error(char *op, char* arg, char* file, int line) { + fprintf(stderr,"%s. %s. %s (%s:%d)\n", + op, arg, sys_errlist[errno], file, line); +} + +void +mkDir(char *path, int level) { + int fd, j; + char newPath[MAXPATHLEN + 1]; + char file[128]; + + if (mkdir(path, 0770) == -1) { + error("mkdir", path, __FILE__, __LINE__); + fprintf(stderr, "length(path) = %d\n", strlen(path)); + fprintf(stderr, ") level = %d\n", level); + exit(2); + } + chdir(path); + + for (j = 0; j < files; j++) { + sprintf(file,"f%05d", j); + if ((fd = creat(file, 0660)) == -1) { + if (errno != EINTR) { + err(1, "%d: creat(%s)", level, file); + break; + } + } + if (write(fd, buffer, fs) != fs) + err(1, "%d: write(%s), %s:%d", level, file, __FILE__, __LINE__); + + if (fd != -1 && close(fd) == -1) + err(2, "%d: close(%d)", level, j); + + } + + if (level < max) { + sprintf(newPath,"d%d", level+1); + mkDir(newPath, level+1); + } +} + +static void +rmFile(void) +{ + int j; + char file[128]; + + for (j = 0; j < files; j++) { + sprintf(file,"f%05d", j); + (void) unlink(file); + } +} + +void +rmDir(char *path, int level) { + char newPath[10]; + + + if (level < max) { + sprintf(newPath,"d%d", level+1); + rmDir(newPath, level+1); + } + rmFile(); + chdir (".."); + if (rmdir(path) == -1) { + error("rmdir", path, __FILE__, __LINE__); + exit(2); + } +} + +void +rmDir2(char *path, int level) { + char newPath[10]; + char help[80]; + + rmFile(); + chdir(path); + sprintf(newPath,"d%d", level+1); + if (access(newPath, R_OK) == 0) + rmDir2(newPath, level+1); + chdir (".."); + if (rmdir(path) == -1) { + error("rmdir", path, __FILE__, __LINE__); + sprintf(help, "rm -rf ./%s", path); + system(help); + } +} + +int +main(int argc, char **argv) +{ + int c, levels = 1, leave = 0; + char path[128], rpath[128] = ""; + char ch = 0; + extern char *optarg; + pid_t pid; + + while ((c = getopt(argc, argv, "ln:r:f:s:")) != -1) + switch (c) { + case 'l': + leave = 1; + break; + case 'r': + strcpy(rpath, optarg); + break; + case 'n': + levels = atoi(optarg); + break; + case 'f': + files = atoi(optarg); + break; + case 's': + sscanf(optarg, "%d%c", &fs, &ch); + if (ch == 'k' || ch == 'K') + fs = fs * 1024; + if (ch == 'm' || ch == 'M') + fs = fs * 1024 * 1024; + break; + default: + fprintf(stderr, + "Usage: %s {-l} | {-n } | -r | -s " + "-f \n", + argv[0]); + printf(" -l: Leave the files.\n"); + printf(" -r: Remove an old tree.\n"); + printf(" -n: Tree depth.\n"); + printf(" -f: Number of files.\n"); + printf(" -s: Size of each file.\n"); + exit(1); + } + + + max = levels; + pid = getpid(); + if ((buffer = calloc(1, fs)) == NULL) + err(1, "calloc(%d)", fs); + + if (strlen(rpath) > 0) { + rmDir2(rpath,1); + } else { + umask(0); + sprintf(path,"p%05d.d%d", pid, 1); + mkDir(path, 1); + if (leave == 0) rmDir(path, 1); + } + return 0; +} diff --git a/test/stress/stress2/tools/iwatch.sh b/test/stress/stress2/tools/iwatch.sh new file mode 100755 index 0000000000..18c8a29805 --- /dev/null +++ b/test/stress/stress2/tools/iwatch.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Watch max inode usage in RUNDIR + +. ../default.cfg + +[ ! -d $RUNDIR ] && mkdir $RUNDIR +imax=0 +kmax=0 +istart=`df -ik $RUNDIR | tail -1 | awk '{print $6}'` +kstart=`df -ik $RUNDIR | tail -1 | awk '{print $3}'` +while true;do + i=`df -ik $RUNDIR | tail -1 | awk '{print $6}'` + k=`df -ik $RUNDIR | tail -1 | awk '{print $3}'` + if [ $i -gt $imax -o $k -gt $kmax ]; then + imax=$i + kmax=$k + printf "%s %d %dk (%d %dk)\n" `date '+%T'` $i $k $((imax - istart)) $((kmax - kstart)) + fi + sleep 1 +done diff --git a/test/stress/stress2/tools/l3.sh b/test/stress/stress2/tools/l3.sh new file mode 100755 index 0000000000..7967b59a9a --- /dev/null +++ b/test/stress/stress2/tools/l3.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Script to catch possible leaks in vm, malloc and mbufs + +i=0 +while true; do + sysctl vm.kvm_free | tail -1 | sed 's/:/,/' + vmstat -z | grep VNODE: | awk '{print $1 "," $4}' | sed 's/,$//' + sleep 1 +done | awk -F, ' +{ +# Pairs of "name, value" are passed to this awk script + name=$1 + size=$2 + if (NF != 2) + print "Number of fields for ", name, "is ", NF + if (size == s[name]) + next; +# print "name, size, old minimum :", name, size, s[name] + + if ((size < s[name]) || (f[name] == 0)) { +# print "Initial value / new minimum", n[name], s[name], size + n[name] = 0 + s[name] = size + f[name] = 1 + } + + if (++n[name] > 120) { + cmd="date '+%T'" + cmd | getline t + close(cmd) + if (++w[name] > 10) + printf "%s \"%s\" may be leaking, size %d\n", t, name, size + n[name] = 0 + s[name] = size + } +}' diff --git a/test/stress/stress2/tools/leaks.sh b/test/stress/stress2/tools/leaks.sh new file mode 100755 index 0000000000..217ad0c14b --- /dev/null +++ b/test/stress/stress2/tools/leaks.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Script to catch possible leaks in vm, malloc and mbufs +# Report values growing in 10 consecuitive samples + +i=0 +while true; do + # Check for leaks in vm.zone + +# ITEM SIZE LIMIT USED FREE REQUESTS +# +# UMA Kegs: 140, 0, 66, 6, 66 +# UMA Zones: 120, 0, 66, 24, 66 + + + vmstat -z | sed '1,3d;s/://g' | \ + sed 's/ */ /g;s/\([0-9]\) *\([0-9]\)/\1,\2/g;s/ \([0-9]\)/,\1/;s/^ *//' | \ + awk -F, ' +/^..*$/{ + gsub("^ *", "", $1); + size=$4; + printf "vmstat -z %s,%s\n", $1, size; +} +' + # vmstat -m + + # Type InUse MemUse HighUse Requests Size(s) + # DEVFS3 168 21K - 169 128 + # DEVFS1 157 40K - 157 256 + # DEVFS 12 1K - 13 16,128 + vmstat -m | \ + sed '1,1d;s/K .*//;s/ [0-9][0-9]* //;s/ */ /g;s/^ *//;s/ /_/g;s/_\([0-9][0-9]*$\)/ \1/' | \ + awk '{printf "vmstat -m %s, %d\n", $1, $2}' + + # Check for leaks in mbufs + +# $ netstat -m +# 1233/597/1830 mbufs in use (current/cache/total) +# 1232/196/1428/8896 mbuf clusters in use (current/cache/total/max) +# 1232/74 mbuf+clusters out of packet secondary zone in use (current/cache) +# 0/0/0/0 4k (page size) jumbo clusters in use (current/cache/total/max) +# 0/0/0/0 9k jumbo clusters in use (current/cache/total/max) +# 0/0/0/0 16k jumbo clusters in use (current/cache/total/max) +# 2772K/541K/3313K bytes allocated to network (current/cache/total) +# 508/7778/5734 requests for mbufs denied (mbufs/clusters/mbuf+clusters) +# 0/0/0 requests for jumbo clusters denied (4k/9k/16k) +# 0/6/2480 sfbufs in use (current/peak/max) +# 0 requests for sfbufs denied +# 0 requests for sfbufs delayed +# 0 requests for I/O initiated by sendfile +# 251 calls to protocol drain routines + + + netstat -m | head -10 | sed 's#/# #g;s/k / /;s/K / /' | awk ' +/mbufs / {mbufs=$1}; +/ clusters/ {clusters=$2}; +/sfbufs in use/ {sfbufs=$3}; +/allocated/ {allocated=$1} +END { + print "mbufs,", mbufs; + print "clusters,", clusters; + print "sfbufs,", sfbufs; + print "allocatedToNetwork,", allocated; +} +' + sysctl vm.kvm_free | tail -1 | sed 's/:/,/' + sleep 10 +done | awk -F, ' +{ +# Pairs of "name, value" are passed to this awk script + name=$1; + size=$2; +# print "name, size :", name, size; + if (NF != 2) + print "Number of fields for ", name, "is ", NF; + if (size > s[name]) { + n[name]++; + if (n[name] > 10) { + cmd="date '+%T'"; + cmd | getline t; + close(cmd); + printf "%s \"%s\" may be leaking, size %d\n", t, name, size; + n[name] = 0; + } + s[name] = size; + } else { + if (n[name] > 0) + n[name]--; + } +}' diff --git a/test/stress/stress2/tools/leaks2.sh b/test/stress/stress2/tools/leaks2.sh new file mode 100755 index 0000000000..7adcd4b4a4 --- /dev/null +++ b/test/stress/stress2/tools/leaks2.sh @@ -0,0 +1,117 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Script to catch possible leaks in vm, malloc and mbufs +# This version looks for increse in minimum values + +i=0 +while true; do + # Check for leaks in vm.zone + +# ITEM SIZE LIMIT USED FREE REQUESTS +# +# UMA Kegs: 140, 0, 66, 6, 66 +# UMA Zones: 120, 0, 66, 24, 66 + + + vmstat -z | sed '1,3d;s/://g' | \ + sed 's/ */ /g;s/\([0-9]\) *\([0-9]\)/\1,\2/g;s/ \([0-9]\)/,\1/;s/^ *//' | \ + awk -F, ' +/^..*$/{ + gsub("^ *", "", $1); + size=$4; + printf "vmstat -z %s,%s\n", $1, size; +} +' + # Check for leaks in mbufs + +# $ netstat -m +# 1233/597/1830 mbufs in use (current/cache/total) +# 1232/196/1428/8896 mbuf clusters in use (current/cache/total/max) +# 1232/74 mbuf+clusters out of packet secondary zone in use (current/cache) +# 0/0/0/0 4k (page size) jumbo clusters in use (current/cache/total/max) +# 0/0/0/0 9k jumbo clusters in use (current/cache/total/max) +# 0/0/0/0 16k jumbo clusters in use (current/cache/total/max) +# 2772K/541K/3313K bytes allocated to network (current/cache/total) +# 508/7778/5734 requests for mbufs denied (mbufs/clusters/mbuf+clusters) +# 0/0/0 requests for jumbo clusters denied (4k/9k/16k) +# 0/6/2480 sfbufs in use (current/peak/max) +# 0 requests for sfbufs denied +# 0 requests for sfbufs delayed +# 0 requests for I/O initiated by sendfile +# 251 calls to protocol drain routines + + + netstat -m | head -10 | sed 's#/# #g;s/k / /;s/K / /' | awk ' +/mbufs / {mbufs=$1}; +/ clusters/ {clusters=$2}; +/sfbufs in use/ {sfbufs=$3}; +/allocated/ {allocated=$1} +END { + print "mbufs,", mbufs; + print "clusters,", clusters; + print "sfbufs,", sfbufs; + print "allocatedToNetwork,", allocated; +} +' +# sysctl vm.kvm_free | tail -1 | sed 's/:/,/' # Need used here! + sleep 1 +done | awk -F, ' +{ +# Pairs of "name, value" are passed to this awk script + name=$1 + size=$2 + if (NF != 2) + print "Number of fields for ", name, "is ", NF + if (size == s[name]) + next; +# print "name, size, old minimum :", name, size, s[name] + + if ((size - 10 < s[name]) || (f[name] == 0)) { +# print "Initial value / new minimum", n[name], s[name], size + n[name] = 0 + if (f[name] == 0) + f[name] = 1 + if (f[name] != 2) + s[name] = size + } + + if (++n[name] > 120) { + cmd="date '+%T'" + cmd | getline t + close(cmd) +# if (++w[name] > 4) { + printf "%s \"%s\" may be leaking, size %d\n", t, name, size + f[name] = 2 +# } + n[name] = 0 + s[name] = size + } +}' diff --git a/test/stress/stress2/tools/module/Makefile b/test/stress/stress2/tools/module/Makefile new file mode 100644 index 0000000000..e78be1c481 --- /dev/null +++ b/test/stress/stress2/tools/module/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +KMOD= ptest +SRCS= ptest.c + +CFLAGS+=-g + +.include diff --git a/test/stress/stress2/tools/module/ptest.c b/test/stress/stress2/tools/module/ptest.c new file mode 100644 index 0000000000..68df24a842 --- /dev/null +++ b/test/stress/stress2/tools/module/ptest.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2008 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int panic_type = 0; + +static int +sysctl_panic_type(SYSCTL_HANDLER_ARGS) +{ + int error, value; + volatile int i; + + /* Write out the old value. */ + error = SYSCTL_OUT(req, &panic_type, sizeof(int)); + if (error || req->newptr == NULL) + return (error); + + /* Read in and verify the new value. */ + error = SYSCTL_IN(req, &value, sizeof(int)); + if (error) + return (error); + if (value < 0) + return (EINVAL); + panic_type = value; + + if (panic_type == 1) + panic("Test panic type 1"); + + if (panic_type == 2) + i = *(int *)0; /* Fatal trap */ + + return (0); +} + + +SYSCTL_PROC(_debug, OID_AUTO, panic_type, CTLTYPE_INT|CTLFLAG_RW, + &panic_type, 0, sysctl_panic_type, "I", + "Test panic type"); + + +static int +ptest_modevent(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + return(0); + case MOD_UNLOAD: + return (0); + default: + break; + } + + return (0); +} + +moduledata_t ptest_mdata = { + "ptest", + ptest_modevent, + NULL +}; + +DECLARE_MODULE(ptest, ptest_mdata, SI_SUB_DRIVERS, SI_ORDER_ANY); +MODULE_VERSION(ptest, 1); diff --git a/test/stress/stress2/tools/monitor.sh b/test/stress/stress2/tools/monitor.sh new file mode 100755 index 0000000000..b0217b1bb6 --- /dev/null +++ b/test/stress/stress2/tools/monitor.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Script to monitor test box + +font="fixed" +xterm -geo 164x21+1+1 -fn "$font" \ + -T top \ + -e "sh -c \"ssh -t crashbox 'top -s 1';sleep 36000\""& +xterm -geo 164x5+1+307 -fn "$font" \ + -T leaks.sh \ + -e "sh -c \"ssh -n crashbox '~pho/stress2/tools/leaks.sh';sleep 36000\""& +xterm -geo 164x14+1+405 -fn "$font" \ + -T 'tail -F /var/log/messages' \ + -e "sh -c \"ssh crashbox 'tail -F /var/log/messages';sleep 36000\""& diff --git a/test/stress/stress2/tools/ptsleak.sh b/test/stress/stress2/tools/ptsleak.sh new file mode 100755 index 0000000000..147e5f3388 --- /dev/null +++ b/test/stress/stress2/tools/ptsleak.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Keep count of pts that hasn't been in use for the last 15 minutes + +max=0 +while true; do + n=`find /dev/pts -mtime +15m 2>/dev/null | wc -l` + if [ $n -gt $max ]; then + max=$n + echo "`date '+%T'` $n" + fi + sleep 30 +done diff --git a/test/stress/stress2/tools/ptyleak.sh b/test/stress/stress2/tools/ptyleak.sh new file mode 100755 index 0000000000..e4fa3f824c --- /dev/null +++ b/test/stress/stress2/tools/ptyleak.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Keep count of ptys that hasn't been in use for the last 15 minutes + +max=0 +while true; do + n=`find /dev -mtime +15m 2>/dev/null | \ + egrep "/dev/pty[p-sP-S][0-9a-v]|/dev/tty[p-sP-S][0-9a-v]" | wc -l` + if [ $n -gt $max ]; then + max=$n + echo "`date '+%T'` $n" + fi + sleep 30 +done diff --git a/test/stress/stress2/tools/rwatch.sh b/test/stress/stress2/tools/rwatch.sh new file mode 100755 index 0000000000..4f699b3f75 --- /dev/null +++ b/test/stress/stress2/tools/rwatch.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# +# Copyright (c) 2008 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$ +# + +# Watch disk resources for a test program + +. ../../default.cfg + +unset LOAD +unset runLOAD +unset swapLOAD +unset rwLOAD +unset mkdirLOAD +unset creatLOAD +unset symlinkLOAD + +[ ! -d $RUNDIR ] && mkdir $RUNDIR +imax=0 +kmax=0 +istart=`df -ik $RUNDIR | tail -1 | awk '{print $6}'` +kstart=`df -ik $RUNDIR | tail -1 | awk '{print $3}'` + +"$@" & + +while ps -p $! > /dev/null; do + i=`df -ik $RUNDIR | tail -1 | awk '{print $6}'` + k=`df -ik $RUNDIR | tail -1 | awk '{print $3}'` + if [ $i -gt $imax -o $k -gt $kmax ]; then + imax=$i + kmax=$k + fi + sleep 1 +done +printf "Disk usage: %d inodes and %dk\n" $((imax - istart)) $((kmax - kstart)) +wait diff --git a/test/stress/stress2/udp.cfg b/test/stress/stress2/udp.cfg new file mode 100644 index 0000000000..eb9460fc4d --- /dev/null +++ b/test/stress/stress2/udp.cfg @@ -0,0 +1,11 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +# Only run these three test programs for VFS tests + +export udpLOAD=100 +export TESTPROGS="testcases/swap/swap testcases/udp/udp" diff --git a/test/stress/stress2/vfs.cfg b/test/stress/stress2/vfs.cfg new file mode 100644 index 0000000000..ab17b5c407 --- /dev/null +++ b/test/stress/stress2/vfs.cfg @@ -0,0 +1,10 @@ +# $FreeBSD$ + +# Stress Test Suite Configuration + +# Default values +. ./default.cfg + +# Only run these three test programs for VFS tests + +export TESTPROGS="testcases/swap/swap testcases/creat/creat testcases/mkdir/mkdir" -- 2.41.0

    +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

  • zK+h;^OpvNl&r z2Wuo4G?*kbiS2I$Gkd$zr6ecMBB0IpDt5E|=U3AA{7x$hpwa% zh-kcHC#%=xNuc8GLT}dAX?>lOT9n;0Ar_A(7OtP&{#DypSa328ags&S#%%wWcAvAr zNKVnu5iv2t!^*d01m@=E4?a~{TdoSvG=T-4cswQdIQc0#wH9o(s9#3?hC>6WL01{_ zQNT1K_3`VrfEz#GC~6uS_JDJXRrb!y*Vo`51B1${K*3RQTc&TnAAjbP6w{o1`|c^V zmSeD#dQ{l5hT1bXBJsRc^V#Y?->@{~;9x{qEvr-kL(A4?wGS#>a&+KK#~#kDHziS` z_lM7Ez*f7@W3y>dxlubht3M0mjG2i5?y+7DF+5@itoh%fLeL69>b7P&(p34v!#`Pf zHYaylP!>789@P>rUPgN$qUrt% zU}bO*nS`a`k;nMOif(#v=89cIHAGXT;y$1|#e{R(ZJGI52Ju1Dss4y@+D*c0afJHZLktBYHufD^tcmt#`n7$=IO1)vr=}nK)^Ke{Fxca;5Wp0QY z`M13OGzK>kge&+D`69TUuV{fe8>pyM;PJv^ZPe5jthC}Q3diQN>fIh+tv~}I(+-0Y zgoL;YWjIRWMPa7xJR@DDpW!QO(|2BV!S7^kraBBEA7s8BpuI@cmGs?5c~XQReX?_)%(b(dfgDc(Puu1Xn}x zdd(jLt_#mreC7-lubRl*iT&rW%>!E{KYl>y=;*$;>HhPyU-*t6EAJFcmD($4tM@G$ zI$~G4coA05u5XriJ})NuQ9={pdVPL?hw|~EOG@s`uP!c|o(J70kpC7)Ou_PifLkX^ zmX8lFUsWcq`+|1u?&-NJU_XzL`wRR2{a)=8+M{?=)j0H~Cm@js&XUmkl%CiyUD^eo z`iXB}aQojQ;nhj|9`$B$hsoeQTM8Q;-9#(&YO>rUhEd}FQ+fx+TCMWkbA8_&4tiO- z3VBmJfKpAZu(3W=#aK zy?wNiQPkU4l;u2zNG1H-xDaUaZTW1MVV(UoRppLuB*_k)@7E_H} zvNLDs@3Jz~-g^AwBepz+ZPF>gX>1)d*hSjvc1#a9wQ}}!1J(;1h85-4f8pgpBtBk~ z3B&F_j=IcGS*PaCG!~9E&U5i#->RaS{PiWSn`k(4R^Ag*ZSGUeD# z7Hkt>|GtDwsb_1em!)GjY;~(D{DYO{ATQqs;lJVnhpEAg$l{d`ofPwoewEfh>Kg7$ z#@gG-z|b;s3Ox-S9SnV;@pox4&K^ht!<*)Ysf}2g-e?x32ZF-Sp54vVC%(r`EI?%0owIXzZw+YZ_|_tL;GrHq!c$Nd$r#4ncEx(rM;T_HT7FwN?W79 ze5OFPUMu1&`ef%eB7NQZ&b=?Fq?84ll(vTmVF4}Q_2!Lhz#%p8HZ2Xdy56#uqNMD( zxo?}|1&3a1+U?n3<7vho3Y%4|)EjrCedcbecR~wuaS;;#E#gk8#8rzJt~9G;8wYyt;!Yn*XFEqL=uJvLJTf z=Mcj3GCa*s=j2^oLfu`8tQ&RFF}u*!BX&!_Q=RJ)HxEj?IZ8YVbe1^SW2Tu@5kKDL z>krHG2w}sGcffd-z;nc9g0?U%@6>2B2Heg+vA9ib4RZargR~14yYD4r22%4C3Uwgp zL*t(IoN#}U{TtW99-j#sc!E0{q2A6DQk0;Q)ZUt}$nk?KpIIGr`+C5+(n={wifMNG zNmt4C+Kj%;p2k!wp9OK~PV)-kY0nu{ z&c)wyURf=rA%Nz#pHi+R6v(*mFhvYULESrWBM_RPC-3xZZ24vml0SC)PI=>x@}>c2 zM2C;L75x_MK!YxCML@w)Kuv9)@lk+xSfTZJ>W{ZYgL9Gv6@0F`VNXrcdJqx=ZfS1T zuRVWAYh6r`{UDQ25`OrYNpB}QTh?P^e_pYfD$mNhjcuweTfW@Y?hVK0uOLCYPQAiH zZu^?=FT2SH?4EaWsoMR$a-qx;1^HIvjDH;TZ2rEk{LbA&3N9);KHZs7rhF`p z_i^tZV^Fyh@czSx_jg6%V~$CNM@-<&hlq;ge%--C<0>yiy80g6kDN)==kM+Pwy~wQ zTVLEsjM9dL6)sKVDBu>H>9(<111|ECeiYNj3+ED9rGi|nrR3%23i8%XAfmQjNbUU1 z36lEXaT`FgKwFBj;3;Z0k)R~ac$1QyBhr5uZhm(Cw=Vn2U-aoI-*5*f*TamcEyoserjd!59A4Guq;2~!E#!*yyA0-)i$?hO%qzhM(Mb;LzqG1T~R zV7Ay+I9Vc?4%z;yC&vXor@m6cNK*@1O&%Sk(WQmo_ltSFtNiEG>fw{g!ty(gXr6s= z{a{cA>I@_=vw_bPF8%xABdT}u?%XBpn=Fj82cvPh1U`YNNXKsd97G->Awk~U7qsGS zYhpAsrE__^jcSSHlp?JD)qQJSQYls`8I-g>8PAN9`^lyrPgwm%&wsYk_9&F9X@Ple zf{j#mq+Mq3j0;NxFy|vy_Lp?{gpu#cUjO#Ri!HqT;YB`0icR6}er*3=rn((~f<;gK z$|HwgjWT-fxF*Piwu1xzGWf#>DZUq)w1oT3l9MVqM~xDn?@)Qi%gB zz2-5M-wo$HL$6^l!sboeE3WK*H+8lvZl!g;7yeft_D+Y}X4h&_ZfytiDJ>cFaB^At zgygKi#vg3vuSEPtu)`ikL)cX-Dhzl4M?Z3OZOZ$m85SSbAFA%1b~|mAMM*FZJl`Wx zSAY56VYh$8_(+v+45QC7B`C0$pe}=FUON{HI&eb`q3_hYdU#If~Gt+6P?8cgi zB5uOvQ)re|i14YRArRQU69MgN&tW_qA6ai5nE3f$i_Qh8IeM`H?P1*$4!l~68a^8d zROC1dWhhi8LYb0op(*XtlZi00UlZCsD0x{!=5adF`L9ab$u@pUCT*xYkC`ru>=9Wu30Z-$e6@6 zW~y(r@fWh140AOhmKl0YPZjS6kmk{MGJ$^OjRQ8rHu|{KDLC2Z0=|wIaf1u@3O)Fz zx3|k+Q|ILbkX}7=&uwQ%HQbPd`z8#HXG07OCde4YY>{aYmRjhQ2Yf_QZ`k>? ze(_)=G>}fVjs0}&ZJtM}(|Rf?5i$yd+yQCZDCs8+C$39)FJ%oTu8YDBvRXX$%n9?88qeC>-S9G?0tb}8Bbuw{!-59xvXbz&U{9o z$a3LXuJX6+?61HOk2M-|x0_L!0Db%AxK-rG{;UV`KCHVmP&toKIO)GtymR)wTg z$fm9osJZNVx8=v-kCFi<+pc1g8v3$~8vEKA7^9Q4>sf{@WE9ygFzGzMQKJJo^h`GJ z^)Nbt(#(31ctyMi)9KGV1>Uu1*J?MB!)Y@#F7M(TNB^R;t1mVt8sJQiSxA6<5NFM- ziP^HyB>bK(b1$)GIubT50|3lEtVT})#tlEiDVbY5a(bH%c9~~qr5j=n4<9!M(BA9X zXIYb)wraWBUYPBL{$uoE)z=u7vzW@MN`CA2Qa@_w|13mf$#H-jsjs(1nGy2fgRaV! zAYc}5Igr=$SZe`!0LWtHf5)JoPd9HS@Cd@Q{Le^Fsj7G=Rwd=*R$Di0g%tpO!%CsMAIX@N;AXg0^prQSBbb|yc#F>Z<1BXn`wRow$+ebyU{1< zF%xS`<>H4jL@9UO+Yg#FB~?Jf>tu5K0Q&Dk^G-UU&Bjb4tHb`=zf@xU1a3&`?kaEn zlX*~OH#U(dv33R%C-B}AuW$V0@`UKZ@u|9`eYEx z-G|gu0*QH!gg2VwFF1cH#_^Ae?;zZwh_T)lIdJiOCe~kUxAp+;#|EBBsN{Nb@jh9a zk-_37UK+2fS`_f+mn+)$^t3d6=Rx1>tVhbttC1eaTd;3`z1A{fNZ2Vt6wI(oJ}l3c z>MJeGBc&+BXYyVh|H#<22)Y;;8#`KRdMMm^YU-h>aOZ~fOU$b*K&fx$&kqJ(x@zw< zJ*IwzrGirQGFl&p&8jW@!Kb1iN~h?MERvD$_|`|BobToM=6+aM7;NM9&ousicZXjj zevE-?Ix#ok`$5rHRjFL#X0*~wp0Z_V8-c>A$CEErvh!AuPEbFSwLH<%N*+b*lUo8E zcum0$Qx5LG36I`d(Uye8|Q4@U!x(FH3 zIT!!^dNO-|l!f*4Pb5pnZQ)8;Y;r1Wsa$M!GwZ=z%TcmGdYw9XZ(_ON&o0 z8QSi2Tz?ewtuv8fnZoqECHzbl4L5cprj9BwV}ecrfxRCW!M>AkX}1r{y%*q2e2=nk ztxCS>W*d0}iwX%nUTD&chqAvr5YSMIKPk`CqaKr}we8pwSdDiWVrl1_&l#={-j;dr zkZU07iSI6XygSp=_nT)CwHEE(d{KNSZ^xs?+x?9IIYkqy!)kPDV424?E}9EI$Ms5O zEB=et{;XHbZi|_#hsR(G~X!;)B>I@8KXHfvwL{- z^Y=ZIKZW{Exb3!Y{Qo(Z;jZ`b9tKQ6nT~&1HM#YH6P>F-ACL!AI_`85-L!Ap z&LPX@jUmo&{okb1{|27iu6R#B1;^fBQB1kiAUdnA4LB1UUU>H$oaoL+y8_&LNtvcsSQTEzkztuvA(>0Q`}aw zE%IW=18n?7$Y?|4(f{8TCCmbsEd%^zY>oT?7ALxoj9LMM{Z+RKf0#mhssar zV=Q%P)hxX7`O6~Y;9AJBA{9$vhW~SGq@|P=+y|JfTktaxG@K-ynMYmSePtijgH(Wu zziD9p$G2;{Q;sAnLy|30g>`-~lHax7X^CTfxJ^+!2SsP#0}&sJyT$7#cxwj*GlLxI z6-Qgmw|)ark%BpQuC)T%) z)iMe2CMdTh(t>1+_!$+G)aG|y(WFKfomBsuEC31N7j+QF0`90|qdKFbA zqOQAlJBmK4{P;3Tw>e7mR)wEh(~tA_U#+{}k7sX&Tlg4xC7MBJ$+Y{3VX9LU3UB&f znBi^9O!Sa;mV#{+e2Rs}scg|lF&^2gT&N2r8#+#$I~;F71q?Hy9uRt^P+9r(G7#wz z{rn6vbWX3aJexHS$i5w{yJ)+6?bNAPPA4>hV1WpUj=p#>&pQG|4U7D(zykqnbY+=98rto(|d41)4H~hNm&$Qkp!9 z>@cMaZxNc{yCiY$y{%XHWR{kk?|_yRG8z-Map;Y&m2jB8{?O(&50xde&pdBUGZB-W z0<==s2JGd>mL*YUnViKZ*Xj&T=h^IyRpb7mkj>RDZ$>Y78L@j~lk?@}uH^mE&Y5(K z?hVCGufE>>Z^yw{`S%j-U=oMvLV(LBMjNKHl>qF@A()B zvs1Lt()&FzhQ>5qsJn8ltmGc5_OP|LFwLy>!9LHe6CElyKjJ4cqN!&i@PggX{@0~X z;vTnaUK0I73)bkPAOAtCe!8_e)^;L(w6>UrA))&B2FT$k*=_E;7gxFABVRjKg}5#* z+Z_{rAr6YMU2LY|T3%+ImWYQ8W>}GfUgF9Z^NYa{rC&uivzHyqr|!xMEMj|A3E25@ zUEx|91R;YL)X&!jy`5D4drgSr-~Z$8FWai_)-Pa~2I($Ik?!s;B?M`tyFMjBB% zC8a}p(cMUQr*wnVJ-x2I_y0Mb7xxFa*DDX#;ukZ{bBuAujA!Pg>cn_q_M$}|ok20! zcmILCiD*RDi)H+%8q80&V>A4iFfW$&jPVbvDj}09+fqFn$+z+zo7R!?+BDisoYu3? z5Xr(mm_dvm+KTty?h{xqYim^DNh{FMTY{6M>yZZfKIaWZ;cS6ytFM~6ugPBa#}1F_ z=(>dT^YrxZAvr`!&x~wCLF{{D56aDL=2Ok#tu3a@3(RGxU+a%duvl1Il-qFPmp&ed zsi{SYRH*6<|DaG$Y{6L!K&xVwOT^R(cAz3PS$X}AXTAO4I;JF_xslQHZFBMofIo|Z z#`BEcJ8fP*_go-VjrkxekJ;fh^FbbSqxYC>?Wftd_pZh#of``5b3S>aJ`SIwoa5O9 zkz_U{D#p^joU(chV3L+dAzCV70+w7iT!Yu0pFcpib&rn!?K$A%mKft{VG=P#_` z^jX9=9sPt2fiO|aeJIu};cy+4(ulCjRsZQ@-+Vd}X7{zEZXz>|hTmyZ!%5o*s=r4OTvt5rnb+TmuAIN* zEe(kx_vczDI@#}AwChRzoL{ArY*k*7=6Njp&)$oWJjJbujE*idtrD`YvbDp*{=k0A z8%Zt1cPrL|?7y@wx@deiFmzs$wVEmSjc2-;yV_|xEGTGnr|ErKyATTjDLKJ6cP76V z^6oV#+VjHCRw48q;6N9v z-rpOL3nc6P<{mGrlq`MxY_jHRFsA=;Jv924_?wZ5FPuMBlO|uq>dkv^sd@NJ%+}1> z&beWFERRHaf-Z!Xj>GKGy(}(m_=P4~Td+dZpJb|11ZWsQc6mqa#n63H52Sh@)kE(! zW+&kfO+xKW>!}KF(V|TD!hv57C)38Q6EWp899=($eKp+``5zuHc6nlcadg#gGO~_( zu2uYU?c^E3_t4Yd|JCcOPx`9moZ&vVtlDgxxI_FYODU7kZEJjn`K8y@;b;;b5mueo z^tlFen#t_OQK(K53c)aJZ>`5K44JZ%(l1f7^WIKUA#3O0&oJFyt4)-J3-bJ9pV`QT z8VqhW!%Sqpu{O89izao4W3APCHJBKUjQl{wx26}FpVo7(mv&DuU0&0qznoHQ9b>h` zw*Q81hz#dtX5Y3G|4R6}1Kige6lCP&hdVe&Mlk1g^TnP&CiK^46PfkszAjd*qSToC zp$xP$qIq6XUw%1t-j2vh<+9frY?j*WMbj+Pj~RaLPSA5)7B^(%6%NM|kS|%Jaut(O z(`qK@!T!r=x&aJn9Qn3=77XoQ4xw+i?c{9to>G=) z1oYc4HuxT_sGd0+kXf3O^GB?GjZpA)x2;wif{B=pH^E5X!SAW^m=^faR$=40F;Qk= zQ2T&tu`AR{+-S79P(00W?ke7_n0Yy`HWdPYS9IEt@{cYdK0LN_;h9WlXFTKfp>1-)9tS-r(5Yzy_xOlm8maNx%(JtmKZx` zpw8g$P-R=I^&J-0U9IFgpl6~-<$G?@jl-CTXxY0mc6T`8b)DZTT6-f$*$rv4`W-nz z{?M^JA14Zp))CvXI7|FmKIk^`oHUvZ6=*Q)K>1q|Pn^b* zwz2EaHoSkVG7;hPp>r8d#vtakiW_=q@?GS?aTo=>@@dnOjZa;3+pFB~UHB}i1~nS$ zJDvgVo=HEYWJBg3^*q$J)>T#-$U{Wjg)*(DDpzR9W8v#>e>GG^%|i2rBkZ;svLJO| zUN4X)-#;D-GQiE_(xvFQJ63Os5JxxhFUAN}r2V<7<{bE-lIq5<*z6%G=&L7~nAfA* zA0wwA=&YW0J~9?HyKQ&AwB-u16X(sQMj?1mE-`nVBJo78>(Bd))7gbSmcm)0-y(pi zI#Y3(H?SES9I`Me<=kv%J2^%J{k}K={3>Hc-NY4fL;ye-Va8U#Grh37N(oZiA;!{?A zyENd&L~qn;3KU^r9-eP{On*Y1YcWy3I^i3445f=HUH$5l6s6o;J^HOv%i%o(hUnB?k2q|TyEh>(QQRyvPFDsZ#Y;B>t4We{ zdPhhlRZjoGC(%#5rV#Xg$t!Dhh`g7Pc>l)6p?-z+H^Iy616y5qI%xfYK-%cal4Gb_k1tt z)a$k9u`s~6kY^>&YrlvAiP@aqcy#ql)ih4+n^XKc6rJ0ZBkgqKBPO~pA0q#W{fI{R)7fNe`b5+8azMa#7&__q z1{!Z>i9*VkJTIW9p!8zcZbS+K>2XytzB1e!?OO(J(jLF`^m6G8pZkM;Jnn1^EQ>cB#`l| z1tjLIBsy(Iy-Xv%0%gIjhjoZy1q;a~a==JH%de^M_k1zU-bzzy6CttcT0SFyy_EKbnf^W+bj&76L4rGaK|{pEw_Y8WX$m(32Un=mf_Vo8vJPo?vH+w&hB zi9U3@_!h&Ddm(q&eZG7Mtm27hR|o;^3g)Bf>)U1ni&qj=SW&Y%_D|bGbFR(@o|0>> zI0Z~Xe(&WQY)xE#5tObI{Difr^`$NI@5`sro#<84Yq+a_#9H#xBdgeKgiG$c54&^D zW+`fnCcOPRSL-a88G@f8w9ol+Ga}mjo*%Q#Yuc$F2~i}!#r>&KxNVruhXui7`Ad&z z;tgxi8D1dl5f8@WZ7w@Uh0W65sFDbo1@As0wcLiQ%1Pcs}!R)uafq<^@#Z9C^VX;bDmH=S;N zcm$3ZkUOlDva3Cx#={=|vASrs)th=J?rc0Hf^lyA*`p{{wh zKC1q~=as*MO8W8%oBqwvIknhNIZqv8-r_dv?J>+v%>rD1jF&6CqolHsyWa6n=iBWl z7~VE?Cw(U0yIyr-h&(T;K5hHJ4&GlK+}o;c8HINrdM<=MKTLiX0Pv6=7V#1`%#z@? z_z@iIRlnjB?Oi5keQxl`QnThs~#n zO$E#<3%JFRp|{?ynogDJFQ=~hL^nyd@>xPLxjDvn$|TnKe))%i<9;|@^V5@1=)PU= zYSLm#vzg{|kv$cPH1pf^!q7k!Av-#Sw_HLKx)xlD+LVSrFC=iT+BI?zAuOSiRY(x+ z|3XcAF5F`2O*QB*8x1M(#L1-H+pcZ7OPuX1ig_23JZG{glHq>&(`_%gPL$HyL1MJL zp_KGjN?S-&mjokAXD!$%wRRewV(pwf{_3-G= zY`64RT}!0>;f(QZr0J)p>+coaTA$mCDJf-pe+sdepWR^`kdQC(T`%tbtemDY@ZrdN z-_jd>Y&%u-%ci2mZF`WqwPorN*&wp)SiT{_>UCJ`u3Zrs=^f72;Abp5x?PSe{iwdo zPXVHCjs7axVgWEAFld=z@kc`*uMbjbUrwcwC_l{#xVBcje+2r(EcpQ?dsR4uck*}S zgzvMX-zbHAbBc;)!FddKrb+lVu}u&Bv7WVuiT<(xx8IXhRX3bMZFotA!T>WP&(2)f z<_=Bz6gIZAq|bMJ_l0YMm{@9SazCzv`Z72DLI+9MvO_CVDlt<9+lK6*@8a6p2-lZ{ z7JN80yq;s<%d$kOc9zlGVl11jZiU;>9BPls%ymNR^)KA|jwV+G&csw&N zYsQd3g#1Sjwjci7-*MM!tq_eH%vG#;X8b~#giGP5*v!gTKNTP)`?4FgapeZT?V)<| zJhth2#_R5|^@ynnlW2cjP#~mF@KV(La5lGZn2gh$1||2X!|&lJ%%tt%sJ_j`Bjd8b z;98HTWAyIwb1d#*#S>2eRV#=CHm9$940qJ53o0GzdKqtOem)RUdT{;y!&Mb~R*}E< z*uT&Jk-@y{&?IM3sW$}8(^J{Ur}T(2WA7nPx~%X=y~4pIi9KN?3# z8Qy?N>jq7%e}NEYhsmtb1*GfqUL~WfLA-tb=GX8u$6A^ll_7O zj;!V3(5Uy^q<03rKVDH$f$&=B$udrp&F;!_^L2*-%i%nz-W2w}Myj}S(*l@M!rgYT`eC7j@lqq#^lV8Y~{1T=2jzZeD}e8urT3~rLh5b zq~)XV$xS_DN%t$~n?&z1^Dn%J*TDIX+&RMkbzgz>>ZEWZHlr-?rDpIEVhm^!%pA_^ zwLj#df9E3@Y_Cc@4P|5?#`vYaJ!ReXU24p~wxD@!|De+6bh!47G}~L$;ahsno8%Pa zyNdXIpR|?Bm-oWk`gavc#W$R!{tGKD6-x`(&4+Gom83~0nZlfQE;X?|-DIEDtt}nl zSMleXGf+f5zRET7ZCtv4j_wO_#F37li~i?ENI7pjG6F^UZp59v*9-({q==Uf%uW?2 zddH(9Z>X6c+u6$dvSZ{=4CS1u&p z9<%;K`v0*jfk@Q+P5FH0`=kb8M>h=xX4X7g;9mbcBp`dih9Jti`XhnnT?W_s#XzIc zdEVJ!GJGP1Afu~t8!aB>c)C@XPhXY-6A2C`K#Y!S%SXiXyZOjOX?u4yYS8rc?2s|E zKCMBR?+*j=php4lo4-Gm$mtk8_{nsIgCl#y%3pQS#AQ+5h5gSZC@_)H?mRP2S(YH1 zxm89@|J)&b7VF=pZiA$p6iA6@M2KSMTYMS zF#UUv&N8U=CxJ!Rxw(cn_jq$}AhYNjI2)b&jW7OvrQi*;9hJk~P&8~np@$gvwKtw`pW7~lLJvck!c@uw4 zp~)(+FquN7w4bpd#U;N*TaMCFK zQK&IrShc{W51va#Lb|m!Uc5i}zX34VgY3d(MQmq93lqQO@t&!7@&E70v4{S+nf>Mc z`Nh9ij}RViO-laX=IbJ}BI{&!Fsgh8)0F}i}v4`sjKEW@EIr6^?gZ`kS+3^JH%9i4`gV9+=-n8kOQ zsZSF*P@;gB{(G6=@3L-g*P&=HLs5yG#)NOw%5~>wXY18|sB8~@E72(X5Q)#+?jO$ANS7U!Ax4HNPhB|@w8ujrkXzyxqU!8*u)FZ-&O-2VX! z8+#*8jg5dwo=yT`W3<(v1CO#j&&ceHs+tB~_E4X04Wvr|`OD`iETnqkze6jH;Fuao zz zus(D8PkUcFAVD@B?k<|1Q2J#KX3B*74`U8~m%$c-;lyA)IG$}(EgBF} z4Yt$VS`HO!;QqT>=xo`-)SFza0yKRd&iZ5^$6EslkmnxLYImOVS(%&RB)a#nXlW5g z!4&-fHD92`9fxy!5XhfaKIuRtF9kD6FUX)-z656RY_pFsa{_ctyR^viz3!)qohnu@ z(QR~ESpgj@pU{Z8_9pU&!m+6ES#&)fZa*&T;?Tb9){V>D4kVOjA)vSrNFeHF#j+L*uqJIQMG7fD3H}{cO7_^C~6`Brw zIVFgpMA%p_-Oy+PHJHA)>tUew5&`8CDT8|PRE@qG73^x>+ z^0n^TSrU`B@z0Nau-FY_2XS~%c=2N#@b*g$XFF*QfxFYb@(2$h5ejKMiW&|p5YP7Q zbl=e_1(w(bkJ)kuiNLR4ak;|dy$s`6+a6R#Bh@#{3Uz8bw_Ih)vUNT_S!ihByS&Uc zMPAOXjzdrxJb9;GZ%@kf%EboJR{NJ`Mj1VLn1ALT>C-X&>(^2@@WxOM4kvYXi+-2C zWWBEs2S!IV6kc1C1Ga2+52xQ+*JGra%a{gqzzOF{yxL939}#OtTQ zwY^`tch!E+kM3`VM@1e^yTGKuM8#xcU3XRjnIvckN07T)ujN(vE26C z%$5g;Yk6_KQBlDr4o)H1*fyFPc6oWJ-{N&v zCTiIJX>ZRmJT^Mo7o?ba4#Z(^c=9*9pRnjPaXEB>?L{)fk;I}0qkbTh(P1Fo^ zd9;|MgmIj)OuP!Ksz#kbJ!yY##m;k|>93b?EhF_F0cp88zhRcX{UH(y#> z3Jlh{MTaHifi}zM3)tXm4F8yq(2LzM&9V>b*OeUY6?cFByi4bczp+1@d!;wU$?!gj z^7j57*2;8Zrd)4mt_Ktecs$z-j4iDhj-+x!eu63jwr9USQuk9&B33icv2=cu`0^r+ zBISTFU}(aGE`a45J;y98%~`{6v_4sBk?`tW!n722!$%8D)hyMD9~)XEfmUy(_R!PP zB5W%}_TL@LV%_6(Kh|AA2YV|H<>+*XwGGKtyUG|oi@*;XSZ-bTzw5iQK{yshs3cLI3BacLX1~~NW zRMCf1SV#U4#kGob6uzMMEWGP56|g}_`yCX-vjv8j;xvSCcc{(h;qAryB1T3sO1ua5 ztz$^3?WhRwhH!zM%CnH;|NJDO_x=0#TSzq;vuD!s=VdIUn15Ug zF&oCW%uEsIoncU1k=96~^Iht5i}wxk$_ONO#tccP&i2#xN;%;a^`0&$`G7mB6)T*5# zP=O6;0U7oCVu8=J%W8z~()GcII$QcZ=luz4@eAM|kW0P+dzM3*%4PLx3O*6rX9aBT zh5rqw7Sz%VuyMP91=Z{)Xt4e6YyG_^}lyEIkMD>Xp3TvDgX#K%6#>U)~znzgd2!4IOqLjl)Ss=^hei>oWM2^AHUzjg>2 zkAW~>Hj0=#Vpe=~``fb(iW3WgZAo2dxoNn|?KMATb#D;rdjYxFPPW z*R>jhLddw>eZ>>eY5(}kKx29c%Dt;0CS?oC&3%4h z;ROPgH6lljb#-RvwWj!~KmrF?ee`?7t&AP7*B)IVoxrE`$_DK}f!#&%ANPq7B65)C z(E9$iba+^yqfqmQiu4=Swm$XuKUK+``{O7B5k)=E^X$D03lkxB$VRa1_qH0nox=|K|Q){2T2_#Z(wQ6SD*GUkij}y zIPTl+^`Zlc=ZFvniV(hzXZt5;2|d6*?;z(Fm45-;EhOEhjVU82cKP2EGMC?OHJ zwwdYmn?3-3KvVv#N$bN0Vv;0QgUnSU=RuR>gR_5J1bV8{&7zn?<4YvwIBXnG!SBs9KswYg!N=vh+#32;- z0u9AgOqjZfCMyu6_ ze+bE6vt0KrfFq80|DZhB3vIxgA%2fd!=`H|2Ni9j-n@=~x5L--oBq=>OAoYqP^Zpv zA;5RljiYqBf6{WJzdlHn2Qmd;pra$a2b%^M$z7X1|E$1#ixYeqAzWQFC{E5NU)EXTWolrY$W$r6(ijSx=M4;i83M2^j^8~i17aqm!Y@e2V-9G!Df zSqiSI8n?5pppqs9*?sAmqwK-_`)IOJcAwsU)iS|MNO0 zjlZXUaGDK%l?+4IYj#5;Sq0_ob++>pg-YZd&A!+37S$wceu3oa>?SgDa>#yX)|Y#~ zj!&CFjZeMxbi~--%CqQ~y!wq!)SR3bw`ZFM{*T;#AHD-T-Sz-ZAReb^1%Cc-H7Bu| zg#|4wt;1p++Uv?1YWc(mFnTV|;`Bb{h-4n0GOn(#Lv`&JR`a-n3E9F=yUXLn#on?Z z;dGYgBdagA`U&zpdML?&+q2HhV!b@K*m=3hRmMQ`j_!RG>+F1sTQaTTI zqPT2ew87MmFN+I!T^5~2Q4XoMcwGSxTl4s8z4YxEx|;LpT1PuCt`~sQlDFRzyX2t7 zjsR9TZzM5?t^x=Y@CT>9a~b?Ks_64T>J)KYxxnoZhw>CFvm#C}V+LRmv11B2O|DSX%{E*BglirCp%p8k{)w-*qRWp)mu@JFP5}tUt?fL>X&3~ZL#XAx(y11p#^r-T9Sm|2pT|E}5%t3XLm)o_K7tS%TcyrcyC21W zosc6_#5Xk`>)16ZX9lOJr!dR!&uJG%kOtW4U@lORkSr(i1~|urF1j#8^YZeLGH<|S z0xslre^gKIxfKrph=ehPL>$WPi@ocu1SP+lW%svl-@e=S`u(HO#hD+4JB-}~ZR#QV_sNDvwJ}CyDk>L^9oeBf(kxbxnYLhahKL zzj*Ni0A}yUt66X$i&o(~QlII!fIEN%v;cM#K$-yC#u5UYC-mPZ6c3ITqhtI3W50g| z5}5UCDDW=-@cQ8YH>&*qy&o?TLq@G@y)+EP*AkVhZ?o5i&Gentxl*RlXF0s&0*qhf zy;-Y%R77@IZEdO1USgf1a$2Ha-YdL|dM0bo{+PI|%@5CYL`Z$=@saFsS9;}UnCts7 zeG(TdhkjCODlsA9T#h7SPV4FH5IVj?l_VuHws$8kG2^lkvBlV6d}ivRo?uDj`1m*= zMSpH@k*;rWmk9PMX>m!AqoMJ2Awtzt*2yP7(WwQ^glR^6@C&oaHb>Fb`4-Fd1Vv=( zf@&V|t5NpZd;2?C8oV*7ZK(TnP$_I+L>-nIuyApweyGwmN{LidR5(Nvb9-GM@`L6o z0Ik)gZF0M$D5ZuqweHBq6>@##Nh0b&_QId8RSIz8yx^WtkE;D)BbWN4;@&whfsRA} zW;0e4v}LQ6`^HdJRduetf*#?S9L+7#OD(uGtp8o=g)5Bv7D0^ZY?Eb;`G`ijE?C@E zW<&T&ca~HQ1vx}BN6LYM^V7zWV_%e^W4)nQn)vwXy8chEfFH6=zuO~9J1@$QCbqRR3Jmts90!2{uhdbS&3*Ull zzII^mf{G5Pd|~z#eS?0)7Zm&IiR}k?HT;B=(lU~BmfWvCLYW+@2FqOU_7C&WBBN$I zs_lCs@Tg>C9@c^|wrXfRGt7s(br0m>g?A4UwUT@G89oVoWzwF=xEtKQicyuuUDCZ_ z#jb<%srgjjoSc!_a0gyBN9=`AY{ z0R9WLHU^DO(wYgKSJ=nj0Zs)UaE6fDTr`q?3$F5Mz2g zJ$Oa^O7$q)=?$^HUpv{lN4~XhH-P5@{u(gwY$-YdWIdpDrCGV&*Bl2Mz7Cs* zj)rnd#&Xet1KklHv};Y7T0rUi966cC8g%Vbpzykym{|MsHAEUslFG)oyllzvZ z8p_=x12uhOa&mJ1>u47D7uYl9W_FWax&>dquOwI3KibEC(OAbl|X$^^UW46ZSXq34?Z{VBN zFf-Co4^X)eJWSaTY5rhA)`)TYZ6wnPgUclr7j--P%nP4ZvTg+KO)?9&^{!gB+j8N{zRBz~{-NnxEaZ+E>s3hvqS>By*k1q|Qunoj%YI2ZC@|Nq= zvy3g>c7%+EWJz=H+q>zf8uI4G>{jL$-#0F>7Htm+OJ&-*5Q$v!Qb0NRJ8K!xhzrw# z?0uQ#)=srUB>LaRemgrAL|uzSK50uknLRwQE9^L`{05pkWcR zLuFhw_u4n^bjL?P7a{7eFr9b5EMD(cv^{m2aIro}EgQylB1gV$kGSykR1Y8tgn5|n zi6mh3f?*i$%kEV0?;koDfw|byk+oE{bHs+lZORtHg|2{o7ueitX>pnfD8t&>9T)y_ zt8Umu<%D7FtyKOg9(wv0wbS2TyhENT z_VMaRS0l11EE4P$a}!4_cqvK_yf@Kpl(O7(vHD2=TY32|6Wx!Sst$YXo*0qE=brD? z-8A;_4DqFvphDP%6Jn7$A1O}&f1A^GltH#C{dK3&{=rZjd8j{EYXug1@`aVyVF(I= zsp9a@A4L2L2~$&QG>FlL)zV@drCNAjjF?d~jTh_e0)M$&Im}g39#jPiSLJLkc#c2G z)QYu#@c}(hH1357f#(Vc3M2DEa-d8WaAjzFQ6bn1-x|HV;k09m5ug65*xrt5{&R`o#kt&L_q%7!p3Q$GHabg5Ns(ae zuSv9LG*k+O&My)?;4E#tOFfswGiEVp9rj6=9OzUwqn~FQq!{~N%{6adiZYNdm_E{e ze}SKP-`EMZnV{gJ<;0$2U2CfN?(QOi62Gm%mE&k^=ca3^K9Kq{1>IQ;Mw0Zstbkvu zE{kHKUz81}S1-nG77xi$Na3*Tnk-bhIazI!2tfu02+Ue%vs?5Idm>o_S3#J);gksu z4vtZdT9vVMa<6t{V6oHv_c|D5orJ59M)+VuW)eBoQc2G=Z*T958{zZ(qV1v^nOj{7 z#T7It^?B_(7E=8NTNz4W23s}pT)z;jt#_|*x4xPUUs`ZAWQXn)iKZoWabZnd*wDE~ zB7HIA7n^Qp1-eLJtUDhWy!YUT0npdxNhpy;4_OLb1*W-6owM{z^!|{OZx8h604T%b zuG%rIRcz7*$<>S5!IVh7yXYut*wWOxGCH zr-=v(-p7hQVNP5St=|S9k`eMdZGj*VMHP$lxZNsn>p^uiS<=!e0|NsP^asC;uBNmt z*GicLcj-#pf>0uUWR&b;8Lv)lBRw||%#cNE>|>68_7XG+GMrD?!)0 zAAu(T3p&4`fX88lzQ{sNEv?5|%f-JERn~sH z#%M+kr`jaRuOSFa!fT%%7=XkM5PcUveoM_7+IA~k^!AfqhQP`L687&6N6its-t}Y^ z`A}#WNp3DK+%N`z4R?HajGlw`i&uW{>QYU9A^Tgr7O$)I4vDGjeCF*cYEi zfXpPfMptAXefDMfp;T?m;M-{VknZuW+VZ0 zX)OhyLG;CtGWzIAB${_0nAR}L@ouYPhkH71qR@hTzQhp!ZR&jvFc^o9E=<%^EG&x3TrQ$`gtD zL9(*QontiaeTTpb4fUYRA5Wzti9kpS!wJ7@?Hko7R(m@$o>7;uj$X0pOZ0Bvi8y`2 zlRp{WC1?N{_W;mXz?2D}H5ZKlnYC2tAz{3szWzyNkPDOm7=HH-f|orgWsX21OS6Sv z&KcBEs6;SO?GbXQZL{f#GW9Dmj_T6JMVti-4#oU`!?&y?b8-iP3Y_1L7+=M(!Bn z$zbU>Zy5Q0Gt;}j$p`{6z?1@1bPs}XmYxaEs!GCmgoH?{?5JFOMNGm!JwS5!;8*(1 zlao~t8{O=Sy~x#%D|p9h`6W3S35A;OCxBPVbf`qEf~B5Am>L9>71_*DH2S4$twt&# z_6RG;s|K@x#%k@Q#P=?0taM-=qWT+2?5(tT^9!ztdB`V!K<`~sax;i?)Uc%4>&<3h zMN3SH75PK=6+Q6;*lSbM*A7baPt~0dx|El%T-(09%n&W1LxM_p-TDn_w6g;k?X4%K z)k0`&z=qM_CT3>|b^<Q7QLq;}Mg3>;kwHZugeo0I`NSok|g?w{;ZQj{( zz9Ln)=PiLUNc_7l0~7e|t|-)%2nRtjC;eQHNEgl5lO$=G86or;6(|b(KBRY$anEAS z3j0e^b}GS7tTKX?{P==j*!rxmTj&qv*@Qd$;fbND zSKE8%!j}5ppHtP~4Qwgu1BJXvtFQJinJ#S%>FbuyongngzqJQKD3o{Zj)zHVRiCW$Ah>uaLU zOhQ4oc?}s9&)EKtiv4Aa$C=ZRTec=0GiGHmfjxU_JSpu=;wXEDY?dm_%dpD{ zKdpcx1rb0jEG!J+%Wp;Smwzk+c0K9OzhJoDyt457sCKJp;%9dB6{g1@ZQDH8!%=5! zOFOq)2JZ|>k5!{==j?!^r`W9rzaCkXN%^<_>qr9$_TV(XaZ)RI2H7Kn2;#f)uHL@+ zB0XCLzTm}^CxO5kx(7yaX_d<|l9pzh!`eAwHmM0a?7UdVVv`nUy$6vLA2|`e6_-2ur6&$pdys~AtmatV* zG@zQh$>whvMC_Nh*HtZVe3yIahWD4ZhfI%iZxwz$dx6TJ2HCzjQl*QfU00S;9h9=h z5y%kIdy>RC>neB)t|V%L?(NJC9=wJwAyPS>Nm1cNfgQb|yDAeEzAOa~SjYHmN3Rdi zBcj&)?`kt3fjkw?Rm5cqDH4;#Z;DSk^x!ejPhZ_!9Ru-{1EUf0uHp29d z*j>Hm4<8ocYatfALiu@1|Kb(LFDQF*{k}s!Tto8#W&w!*0lM}ki~2K^#T$k3EbGwdaO@u(bkA4!SO4xBe&=0doy2c=6$*M@qFv8NRpvH*XYfve?^+iFMWl2;50v#flxV}P5-Wd z^A76s$|z7osB}OeM+$s^XD!jJKyN{R0z`$EiD|e<+C_()Svgk*?K(o#;)tRe zz|0ge*JI~1Nem5~JU$5t(`#q9JhsYFiaq)pF8B5wpQlDEy&(@}Kk-)<=XqmXHs)j@ zn^~FRQL&K{t?pbrok6ok(L2cNq`v5}y!J~-@}ofSp{1raGdCv__4Ao2)gDi}y}>y@ z&p3jG?;8`Ieu)Az^I-6>-qLtnB`e3IG1KlwAmXoKnGa&mwjjF=D3ZYUe)J?h<0Gki zzn|eXW!4hRRbxs>8w+`bNuTu4fd|IWhYKKHKHrV`mxCk( z`O1a1oB}Nqf~5ib=+4FjK!wZ2$IJa#B<0gRmCJ7b4h*b~=my%>}3ca2J{O z#C{PtNC@vfIxTNEC5PGHb08b(x2Dcgf_T^#U`;Hf#^ZdD5z;yW`FY>~@fbCtNchi# zFhrCq!$D4yrFQlRy3MX5O)#wCve^1)mMCi+%bEuOzY1^OIBG@c5+oyo>LhJ&H%86! zIOZ4}b+rDIl?j_17nxc8|UH6m?*AJ-L1IaYK_B zYJSntZ?AD|O}e)1zG`+fib1{SL`PmN*%oMSX0>HwQ4RNXjH%baIlei|(4w`EV<7OY z_VPNEA2PO9B-EBj?sgX1t*;3Mf2Spfbq268S*yEP-RJD+7FII0JoZa-d2bT{QOJep z)09{C3o~$Y*8)l?LF^W#n%;!ZL}pn?a6|eE3R8m3$=LW+!P)h7@3llA!wqtdZ;HsA z>Gn}OjcODMNcG<6i3FN_;1fp$tWD4;ayiKE1UMW72~15*+qpnu+*N5QQzO&uOFTSy zwE)E-^mXNg^{y~~kaXsRe~UuuG*@ZFaw-6a+6yG`B6)&AS4-y+kNv@V(x?I;`z_?` zBu8zl$i?Er0|lvkyZlY{1pYddDwZIo}JJEL+yIr^utI46$j$%`-*>LzsumE3ULdT$>_B6;jRY~23ljtIMn+=X`L5mz{oUEQ48 zbvfR-_<*H<_fa1BUtkE)n*cFCPO->jPi3UQPL*l>Q;;~O^Lebl5ZX@kZVSg%Kext- zIM}%D-B8-bl=_;#L{K0iG;vUEGOvR^pp31z8z_l{a1z8byl}pz8PTDQLp3b=I6feh z-#$Q`Z^Vv%a{%`^&+Zrn_|^uy%gZ}rMpL*flurNqBVKrQ9#twbAR3yt=)J+Pab#;n zfuQ>zFVaJN+ohwGf2I-jY0Fe6VXDfjfD?rx80ZoiM zCLzPgDT=Yj+|khyn5lrX7NMY2@~AVMoy;a*0VHqMkALL}1XN`mg}Rzb%C0_;OqP$%~L`f$GM;M4b8LUG)!>uie(n>h{UQ+xaKw$tp!pmo8!}usPKKmdXk*rX#NXv>gicZMJ;4ITH_j0y zpC)COwNPg=lG=Zx`)e;pyR2Ef=ShX?w8VDm7^d)7TzMn1nA6#YOlsH-tr%E0lkpb! zCIF=l2CC()f-fA?v z@M5ZPInb|XadAO_L%(#4j5rKF#Uznvp2=Oro z^iZvMZ$r~n3_j`_ywxn0^taaIMbS z-AhYIfTgYg2C`tjOBFLb4_`80LJG_2heVr$^XKzG zve-?f4!LeF<~=Hf&Q2JFk1iFzpI!$58PtluW6DsgC7cwFM+sWMuO4{OjKmzO)~r}R zPk%0y9}Kzm-f1`cp!R%yTW;Yy?*lVMfGVTmYBJ^$!;M3ufob)7%9Wg}Zs-f{BDc7R zzQIA503JO?%?Fq6!m`jv7L_kA8CA;l0)E1Mb`h67_oJ*1{M!>|&z6%M!sbg73B&D*pooKe zVzZoMVPcXWo3M{?csqdWxI2lUv}t5P=O+s!5fGcz_S=iSGbu%4|4&^7hKPuM>u~Sk z;lYTcXUJc*(uibY4-C*{`5p|iBNFS!+@)cQH}3Ay2)SRaYf`3G6If7{Rn#Qt-bf=?LxK$Y!no54LL%64QZ&405FADNz`cQ^ZdbB zF(esJM_YQ-`lgZ*sWQKB45km`%KGdqLinhg5K4qpcsQR6K_8hfbM>%fCG!sfQp4s; zyf1@QB7`v4wEgy!E#6;XASGZ&v^UI~Ew64nMLYjh)4x7mUG}(2RZwJQcIpciYun@3 z^?VYj?F6xX-~(2IR2>OcO#IcH&cg%d8(%$|dp=XZ?ywbIXASPE5J{SM+`T{AQ=Tdh2vM;Ft;V8;E2SUS;0lZ0b?lnlI6k z3oZgtd>+oeM*&YYD|pU$(n+cPRF|G@^&PufPFJmF_f{ftBAVufsn(FoIdfF?A*q4( zU1A1?pHq@z9l4)Ku)(e9;PuKdg;c^Qpa{nmg1!%w)Ms088?X4jyFHAiF=Uv&KW_zv zgnS4K58MH%AtQsBAzTPWwTS`@;{jWP10{41G)JeZ2~zKRN8>&3PefHMqgnML!KK#Q zcVj!Ctwo6YHFAAWuS4X7R5~w#1+0e_-C}_!^*oRn5yhwDi;518=Zn6j4j`YXPEMLh zB>Gs!%{Y5CntlpF`oI$R;)DDWu5(s}Uhd|R!4}V}AFE9*Lf|ZWzvAF^e*%yE2SCE< z05+tiMrz<0d>S>o$NS~{P8E8q_UV3`50vJ>0<=#YG&~ftX~^6+pxh4&rEf5tz`=t41SSFDv zpk+@8#EQ1~nSgn{+z%jv0c@Rw4F5gsT^AL?8M!quq|ZDDlo6jR?6e@unUd6wBNo+E zU1|4p_;>>YoNAU&aH*i%}p$?EnNU2=XYN4a;cVsMIKl*X_;+8-q|EJQw4j$2Zxm)=LYdfCkv&h4;JT ziqn(TUjg44CjXOE>^;T@^YG`Q4Z6nl8G_N*{~7he3iAbQvi$4Erq_Ze2@ybnA9*~9`7-np&_r-!VF_VqD7?m6rNaE3ZO%v8L4w~4 z85B)C29f-tzS;uk%|%j_RIEAN+$?aD=XZSk{?+)7*4l2R$sO0e6LeIo1h#;<1lS70 z$uC9Uo)hV^0KQfbk+j8V8>cd%y$b!%nAn%>HzFYo4*>?fB)bB#Vhm5YPLd{JtuxC)o7pQ zoW(|W#g<>D+H5LgCo3xpr7$TPI;#jAg8V;Qx1RagQ_Vpg1IBLG4LJi>1Z}}?-~!+s z(>~||kPCXXs^A?sJEo#YUBdEde^G$CUj)c2W&k9(KA(_f{=#n!+1K$L z5_@|?)6E|bmmYppx;K^;RJLU{UsG(Ax7PDRLwj+2NChtC$CpNaT%`#B0R&IM=8DG9 z|Io`h#?}aB*-*eWeMK5$nt$jJ3?>uM)yEeX0nK3O^=S#4h|~Vnts_7bUMy=HcU!sF zhr|Uqx&sN?NwLIesm@EE;gLPKGv;Pe)bZB;Kn7`~GpJFzSD-h+c!v}0BUiGZ@3JVT zo=>CgbR+F2_=DI!&xE8&kEO3{?h0oK(0Rcq!gnCh=(lF$MY(TyUv4 zBM8-2GwKdF53A{xRa;MV$vXJ>l{)wiZYK>VSAWzGxW3Wk7;PiFt18_!jqc5q29+3A z^^X=uwr2f-sv7o&f(BzE)Jnvv8BqFF-1>@h=il4B;K3qm-RH4h;?6n>=Gd=|gW$;4 zaCCt2W23`fH`f}NJ@u#bo3J2U^;H^-F8dq&5fSO<+Sh+Q5`n>5&~d&Zs~b?bC(DSE zEOtVWef?feE4sJ0w};RT`E9EO93Lj(=VROZ&z59QK#12e<&xSFcuXTzaXXKxoWxdgEsT{AN%;Uw3>w~1QO|4SL6yMN5+M7X3LRT z?iD*Wfm7PKLZcH&7Dvzw%r?EG4NbT?Y zF;ekipxn?$;dNrvFIbrHKC#-KdD%@ky2JxQZn|!>k%Rzjn|hrgwgG-kXuegIGc7ff z4HwPiCIsY)3;XDuxmklZ4cd%00_;KGd8Q5nc8a-GlvdwGrbp+|FeOZu7yZIiJ2U|dD+&uuV-O%; z*%Ovo1R>A;fj9I`p$aj|AgnP!5I5qOCa?tUgmRo?uM5$X?&6Kh9RRqAR9xwDX4Hf* z+FcM%IF;scn3u%bqf~Hdo6c*_X3;x5SjNct%H{>iOfYbu2I8w~3O~<`yOTho2i5D8WK^GDdg5|I{ z$1%0a#k7G*#F=@uSP&7P`qv&6GTVNx(q+h>9CVh>z9Px?wJC@ZR$DmS`R{LFeR-fm{UCtMOzMgT4g}P)qCSb!+ zBm~F$)+aDBV!wN<{#JgCRn#T-+b3)4+u|TOgAwU`7fnD$aoYbAnU>}Wrcl^g&Z~gu zYiO*muMb)+Uav=YhHF5>@B~yXaM3`})>e%1MF$GYHpzVLmPa7lE92{U@dV^~3i9$9 z@PhRs9vvo0?LN$QTT(x5{x3Dy7sh1z;qFT4pw%P8U9JFdI4UGWrlSMOoCO$Fy-4T# zLH#cP$K>-klU&YXwLJikK{i@8P+4J30ZY6Q$25dh6L4o>Vz22-PT7>JhKGE=RfS4{ zI?LedWl z!%*d2X33yhHd|qI;6jhq&t2}%0-mhDfovDtZGFZ57J`6|~w}OGo4328IeSla*bQ`z`2?`RUXosv64-U?Uc@ddcaTM?$qiVA&qGsvqrn8I--zRXRDUXE3c`|_B5L*c^W%OMFXJf0 zpvh^={=>;&MnewyMmFp}!uz%4^tS7Vnp#p^S|)kg^kM!VY97+7wS7r?>-*b1NgNzD zS0jCs#JOKxrbm!U6d6N9)0xs`2&#Ftwq*62E*e_OYuXJ5X9BD`jer&1dI+i=Y^Y}C zrE9~384V1j)n&@@OyGT#F1<2TeflwNK%~2*0P=O#GxK)`n_g=lx0HDo?KMJl)J=IH zG<<~a%CXx^Vt7t;dU&p=q!|R)iZ31V?fwYO-Z?(?NeAnF`uO|$*&OF~q#TGt<(U4J zg4A^kC7Aj?@O#XIdGBVm+37K0hK2K$0m`gejLDqcf%C_m*5I9Vf>cu6%oFSYI7ULs zU59jPbdwqOw}IX=pa)1wd(tVPw&I@U*aR-c*N!aArTsh_hj^`YaukKcURaHB7UlR{ zU^aXTo~QmGz!U2n_LLy$%VyiFHcC!87TL*_Y3(LfK{CNSP^@oUU#hGWmNx4tq!{Vh zAJc{(_H7jD4UOz!tS8~T#dHHh$<~B2t&SKIDJ|pr7;w~6Zdqn|ntwHqm)mzH=w7a~ z^_wC{U|xQ&GsSE?d>jX&lb+RVJ*@No&^O12!7gsiTBKwd!o z>-PwOSPUkC;0Btk@h}VOEYM0Yw45+z7yv%AW^^vjas!&+A6X1N7Q##iollk1<-7a- zv(5xIzeR~sAN#3)tgl(PIkon;svXamwHUb?`;DxxTblly$uTs^8!>sRHgBGQO<$8YF=q(-VWuSJzb!x#J(zVU13X%kw z4sRh&;_Le>c|&Jnrr^$?_V^+{7DYaUAxg-|Y$oR;z`CDK$&=*J(*f zX1Q39*IMkE;q4kdG$TF03r4dEu2!Npp?w7Cze3v{VD7(*Ff4}yguLD)h$#T^Wtq9D z3%>Y3gby@)I1%5HS&Kprz|AxGUZWFZzGimV{d%MJB3*e2<)?W}V&aYsyh^z8mGL{# zVOJh4p*EfqeFb)&BT-`dB9H4wuiJA|wh~xQ>bek;w%=t*BbJyNb{XYV@*4sD@~_v<#^*gCLmBM^a>fD@b#x$vnkyh=hU$8 zo5h($t`IuOHHS891KW5F-QgG8N(HB*cm=pm_Qf5ZdIsXWaLFS1Tv|LV6)j`?smu1c z-AN_xE-NN39$KSVsMq1y9Lv^kfQvPj2R=5tzWJ>x|;?}9Es@+u& zE0NvqM6u6vo3* zZ8bq(-)6t~6ElErR0Gamydkj{3|l~~iwqB>yagqUVP>5YZw3d#2`<&qGAUa~bN4pG zx?kCe10wDAO&P8)iv_Dn+;8&Mg8ygQyQx03_V=+H99}wL;L8AA*+?+xO!-wjGvc-W zh|q`xBML9I70g#U0``C;3Il^NY4K zC8qP96NFyw2SA~v0YOEAl(ePV$)uO3O4MgAijB#am@Ajgg`b?La0%g=HAcu(@)_$6 zZ8`|FS(9rIHK8U)7lYmB>le7WT#DzoQ*rS1FksH&;OnpH{605}mhhkjS(=6UZH%;+ zcMNPO=}W5(BPJ~};kpk!t74HPX!w&#b=tTwJ&Po{cq60um+Jm{=|dlfFu%cY`B6yO zIZ*3l-`Ixr?3R0bzy<$2T<{%Dt=sq(pb2Zf*~x#P9DHoqCwz53uAiE&)--u z8=pHvr*xN=3Gvf+#~iI9Vn(yu}N%}W?w_T$i6~F!2S6+y#6?3k4 zyx-?Lke#&p^OFGMIxTEw)^7H&6zTS;B8S~#pONc|utl{p9EISPIp)1rf>dq#aWxj( zG7J|o{wKLBUX-qTowS*9ecfz+cC79shCL?7n3x!UE;JSFeX)DW*6_{>cvx8SGV?u( zTiP`Mh3j5*LA7^u;IWu^lT&rqm85_i(#jYJ{wV&}P2*(HQlWzTPirO35l{fQXu+F- zAyzp3+}wR+^vws1*e5liKBz zF+6bPHBHxkVEh_7n#7(e&I#ZFbo(aCeTo1%9! z34u7#T@3maG`>nQL-QgJ(?WF@&WoUv2fi^-(db3mI&pquYM^d7qLp#Gwd%Qpc7Xw2 zPy*sTOxF54I=;0Zm&xE2gWXR)!+s1C?Ij|Faf1h-HUDJ)S1v&oNFLYM*Wu9!2S?CE zs;7%5qsS#gi+Tn&pa^#Zu(iAuk)S41YZpo<;Z zKIyb}3-~>XNlnUIn{Yk$x?d)C2|y7sXa!j}?aetHhCCS`ajq0n*6>pL%b@=rcat<3 z{~?AZ+&>{IDH!x3lax~SjU4|+te+n!gH>M3z0Q8+OT=?ciO_U~im<~|-b_VYPgRW@aha)ZK@ZRl&TD7k$;b2=|14EI9XI$0cx+`RW53R& zgXSDTi6A5-Tq()NgPuTH%A=`4HY>}tj8}OfAFrbLQru-s3HCRg2it0SR27vOMCPtO zS2uxCHESre;L@K;O}uzfsjwDRF#Lq`=JqwK(^h-C_X9lgyOqsNSVybzYy^xDH7eo_ zAQJW$+1ZTO2KQ%9H)`eR7pp+tJ`42r&hxZietia5JK2Z)}9!F!0~iZ4DEwZQi8SUVUam+dE*ryLDhP=&halEmI=za@q>D ztkrDt-l1mdZC9RmJs>J15w5?|{)5@?t-*uleIB_I+#g1C^N-ON*sxZzSJKh(Cal$0qVsJ|4Ty zU1}88i|ry;89_>G9$ZFMGU|Z_qWal_>Fht$Y1vh z1%~L2W4E#+P=5D<5eN>+)`gp~A-mnqKSa1l>5;;|O?rl#Fx;MFQp$Prc+4?{t<{xh zn=w9M(&AuYZ5#3d?-QRwR49IlJY`w}BU(AR>E`-H{&X4|uK5YHgFrC(LjZ6D(LG|MC` zod&Xm&d2CGS!ZXWL+&vA_12$-VLBLxSq3HE`a_$K-7}-3gqy{dwJuKElk*Fmd*84) z)J+%jT%3g7iPub-+Y>4g8=Y)X3lQswe}5?}`OA&`^Bfko=-PUx^xN-igor1;c)V8c z!^E-}oESMfF<%B>eHqJEDZj8iQPo8krVmb_^2}*hb#dYqttg%t$#M7|gjBK8k8UeQ zW#K;|vwBJWY_kW>yPocDT;xFD&EvE)z6l6%cIi%D@d(P2!!C-{J*#WBm^~ERe_RWF zA+38BMgyE3TxB*Fg}ak8@LfO6G%N48cYa&*plij8OT^=>9Ps!M>c3x7fu#Rcl(4>* z&!IRud|jSBGl)*k8!#|np3Ci?IPRCyvxkp_jV4kLcgd%KIv9y0vb!+!7*b{&?6sUm; zy6WkSgpf~Y=7aJhZ3}&0UM@m-|9r7v&$ zZSB{<6oMif#RiUgqG>88o}V*M3-Ys*D@wOqj<&wSh(i(zSWG`=REHXdgxtofg0+?m z^`RxRw^LMTN#ZAA;6?guKUsGUmPbS-x8k7548LdJ-6yM)UEL}X>?5%xXxj^HmLAuy za!DP=VKH?cp;z5Mk1Dt3IMs!{QdOY7p@U-EC6fqA znD$a!Cb|2gDp+VYg#R&j3D$rX9qy3FZUQ+G)*`ECb)5s|6dDrCrYx`u&D#l?C^ml? z3IZIo|Fxza_TO_RNLIt_US$f1ehPz|xMFW39pcy17w*HbcW?80@c5qo)Ue^1I*BxT(VmsNsV+heIb z(Z527$z%`y=IfXx&9V!>LQcy5&h;L4PNeh9LUngdyhbF;^z)m~V|9INj5QQpQscrR z#)A^C{&m*fv_UOprjpJbAFDw|$BnxwtyNMgVkwY_b$Yre1?k|4f-T*2;6vOk&ew|T ztR($bq);qoBW18zU+-zJOBCm)m@Qwo9Z93sq9xL(9d4Y+J#;1fcx!}6^oCOXaEK{K zbQvQ4GSH$}%}^rt_XISwm+Sr44GSX~=hgQ(49D{liWEwPoHxb5T7rkvUAW4kzIo@p zFpEKy9d>W4&$41Mcd}ns(zqV-AKLf+ND12`c%jV8vme|~n7_w( z8M<%S>F#0)^16%l$KX;w@M8RLEhBtLlceF$@b|2)lxb339T78v)2ub(+)iI2qd-5B zSI}Gkto>f9xVtM#eo29e((Y~0U6g{<@`+UFhc93FH{x*pvtbBfVMgZNrq5oj!o4&$ zLhOsB!bD#ESX!ulmDT9fwdwwgrOpLc2GX>Y(@5t1I91TJKTW%8o+-Yz{dpDcTD{Up z+YctgvB}Mg=i7#DMv{2n%R-ifna9;4>VIsVuDm5(2pE1*+al4(>rD zq0OMOqDbBj_V8!y2rv5gjcy%VgJCsg&#DCXH44F-@c(bP5bDI&S}~@qXPQ zk-Joqoqzo7Xn~Z5JNxeXOU+4x>jhu%cT6K6l&uKQ+#IBdYQb-7gBGqyKMy0b0&Aa| zZVzf_#%2xvHMYL;Msi85%eLIePY2!hYpcI`<0I)GXw{@L@ML^uTw-t0UI_7+jF9vOz1-M1fJY`a@_tKhV6(*#!QB@Wqv&KqmiRkgIqa^xc4&J_z8CMA4 zm_0V$m{QJ@n3*B@$IN?!ETvWtUJvN_Hg zThJdB`Cpy=F&JmB2)Ey-n8ZuCUa7G<>~>Md`!5#7(?@2M+mcJTi+k)uI+6b<^`{K9 zpAaLiS2|hD83qCE10H)MJ7*fT>bG)+XzJm!rFv;Fpr1JK`gy!f z#uT!@B#g^)eO*h-zVqENM#!xo*2^GA-Zs=KKHbECc}yMZ{IK^ZD6&8-+}E=tW5=q9gp zWW1V2iP)RXerfX=D}vX|vZWk`1IQS;5)-c$`0a1WnQ#d{BY;d8{}awEhWAd7+&5P( zwTea80-IDvXz!fQ7hJ>yHyk>v=-2xd(LY%zPyIfMrDf03Y`nnp6wlQ6AokiGo=oFm zYnJ!a%8{^p2)cLOi`$vh3z;sSe_tx}pLH6UWi!W3b9JN4%i|i7DzK12CFNw4#EZ~2 zJ!e=}>RLYKgtNfj&g8H9mGe<#+nBj-B&dAK)%Wv>g5e-}hlv`E@olUBCm5$o?i0)N z>b9!rc9vfWImvC1^(m9bszeg=9ReOSj`=i%K9M*7uE_ZI9Y}cFxrd_AbgUIas$Dx5 z=lw77?C(gs{V@a(*Qwd<$adU%By6!#b|;TVRqh9^1lsr;q4HeF|2}lI&2W9E#BvZU z;@8}B;??`tN8cA%+X^RP9O<=A?<`go+f^E_lHRB2u5p0IEUj)U?#)6?2u^4%b)+Q#$NHdn3}et%1BpjXW> z2!i^b2mX1u?fZ6$7;$>gP*c3=;U`jaR^ork(r1|t2M8TK>07=Jf&V$m-uJB1Xyu97 zk-6!gp&O`X%^Uvf#jgPuf7*bJ(7X4~7N~nC^A!H>pML_=PR_3t^v_8c$-dHHC-V)1 zE)jDxnC6?>KR+QI{3&M-lncQ>T~La@GyGp zNT$Hk+H6RDVpl8q5Gg!<+2vq7G}p$?PR)-?Vb6DFv7owC*4oBUjnoDLs(Wg|MeCQk z+^KrrA#9BjX={7)hLNU^zAUahNovrZzWy#lr%2FF|KIn#q&&GBlci7&M!J+plEWzZ zqjS`w@cV@e7hmPjcPFk^2P2~a@CkTQzal{1e~1mZLt<7-am%}ib<%R&DvA`jVB2F4t8$X*I9y^Q4hmp=ADI%Na%U8I6AKxqgVg_*72L&Fz z^l{3GpcnH!ZG&amUyb=qw#JU`;Qg71bmS@G^C5|7d?($`qrtb>?W5@rULzkOoT7Ul zHty9<2mXGD{{6DxN0Oql4SY{>%TMX`x61{QOwG>Sb@2s*F(&~X9~5t4oHeQb_vC^| z<{iI=&*1bR;M3>|_L)z3z{+F0og}xFT6;FO)uSy_AjJQAyuBP@q!s(?M0TjRue~S8 zM<^5SDVp~5_Qv6O7ROTTFBQ7oWp_mSXG>L)G$InbJZ@YCMhA^A;WLW=TfeKw?}QCb z8f*iYeEh-&h`7e~+PQ|r_W8(G4_A_w=7VY;9h}vp?*09j6J|0IzoU|VNBdxJ#@ML; zu=${F@os`E-|UfSsYvPXGw#RMWQ zsf?6-HVn+ATu}E1+7A5(cO$Ll%gvHeMC7TDZX(6*WcJMB?w{rL#LhjwZJOLaUT}S| zhj2IHa8&z}Exa%IvN1gC|8)1ba(pZMK}i-T-4bH;Zz1i2VFosB@Xj6mYzk0OfdRNuK%N=y8+aeJ34OXsz{nt4FB zhAUntf=b)MS|T#;JOLg`_Yjo zoouWB@Ox87JTlpc=La;$NWK=a<%WcmS>ZJz&HL3ehbHsr=BJz>zVqKgLr8fTWC)?-s7tUJ7Qc2x_cSugai7U$Wp?NB{`@Eu{^)FG z(DXN=!Px5F`*T3#U+Rt9@&U?}?zj&ZzD5HHy_0@GS9EwzII7-u~Wjs}*TR zu|!%XP^ads<9;RePMgL|Z?;jve8f5qt%d!cFZptn;a#PXZorf2h~Bhp14nUNvFXL3 zR523vf=2S8o2f{p-BA?}d(%+$PFTsXiTz>f^zqs0xsgq3`WWYaDr%l_^P9_IylvyE z7M7;Xshu$T5fen+Rs#GH$i(AX71m5Hdoyb_R4l^F4x^g1*$NoO&p4R&|M$D|kU{8p zTs=!UA9GGQE^t*iwOcA~lCb(jnb7}N)jz>@+eZ=$f4T`F3#24==roa&fBD}E^m*yU ze=9>U1nPgw zvn>Sfn1yd1XXWL|31ETQ7h56 zub0sUCws4?bDOA7Q<_|A`5LWfDOEA7^tUoi827 zMjK=e0q7YJzTJV>4FE5ysLbW2za|Nx#C3Q}`49kR%OsGhqmxT`dqA3+z&IWVF#iBm zQUwjPmg`OqFfu%|#imv3bSK#e!K4Q2sr8+mo6`aMj%D!DP(mJ8Fv`ar5#vQIvIi(j zW~Dt@Q~`dnv@T}C@VRxSU;rTI@;V={0C~aOEQMUMq*;`sMy8s6Oz-oKm7y_sWaI9%G8_t3GXz?zNC8ZNPQOC_rUOJ!#!Q)#13mu?NegNv& z)*Qgn?0{|4AKrEozXO zkZsbxCli(EVH-7*WreRsBjBt8Qgv@{Z(mp>;Qx3ITo)>pR!o@_kkYYlw9uEVI5DSX zG`~G}T!+YPX*T=J+OB6WA5!uy0-E?UPHh0{Ekizv{AAT zA_@km^|k6So>~B00>6P!Y#ilsu{yg_2j9cFLS3n1VO+`#V7plX7e^a~0(tURc59so zD;zYfzzD2pi03>eT+d!u6ao8J?5sFMt%PGiPDntg%{+fQF-j;oYj@S5zJ%>P*fcV| z>b>9t@kguFe=`g_!`jH`;2pK(C}^9cSMqzm%bl8bWDl^wt-U>SMns~So*sC;O)V|a z9+6xi!94`#NxI?B4-BlD9~d9y^W`!DVc8SpySSIq;@oW-0{{9#;5-bR7pPUrbb!Eb zCGAAZiLew8ShR2G0gWWO)2RDE94(FC)7|nD@IXW1BPaa=V7C{SnCR#)+d$OU3n=ei zRfpFhxO_f&gRD9FcqR{-NoV0Yh&Ct3$14|5$yMMDK*kJBo;O&Pmq4`% zmICStXw+9PhRl4t^d3ZV6}JiUjIQS=Y{LLHBU~Va38YB0IX&Lr%sG6I(=U+E0i49= ztpyT#yj6&sMjZ%0*?7a+jWkyPRl`rwQNFJMPUUDJVT3%mf`BL)eMP{i=ik!8*Az7O z5{jFLrzaGr(sY8tb5e%xr$ClHK$j2?0k>$~m@sp#eB9@XrrF-)L|kM{b*BnAqKYBK zpxy_J7XXo>HYXc@r0N)KkUfNMQbQf!ckmH>cpJu4Z3ANvf%9U z5*Udd0&2X#t6;OSU$7&1s_4MnAjSaEpMQHEc=*3+0a~pkUO-^X_V^3b{sQ|zUIZ#* zzpGU61;_$ulhyhDjcG**LiaVAL(Ub=LNyB3jE5M_ooFaNmyF@q>=lA=t43?u3X|C+ zrKzSpGX|Z;yL12FIRv58}7X7Rk0Ts1Lzugd4{F2rE~tD_C49i zfJ{qkPU z!RO3d68M`4E#h&y5C{YRE#hNf|Bz1({Hk7*BHx=#0ms{N_4R4*gJvxNJ72D}#w z`zCc3?PV0?IYB8=piY&;oF0-0;_*iPm^!gw;_f-?sgi_s5nx84Tl|$=M``d)0!bbJ zA=wD8Hp^=`Ld)R7-aWEem@*5A^Gs^-75ep@^SlLDaEz~}^?rb6iHQCnyVYS*8v?oXxk>Q9OF*2_NTfqSrPnr`1E+irzHpgJ<~h{k8|K$ zy*-!+-9)wQr@(Q3u=LHoiw|lVae+=% zk3ms~B|JZnSi^PeQo~mXDCa!q4&mkjiYtID6$f!Y`AX%p5vLF5{O+4vaTum15SB5a zl^K|x>C5bn;U{Of`}k%upn_(l6}K1#r9&yAm8WG!g)#YsXRE@vtJt~dbF2If$;1uz z;2i_LbMoU=%TubhhDy5~X2Y&}xnfLj=2gs~NhfEj2cc3)tfPiY2s$=r&*y;N874;U z1Hv#{!teg2&9{i3NQer792m%~^~z1Kp=~#BzOifdbdzrk>VgL1XSKKYi`_K!oau8I(c8 z>|-jYP5GHy;{07TsS$<69Lao$u}!uUnjv5{%1_R|U(Q%}80`}4-lK$H0wFaZC<2kd z928!Yybkx96VB&;tbh^TH41LjjZIBhoQV}1h8M)hu-WOHdk+UnUWQoxDf0Vs|7UE*(8PC2@q}@Vj2FpOr%TOl^Tob>6m;*Ow4n#!6HIFs|eDc*D_oj%52yRm& zo`Z4SywS4pOcL_5z;oe1FRcX7k6rhifrh81(teUYC2Xj|Y*Nm$1 z$Mt$*?GTxBxBXVn(}MtZukyKJUU$grx>#*h_Ve?*iMB2{1(G{o9cH7!Pr#qsz@{_! zO%zm^+*$rB8#bMG&@+&Wy;ue{+1bTqsz~*%6iO#_)U)GKjzp|CW>CXJF#KO+jqsyaZqR_L5S9Lzvl&@M` zFU+bZT^vb15;!NXB+7z%L!Q%-2CH;MmLnAZYpg?MQliI5Wy2xVxIcn$uE~vkG6kf2 z0O25PsMJ-5FH)W4913q}X(@dI?7Px6?jkidKywa#zVK`?QVtKx@pjBPx)i>8cxib* zYm=xEE~5TBvZ1RE%Y{GzK}Dl4s+H1ANLvK&>6vK`a>TT0E=^ts9tOcy^k@hQYbgU} z2WSw2$)H zVt{J}QsUb67!Todv$nqj(!q;sW@;1HG-Sv}Z?4bQAZ`mRk`lI%Jqn#EWRr1_7_