ia64/xen-unstable

changeset 6058: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>
author kaf24@firebug.cl.cam.ac.uk
date Mon Aug 08 09:13:19 2005 +0000 (2005-08-08)
parents b60643391488
children 6fc0b68b0a9c
files tools/xenstore/Makefile tools/xenstore/testsuite/01simple.test tools/xenstore/testsuite/02directory.test tools/xenstore/testsuite/03write.test tools/xenstore/testsuite/04rm.test tools/xenstore/testsuite/05filepermissions.test tools/xenstore/testsuite/06dirpermissions.test tools/xenstore/testsuite/07watch.test tools/xenstore/testsuite/08transaction.slowtest tools/xenstore/testsuite/08transaction.test tools/xenstore/testsuite/09domain.test tools/xenstore/testsuite/10domain-homedir.test tools/xenstore/testsuite/11domain-watch.test tools/xenstore/testsuite/12readonly.test tools/xenstore/testsuite/13watch-ack.test tools/xenstore/testsuite/14complexperms.test tools/xenstore/testsuite/15nowait.test tools/xenstore/utils.c tools/xenstore/xenstored_core.c tools/xenstore/xenstored_core.h tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_domain.h tools/xenstore/xs.c tools/xenstore/xs_crashme.c tools/xenstore/xs_lib.c tools/xenstore/xs_random.c tools/xenstore/xs_test.c
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();