direct-io.hg
changeset 6043:a9ee400a5da9
1) More testing: include tests which I forgot in previous patch, remove
xs_watch_stress, reduce cycles in "make check" random test.
2) xs_crashme: corrupt random packets going to xenstored, watch it
crash.
3) Handle second input from before we finished output on first one.
4) Fix bug where one-arg operations are given zero args.
5) Fix bug where SET_PERMS fails after blocking on transaction.
6) Fix memory leak when DIRECTORY op given no argument.
7) Fail on first memory leak, for better testing.
8) Fix missing waiting_for_ack initialization for new connections.
9) Ensure all input and output is handled for domains so we don't stall.
10) Fix overrun bug in xs_count_strings on non-nul-terminated strings.
11) New test for clients which write without waiting for response.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
xs_watch_stress, reduce cycles in "make check" random test.
2) xs_crashme: corrupt random packets going to xenstored, watch it
crash.
3) Handle second input from before we finished output on first one.
4) Fix bug where one-arg operations are given zero args.
5) Fix bug where SET_PERMS fails after blocking on transaction.
6) Fix memory leak when DIRECTORY op given no argument.
7) Fail on first memory leak, for better testing.
8) Fix missing waiting_for_ack initialization for new connections.
9) Ensure all input and output is handled for domains so we don't stall.
10) Fix overrun bug in xs_count_strings on non-nul-terminated strings.
11) New test for clients which write without waiting for response.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
line diff
1.1 --- a/tools/xenstore/Makefile Mon Aug 08 09:12:22 2005 +0000 1.2 +++ b/tools/xenstore/Makefile Mon Aug 08 09:13:19 2005 +0000 1.3 @@ -41,9 +41,9 @@ xenstored_test: xenstored_core_test.o xe 1.4 xs_test: xs_test.o xs_lib.o utils.o 1.5 xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o 1.6 xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o 1.7 -xs_watch_stress: xs_watch_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o 1.8 +xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o 1.9 1.10 -xs_test.o xs_stress.o xs_watch_stress.o xenstored_core_test.o xenstored_watch_test.o xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o talloc_test.o fake_libxc.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS) 1.11 +xs_test.o xs_stress.o xenstored_core_test.o xenstored_watch_test.o xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o talloc_test.o fake_libxc.o xs_crashme.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS) 1.12 1.13 xenstored_%_test.o: xenstored_%.c 1.14 $(COMPILE.c) -o $@ $< 1.15 @@ -65,7 +65,7 @@ libxenstore-pic.a: $(LIB_OBJS_PIC) 1.16 1.17 clean: testsuite-clean 1.18 rm -f *.o *.opic *.a 1.19 - rm -f xen xenstored xs_random xs_stress xs_watch_stress 1.20 + rm -f xen xenstored xs_random xs_stress xs_crashme 1.21 rm -f xs_test xenstored_test xs_dom0_test 1.22 -$(RM) $(PROG_DEP) 1.23 1.24 @@ -96,14 +96,18 @@ randomcheck: xs_random xenstored_test 1.25 $(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo 1.26 $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED) 1.27 1.28 +crashme: xs_crashme xenstored_test 1.29 + rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace 1.30 + export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null 1.31 + if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind complained; cat /tmp/xs_crashme.vglog*; exit 1; fi 1.32 + rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace 1.33 + 1.34 randomcheck-fast: xs_random xenstored_test 1.35 - @$(TESTENV) ./xs_random --fast /tmp/xs_random 10000 $(RANDSEED) 1.36 + @$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED) 1.37 1.38 -stresstest: xs_stress xs_watch_stress xenstored_test 1.39 +stresstest: xs_stress xenstored_test 1.40 rm -rf $(TESTDIR)/store $(TESTDIR)/transactions 1.41 export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret 1.42 - rm -rf $(TESTDIR)/store $(TESTDIR)/transactions 1.43 - export $(TESTENV); PID=`./xenstored_test --output-pid`; ./xs_watch_stress; ret=$$?; kill $$PID; exit $$ret 1.44 1.45 xs_dom0_test: xs_dom0_test.o utils.o 1.46 $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxc -o $@
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/xenstore/testsuite/01simple.test Mon Aug 08 09:13:19 2005 +0000 2.3 @@ -0,0 +1,4 @@ 2.4 +# Create an entry, read it. 2.5 +write /test create contents 2.6 +expect contents 2.7 +read /test
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/xenstore/testsuite/02directory.test Mon Aug 08 09:13:19 2005 +0000 3.3 @@ -0,0 +1,34 @@ 3.4 +# Root directory has only tool dir in it. 3.5 +expect tool 3.6 +dir / 3.7 + 3.8 +# Create a file. 3.9 +write /test create contents 3.10 + 3.11 +# Directory shows it. 3.12 +expect test 3.13 +expect tool 3.14 +dir / 3.15 + 3.16 +# Make a new directory, check it's there 3.17 +mkdir /dir 3.18 +expect dir 3.19 +expect test 3.20 +expect tool 3.21 +dir / 3.22 + 3.23 +# Check it's empty. 3.24 +dir /dir 3.25 + 3.26 +# Create a file, check it exists. 3.27 +write /dir/test2 create contents2 3.28 +expect test2 3.29 +dir /dir 3.30 +expect contents2 3.31 +read /dir/test2 3.32 + 3.33 +# Creating dir over the top should fail. 3.34 +expect mkdir failed: File exists 3.35 +mkdir /dir 3.36 +expect mkdir failed: File exists 3.37 +mkdir /dir/test2
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tools/xenstore/testsuite/03write.test Mon Aug 08 09:13:19 2005 +0000 4.3 @@ -0,0 +1,20 @@ 4.4 +# Write without create fails. 4.5 +expect write failed: No such file or directory 4.6 +write /test none contents 4.7 + 4.8 +# Exclusive write succeeds 4.9 +write /test excl contents 4.10 +expect contents 4.11 +read /test 4.12 + 4.13 +# Exclusive write fails to overwrite. 4.14 +expect write failed: File exists 4.15 +write /test excl contents 4.16 + 4.17 +# Non-exclusive overwrite succeeds. 4.18 +write /test none contents2 4.19 +expect contents2 4.20 +read /test 4.21 +write /test create contents3 4.22 +expect contents3 4.23 +read /test
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/xenstore/testsuite/04rm.test Mon Aug 08 09:13:19 2005 +0000 5.3 @@ -0,0 +1,18 @@ 5.4 +# Remove non-existant fails. 5.5 +expect rm failed: No such file or directory 5.6 +rm /test 5.7 +expect rm failed: No such file or directory 5.8 +rm /dir/test 5.9 + 5.10 +# Create file and remove it 5.11 +write /test excl contents 5.12 +rm /test 5.13 + 5.14 +# Create directory and remove it. 5.15 +mkdir /dir 5.16 +rm /dir 5.17 + 5.18 +# Create directory, create file, remove all. 5.19 +mkdir /dir 5.20 +write /dir/test excl contents 5.21 +rm /dir
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/xenstore/testsuite/05filepermissions.test Mon Aug 08 09:13:19 2005 +0000 6.3 @@ -0,0 +1,81 @@ 6.4 +# Fail to get perms on non-existent file. 6.5 +expect getperm failed: No such file or directory 6.6 +getperm /test 6.7 +expect getperm failed: No such file or directory 6.8 +getperm /dir/test 6.9 + 6.10 +# Create file: inherits from root (0 READ) 6.11 +write /test excl contents 6.12 +expect 0 READ 6.13 +getperm /test 6.14 +setid 1 6.15 +expect 0 READ 6.16 +getperm /test 6.17 +expect contents 6.18 +read /test 6.19 +expect write failed: Permission denied 6.20 +write /test none contents 6.21 + 6.22 +# Take away read access to file. 6.23 +setid 0 6.24 +setperm /test 0 NONE 6.25 +setid 1 6.26 +expect getperm failed: Permission denied 6.27 +getperm /test 6.28 +expect read failed: Permission denied 6.29 +read /test 6.30 +expect write failed: Permission denied 6.31 +write /test none contents 6.32 + 6.33 +# Grant everyone write access to file. 6.34 +setid 0 6.35 +setperm /test 0 WRITE 6.36 +setid 1 6.37 +expect getperm failed: Permission denied 6.38 +getperm /test 6.39 +expect read failed: Permission denied 6.40 +read /test 6.41 +write /test none contents2 6.42 +setid 0 6.43 +expect contents2 6.44 +read /test 6.45 + 6.46 +# Grant everyone both read and write access. 6.47 +setperm /test 0 READ/WRITE 6.48 +setid 1 6.49 +expect 0 READ/WRITE 6.50 +getperm /test 6.51 +expect contents2 6.52 +read /test 6.53 +write /test none contents3 6.54 +expect contents3 6.55 +read /test 6.56 + 6.57 +# Change so that user 1 owns it, noone else can do anything. 6.58 +setid 0 6.59 +setperm /test 1 NONE 6.60 +setid 1 6.61 +expect 1 NONE 6.62 +getperm /test 6.63 +expect contents3 6.64 +read /test 6.65 +write /test none contents4 6.66 + 6.67 +# User 2 can do nothing. 6.68 +setid 2 6.69 +expect setperm failed: Permission denied 6.70 +setperm /test 2 NONE 6.71 +expect getperm failed: Permission denied 6.72 +getperm /test 6.73 +expect read failed: Permission denied 6.74 +read /test 6.75 +expect write failed: Permission denied 6.76 +write /test none contents4 6.77 + 6.78 +# Tools can always access things. 6.79 +setid 0 6.80 +expect 1 NONE 6.81 +getperm /test 6.82 +expect contents4 6.83 +read /test 6.84 +write /test none contents5
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/xenstore/testsuite/06dirpermissions.test Mon Aug 08 09:13:19 2005 +0000 7.3 @@ -0,0 +1,119 @@ 7.4 +# Root directory: owned by tool, everyone has read access. 7.5 +expect 0 READ 7.6 +getperm / 7.7 + 7.8 +# Create directory: inherits from root. 7.9 +mkdir /dir 7.10 +expect 0 READ 7.11 +getperm /dir 7.12 +setid 1 7.13 +expect 0 READ 7.14 +getperm /dir 7.15 +dir /dir 7.16 +expect write failed: Permission denied 7.17 +write /dir/test create contents2 7.18 + 7.19 +# Remove everyone's read access to directoy. 7.20 +setid 0 7.21 +setperm /dir 0 NONE 7.22 +setid 1 7.23 +expect dir failed: Permission denied 7.24 +dir /dir 7.25 +expect read failed: Permission denied 7.26 +read /dir/test create contents2 7.27 +expect write failed: Permission denied 7.28 +write /dir/test create contents2 7.29 + 7.30 +# Grant everyone write access to directory. 7.31 +setid 0 7.32 +setperm /dir 0 WRITE 7.33 +setid 1 7.34 +expect getperm failed: Permission denied 7.35 +getperm /dir 7.36 +expect dir failed: Permission denied 7.37 +dir /dir 7.38 +write /dir/test create contents 7.39 +setid 0 7.40 +expect 1 WRITE 7.41 +getperm /dir/test 7.42 +setperm /dir/test 0 NONE 7.43 +expect contents 7.44 +read /dir/test 7.45 + 7.46 +# Grant everyone both read and write access. 7.47 +setperm /dir 0 READ/WRITE 7.48 +setid 1 7.49 +expect 0 READ/WRITE 7.50 +getperm /dir 7.51 +expect test 7.52 +dir /dir 7.53 +write /dir/test2 create contents 7.54 +expect contents 7.55 +read /dir/test2 7.56 +setperm /dir/test2 1 NONE 7.57 + 7.58 +# Change so that user 1 owns it, noone else can do anything. 7.59 +setid 0 7.60 +setperm /dir 1 NONE 7.61 +expect 1 NONE 7.62 +getperm /dir 7.63 +expect test 7.64 +expect test2 7.65 +dir /dir 7.66 +write /dir/test3 create contents 7.67 + 7.68 +# User 2 can do nothing. Can't even tell if file exists. 7.69 +setid 2 7.70 +expect setperm failed: Permission denied 7.71 +setperm /dir 2 NONE 7.72 +expect getperm failed: Permission denied 7.73 +getperm /dir 7.74 +expect dir failed: Permission denied 7.75 +dir /dir 7.76 +expect read failed: Permission denied 7.77 +read /dir/test 7.78 +expect read failed: Permission denied 7.79 +read /dir/test2 7.80 +expect read failed: Permission denied 7.81 +read /dir/test3 7.82 +expect read failed: Permission denied 7.83 +read /dir/test4 7.84 +expect write failed: Permission denied 7.85 +write /dir/test none contents 7.86 +expect write failed: Permission denied 7.87 +write /dir/test create contents 7.88 +expect write failed: Permission denied 7.89 +write /dir/test excl contents 7.90 +expect write failed: Permission denied 7.91 +write /dir/test4 none contents 7.92 +expect write failed: Permission denied 7.93 +write /dir/test4 create contents 7.94 +expect write failed: Permission denied 7.95 +write /dir/test4 excl contents 7.96 + 7.97 +# Tools can always access things. 7.98 +setid 0 7.99 +expect 1 NONE 7.100 +getperm /dir 7.101 +expect test 7.102 +expect test2 7.103 +expect test3 7.104 +dir /dir 7.105 +write /dir/test4 create contents 7.106 + 7.107 +# Inherited by child. 7.108 +mkdir /dir/subdir 7.109 +expect 1 NONE 7.110 +getperm /dir/subdir 7.111 +write /dir/subfile excl contents 7.112 +expect 1 NONE 7.113 +getperm /dir/subfile 7.114 + 7.115 +# But for domains, they own it. 7.116 +setperm /dir/subdir 2 READ/WRITE 7.117 +expect 2 READ/WRITE 7.118 +getperm /dir/subdir 7.119 +setid 3 7.120 +write /dir/subdir/subfile excl contents 7.121 +expect 3 READ/WRITE 7.122 +getperm /dir/subdir/subfile
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/xenstore/testsuite/07watch.test Mon Aug 08 09:13:19 2005 +0000 8.3 @@ -0,0 +1,194 @@ 8.4 +# Watch something, write to it, check watch has fired. 8.5 +write /test create contents 8.6 + 8.7 +1 watch /test token 8.8 +2 write /test create contents2 8.9 +expect 1:/test:token 8.10 +1 waitwatch 8.11 +1 ackwatch token 8.12 +1 close 8.13 + 8.14 +# Check that reads don't set it off. 8.15 +1 watch /test token 8.16 +expect 2:contents2 8.17 +2 read /test 8.18 +expect 1: waitwatch failed: Connection timed out 8.19 +1 waitwatch 8.20 +1 close 8.21 + 8.22 +# mkdir, setperm and rm should (also tests watching dirs) 8.23 +mkdir /dir 8.24 +1 watch /dir token 8.25 +2 mkdir /dir/newdir 8.26 +expect 1:/dir/newdir:token 8.27 +1 waitwatch 8.28 +1 ackwatch token 8.29 +2 setperm /dir/newdir 0 READ 8.30 +expect 1:/dir/newdir:token 8.31 +1 waitwatch 8.32 +1 ackwatch token 8.33 +2 rm /dir/newdir 8.34 +expect 1:/dir/newdir:token 8.35 +1 waitwatch 8.36 +1 ackwatch token 8.37 +1 close 8.38 +2 close 8.39 + 8.40 +# We don't get a watch from our own commands. 8.41 +watch /dir token 8.42 +mkdir /dir/newdir 8.43 +expect waitwatch failed: Connection timed out 8.44 +waitwatch 8.45 +close 8.46 + 8.47 +# ignore watches while doing commands, should work. 8.48 +watch /dir token 8.49 +1 write /dir/test create contents 8.50 +expect contents 8.51 +read /dir/test 8.52 +expect /dir/test:token 8.53 +waitwatch 8.54 +ackwatch token 8.55 +close 8.56 + 8.57 +# watch priority test: all simultaneous 8.58 +1 watch /dir token1 8.59 +3 watch /dir token3 8.60 +2 watch /dir token2 8.61 +write /dir/test create contents 8.62 +expect 3:/dir/test:token3 8.63 +3 waitwatch 8.64 +3 ackwatch token3 8.65 +expect 2:/dir/test:token2 8.66 +2 waitwatch 8.67 +2 ackwatch token2 8.68 +expect 1:/dir/test:token1 8.69 +1 waitwatch 8.70 +1 ackwatch token1 8.71 +1 close 8.72 +2 close 8.73 +3 close 8.74 + 8.75 +# If one dies (without acking), the other should still get ack. 8.76 +1 watch /dir token1 8.77 +2 watch /dir token2 8.78 +write /dir/test create contents 8.79 +expect 2:/dir/test:token2 8.80 +2 waitwatch 8.81 +2 close 8.82 +expect 1:/dir/test:token1 8.83 +1 waitwatch 8.84 +1 ackwatch token1 8.85 +1 close 8.86 + 8.87 +# If one dies (without reading at all), the other should still get ack. 8.88 +1 watch /dir token1 8.89 +2 watch /dir token2 8.90 +write /dir/test create contents 8.91 +2 close 8.92 +expect 1:/dir/test:token1 8.93 +1 waitwatch 8.94 +1 ackwatch token1 8.95 +1 close 8.96 +2 close 8.97 + 8.98 +# unwatch 8.99 +1 watch /dir token1 8.100 +1 unwatch /dir token1 8.101 +1 watch /dir token2 8.102 +2 write /dir/test2 create contents 8.103 +expect 1:/dir/test2:token2 8.104 +1 waitwatch 8.105 +1 unwatch /dir token2 8.106 +1 close 8.107 +2 close 8.108 + 8.109 +# unwatch while watch pending. Other watcher still gets the event. 8.110 +1 watch /dir token1 8.111 +2 watch /dir token2 8.112 +write /dir/test create contents 8.113 +2 unwatch /dir token2 8.114 +expect 1:/dir/test:token1 8.115 +1 waitwatch 8.116 +1 ackwatch token1 8.117 +1 close 8.118 +2 close 8.119 + 8.120 +# unwatch while watch pending. Should clear this so we get next event. 8.121 +1 watch /dir token1 8.122 +write /dir/test create contents 8.123 +1 unwatch /dir token1 8.124 +1 watch /dir/test token2 8.125 +write /dir/test none contents2 8.126 +expect 1:/dir/test:token2 8.127 +1 waitwatch 8.128 +1 ackwatch token2 8.129 + 8.130 +# check we only get notified once. 8.131 +1 watch /test token 8.132 +2 write /test create contents2 8.133 +expect 1:/test:token 8.134 +1 waitwatch 8.135 +1 ackwatch token 8.136 +expect 1: waitwatch failed: Connection timed out 8.137 +1 waitwatch 8.138 +1 close 8.139 + 8.140 +# watches are queued in order. 8.141 +1 watch / token 8.142 +2 write /test1 create contents 8.143 +2 write /test2 create contents 8.144 +2 write /test3 create contents 8.145 +expect 1:/test1:token 8.146 +1 waitwatch 8.147 +1 ackwatch token 8.148 +expect 1:/test2:token 8.149 +1 waitwatch 8.150 +1 ackwatch token 8.151 +expect 1:/test3:token 8.152 +1 waitwatch 8.153 +1 ackwatch token 8.154 +1 close 8.155 + 8.156 +# Creation of subpaths should be covered correctly. 8.157 +1 watch / token 8.158 +2 write /test/subnode create contents2 8.159 +2 write /test/subnode/subnode create contents2 8.160 +expect 1:/test/subnode:token 8.161 +1 waitwatch 8.162 +1 ackwatch token 8.163 +expect 1:/test/subnode/subnode:token 8.164 +1 waitwatch 8.165 +1 ackwatch token 8.166 +expect 1: waitwatch failed: Connection timed out 8.167 +1 waitwatch 8.168 +1 close 8.169 + 8.170 +# Watch event must have happened before we registered interest. 8.171 +1 watch / token 8.172 +2 write /test/subnode create contents2 8.173 +1 watch / token2 0 8.174 +expect 1:/test/subnode:token 8.175 +1 waitwatch 8.176 +1 ackwatch token 8.177 +expect 1: waitwatch failed: Connection timed out 8.178 +1 waitwatch 8.179 +1 close 8.180 + 8.181 +# Rm fires notification on child. 8.182 +1 watch /test/subnode token 8.183 +2 rm /test 8.184 +expect 1:/test/subnode:token 8.185 +1 waitwatch 8.186 +1 ackwatch token 8.187 + 8.188 +# Watch should not double-send after we ack, even if we did something in between. 8.189 +1 watch /test2 token 8.190 +2 write /test2/foo create contents2 8.191 +expect 1:/test2/foo:token 8.192 +1 waitwatch 8.193 +expect 1:contents2 8.194 +1 read /test2/foo 8.195 +1 ackwatch token 8.196 +expect 1: waitwatch failed: Connection timed out 8.197 +1 waitwatch
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/xenstore/testsuite/08transaction.slowtest Mon Aug 08 09:13:19 2005 +0000 9.3 @@ -0,0 +1,21 @@ 9.4 +# Test transaction timeouts. Take a second each. 9.5 + 9.6 +mkdir /test 9.7 +write /test/entry1 create contents 9.8 + 9.9 +# Transactions can take as long as the want... 9.10 +start /test 9.11 +sleep 1100 9.12 +rm /test/entry1 9.13 +commit 9.14 +dir /test 9.15 + 9.16 +# ... as long as noone is waiting. 9.17 +1 start /test 9.18 +notimeout 9.19 +2 mkdir /test/dir 9.20 +1 mkdir /test/dir 9.21 +expect 1:dir 9.22 +1 dir /test 9.23 +expect 1: commit failed: Connection timed out 9.24 +1 commit
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/xenstore/testsuite/08transaction.test Mon Aug 08 09:13:19 2005 +0000 10.3 @@ -0,0 +1,96 @@ 10.4 +# Test transactions. 10.5 + 10.6 +mkdir /test 10.7 + 10.8 +# Simple transaction: create a file inside transaction. 10.9 +1 start /test 10.10 +1 write /test/entry1 create contents 10.11 +2 dir /test 10.12 +expect 1:entry1 10.13 +1 dir /test 10.14 +1 commit 10.15 +expect 2:contents 10.16 +2 read /test/entry1 10.17 + 10.18 +rm /test/entry1 10.19 + 10.20 +# Create a file and abort transaction. 10.21 +1 start /test 10.22 +1 write /test/entry1 create contents 10.23 +2 dir /test 10.24 +expect 1:entry1 10.25 +1 dir /test 10.26 +1 abort 10.27 +2 dir /test 10.28 + 10.29 +write /test/entry1 create contents 10.30 +# Delete in transaction, commit 10.31 +1 start /test 10.32 +1 rm /test/entry1 10.33 +expect 2:entry1 10.34 +2 dir /test 10.35 +1 dir /test 10.36 +1 commit 10.37 +2 dir /test 10.38 + 10.39 +# Delete in transaction, abort. 10.40 +write /test/entry1 create contents 10.41 +1 start /test 10.42 +1 rm /test/entry1 10.43 +expect 2:entry1 10.44 +2 dir /test 10.45 +1 dir /test 10.46 +1 abort 10.47 +expect 2:entry1 10.48 +2 dir /test 10.49 + 10.50 +# Events inside transactions don't trigger watches until (successful) commit. 10.51 +mkdir /test/dir 10.52 +1 watch /test token 10.53 +2 start /test 10.54 +2 mkdir /test/dir/sub 10.55 +expect 1: waitwatch failed: Connection timed out 10.56 +1 waitwatch 10.57 +2 close 10.58 +1 close 10.59 + 10.60 +1 watch /test token 10.61 +2 start /test 10.62 +2 mkdir /test/dir/sub 10.63 +2 abort 10.64 +expect 1: waitwatch failed: Connection timed out 10.65 +1 waitwatch 10.66 +1 close 10.67 + 10.68 +1 watch /test token 10.69 +2 start /test 10.70 +2 mkdir /test/dir/sub 10.71 +2 commit 10.72 +expect 1:/test/dir/sub:token 10.73 +1 waitwatch 10.74 +1 ackwatch token 10.75 +1 close 10.76 + 10.77 +# Rm inside transaction works like rm outside: children get notified. 10.78 +1 watch /test/dir/sub token 10.79 +2 start /test 10.80 +2 rm /test/dir 10.81 +2 commit 10.82 +expect 1:/test/dir/sub:token 10.83 +1 waitwatch 10.84 +1 ackwatch token 10.85 +1 close 10.86 + 10.87 +# Multiple events from single transaction don't trigger assert 10.88 +1 watch /test token 10.89 +2 start /test 10.90 +2 write /test/1 create contents 10.91 +2 write /test/2 create contents 10.92 +2 commit 10.93 +expect 1:/test/1:token 10.94 +1 waitwatch 10.95 +1 ackwatch token 10.96 +expect 1:/test/2:token 10.97 +1 waitwatch 10.98 +1 ackwatch token 10.99 +1 close
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/tools/xenstore/testsuite/09domain.test Mon Aug 08 09:13:19 2005 +0000 11.3 @@ -0,0 +1,19 @@ 11.4 +# Test domain communication. 11.5 + 11.6 +# Create a domain, write an entry. 11.7 +expect handle is 1 11.8 +introduce 1 100 7 /my/home 11.9 +1 write /entry1 create contents 11.10 +expect entry1 11.11 +expect tool 11.12 +dir / 11.13 +close 11.14 + 11.15 +# Release that domain. 11.16 +release 1 11.17 +close 11.18 + 11.19 +# Introduce and release by same connection. 11.20 +expect handle is 2 11.21 +introduce 1 100 7 /my/home 11.22 +release 1
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/xenstore/testsuite/10domain-homedir.test Mon Aug 08 09:13:19 2005 +0000 12.3 @@ -0,0 +1,19 @@ 12.4 +# Test domain "implicit" paths. 12.5 + 12.6 +# Create a domain, write an entry using implicit path, read using implicit 12.7 +mkdir /home 12.8 +expect handle is 1 12.9 +introduce 1 100 7 /home 12.10 +1 write entry1 create contents 12.11 +expect contents 12.12 +read /home/entry1 12.13 +expect entry1 12.14 +dir /home 12.15 + 12.16 +# Place a watch using a relative path: expect relative answer. 12.17 +1 mkdir foo 12.18 +1 watch foo token 12.19 +write /home/foo/bar create contents 12.20 +expect 1:foo/bar:token 12.21 +1 waitwatch 12.22 +1 ackwatch token
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/tools/xenstore/testsuite/11domain-watch.test Mon Aug 08 09:13:19 2005 +0000 13.3 @@ -0,0 +1,52 @@ 13.4 +# Test watching from a domain. 13.5 + 13.6 +# Watch something, write to it, check watch has fired. 13.7 +write /test create contents 13.8 +mkdir /dir 13.9 + 13.10 +expect handle is 1 13.11 +introduce 1 100 7 /my/home 13.12 +1 watch /test token 13.13 +write /test create contents2 13.14 +expect 1:/test:token 13.15 +1 waitwatch 13.16 +1 ackwatch token 13.17 +1 unwatch /test token 13.18 +release 1 13.19 +1 close 13.20 + 13.21 +# ignore watches while doing commands, should work. 13.22 +expect handle is 1 13.23 +introduce 1 100 7 /my/home 13.24 +1 watch /dir token 13.25 +write /dir/test create contents 13.26 +1 write /dir/test2 create contents2 13.27 +1 write /dir/test3 create contents3 13.28 +1 write /dir/test4 create contents4 13.29 +expect 1:/dir/test:token 13.30 +1 waitwatch 13.31 +1 ackwatch token 13.32 +release 1 13.33 +1 close 13.34 + 13.35 +# unwatch 13.36 +expect handle is 1 13.37 +introduce 1 100 7 /my/home 13.38 +1 watch /dir token1 13.39 +1 unwatch /dir token1 13.40 +1 watch /dir token2 13.41 +write /dir/test2 create contents 13.42 +expect 1:/dir/test2:token2 13.43 +1 waitwatch 13.44 +1 unwatch /dir token2 13.45 +release 1 13.46 +1 close 13.47 + 13.48 +# unwatch while watch pending. 13.49 +expect handle is 1 13.50 +introduce 1 100 7 /my/home 13.51 +1 watch /dir token1 13.52 +write /dir/test2 create contents 13.53 +1 unwatch /dir token1 13.54 +release 1 13.55 +1 close
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/tools/xenstore/testsuite/12readonly.test Mon Aug 08 09:13:19 2005 +0000 14.3 @@ -0,0 +1,41 @@ 14.4 +# Test that read only connection can't alter store. 14.5 + 14.6 +write /test create contents 14.7 + 14.8 +readonly 14.9 +expect test 14.10 +expect tool 14.11 +dir / 14.12 + 14.13 +expect contents 14.14 +read /test 14.15 +expect 0 READ 14.16 +getperm /test 14.17 +watch /test token 14.18 +unwatch /test token 14.19 +start / 14.20 +commit 14.21 +start / 14.22 +abort 14.23 + 14.24 +# These don't work 14.25 +expect write failed: Read-only file system 14.26 +write /test2 create contents 14.27 +expect write failed: Read-only file system 14.28 +write /test create contents 14.29 +expect setperm failed: Read-only file system 14.30 +setperm /test 100 NONE 14.31 +expect setperm failed: Read-only file system 14.32 +setperm /test 100 NONE 14.33 +expect shutdown failed: Read-only file system 14.34 +shutdown 14.35 +expect introduce failed: Read-only file system 14.36 +introduce 1 100 7 /home 14.37 + 14.38 +# Check that watches work like normal. 14.39 +watch / token 14.40 +1 readwrite 14.41 +1 write /test create contents 14.42 +expect /test:token 14.43 +waitwatch 14.44 +ackwatch token
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/tools/xenstore/testsuite/13watch-ack.test Mon Aug 08 09:13:19 2005 +0000 15.3 @@ -0,0 +1,22 @@ 15.4 +# This demonstrates a bug where an xs_acknowledge_watch returns 15.5 +# EINVAL, because the daemon doesn't track what watch event it sent 15.6 +# and relies on it being the "first" watch which has an event. 15.7 +# Watches firing after the first event is sent out will change this. 15.8 + 15.9 +# Create three things to watch. 15.10 +mkdir /test 15.11 +mkdir /test/1 15.12 +mkdir /test/2 15.13 +mkdir /test/3 15.14 + 15.15 +# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2. 15.16 +1 watch /test/1 token1 15.17 +1 watch /test/2 token2 15.18 +1 watch /test/3 token3 15.19 +2 write /test/2 create contents2 15.20 +expect 1:/test/2:token2 15.21 +1 waitwatch 15.22 +3 write /test/1 create contents1 15.23 +4 write /test/3 create contents3 15.24 +1 ackwatch token2 15.25 +1 close
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/tools/xenstore/testsuite/14complexperms.test Mon Aug 08 09:13:19 2005 +0000 16.3 @@ -0,0 +1,99 @@ 16.4 +# We should not be able to tell the difference between a node which 16.5 +# doesn't exist, and a node we don't have permission on, if we don't 16.6 +# have permission on it directory. 16.7 + 16.8 +mkdir /dir 16.9 +setperm /dir 0 NONE 16.10 + 16.11 +# First when it doesn't exist 16.12 +setid 1 16.13 +expect *Permission denied 16.14 +dir /dir/file 16.15 +expect *Permission denied 16.16 +read /dir/file 16.17 +expect *Permission denied 16.18 +write /dir/file none value 16.19 +expect *Permission denied 16.20 +write /dir/file create value 16.21 +expect *Permission denied 16.22 +write /dir/file excl value 16.23 +expect write failed: Invalid argument 16.24 +write /dir/file crap value 16.25 +expect *Permission denied 16.26 +mkdir /dir/file 16.27 +expect *Permission denied 16.28 +rm /dir/file 16.29 +expect *Permission denied 16.30 +rm /dir 16.31 +expect *Permission denied 16.32 +getperm /dir/file 16.33 +expect *Permission denied 16.34 +setperm /dir/file 0 NONE 16.35 +watch /dir/file token 16.36 +setid 0 16.37 +write /dir/file create contents 16.38 +rm /dir/file 16.39 +setid 1 16.40 +expect waitwatch failed: Connection timed out 16.41 +waitwatch 16.42 +unwatch /dir/file token 16.43 +expect *No such file or directory 16.44 +unwatch /dir/file token 16.45 +expect *Permission denied 16.46 +start /dir/file 16.47 +expect *No such file or directory 16.48 +abort 16.49 +expect *Permission denied 16.50 +start /dir/file 16.51 +expect *No such file or directory 16.52 +commit 16.53 +expect *Permission denied 16.54 +introduce 2 100 7 /dir/file 16.55 + 16.56 +# Now it exists 16.57 +setid 0 16.58 +write /dir/file create contents 16.59 + 16.60 +setid 1 16.61 +expect *Permission denied 16.62 +dir /dir/file 16.63 +expect *Permission denied 16.64 +read /dir/file 16.65 +expect *Permission denied 16.66 +write /dir/file none value 16.67 +expect *Permission denied 16.68 +write /dir/file create value 16.69 +expect *Permission denied 16.70 +write /dir/file excl value 16.71 +expect write failed: Invalid argument 16.72 +write /dir/file crap value 16.73 +expect *Permission denied 16.74 +mkdir /dir/file 16.75 +expect *Permission denied 16.76 +rm /dir/file 16.77 +expect *Permission denied 16.78 +rm /dir 16.79 +expect *Permission denied 16.80 +getperm /dir/file 16.81 +expect *Permission denied 16.82 +setperm /dir/file 0 NONE 16.83 +watch /dir/file token 16.84 +setid 0 16.85 +write /dir/file create contents 16.86 +rm /dir/file 16.87 +setid 1 16.88 +expect waitwatch failed: Connection timed out 16.89 +waitwatch 16.90 +unwatch /dir/file token 16.91 +expect *No such file or directory 16.92 +unwatch /dir/file token 16.93 +expect *Permission denied 16.94 +start /dir/file 16.95 +expect *No such file or directory 16.96 +abort 16.97 +expect *Permission denied 16.98 +start /dir/file 16.99 +expect *No such file or directory 16.100 +commit 16.101 +expect *Permission denied 16.102 +introduce 2 100 7 /dir/file
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/tools/xenstore/testsuite/15nowait.test Mon Aug 08 09:13:19 2005 +0000 17.3 @@ -0,0 +1,25 @@ 17.4 +# If we don't wait for an ack, we can crash daemon as it never expects to be 17.5 +# sending out two replies on top of each other. 17.6 +noackwrite /1 create 1 17.7 +noackwrite /2 create 2 17.8 +noackwrite /3 create 3 17.9 +noackwrite /4 create 4 17.10 +noackwrite /5 create 5 17.11 +readack 17.12 +readack 17.13 +readack 17.14 +readack 17.15 +readack 17.16 + 17.17 +expect handle is 1 17.18 +introduce 1 100 7 /my/home 17.19 +1 noackwrite /1 create 1 17.20 +1 noackwrite /2 create 2 17.21 +1 noackwrite /3 create 3 17.22 +1 noackwrite /4 create 4 17.23 +1 noackwrite /5 create 5 17.24 +1 readack 17.25 +1 readack 17.26 +1 readack 17.27 +1 readack 17.28 +1 readack
18.1 --- a/tools/xenstore/utils.c Mon Aug 08 09:12:22 2005 +0000 18.2 +++ b/tools/xenstore/utils.c Mon Aug 08 09:13:19 2005 +0000 18.3 @@ -84,9 +84,6 @@ void *malloc_nofail(size_t size) 18.4 void daemonize(void) 18.5 { 18.6 pid_t pid; 18.7 - int fd; 18.8 - size_t len; 18.9 - char buf[100]; 18.10 18.11 /* Separate from our parent via fork, so init inherits us. */ 18.12 if ((pid = fork()) < 0) 18.13 @@ -104,18 +101,6 @@ void daemonize(void) 18.14 chdir("/"); 18.15 /* Discard our parent's old-fashioned umask prejudices. */ 18.16 umask(0); 18.17 - 18.18 - fd = open("/var/run/xenstored.pid", O_RDWR | O_CREAT); 18.19 - if (fd == -1) { 18.20 - exit(1); 18.21 - } 18.22 - 18.23 - if (lockf(fd, F_TLOCK, 0) == -1) { 18.24 - exit(1); 18.25 - } 18.26 - 18.27 - len = sprintf(buf, "%d\n", getpid()); 18.28 - write(fd, buf, len); 18.29 } 18.30 18.31
19.1 --- a/tools/xenstore/xenstored_core.c Mon Aug 08 09:12:22 2005 +0000 19.2 +++ b/tools/xenstore/xenstored_core.c Mon Aug 08 09:13:19 2005 +0000 19.3 @@ -252,6 +252,7 @@ static bool write_message(struct connect 19.4 int ret; 19.5 struct buffered_data *out = conn->out; 19.6 19.7 + assert(conn->state != BLOCKED); 19.8 if (out->inhdr) { 19.9 if (verbose) 19.10 xprintf("Writing msg %s (%s) out to %p\n", 19.11 @@ -289,6 +290,10 @@ static bool write_message(struct connect 19.12 talloc_free(out); 19.13 19.14 queue_next_event(conn); 19.15 + 19.16 + /* No longer busy? */ 19.17 + if (!conn->out) 19.18 + conn->state = OK; 19.19 return true; 19.20 } 19.21 19.22 @@ -492,6 +497,8 @@ void send_reply(struct connection *conn, 19.23 conn->waiting_reply = bdata; 19.24 } else 19.25 conn->out = bdata; 19.26 + assert(conn->state != BLOCKED); 19.27 + conn->state = BUSY; 19.28 } 19.29 19.30 /* Some routines (write, mkdir, etc) just need a non-error return */ 19.31 @@ -544,7 +551,7 @@ bool is_valid_nodename(const char *node) 19.32 /* We expect one arg in the input: return NULL otherwise. */ 19.33 static const char *onearg(struct buffered_data *in) 19.34 { 19.35 - if (get_string(in, 0) != in->used) 19.36 + if (!in->used || get_string(in, 0) != in->used) 19.37 return NULL; 19.38 return in->buffer; 19.39 } 19.40 @@ -807,7 +814,7 @@ bool check_node_perms(struct connection 19.41 19.42 static void send_directory(struct connection *conn, const char *node) 19.43 { 19.44 - char *path, *reply = talloc_strdup(node, ""); 19.45 + char *path, *reply; 19.46 unsigned int reply_len = 0; 19.47 DIR **dir; 19.48 struct dirent *dirent; 19.49 @@ -825,6 +832,7 @@ static void send_directory(struct connec 19.50 return; 19.51 } 19.52 19.53 + reply = talloc_strdup(node, ""); 19.54 while ((dirent = readdir(*dir)) != NULL) { 19.55 int len = strlen(dirent->d_name) + 1; 19.56 19.57 @@ -1082,7 +1090,7 @@ static void do_get_perms(struct connecti 19.58 static void do_set_perms(struct connection *conn, struct buffered_data *in) 19.59 { 19.60 unsigned int num; 19.61 - char *node; 19.62 + char *node, *permstr; 19.63 struct xs_permissions *perms; 19.64 19.65 num = xs_count_strings(in->buffer, in->used); 19.66 @@ -1093,7 +1101,7 @@ static void do_set_perms(struct connecti 19.67 19.68 /* First arg is node name. */ 19.69 node = canonicalize(conn, in->buffer); 19.70 - in->buffer += strlen(in->buffer) + 1; 19.71 + permstr = in->buffer + strlen(in->buffer) + 1; 19.72 num--; 19.73 19.74 if (!within_transaction(conn->transaction, node)) { 19.75 @@ -1111,7 +1119,7 @@ static void do_set_perms(struct connecti 19.76 } 19.77 19.78 perms = talloc_array(node, struct xs_permissions, num); 19.79 - if (!xs_strings_to_perms(perms, num, in->buffer)) { 19.80 + if (!xs_strings_to_perms(perms, num, permstr)) { 19.81 send_error(conn, errno); 19.82 return; 19.83 } 19.84 @@ -1280,8 +1288,10 @@ end: 19.85 talloc_free(in); 19.86 talloc_set_fail_handler(NULL, NULL); 19.87 if (talloc_total_blocks(NULL) 19.88 - != talloc_total_blocks(talloc_autofree_context()) + 1) 19.89 + != talloc_total_blocks(talloc_autofree_context()) + 1) { 19.90 talloc_report_full(NULL, stderr); 19.91 + abort(); 19.92 + } 19.93 } 19.94 19.95 /* Errors in reading or allocating here mean we get out of sync, so we 19.96 @@ -1305,8 +1315,10 @@ void handle_input(struct connection *con 19.97 return; 19.98 19.99 if (in->hdr.msg.len > PATH_MAX) { 19.100 +#ifndef TESTING 19.101 syslog(LOG_DAEMON, "Client tried to feed us %i", 19.102 in->hdr.msg.len); 19.103 +#endif 19.104 goto bad_client; 19.105 } 19.106 19.107 @@ -1357,6 +1369,7 @@ static void unblock_connections(void) 19.108 consider_message(i); 19.109 } 19.110 break; 19.111 + case BUSY: 19.112 case OK: 19.113 break; 19.114 } 19.115 @@ -1382,6 +1395,7 @@ struct connection *new_connection(connwr 19.116 new->state = OK; 19.117 new->blocked_by = NULL; 19.118 new->out = new->waiting_reply = NULL; 19.119 + new->waiting_for_ack = NULL; 19.120 new->fd = -1; 19.121 new->id = 0; 19.122 new->domain = NULL; 19.123 @@ -1461,6 +1475,7 @@ void dump_connection(void) 19.124 printf(" state = %s\n", 19.125 i->state == OK ? "OK" 19.126 : i->state == BLOCKED ? "BLOCKED" 19.127 + : i->state == BUSY ? "BUSY" 19.128 : "INVALID"); 19.129 if (i->id) 19.130 printf(" id = %i\n", i->id); 19.131 @@ -1631,6 +1646,7 @@ int main(int argc, char *argv[]) 19.132 max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd); 19.133 19.134 /* Main loop. */ 19.135 + /* FIXME: Rewrite so noone can starve. */ 19.136 for (;;) { 19.137 struct connection *i; 19.138 struct timeval *tvp = NULL, tv; 19.139 @@ -1675,10 +1691,22 @@ int main(int argc, char *argv[]) 19.140 } 19.141 } 19.142 19.143 - /* Flush output for domain connections, */ 19.144 - list_for_each_entry(i, &connections, list) 19.145 - if (i->domain && i->out) 19.146 + /* Handle all possible I/O for domain connections. */ 19.147 + more: 19.148 + list_for_each_entry(i, &connections, list) { 19.149 + if (!i->domain) 19.150 + continue; 19.151 + 19.152 + if (domain_can_read(i)) { 19.153 + handle_input(i); 19.154 + goto more; 19.155 + } 19.156 + 19.157 + if (domain_can_write(i)) { 19.158 handle_output(i); 19.159 + goto more; 19.160 + } 19.161 + } 19.162 19.163 if (tvp) { 19.164 check_transaction_timeout();
20.1 --- a/tools/xenstore/xenstored_core.h Mon Aug 08 09:12:22 2005 +0000 20.2 +++ b/tools/xenstore/xenstored_core.h Mon Aug 08 09:13:19 2005 +0000 20.3 @@ -51,6 +51,8 @@ enum state 20.4 { 20.5 /* Blocked by transaction. */ 20.6 BLOCKED, 20.7 + /* Doing action, not listening */ 20.8 + BUSY, 20.9 /* Completed */ 20.10 OK, 20.11 }; 20.12 @@ -65,7 +67,7 @@ struct connection 20.13 /* Who am I? 0 for socket connections. */ 20.14 domid_t id; 20.15 20.16 - /* Blocked on transaction? */ 20.17 + /* Blocked on transaction? Busy? */ 20.18 enum state state; 20.19 20.20 /* Node we are waiting for (if state == BLOCKED) */
21.1 --- a/tools/xenstore/xenstored_domain.c Mon Aug 08 09:12:22 2005 +0000 21.2 +++ b/tools/xenstore/xenstored_domain.c Mon Aug 08 09:13:19 2005 +0000 21.3 @@ -227,34 +227,29 @@ static struct domain *find_domain(u16 po 21.4 return NULL; 21.5 } 21.6 21.7 +/* We scan all domains rather than use the information given here. */ 21.8 void handle_event(int event_fd) 21.9 { 21.10 u16 port; 21.11 - struct domain *domain; 21.12 21.13 if (read(event_fd, &port, sizeof(port)) != sizeof(port)) 21.14 barf_perror("Failed to read from event fd"); 21.15 - 21.16 - /* We have to handle *all* the data available before we ack: 21.17 - * careful that handle_input/handle_output can destroy conn. 21.18 - */ 21.19 - while ((domain = find_domain(port)) != NULL) { 21.20 - if (domain->conn->state == OK 21.21 - && buffer_has_input(domain->input)) 21.22 - handle_input(domain->conn); 21.23 - else if (domain->conn->out 21.24 - && buffer_has_output_room(domain->output)) 21.25 - handle_output(domain->conn); 21.26 - else 21.27 - break; 21.28 - } 21.29 - 21.30 #ifndef TESTING 21.31 if (write(event_fd, &port, sizeof(port)) != sizeof(port)) 21.32 barf_perror("Failed to write to event fd"); 21.33 #endif 21.34 } 21.35 21.36 +bool domain_can_read(struct connection *conn) 21.37 +{ 21.38 + return conn->state == OK && buffer_has_input(conn->domain->input); 21.39 +} 21.40 + 21.41 +bool domain_can_write(struct connection *conn) 21.42 +{ 21.43 + return conn->out && buffer_has_output_room(conn->domain->output); 21.44 +} 21.45 + 21.46 static struct domain *new_domain(void *context, domid_t domid, 21.47 unsigned long mfn, int port, 21.48 const char *path)
22.1 --- a/tools/xenstore/xenstored_domain.h Mon Aug 08 09:12:22 2005 +0000 22.2 +++ b/tools/xenstore/xenstored_domain.h Mon Aug 08 09:13:19 2005 +0000 22.3 @@ -40,4 +40,8 @@ const char *get_implicit_path(const stru 22.4 /* Read existing connection information from store. */ 22.5 void restore_existing_connections(void); 22.6 22.7 +/* Can connection attached to domain read/write. */ 22.8 +bool domain_can_read(struct connection *conn); 22.9 +bool domain_can_write(struct connection *conn); 22.10 + 22.11 #endif /* _XENSTORED_DOMAIN_H */
23.1 --- a/tools/xenstore/xs.c Mon Aug 08 09:12:22 2005 +0000 23.2 +++ b/tools/xenstore/xs.c Mon Aug 08 09:13:19 2005 +0000 23.3 @@ -204,13 +204,19 @@ static void *xs_talkv(struct xs_handle * 23.4 return NULL; 23.5 } 23.6 23.7 - assert(msg.type == type); 23.8 + if (msg.type != type) { 23.9 + free(ret); 23.10 + saved_errno = EBADF; 23.11 + goto close_fd; 23.12 + 23.13 + } 23.14 return ret; 23.15 23.16 fail: 23.17 /* We're in a bad state, so close fd. */ 23.18 saved_errno = errno; 23.19 sigaction(SIGPIPE, &oldact, NULL); 23.20 +close_fd: 23.21 close(h->fd); 23.22 h->fd = -1; 23.23 errno = saved_errno;
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/tools/xenstore/xs_crashme.c Mon Aug 08 09:13:19 2005 +0000 24.3 @@ -0,0 +1,413 @@ 24.4 +/* Code which randomly corrupts bits going to the daemon. 24.5 + Copyright (C) 2005 Rusty Russell IBM Corporation 24.6 + 24.7 + This program is free software; you can redistribute it and/or modify 24.8 + it under the terms of the GNU General Public License as published by 24.9 + the Free Software Foundation; either version 2 of the License, or 24.10 + (at your option) any later version. 24.11 + 24.12 + This program is distributed in the hope that it will be useful, 24.13 + but WITHOUT ANY WARRANTY; without even the implied warranty of 24.14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24.15 + GNU General Public License for more details. 24.16 + 24.17 + You should have received a copy of the GNU General Public License 24.18 + along with this program; if not, write to the Free Software 24.19 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24.20 +*/ 24.21 +#include <stdbool.h> 24.22 +#include <stdio.h> 24.23 +#include <sys/types.h> 24.24 +#include <stdarg.h> 24.25 +#include <string.h> 24.26 +#include <sys/time.h> 24.27 +#include "xs.h" 24.28 +#include "talloc.h" 24.29 +#include <errno.h> 24.30 +#include "xenstored.h" 24.31 + 24.32 +#define XSTEST 24.33 +#define RAND_FREQ 128 /* One char in 32 is corrupted. */ 24.34 + 24.35 +/* jhash.h: Jenkins hash support. 24.36 + * 24.37 + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) 24.38 + * 24.39 + * http://burtleburtle.net/bob/hash/ 24.40 + * 24.41 + * These are the credits from Bob's sources: 24.42 + * 24.43 + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. 24.44 + * hash(), hash2(), hash3, and mix() are externally useful functions. 24.45 + * Routines to test the hash are included if SELF_TEST is defined. 24.46 + * You can use this free for any purpose. It has no warranty. 24.47 + * 24.48 + * Copyright (C) 2003 David S. Miller (davem@redhat.com) 24.49 + * 24.50 + * I've modified Bob's hash to be useful in the Linux kernel, and 24.51 + * any bugs present are surely my fault. -DaveM 24.52 + */ 24.53 + 24.54 +/* NOTE: Arguments are modified. */ 24.55 +#define __jhash_mix(a, b, c) \ 24.56 +{ \ 24.57 + a -= b; a -= c; a ^= (c>>13); \ 24.58 + b -= c; b -= a; b ^= (a<<8); \ 24.59 + c -= a; c -= b; c ^= (b>>13); \ 24.60 + a -= b; a -= c; a ^= (c>>12); \ 24.61 + b -= c; b -= a; b ^= (a<<16); \ 24.62 + c -= a; c -= b; c ^= (b>>5); \ 24.63 + a -= b; a -= c; a ^= (c>>3); \ 24.64 + b -= c; b -= a; b ^= (a<<10); \ 24.65 + c -= a; c -= b; c ^= (b>>15); \ 24.66 +} 24.67 + 24.68 +/* The golden ration: an arbitrary value */ 24.69 +#define JHASH_GOLDEN_RATIO 0x9e3779b9 24.70 + 24.71 +/* The most generic version, hashes an arbitrary sequence 24.72 + * of bytes. No alignment or length assumptions are made about 24.73 + * the input key. 24.74 + */ 24.75 +static inline u32 jhash(const void *key, u32 length, u32 initval) 24.76 +{ 24.77 + u32 a, b, c, len; 24.78 + const u8 *k = key; 24.79 + 24.80 + len = length; 24.81 + a = b = JHASH_GOLDEN_RATIO; 24.82 + c = initval; 24.83 + 24.84 + while (len >= 12) { 24.85 + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); 24.86 + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); 24.87 + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); 24.88 + 24.89 + __jhash_mix(a,b,c); 24.90 + 24.91 + k += 12; 24.92 + len -= 12; 24.93 + } 24.94 + 24.95 + c += length; 24.96 + switch (len) { 24.97 + case 11: c += ((u32)k[10]<<24); 24.98 + case 10: c += ((u32)k[9]<<16); 24.99 + case 9 : c += ((u32)k[8]<<8); 24.100 + case 8 : b += ((u32)k[7]<<24); 24.101 + case 7 : b += ((u32)k[6]<<16); 24.102 + case 6 : b += ((u32)k[5]<<8); 24.103 + case 5 : b += k[4]; 24.104 + case 4 : a += ((u32)k[3]<<24); 24.105 + case 3 : a += ((u32)k[2]<<16); 24.106 + case 2 : a += ((u32)k[1]<<8); 24.107 + case 1 : a += k[0]; 24.108 + }; 24.109 + 24.110 + __jhash_mix(a,b,c); 24.111 + 24.112 + return c; 24.113 +} 24.114 + 24.115 +/* A special optimized version that handles 1 or more of u32s. 24.116 + * The length parameter here is the number of u32s in the key. 24.117 + */ 24.118 +static inline u32 jhash2(u32 *k, u32 length, u32 initval) 24.119 +{ 24.120 + u32 a, b, c, len; 24.121 + 24.122 + a = b = JHASH_GOLDEN_RATIO; 24.123 + c = initval; 24.124 + len = length; 24.125 + 24.126 + while (len >= 3) { 24.127 + a += k[0]; 24.128 + b += k[1]; 24.129 + c += k[2]; 24.130 + __jhash_mix(a, b, c); 24.131 + k += 3; len -= 3; 24.132 + } 24.133 + 24.134 + c += length * 4; 24.135 + 24.136 + switch (len) { 24.137 + case 2 : b += k[1]; 24.138 + case 1 : a += k[0]; 24.139 + }; 24.140 + 24.141 + __jhash_mix(a,b,c); 24.142 + 24.143 + return c; 24.144 +} 24.145 + 24.146 + 24.147 +/* A special ultra-optimized versions that knows they are hashing exactly 24.148 + * 3, 2 or 1 word(s). 24.149 + * 24.150 + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally 24.151 + * done at the end is not done here. 24.152 + */ 24.153 +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) 24.154 +{ 24.155 + a += JHASH_GOLDEN_RATIO; 24.156 + b += JHASH_GOLDEN_RATIO; 24.157 + c += initval; 24.158 + 24.159 + __jhash_mix(a, b, c); 24.160 + 24.161 + return c; 24.162 +} 24.163 + 24.164 +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) 24.165 +{ 24.166 + return jhash_3words(a, b, 0, initval); 24.167 +} 24.168 + 24.169 +static inline u32 jhash_1word(u32 a, u32 initval) 24.170 +{ 24.171 + return jhash_3words(a, 0, 0, initval); 24.172 +} 24.173 + 24.174 +static unsigned int get_randomness(int *state) 24.175 +{ 24.176 + return jhash_1word((*state)++, *state * 1103515243); 24.177 +} 24.178 + 24.179 +static int state; 24.180 + 24.181 +/* Lengthening headers is pointless: other end will just wait for more 24.182 + * data and timeout. We merely shorten the length. */ 24.183 +static void corrupt_header(char *output, const struct xsd_sockmsg *msg, 24.184 + unsigned int *next_bit) 24.185 +{ 24.186 + struct xsd_sockmsg newmsg = *msg; 24.187 + 24.188 + while (*next_bit < sizeof(*msg)) { 24.189 + if (newmsg.len) 24.190 + newmsg.len = get_randomness(&state) % newmsg.len; 24.191 + *next_bit += get_randomness(&state) % RAND_FREQ; 24.192 + } 24.193 + memcpy(output, &newmsg, sizeof(newmsg)); 24.194 +} 24.195 + 24.196 +#define read_all_choice read_all 24.197 +static bool write_all_choice(int fd, const void *data, unsigned int len) 24.198 +{ 24.199 + char corrupt_data[len]; 24.200 + bool ret; 24.201 + static unsigned int next_bit; 24.202 + 24.203 + if (len == sizeof(struct xsd_sockmsg) 24.204 + && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0) 24.205 + corrupt_header(corrupt_data, data, &next_bit); 24.206 + else { 24.207 + memcpy(corrupt_data, data, len); 24.208 + while (next_bit < len * CHAR_BIT) { 24.209 + corrupt_data[next_bit/CHAR_BIT] 24.210 + ^= (1 << (next_bit%CHAR_BIT)); 24.211 + next_bit += get_randomness(&state) % RAND_FREQ; 24.212 + } 24.213 + } 24.214 + 24.215 + ret = xs_write_all(fd, corrupt_data, len); 24.216 + next_bit -= len * CHAR_BIT; 24.217 + return ret; 24.218 +} 24.219 + 24.220 +#include "xs.c" 24.221 + 24.222 +static char *random_path(void) 24.223 +{ 24.224 + unsigned int i; 24.225 + char *ret = NULL; 24.226 + 24.227 + if (get_randomness(&state) % 20 == 0) 24.228 + return talloc_strdup(NULL, "/"); 24.229 + 24.230 + for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) { 24.231 + ret = talloc_asprintf_append(ret, "/%i", 24.232 + get_randomness(&state) % 15); 24.233 + } 24.234 + return ret; 24.235 +} 24.236 + 24.237 +static int random_flags(int *state) 24.238 +{ 24.239 + switch (get_randomness(state) % 4) { 24.240 + case 0: 24.241 + return 0; 24.242 + case 1: 24.243 + return O_CREAT; 24.244 + case 2: 24.245 + return O_CREAT|O_EXCL; 24.246 + default: 24.247 + return get_randomness(state); 24.248 + } 24.249 +} 24.250 + 24.251 +/* Do the next operation, return the results. */ 24.252 +static void do_next_op(struct xs_handle *h, bool verbose) 24.253 +{ 24.254 + char *name; 24.255 + unsigned int num; 24.256 + 24.257 + if (verbose) 24.258 + printf("State %i: ", state); 24.259 + 24.260 + name = random_path(); 24.261 + switch (get_randomness(&state) % 9) { 24.262 + case 0: 24.263 + if (verbose) 24.264 + printf("DIR %s\n", name); 24.265 + free(xs_directory(h, name, &num)); 24.266 + break; 24.267 + case 1: 24.268 + if (verbose) 24.269 + printf("READ %s\n", name); 24.270 + free(xs_read(h, name, &num)); 24.271 + break; 24.272 + case 2: { 24.273 + int flags = random_flags(&state); 24.274 + char *contents = talloc_asprintf(NULL, "%i", 24.275 + get_randomness(&state)); 24.276 + unsigned int len = get_randomness(&state)%(strlen(contents)+1); 24.277 + if (verbose) 24.278 + printf("WRITE %s %s %.*s\n", name, 24.279 + flags == O_CREAT ? "O_CREAT" 24.280 + : flags == (O_CREAT|O_EXCL) ? "O_CREAT|O_EXCL" 24.281 + : flags == 0 ? "0" : "CRAPFLAGS", 24.282 + len, contents); 24.283 + xs_write(h, name, contents, len, flags); 24.284 + break; 24.285 + } 24.286 + case 3: 24.287 + if (verbose) 24.288 + printf("MKDIR %s\n", name); 24.289 + xs_mkdir(h, name); 24.290 + break; 24.291 + case 4: 24.292 + if (verbose) 24.293 + printf("RM %s\n", name); 24.294 + xs_rm(h, name); 24.295 + break; 24.296 + case 5: 24.297 + if (verbose) 24.298 + printf("GETPERMS %s\n", name); 24.299 + free(xs_get_permissions(h, name, &num)); 24.300 + break; 24.301 + case 6: { 24.302 + unsigned int i, num = get_randomness(&state)%8; 24.303 + struct xs_permissions perms[num]; 24.304 + 24.305 + if (verbose) 24.306 + printf("SETPERMS %s: ", name); 24.307 + for (i = 0; i < num; i++) { 24.308 + perms[i].id = get_randomness(&state)%8; 24.309 + perms[i].perms = get_randomness(&state)%4; 24.310 + if (verbose) 24.311 + printf("%i%c ", perms[i].id, 24.312 + perms[i].perms == XS_PERM_WRITE ? 'W' 24.313 + : perms[i].perms == XS_PERM_READ ? 'R' 24.314 + : perms[i].perms == 24.315 + (XS_PERM_READ|XS_PERM_WRITE) ? 'B' 24.316 + : 'N'); 24.317 + } 24.318 + if (verbose) 24.319 + printf("\n"); 24.320 + xs_set_permissions(h, name, perms, num); 24.321 + break; 24.322 + } 24.323 + case 7: { 24.324 + if (verbose) 24.325 + printf("START %s\n", name); 24.326 + xs_transaction_start(h, name); 24.327 + break; 24.328 + } 24.329 + case 8: { 24.330 + bool abort = (get_randomness(&state) % 2); 24.331 + 24.332 + if (verbose) 24.333 + printf("STOP %s\n", abort ? "ABORT" : "COMMIT"); 24.334 + xs_transaction_end(h, abort); 24.335 + break; 24.336 + } 24.337 + default: 24.338 + barf("Impossible randomness"); 24.339 + } 24.340 +} 24.341 + 24.342 +static struct xs_handle *h; 24.343 +static void alarmed(int sig __attribute__((unused))) 24.344 +{ 24.345 + /* We force close on timeout. */ 24.346 + close(h->fd); 24.347 +} 24.348 + 24.349 +static int start_daemon(void) 24.350 +{ 24.351 + int fds[2]; 24.352 + int daemon_pid; 24.353 + 24.354 + /* Start daemon. */ 24.355 + pipe(fds); 24.356 + if ((daemon_pid = fork())) { 24.357 + /* Child writes PID when its ready: we wait for that. */ 24.358 + char buffer[20]; 24.359 + close(fds[1]); 24.360 + if (read(fds[0], buffer, sizeof(buffer)) < 0) 24.361 + barf("Failed to summon daemon"); 24.362 + close(fds[0]); 24.363 + return daemon_pid; 24.364 + } else { 24.365 + dup2(fds[1], STDOUT_FILENO); 24.366 + close(fds[0]); 24.367 +#if 1 24.368 + execlp("valgrind", "valgrind", "--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid", 24.369 + "--no-fork", "--trace-file=/tmp/trace", NULL); 24.370 +#else 24.371 + execlp("./xenstored_test", "xenstored_test", "--output-pid", 24.372 + "--no-fork", NULL); 24.373 +#endif 24.374 + exit(1); 24.375 + } 24.376 +} 24.377 + 24.378 + 24.379 +int main(int argc, char **argv) 24.380 +{ 24.381 + unsigned int i; 24.382 + int pid; 24.383 + 24.384 + if (argc != 3 && argc != 4) 24.385 + barf("Usage: xs_crashme <iterations> <seed> [pid]"); 24.386 + 24.387 + if (argc == 3) 24.388 + pid = start_daemon(); 24.389 + else 24.390 + pid = atoi(argv[3]); 24.391 + 24.392 + state = atoi(argv[2]); 24.393 + h = xs_daemon_open(); 24.394 + if (!h) 24.395 + barf_perror("Opening connection to daemon"); 24.396 + signal(SIGALRM, alarmed); 24.397 + for (i = 0; i < (unsigned)atoi(argv[1]); i++) { 24.398 + alarm(1); 24.399 + do_next_op(h, false); 24.400 + if (i % (atoi(argv[1]) / 72 ?: 1) == 0) { 24.401 + printf("."); 24.402 + fflush(stdout); 24.403 + } 24.404 + if (kill(pid, 0) != 0) 24.405 + barf_perror("Pinging daemon on iteration %i", i); 24.406 + if (h->fd < 0) { 24.407 + xs_daemon_close(h); 24.408 + h = xs_daemon_open(); 24.409 + if (!h) 24.410 + barf_perror("Connecting on iteration %i", i); 24.411 + } 24.412 + } 24.413 + kill(pid, SIGTERM); 24.414 + return 0; 24.415 +} 24.416 +
25.1 --- a/tools/xenstore/xs_lib.c Mon Aug 08 09:12:22 2005 +0000 25.2 +++ b/tools/xenstore/xs_lib.c Mon Aug 08 09:13:19 2005 +0000 25.3 @@ -152,8 +152,9 @@ unsigned int xs_count_strings(const char 25.4 unsigned int num; 25.5 const char *p; 25.6 25.7 - for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) 25.8 - num++; 25.9 + for (p = strings, num = 0; p < strings + len; p++) 25.10 + if (*p == '\0') 25.11 + num++; 25.12 25.13 return num; 25.14 }
26.1 --- a/tools/xenstore/xs_random.c Mon Aug 08 09:12:22 2005 +0000 26.2 +++ b/tools/xenstore/xs_random.c Mon Aug 08 09:13:19 2005 +0000 26.3 @@ -349,19 +349,12 @@ static bool file_mkdir(struct file_ops_i 26.4 { 26.5 char *dirname = path_to_name(info, path); 26.6 26.7 - /* Same effective order as daemon, so error returns are right. */ 26.8 - if (mkdir(dirname, 0700) != 0) { 26.9 - if (errno != ENOENT && errno != ENOTDIR) 26.10 - write_ok(info, path); 26.11 + if (!write_ok(info, path)) 26.12 return false; 26.13 - } 26.14 26.15 - if (!write_ok(info, path)) { 26.16 - int saved_errno = errno; 26.17 - rmdir(dirname); 26.18 - errno = saved_errno; 26.19 + if (mkdir(dirname, 0700) != 0) 26.20 return false; 26.21 - } 26.22 + 26.23 init_perms(dirname); 26.24 return true; 26.25 } 26.26 @@ -984,13 +977,15 @@ static void cleanup(const char *dir) 26.27 26.28 static void setup_file_ops(const char *dir) 26.29 { 26.30 - char *cmd = talloc_asprintf(NULL, "echo -n r0 > %s/.perms", dir); 26.31 + struct xs_permissions perm = { .id = 0, .perms = XS_PERM_READ }; 26.32 + struct file_ops_info *h = file_handle(dir); 26.33 if (mkdir(dir, 0700) != 0) 26.34 barf_perror("Creating directory %s", dir); 26.35 - if (mkdir(talloc_asprintf(cmd, "%s/tool", dir), 0700) != 0) 26.36 + if (mkdir(talloc_asprintf(h, "%s/tool", dir), 0700) != 0) 26.37 barf_perror("Creating directory %s/tool", dir); 26.38 - do_command(cmd); 26.39 - talloc_free(cmd); 26.40 + if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1)) 26.41 + barf_perror("Setting root perms in %s", dir); 26.42 + file_close(h); 26.43 } 26.44 26.45 static void setup_xs_ops(void)
27.1 --- a/tools/xenstore/xs_test.c Mon Aug 08 09:12:22 2005 +0000 27.2 +++ b/tools/xenstore/xs_test.c Mon Aug 08 09:13:19 2005 +0000 27.3 @@ -28,13 +28,13 @@ 27.4 #include <stdint.h> 27.5 #include <stdbool.h> 27.6 #include <stdlib.h> 27.7 +#include <sys/mman.h> 27.8 #include <fnmatch.h> 27.9 #include <stdarg.h> 27.10 #include <string.h> 27.11 #include <getopt.h> 27.12 #include <ctype.h> 27.13 #include <sys/time.h> 27.14 -#include <sys/mman.h> 27.15 #include "utils.h" 27.16 #include "xs_lib.h" 27.17 #include "list.h" 27.18 @@ -43,7 +43,7 @@ 27.19 27.20 static struct xs_handle *handles[10] = { NULL }; 27.21 27.22 -static unsigned int timeout_ms = 50; 27.23 +static unsigned int timeout_ms = 200; 27.24 static bool timeout_suppressed = true; 27.25 static bool readonly = false; 27.26 static bool print_input = false; 27.27 @@ -213,6 +213,8 @@ static void __attribute__((noreturn)) us 27.28 " notimeout\n" 27.29 " readonly\n" 27.30 " readwrite\n" 27.31 + " noackwrite <path> <flags> <value>...\n" 27.32 + " readack\n" 27.33 " dump\n"); 27.34 } 27.35 27.36 @@ -365,6 +367,45 @@ static void do_write(unsigned int handle 27.37 failed(handle); 27.38 } 27.39 27.40 +static void do_noackwrite(unsigned int handle, 27.41 + char *path, const char *flags, char *data) 27.42 +{ 27.43 + struct xsd_sockmsg msg; 27.44 + 27.45 + /* Format: Flags (as string), path, data. */ 27.46 + if (streq(flags, "none")) 27.47 + flags = XS_WRITE_NONE; 27.48 + else if (streq(flags, "create")) 27.49 + flags = XS_WRITE_CREATE; 27.50 + else if (streq(flags, "excl")) 27.51 + flags = XS_WRITE_CREATE_EXCL; 27.52 + else 27.53 + barf("noackwrite flags 'none', 'create' or 'excl' only"); 27.54 + 27.55 + msg.len = strlen(path) + 1 + strlen(flags) + 1 + strlen(data); 27.56 + msg.type = XS_WRITE; 27.57 + if (!write_all_choice(handles[handle]->fd, &msg, sizeof(msg))) 27.58 + failed(handle); 27.59 + if (!write_all_choice(handles[handle]->fd, path, strlen(path) + 1)) 27.60 + failed(handle); 27.61 + if (!write_all_choice(handles[handle]->fd, flags, strlen(flags) + 1)) 27.62 + failed(handle); 27.63 + if (!write_all_choice(handles[handle]->fd, data, strlen(data))) 27.64 + failed(handle); 27.65 + /* Do not wait for ack. */ 27.66 +} 27.67 + 27.68 +static void do_readack(unsigned int handle) 27.69 +{ 27.70 + enum xsd_sockmsg_type type; 27.71 + char *ret; 27.72 + 27.73 + ret = read_reply(handles[handle]->fd, &type, NULL); 27.74 + if (!ret) 27.75 + failed(handle); 27.76 + free(ret); 27.77 +} 27.78 + 27.79 static void do_setid(unsigned int handle, char *id) 27.80 { 27.81 if (!xs_bool(xs_debug_command(handles[handle], "setid", id, 27.82 @@ -466,6 +507,25 @@ static void do_watch(unsigned int handle 27.83 failed(handle); 27.84 } 27.85 27.86 +static void set_timeout(void) 27.87 +{ 27.88 + struct itimerval timeout; 27.89 + 27.90 + timeout.it_value.tv_sec = timeout_ms / 1000; 27.91 + timeout.it_value.tv_usec = (timeout_ms * 1000) % 1000000; 27.92 + timeout.it_interval.tv_sec = timeout.it_interval.tv_usec = 0; 27.93 + setitimer(ITIMER_REAL, &timeout, NULL); 27.94 +} 27.95 + 27.96 +static void disarm_timeout(void) 27.97 +{ 27.98 + struct itimerval timeout; 27.99 + 27.100 + timeout.it_value.tv_sec = 0; 27.101 + timeout.it_value.tv_usec = 0; 27.102 + setitimer(ITIMER_REAL, &timeout, NULL); 27.103 +} 27.104 + 27.105 static void do_waitwatch(unsigned int handle) 27.106 { 27.107 char **vec; 27.108 @@ -474,14 +534,17 @@ static void do_waitwatch(unsigned int ha 27.109 fd_set set; 27.110 27.111 if (xs_fileno(handles[handle]) != -2) { 27.112 + /* Manually select here so we can time out gracefully. */ 27.113 FD_ZERO(&set); 27.114 FD_SET(xs_fileno(handles[handle]), &set); 27.115 + disarm_timeout(); 27.116 if (select(xs_fileno(handles[handle])+1, &set, 27.117 NULL, NULL, &tv) == 0) { 27.118 errno = ETIMEDOUT; 27.119 failed(handle); 27.120 return; 27.121 } 27.122 + set_timeout(); 27.123 } 27.124 27.125 vec = xs_read_watch(handles[handle]); 27.126 @@ -530,6 +593,9 @@ static void do_introduce(unsigned int ha 27.127 unsigned int i; 27.128 int fd; 27.129 27.130 + /* This mechanism is v. slow w. valgrind running. */ 27.131 + timeout_ms = 5000; 27.132 + 27.133 /* We poll, so ignore signal */ 27.134 signal(SIGUSR2, SIG_IGN); 27.135 for (i = 0; i < ARRAY_SIZE(handles); i++) 27.136 @@ -671,24 +737,6 @@ static void alarmed(int sig __attribute_ 27.137 exit(1); 27.138 } 27.139 27.140 -static void set_timeout(void) 27.141 -{ 27.142 - struct itimerval timeout; 27.143 - 27.144 - timeout.it_interval.tv_sec = timeout_ms / 1000; 27.145 - timeout.it_interval.tv_usec = (timeout_ms * 1000) % 1000000; 27.146 - setitimer(ITIMER_REAL, &timeout, NULL); 27.147 -} 27.148 - 27.149 -static void disarm_timeout(void) 27.150 -{ 27.151 - struct itimerval timeout; 27.152 - 27.153 - timeout.it_interval.tv_sec = 0; 27.154 - timeout.it_interval.tv_usec = 0; 27.155 - setitimer(ITIMER_REAL, &timeout, NULL); 27.156 -} 27.157 - 27.158 static void do_command(unsigned int default_handle, char *line) 27.159 { 27.160 char *endp; 27.161 @@ -779,7 +827,11 @@ static void do_command(unsigned int defa 27.162 readonly = false; 27.163 xs_daemon_close(handles[handle]); 27.164 handles[handle] = NULL; 27.165 - } else 27.166 + } else if (streq(command, "noackwrite")) 27.167 + do_noackwrite(handle, arg(line,1), arg(line,2), arg(line,3)); 27.168 + else if (streq(command, "readack")) 27.169 + do_readack(handle); 27.170 + else 27.171 barf("Unknown command %s", command); 27.172 fflush(stdout); 27.173 disarm_timeout();