ia64/xen-unstable

changeset 5494:999293916aa7

bitkeeper revision 1.1716 (42b336f8VKVQeJVq9gIppvvdYPrMmw)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
author iap10@freefall.cl.cam.ac.uk
date Fri Jun 17 20:47:52 2005 +0000 (2005-06-17)
parents c45207396f75 a9acc88e9d79
children fbf3bae97a88
files .rootkeys BitKeeper/etc/ignore docs/misc/XenDebugger-HOWTO linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h patches/linux-2.6.11/smp-alts.patch tools/Makefile tools/debugger/pdb/readme tools/firmware/vmxassist/Makefile tools/firmware/vmxassist/head.S tools/firmware/vmxassist/trap.S tools/libxc/Makefile tools/python/setup.py tools/python/xen/lowlevel/xs/xs.c tools/python/xen/lowlevel/xu/xu.c tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py tools/python/xen/xend/server/blkif.py tools/python/xen/xend/server/channel.py tools/python/xen/xend/server/console.py tools/python/xen/xend/server/netif.py tools/python/xen/xend/xenstore/xsnode.py tools/python/xen/xend/xenstore/xsobj.py tools/xcs/xcs_proto.h tools/xenstore/Makefile tools/xenstore/testsuite/07watch.sh tools/xenstore/testsuite/10domain-homedir.sh tools/xenstore/testsuite/11domain-watch.sh tools/xenstore/testsuite/12readonly.sh tools/xenstore/testsuite/test.sh tools/xenstore/xenstored_core.c tools/xenstore/xenstored_core.h tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_domain.h tools/xenstore/xenstored_transaction.c tools/xenstore/xenstored_watch.c tools/xenstore/xenstored_watch.h tools/xenstore/xs.c tools/xenstore/xs.h tools/xenstore/xs_dom0_test.c tools/xenstore/xs_lib.c tools/xenstore/xs_lib.h tools/xenstore/xs_stress.c tools/xenstore/xs_test.c tools/xenstore/xs_watch_stress.c xen/drivers/char/serial.c
line diff
     1.1 --- a/.rootkeys	Mon Jun 13 13:18:58 2005 +0000
     1.2 +++ b/.rootkeys	Fri Jun 17 20:47:52 2005 +0000
     1.3 @@ -17,7 +17,6 @@ 4187c1c7IWmBinGdI19kL4MuZ6RLbQ docs/chec
     1.4  3f9e7d60PWZJeVh5xdnk0nLUdxlqEA docs/figs/xenlogo.eps
     1.5  418a3248xjIqmNKo0v_XQSfAvlBGFw docs/html.sty
     1.6  41c0c4116itF389v0CEWcmzue6zJkA docs/misc/VMX_changes.txt
     1.7 -4022a73cgxX1ryj1HgS-IwwB6NUi2A docs/misc/XenDebugger-HOWTO
     1.8  412f4bd9sm5mCQ8BkrgKcAKZGadq7Q docs/misc/blkif-drivers-explained.txt
     1.9  420b949cy9ZGzED74Fz_DaWlK7tT4g docs/misc/crashdb.txt
    1.10  4251a1f82AexscYEiF4Iku8Gc_kWfQ docs/misc/grant-tables.txt
    1.11 @@ -471,6 +470,7 @@ 42372652KCUP-IOH9RN19YQmGhs4aA patches/l
    1.12  428359d4b3fDYtazwXi4UUmSWaOUew patches/linux-2.6.11/linux-2.6.11.12.patch
    1.13  4296fb998LGSWCcljGKbOCUv3h9uRQ patches/linux-2.6.11/net-csum.patch
    1.14  429ae875I9ZrqrRDjGD34IC2kzDREw patches/linux-2.6.11/rcu-nohz.patch
    1.15 +42b165fcilFTNezi9NIsG2ecLZVU0w patches/linux-2.6.11/smp-alts.patch
    1.16  429ba3007184K-y6WHQ6KgY65-lEIQ patches/linux-2.6.11/udp-frag.patch
    1.17  424f001e_M1Tnxc52rDrmCLelnDWMQ patches/linux-2.6.11/x86_64-linux.patch
    1.18  3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile
    1.19 @@ -542,6 +542,7 @@ 42a0c8da81tzhpvIAfkx9nZqUNrQvg tools/deb
    1.20  42a0c8dasiso9c-2sCvHBzP6YVjATA tools/debugger/pdb/evtchn.mli
    1.21  42a0c8daXD_6Y62A_u5-PO_Klrhi0w tools/debugger/pdb/pdb_caml_xc.c
    1.22  42a0c8danJXun9ay5SPBhhkKvuUPfg tools/debugger/pdb/pdb_xen.c
    1.23 +42b03d06llc_GE7fXGQ6-rYR4VFAcw tools/debugger/pdb/readme
    1.24  42a0c8dbjK6Du89D2SUcxsuAdlUu3w tools/debugger/pdb/server.ml
    1.25  401d7e160vaxMBAUSLSicuZ7AQjJ3w tools/examples/Makefile
    1.26  401d7e16UgeqroJQTIhwkrDVkoWgZQ tools/examples/README
    1.27 @@ -1065,6 +1066,9 @@ 42a57d98YGCLyTDSGmoyFqRqQUlagQ tools/xen
    1.28  42a57d98fdO519YyATk4_Zwr1STNfQ tools/xenstore/testsuite/07watch.sh
    1.29  42a57d98zZUtvirUMjmHxFphJjmO7Q tools/xenstore/testsuite/08transaction.sh
    1.30  42a57d98sn9RbpBgHRv1D99Kt7LwYA tools/xenstore/testsuite/09domain.sh
    1.31 +42b2a4bfxAwHlRgd31SJBgFnj8g3MA tools/xenstore/testsuite/10domain-homedir.sh
    1.32 +42b2a4bfHbUp4IB8tfNIa8j37S27fw tools/xenstore/testsuite/11domain-watch.sh
    1.33 +42b2a4bfhrB5v6uYKPj6jSO_Ng0PAA tools/xenstore/testsuite/12readonly.sh
    1.34  42a57d98tSuoFCHnnM2GgENXJrRQmw tools/xenstore/testsuite/test.sh
    1.35  42a57d98zxDP2Ti7dTznGROi66rUGw tools/xenstore/utils.c
    1.36  42a57d98SDvOYCEjmCjwHSk6390GLA tools/xenstore/utils.h
    1.37 @@ -1080,11 +1084,13 @@ 42a57d99izTIjWfG-IjQAPqYlDWJNg tools/xen
    1.38  42a57d99-zLxBjzC7rfj_perV-orUg tools/xenstore/xenstored_watch.h
    1.39  42a57d99BnkhISKgCCRcUqhteyuxCw tools/xenstore/xs.c
    1.40  42a57d99FyiYSz9AkKKROrRydnA-gQ tools/xenstore/xs.h
    1.41 +42b29922EYQ87Y4fwZXSkEHgtQk7CQ tools/xenstore/xs_dom0_test.c
    1.42  42a57d99SrtsJCDUlKyRPf3EX86A1Q tools/xenstore/xs_lib.c
    1.43  42a57d99L2pYeMFyjQ_4Rnb17xTSMg tools/xenstore/xs_lib.h
    1.44  42a57d99Kl6Ba8oCHv2fggl7QN9QZA tools/xenstore/xs_random.c
    1.45  42a57d99SHYR1lQOD0shuErPDg9NKQ tools/xenstore/xs_stress.c
    1.46  42a57d996aBawpkQNOWkNWXD6LrhPg tools/xenstore/xs_test.c
    1.47 +42b2a4bfp-lhxBfenUyHlvw7bPcVgA tools/xenstore/xs_watch_stress.c
    1.48  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.49  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
    1.50  420d52d2_znVbT4JAPIU36vQOme83g tools/xentrace/xenctx.c
     2.1 --- a/BitKeeper/etc/ignore	Mon Jun 13 13:18:58 2005 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Fri Jun 17 20:47:52 2005 +0000
     2.3 @@ -144,9 +144,11 @@ tools/xenstore/testsuite/tmp/*
     2.4  tools/xenstore/xen
     2.5  tools/xenstore/xenstored
     2.6  tools/xenstore/xenstored_test
     2.7 +tools/xenstore/xs_dom0_test
     2.8  tools/xenstore/xs_random
     2.9  tools/xenstore/xs_stress
    2.10  tools/xenstore/xs_test
    2.11 +tools/xenstore/xs_watch_stress
    2.12  tools/xentrace/xentrace
    2.13  tools/xfrd/xfrd
    2.14  xen/BLOG
     3.1 --- a/docs/misc/XenDebugger-HOWTO	Mon Jun 13 13:18:58 2005 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,304 +0,0 @@
     3.4 -Pervasive Debugging 
     3.5 -===================
     3.6 -
     3.7 -Alex Ho (alex.ho at cl.cam.ac.uk)
     3.8 -
     3.9 -Introduction
    3.10 -------------
    3.11 -
    3.12 -The pervasive debugging project is leveraging Xen to 
    3.13 -debug distributed systems.  We have added a gdb stub
    3.14 -to Xen to allow for remote debugging of both Xen and
    3.15 -guest operating systems.  More information about the
    3.16 -pervasive debugger is available at: http://www.cl.cam.ac.uk/netos/pdb
    3.17 -
    3.18 -
    3.19 -Implementation
    3.20 ---------------
    3.21 -
    3.22 -The gdb stub communicates with gdb running over a serial line.
    3.23 -The main entry point is pdb_handle_exception() which is invoked
    3.24 -from:    pdb_key_pressed()    ('D' on the console)
    3.25 -         do_int3_exception()  (interrupt 3: breakpoint exception)
    3.26 -         do_debug()           (interrupt 1: debug exception)
    3.27 -
    3.28 -This accepts characters from the serial port and passes gdb
    3.29 -commands to pdb_process_command() which implements the gdb stub
    3.30 -interface.  This file draws heavily from the kgdb project and
    3.31 -sample gdbstub provided with gdb.
    3.32 -
    3.33 -The stub can examine registers, single step and continue, and
    3.34 -read and write memory (in Xen, a domain, or a Linux process'
    3.35 -address space).  The debugger does not currently trace the 
    3.36 -current process, so all bets are off if context switch occurs
    3.37 -in the domain.
    3.38 -
    3.39 -
    3.40 -Setup
    3.41 ------
    3.42 -
    3.43 - +-------+ telnet +-----------+ serial +-------+ 
    3.44 - |  GDB  |--------|  nsplitd  |--------|  Xen  |
    3.45 - +-------+        +-----------+        +-------+ 
    3.46 -
    3.47 -To run pdb, Xen must be appropriately configured and 
    3.48 -a suitable serial interface attached to the target machine.
    3.49 -GDB and nsplitd can run on the same machine.
    3.50 -
    3.51 -Xen Configuration
    3.52 -
    3.53 -  Add the "pdb=xxx" option to your Xen boot command line
    3.54 -  where xxx is one of the following values:
    3.55 -     com1    gdb stub should communicate on com1
    3.56 -     com1H   gdb stub should communicate on com1 (with high bit set)
    3.57 -     com2    gdb stub should communicate on com2
    3.58 -     com2H   gdb stub should communicate on com2 (with high bit set)
    3.59 -
    3.60 -  Symbolic debugging infomration is quite helpful too:
    3.61 -  xeno.bk/xen/arch/x86/Rules.mk
    3.62 -    add -g to CFLAGS to compile Xen with symbols
    3.63 -  xeno.bk/linux-2.4.27-xen-sparse/arch/xen/Makefile
    3.64 -    add -g to CFLAGS to compile Linux with symbols
    3.65 -
    3.66 -  You may also want to consider dedicating a register to the
    3.67 -  frame pointer (disable the -fomit-frame-pointer compile flag).
    3.68 -
    3.69 -  When booting Xen and domain 0, look for the console text 
    3.70 -  "pdb: pervasive debugger" just before DOM0 starts up.
    3.71 -
    3.72 -Serial Port Configuration
    3.73 -
    3.74 -  pdb expects to communicate with gdb using the serial port.  Since 
    3.75 -  this port is often shared with the machine's console output, pdb can
    3.76 -  discriminate its communication by setting the high bit of each byte.
    3.77 -
    3.78 -  A new tool has been added to the source tree which splits 
    3.79 -  the serial output from a remote machine into two streams: 
    3.80 -  one stream (without the high bit) is the console and 
    3.81 -  one stream (with the high bit stripped) is the pdb communication.
    3.82 -
    3.83 -  See:  xeno.bk/tools/misc/nsplitd
    3.84 -
    3.85 -  nsplitd configuration
    3.86 -  ---------------------
    3.87 -  hostname$ more /etc/xinetd.d/nsplit
    3.88 -  service nsplit1
    3.89 -  {
    3.90 -        socket_type             = stream
    3.91 -        protocol                = tcp
    3.92 -        wait                    = no
    3.93 -        user                    = wanda
    3.94 -        server                  = /usr/sbin/in.nsplitd
    3.95 -        server_args             = serial.cl.cam.ac.uk:wcons00
    3.96 -        disable                 = no
    3.97 -        only_from               = 128.232.0.0/17 127.0.0.1
    3.98 -  }
    3.99 -
   3.100 -  hostname$ egrep 'wcons00|nsplit1' /etc/services
   3.101 -  wcons00         9600/tcp        # Wanda remote console
   3.102 -  nsplit1         12010/tcp       # Nemesis console splitter ports.
   3.103 -
   3.104 -  Note: nsplitd was originally written for the Nemesis project
   3.105 -  at Cambridge.
   3.106 -
   3.107 -  After nsplitd accepts a connection on <port> (12010 in the above
   3.108 -  example), it starts listening on port <port + 1>.  Characters sent 
   3.109 -  to the <port + 1> will have the high bit set and vice versa for 
   3.110 -  characters received.
   3.111 -
   3.112 -  You can connect to the nsplitd using
   3.113 -  'tools/misc/xencons <host> <port>'
   3.114 -
   3.115 -GDB 6.0
   3.116 -  pdb has been tested with gdb 6.0.  It should also work with
   3.117 -  earlier versions.
   3.118 -
   3.119 -
   3.120 -Usage
   3.121 ------
   3.122 -
   3.123 -1. Boot Xen and Linux
   3.124 -2. Interrupt Xen by pressing 'D' at the console
   3.125 -   You should see the console message: 
   3.126 -   (XEN) pdb_handle_exception [0x88][0x101000:0xfc5e72ac]
   3.127 -   At this point Xen is frozen and the pdb stub is waiting for gdb commands 
   3.128 -   on the serial line.
   3.129 -3. Attach with gdb
   3.130 -   (gdb) file xeno.bk/xen/xen
   3.131 -   Reading symbols from xeno.bk/xen/xen...done.
   3.132 -   (gdb) target remote <hostname>:<port + 1>              /* contact nsplitd */
   3.133 -   Remote debugging using serial.srg:12131
   3.134 -   continue_cpu_idle_loop () at current.h:10
   3.135 -   warning: shared library handler failed to enable breakpoint
   3.136 -   (gdb) break __enter_scheduler
   3.137 -   Breakpoint 1 at 0xfc510a94: file schedule.c, line 330.
   3.138 -   (gdb) cont
   3.139 -   Continuing.
   3.140 -
   3.141 -   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.142 -   __enter_scheduler () at schedule.c:330
   3.143 -   (gdb) step
   3.144 -   (gdb) step
   3.145 -   (gdb) print next            /* the variable prev has been optimized away! */
   3.146 -   $1 = (struct task_struct *) 0x0
   3.147 -   (gdb) delete
   3.148 -   Delete all breakpoints? (y or n) y
   3.149 -4. You can add additional symbols to gdb
   3.150 -   (gdb) add-sym xeno.bk/linux-2.4.27-xen0/vmlinux
   3.151 -   add symbol table from file "xeno.bk/linux-2.4.27-xen0/vmlinux" at
   3.152 -   (y or n) y
   3.153 -   Reading symbols from xeno.bk/linux-2.4.27-xen0/vmlinux...done.
   3.154 -   (gdb) x/s cpu_vendor_names[0]
   3.155 -   0xc01530d2 <cpdext+62898>:	 "Intel"
   3.156 -   (gdb) break free_uid
   3.157 -   Breakpoint 2 at 0xc0012250
   3.158 -   (gdb) cont
   3.159 -   Continuing.                                  /* run a command in domain 0 */
   3.160 -
   3.161 -   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.162 -   free_uid (up=0xbffff738) at user.c:77
   3.163 -
   3.164 -   (gdb) print *up
   3.165 -   $2 = {__count = {counter = 0}, processes = {counter = 135190120}, files = {
   3.166 -       counter = 0}, next = 0x395, pprev = 0xbffff878, uid = 134701041}
   3.167 -   (gdb) finish
   3.168 -   Run till exit from #0  free_uid (up=0xbffff738) at user.c:77
   3.169 -
   3.170 -   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.171 -   release_task (p=0xc2da0000) at exit.c:51
   3.172 -   (gdb) print *p
   3.173 -   $3 = {state = 4, flags = 4, sigpending = 0, addr_limit = {seg = 3221225472},
   3.174 -     exec_domain = 0xc016a040, need_resched = 0, ptrace = 0, lock_depth = -1, 
   3.175 -     counter = 1, nice = 0, policy = 0, mm = 0x0, processor = 0, 
   3.176 -     cpus_runnable = 1, cpus_allowed = 4294967295, run_list = {next = 0x0, 
   3.177 -       prev = 0x0}, sleep_time = 18995, next_task = 0xc017c000, 
   3.178 -     prev_task = 0xc2f94000, active_mm = 0x0, local_pages = {next = 0xc2da0054,
   3.179 -       prev = 0xc2da0054}, allocation_order = 0, nr_local_pages = 0, 
   3.180 -     ...
   3.181 -5. To resume Xen, enter the "continue" command to gdb.
   3.182 -   This sends the packet $c#63 along the serial channel.
   3.183 -
   3.184 -   (gdb) cont
   3.185 -   Continuing.
   3.186 -
   3.187 -Debugging Multiple Domains & Processes
   3.188 ---------------------------------------
   3.189 -
   3.190 -pdb supports debugging multiple domains & processes.  You can switch
   3.191 -between different domains and processes within domains and examine
   3.192 -variables in each.
   3.193 -
   3.194 -The pdb context identifies the current debug target.  It is stored
   3.195 -in the xen variable pdb_ctx and defaults to xen.
   3.196 -
   3.197 -   target    pdb_ctx.domain    pdb_ctx.process
   3.198 -   ------    --------------    ---------------
   3.199 -    xen           -1                 -1
   3.200 -  guest os      0,1,2,...            -1
   3.201 -   process      0,1,2,...          0,1,2,...
   3.202 -
   3.203 -Unfortunately, gdb doesn't understand debugging multiple process
   3.204 -simultaneously (we're working on it), so at present you are limited 
   3.205 -to just one set of symbols for symbolic debugging.  When debugging
   3.206 -processes, pdb currently supports just Linux 2.4.
   3.207 -
   3.208 -   define setup
   3.209 -      file xeno-clone/xeno.bk/xen/xen
   3.210 -      add-sym xeno-clone/xeno.bk/linux-2.4.27-xen0/vmlinux
   3.211 -      add-sym ~ach61/a.out
   3.212 -   end
   3.213 -
   3.214 -
   3.215 -1. Connect with gdb as before.  A couple of Linux-specific 
   3.216 -   symbols need to be defined.
   3.217 -
   3.218 -   (gdb) target remote <hostname>:<port + 1>              /* contact nsplitd */
   3.219 -   Remote debugging using serial.srg:12131
   3.220 -   continue_cpu_idle_loop () at current.h:10
   3.221 -   warning: shared library handler failed to enable breakpoint
   3.222 -   (gdb) set pdb_pidhash_addr = &pidhash
   3.223 -   (gdb) set pdb_init_task_union_addr = &init_task_union
   3.224 -
   3.225 -2. The pdb context defaults to Xen and we can read Xen's memory.
   3.226 -   An attempt to access domain 0 memory fails.
   3.227 -  
   3.228 -   (gdb) print pdb_ctx
   3.229 -   $1 = {valid = 0, domain = -1, process = -1, ptbr = 1052672}
   3.230 -   (gdb) print hexchars
   3.231 -   $2 = "0123456789abcdef"
   3.232 -   (gdb) print cpu_vendor_names
   3.233 -   Cannot access memory at address 0xc0191f80
   3.234 -
   3.235 -3. Now we change to domain 0.  In addition to changing pdb_ctx.domain,
   3.236 -   we need to change pdb_ctx.valid to signal pdb of the change.
   3.237 -   It is now possible to examine Xen and Linux memory.
   3.238 -
   3.239 -   (gdb) set pdb_ctx.domain=0
   3.240 -   (gdb) set pdb_ctx.valid=1
   3.241 -   (gdb) print hexchars
   3.242 -   $3 = "0123456789abcdef"
   3.243 -   (gdb) print cpu_vendor_names
   3.244 -   $4 = {0xc0158b46 "Intel", 0xc0158c37 "Cyrix", 0xc0158b55 "AMD", 
   3.245 -     0xc0158c3d "UMC", 0xc0158c41 "NexGen", 0xc0158c48 "Centaur", 
   3.246 -     0xc0158c50 "Rise", 0xc0158c55 "Transmeta"}
   3.247 -
   3.248 -4. Now change to a process within domain 0.  Again, we need to
   3.249 -   change pdb_ctx.valid in addition to pdb_ctx.process.
   3.250 -
   3.251 -   (gdb) set pdb_ctx.process=962
   3.252 -   (gdb) set pdb_ctx.valid =1
   3.253 -   (gdb) print pdb_ctx
   3.254 -   $1 = {valid = 0, domain = 0, process = 962, ptbr = 52998144}
   3.255 -   (gdb) print aho_a
   3.256 -   $2 = 20
   3.257 -
   3.258 -5. Now we can read the same variable from another process running
   3.259 -   the same executable in another domain.
   3.260 -
   3.261 -   (gdb) set pdb_ctx.domain=1
   3.262 -   (gdb) set pdb_ctx.process=1210
   3.263 -   (gdb) set pdb_ctx.valid=1
   3.264 -   (gdb) print pdb_ctx
   3.265 -   $3 = {valid = 0, domain = 1, process = 1210, ptbr = 70574080}
   3.266 -   (gdb) print aho_a
   3.267 -   $4 = 27
   3.268 -
   3.269 -
   3.270 -Some Helpful .gdbinit Commands
   3.271 -------------------------------
   3.272 -
   3.273 -define setup
   3.274 -  file    .../install/boot/xen-syms
   3.275 -  add-sym .../install/boot/vmlinux-syms-2.4.27-xen0
   3.276 -  add-sym /homes/aho/a.out
   3.277 -end
   3.278 -document setup
   3.279 -  load symbols for xen, xenolinux (dom 0), and "a.out"
   3.280 -end
   3.281 -
   3.282 -define setup-linux
   3.283 -  set pdb_pidhash_addr = &pidhash
   3.284 -  set pdb_init_task_union_addr = &init_task_union
   3.285 -
   3.286 -  set task_struct_mm_offset           = (void *)&(init_task_union.task.mm) - (void *)&(init_task_union.task)
   3.287 -  set task_struct_next_task_offset    = (void *)&(init_task_union.task.next_task) - (void *)&(init_task_union.task)
   3.288 -  set task_struct_pid_offset          = (void *)&(init_task_union.task.pid) - (void *)&(init_task_union.task)
   3.289 -  set task_struct_pidhash_next_offset = (void *)&(init_task_union.task.pidhash_next) - (void *)&(init_task_union.task)
   3.290 -  set task_struct_comm_offset         = (void *)&(init_task_union.task.comm) - (void *)&(init_task_union.task)
   3.291 -  set task_struct_comm_length         = sizeof (init_task_union.task.comm)
   3.292 -
   3.293 -  set mm_struct_pgd_offset            = sizeof (struct vm_area_struct *) * 2 + sizeof (rb_root_t)
   3.294 -end
   3.295 -document setup-linux
   3.296 -  define various xenolinux specific offsets and sizes in pdb
   3.297 -end
   3.298 -
   3.299 -
   3.300 -
   3.301 -
   3.302 -Changes
   3.303 --------
   3.304 -
   3.305 -04.07.15 aho .gdbinit
   3.306 -04.02.05 aho creation
   3.307 -04.03.31 aho add description on debugging multiple domains
     4.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig	Mon Jun 13 13:18:58 2005 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig	Fri Jun 17 20:47:52 2005 +0000
     4.3 @@ -372,6 +372,19 @@ config SMP
     4.4  
     4.5  	  If you don't know what to do here, say N.
     4.6  
     4.7 +config SMP_ALTERNATIVES
     4.8 +        bool "SMP alternatives support (EXPERIMENTAL)"
     4.9 +        depends on SMP && EXPERIMENTAL
    4.10 +        help
    4.11 +          Try to reduce the overhead of running an SMP kernel on a uniprocessor
    4.12 +          host slightly by replacing certain key instruction sequences
    4.13 +          according to whether we currently have more than one CPU available.
    4.14 +          This should provide a noticeable boost to performance when
    4.15 +          running SMP kernels on UP machines, and have negligible impact
    4.16 +          when running on an true SMP host.
    4.17 +
    4.18 +          If unsure, say N.
    4.19 +
    4.20  config NR_CPUS
    4.21  	int "Maximum number of CPUs (2-255)"
    4.22  	range 2 255
     5.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile	Mon Jun 13 13:18:58 2005 +0000
     5.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile	Fri Jun 17 20:47:52 2005 +0000
     5.3 @@ -42,6 +42,7 @@ c-obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
     5.4  c-obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
     5.5  c-obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
     5.6  c-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
     5.7 +c-obj-$(CONFIG_SMP_ALTERNATIVES)+= smpalts.o
     5.8  
     5.9  EXTRA_AFLAGS   := -traditional
    5.10  
     6.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Jun 13 13:18:58 2005 +0000
     6.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Fri Jun 17 20:47:52 2005 +0000
     6.3 @@ -54,6 +54,8 @@
     6.4  #include <asm/desc.h>
     6.5  #include <asm/arch_hooks.h>
     6.6  
     6.7 +#include <asm/smp_alt.h>
     6.8 +
     6.9  #ifndef CONFIG_X86_IO_APIC
    6.10  #define Dprintk(args...)
    6.11  #endif
    6.12 @@ -1186,6 +1188,10 @@ static void __init smp_boot_cpus(unsigne
    6.13  		if (max_cpus <= cpucount+1)
    6.14  			continue;
    6.15  
    6.16 +#ifdef CONFIG_SMP_ALTERNATIVES
    6.17 +		if (kicked == 1)
    6.18 +			prepare_for_smp();
    6.19 +#endif
    6.20  		if (do_boot_cpu(cpu))
    6.21  			printk("CPU #%d not responding - cannot use it.\n",
    6.22  								cpu);
    6.23 @@ -1301,6 +1307,11 @@ void __devinit smp_prepare_boot_cpu(void
    6.24  /* must be called with the cpucontrol mutex held */
    6.25  static int __devinit cpu_enable(unsigned int cpu)
    6.26  {
    6.27 +#ifdef CONFIG_SMP_ALTERNATIVES
    6.28 +	if (num_online_cpus() == 1)
    6.29 +		prepare_for_smp();
    6.30 +#endif
    6.31 +
    6.32  	/* get the target out of its holding state */
    6.33  	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
    6.34  	wmb();
    6.35 @@ -1340,6 +1351,12 @@ int __cpu_disable(void)
    6.36  	fixup_irqs(map);
    6.37  	/* It's now safe to remove this processor from the online map */
    6.38  	cpu_clear(cpu, cpu_online_map);
    6.39 +
    6.40 +#ifdef CONFIG_SMP_ALTERNATIVES
    6.41 +	if (num_online_cpus() == 1)
    6.42 +		unprepare_for_smp();
    6.43 +#endif
    6.44 +
    6.45  	return 0;
    6.46  }
    6.47  
     7.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Mon Jun 13 13:18:58 2005 +0000
     7.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Fri Jun 17 20:47:52 2005 +0000
     7.3 @@ -47,6 +47,8 @@
     7.4  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     7.5  EXPORT_SYMBOL(force_evtchn_callback);
     7.6  EXPORT_SYMBOL(evtchn_do_upcall);
     7.7 +EXPORT_SYMBOL(bind_evtchn_to_irq);
     7.8 +EXPORT_SYMBOL(unbind_evtchn_from_irq);
     7.9  #endif
    7.10  
    7.11  /*
     8.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S	Mon Jun 13 13:18:58 2005 +0000
     8.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S	Fri Jun 17 20:47:52 2005 +0000
     8.3 @@ -63,42 +63,28 @@ VGCF_IN_SYSCALL = (1<<8)
     8.4  #define sizeof_vcpu_shift		3
     8.5  
     8.6  #ifdef CONFIG_SMP
     8.7 -#define XEN_GET_VCPU_INFO(reg)
     8.8 -#define preempt_disable(reg)	incl TI_preempt_count(reg)
     8.9 -#define preempt_enable(reg)	decl TI_preempt_count(reg)
    8.10 -#define XEN_LOCK_VCPU_INFO_SMP(reg) preempt_disable(%rbp)		; \
    8.11 -				movl TI_cpu(%rbp),reg			; \
    8.12 +#define preempt_disable(reg)	incl threadinfo_preempt_count(reg)
    8.13 +#define preempt_enable(reg)	decl threadinfo_preempt_count(reg)
    8.14 +#define XEN_GET_VCPU_INFO(reg)	preempt_disable(%rbp)			; \
    8.15 +				movq %gs:pda_cpunumber,reg		; \
    8.16  				shl  $sizeof_vcpu_shift,reg		; \
    8.17 -				addl HYPERVISOR_shared_info,reg
    8.18 -#define XEN_UNLOCK_VCPU_INFO_SMP(reg) preempt_enable(%rbp)
    8.19 -#define XEN_UNLOCK_VCPU_INFO_SMP_fixup .byte 0xff,0xff,0xff
    8.20 -#define Ux00 0xff
    8.21 -#define XEN_LOCKED_BLOCK_EVENTS(reg)	movb $1,evtchn_upcall_mask(reg)
    8.22 -#define XEN_BLOCK_EVENTS(reg)	XEN_LOCK_VCPU_INFO_SMP(reg)		; \
    8.23 -				XEN_LOCKED_BLOCK_EVENTS(reg)		; \
    8.24 -    				XEN_UNLOCK_VCPU_INFO_SMP(reg)
    8.25 -#define XEN_UNBLOCK_EVENTS(reg)	XEN_LOCK_VCPU_INFO_SMP(reg)		; \
    8.26 -				movb $0,evtchn_upcall_mask(reg)		; \
    8.27 -    				XEN_UNLOCK_VCPU_INFO_SMP(reg)
    8.28 -#define XEN_SAVE_UPCALL_MASK(reg,tmp,off) GET_THREAD_INFO(%ebp)		; \
    8.29 -				XEN_LOCK_VCPU_INFO_SMP(reg)		; \
    8.30 -				movb evtchn_upcall_mask(reg), tmp	; \
    8.31 -				movb tmp, off(%rsp)			; \
    8.32 -    				XEN_UNLOCK_VCPU_INFO_SMP(reg)
    8.33 +				addq HYPERVISOR_shared_info,reg
    8.34 +#define XEN_PUT_VCPU_INFO(reg)	preempt_enable(%rbp)			; \
    8.35 +#define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff
    8.36  #else
    8.37  #define XEN_GET_VCPU_INFO(reg)	movq HYPERVISOR_shared_info,reg
    8.38 -#define XEN_LOCK_VCPU_INFO_SMP(reg) movq HYPERVISOR_shared_info,reg
    8.39 -#define XEN_UNLOCK_VCPU_INFO_SMP(reg)
    8.40 -#define XEN_UNLOCK_VCPU_INFO_SMP_fixup
    8.41 -#define Ux00 0x00
    8.42 -#define XEN_LOCKED_BLOCK_EVENTS(reg)	movb $1,evtchn_upcall_mask(reg)
    8.43 -#define XEN_BLOCK_EVENTS(reg)	XEN_LOCKED_BLOCK_EVENTS(reg)
    8.44 -#define XEN_UNBLOCK_EVENTS(reg)	movb $0,evtchn_upcall_mask(reg)
    8.45 -#define XEN_SAVE_UPCALL_MASK(reg,tmp,off) \
    8.46 -	movb evtchn_upcall_mask(reg), tmp; \
    8.47 -	movb tmp, off(%rsp)
    8.48 +#define XEN_PUT_VCPU_INFO(reg)
    8.49 +#define XEN_PUT_VCPU_INFO_fixup
    8.50  #endif
    8.51  
    8.52 +#define XEN_LOCKED_BLOCK_EVENTS(reg)	movb $1,evtchn_upcall_mask(reg)
    8.53 +#define XEN_LOCKED_UNBLOCK_EVENTS(reg)	movb $0,evtchn_upcall_mask(reg)
    8.54 +#define XEN_BLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
    8.55 +				XEN_LOCKED_BLOCK_EVENTS(reg)		; \
    8.56 +    				XEN_PUT_VCPU_INFO(reg)
    8.57 +#define XEN_UNBLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
    8.58 +				XEN_LOCKED_UNBLOCK_EVENTS(reg)		; \
    8.59 +    				XEN_PUT_VCPU_INFO(reg)
    8.60  #define XEN_TEST_PENDING(reg)	testb $0xFF,evtchn_upcall_pending(reg)
    8.61  
    8.62  	.code64
    8.63 @@ -256,8 +242,6 @@ ENTRY(system_call)
    8.64  	CFI_STARTPROC
    8.65  	SAVE_ARGS -8,0
    8.66  	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
    8.67 -        XEN_GET_VCPU_INFO(%r11)
    8.68 -        XEN_SAVE_UPCALL_MASK(%r11,%cl,EVENT_MASK-ARGOFFSET)      # saved %rcx          
    8.69          XEN_UNBLOCK_EVENTS(%r11)        
    8.70  	GET_THREAD_INFO(%rcx)
    8.71  	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
    8.72 @@ -277,7 +261,6 @@ ret_from_sys_call:
    8.73  	/* edi:	flagmask */
    8.74  sysret_check:		
    8.75  	GET_THREAD_INFO(%rcx)
    8.76 -        XEN_GET_VCPU_INFO(%rsi)
    8.77          XEN_BLOCK_EVENTS(%rsi)        
    8.78  	movl threadinfo_flags(%rcx),%edx
    8.79  	andl %edi,%edx
    8.80 @@ -291,7 +274,6 @@ sysret_check:
    8.81  sysret_careful:
    8.82  	bt $TIF_NEED_RESCHED,%edx
    8.83  	jnc sysret_signal
    8.84 -        XEN_GET_VCPU_INFO(%rsi)
    8.85          XEN_BLOCK_EVENTS(%rsi)        
    8.86  	pushq %rdi
    8.87  	call schedule
    8.88 @@ -301,7 +283,6 @@ sysret_careful:
    8.89  	/* Handle a signal */ 
    8.90  sysret_signal:
    8.91  /*	sti */
    8.92 -        XEN_GET_VCPU_INFO(%rsi)
    8.93          XEN_UNBLOCK_EVENTS(%rsi)        
    8.94  	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
    8.95  	jz    1f
    8.96 @@ -345,7 +326,6 @@ badsys:
    8.97   * Has correct top of stack, but partial stack frame.
    8.98   */ 	
    8.99  ENTRY(int_ret_from_sys_call)	
   8.100 -        XEN_GET_VCPU_INFO(%rsi)
   8.101          XEN_BLOCK_EVENTS(%rsi)
   8.102  	testb $3,CS-ARGOFFSET(%rsp)
   8.103          jnz 1f
   8.104 @@ -369,7 +349,6 @@ int_careful:
   8.105  	bt $TIF_NEED_RESCHED,%edx
   8.106  	jnc  int_very_careful
   8.107  /*	sti */
   8.108 -        XEN_GET_VCPU_INFO(%rsi)
   8.109          XEN_UNBLOCK_EVENTS(%rsi)
   8.110  	pushq %rdi
   8.111  	call schedule
   8.112 @@ -379,7 +358,6 @@ int_careful:
   8.113  	/* handle signals and tracing -- both require a full stack frame */
   8.114  int_very_careful:
   8.115  /*	sti */
   8.116 -        XEN_GET_VCPU_INFO(%rsi)
   8.117          XEN_UNBLOCK_EVENTS(%rsi)
   8.118  	SAVE_REST
   8.119  	/* Check for syscall exit trace */	
   8.120 @@ -529,11 +507,11 @@ retint_check:
   8.121  retint_restore_args:
   8.122          movb EVENT_MASK-REST_SKIP(%rsp), %al
   8.123          notb %al			# %al == ~saved_mask
   8.124 -        XEN_LOCK_VCPU_INFO_SMP(%rsi)
   8.125 +        XEN_GET_VCPU_INFO(%rsi)
   8.126          andb evtchn_upcall_mask(%rsi),%al
   8.127  	andb $1,%al			# %al == mask & ~saved_mask
   8.128  	jnz restore_all_enable_events	# != 0 => reenable event delivery      
   8.129 -        XEN_UNLOCK_VCPU_INFO_SMP(%rsi)
   8.130 +        XEN_PUT_VCPU_INFO(%rsi)
   8.131  		
   8.132  	RESTORE_ARGS 0,8,0						
   8.133  	testb $3,8(%rsp)                # check CS
   8.134 @@ -548,13 +526,11 @@ user_mode:
   8.135  retint_careful:
   8.136  	bt    $TIF_NEED_RESCHED,%edx
   8.137  	jnc   retint_signal
   8.138 -	XEN_GET_VCPU_INFO(%rsi)
   8.139  	XEN_UNBLOCK_EVENTS(%rsi)
   8.140  /*	sti */        
   8.141  	pushq %rdi
   8.142  	call  schedule
   8.143  	popq %rdi		
   8.144 -	XEN_GET_VCPU_INFO(%rsi)        
   8.145  	XEN_BLOCK_EVENTS(%rsi)		
   8.146  	GET_THREAD_INFO(%rcx)
   8.147  /*	cli */
   8.148 @@ -563,7 +539,6 @@ retint_careful:
   8.149  retint_signal:
   8.150  	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
   8.151  	jz    retint_restore_args
   8.152 -        XEN_GET_VCPU_INFO(%rsi)
   8.153          XEN_UNBLOCK_EVENTS(%rsi)
   8.154  	SAVE_REST
   8.155  	movq $-1,ORIG_RAX(%rsp) 			
   8.156 @@ -571,7 +546,6 @@ retint_signal:
   8.157  	movq %rsp,%rdi		# &pt_regs
   8.158  	call do_notify_resume
   8.159  	RESTORE_REST
   8.160 -        XEN_GET_VCPU_INFO(%rsi)        
   8.161          XEN_BLOCK_EVENTS(%rsi)		
   8.162  	movl $_TIF_NEED_RESCHED,%edi
   8.163  	GET_THREAD_INFO(%rcx)	
   8.164 @@ -590,10 +564,8 @@ retint_kernel:
   8.165  	jc   retint_restore_args
   8.166  	movl $PREEMPT_ACTIVE,threadinfo_preempt_count(%rcx)
   8.167  /*	sti */
   8.168 -	XEN_GET_VCPU_INFO(%rsi)
   8.169  	XEN_UNBLOCK_EVENTS(%rsi)
   8.170  	call schedule
   8.171 -	XEN_GET_VCPU_INFO(%rsi) /* %esi can be different */
   8.172  	XEN_BLOCK_EVENTS(%rsi)
   8.173  /*	cli */
   8.174  	GET_THREAD_INFO(%rcx)
   8.175 @@ -728,17 +700,10 @@ error_call_handler:
   8.176  	movq %rsp,%rdi
   8.177  	movq ORIG_RAX(%rsp),%rsi	# get error code 
   8.178  	movq $-1,ORIG_RAX(%rsp)
   8.179 -        leaq do_hypervisor_callback,%rcx
   8.180 -        cmpq %rax,%rcx
   8.181 -        je 0f                           # don't save event mask for callbacks
   8.182 -        XEN_GET_VCPU_INFO(%r11)
   8.183 -        XEN_SAVE_UPCALL_MASK(%r11,%cl,EVENT_MASK)
   8.184 -0:              
   8.185  	call *%rax
   8.186  error_exit:		
   8.187  	RESTORE_REST
   8.188  /*	cli */
   8.189 -	XEN_GET_VCPU_INFO(%rsi)        
   8.190  	XEN_BLOCK_EVENTS(%rsi)		
   8.191  	GET_THREAD_INFO(%rcx)	
   8.192  	testb $3,CS-ARGOFFSET(%rsp)
   8.193 @@ -807,7 +772,7 @@ restore_all_enable_events:
   8.194  scrit:	/**** START OF CRITICAL REGION ****/
   8.195  	XEN_TEST_PENDING(%rsi)
   8.196  	jnz  14f			# process more events if necessary...
   8.197 -	XEN_UNLOCK_VCPU_INFO_SMP(%rsi)
   8.198 +	XEN_PUT_VCPU_INFO(%rsi)
   8.199          RESTORE_ARGS 0,8,0
   8.200          testb $3,8(%rsp)                # check CS
   8.201          jnz  crit_user_mode
   8.202 @@ -817,7 +782,7 @@ crit_user_mode:
   8.203          SWITCH_TO_USER 0
   8.204          
   8.205  14:	XEN_LOCKED_BLOCK_EVENTS(%rsi)
   8.206 -	XEN_UNLOCK_VCPU_INFO_SMP(%rsi)
   8.207 +	XEN_PUT_VCPU_INFO(%rsi)
   8.208  	SAVE_REST
   8.209          movq %rsp,%rdi                  # set the argument again
   8.210  	jmp  11b
     9.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c	Mon Jun 13 13:18:58 2005 +0000
     9.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c	Fri Jun 17 20:47:52 2005 +0000
     9.3 @@ -727,23 +727,20 @@ void __init setup_arch(char **cmdline_p)
     9.4         acpi_reserve_bootmem();
     9.5  #endif
     9.6  #ifdef CONFIG_BLK_DEV_INITRD
     9.7 -        if (xen_start_info.mod_start) {
     9.8 -                if (LOADER_TYPE && INITRD_START) {
     9.9 -                        if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
    9.10 -                                /* reserve_bootmem_generic(INITRD_START, INITRD_SIZE); */
    9.11 -                                initrd_start = INITRD_START + PAGE_OFFSET;
    9.12 -                                initrd_end = initrd_start+INITRD_SIZE;
    9.13 -                                initrd_below_start_ok = 1;
    9.14 -                        }
    9.15 -                        else {
    9.16 -                                printk(KERN_ERR "initrd extends beyond end of memory "
    9.17 -                                       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
    9.18 -                                       (unsigned long)(INITRD_START + INITRD_SIZE),
    9.19 -                                       (unsigned long)(end_pfn << PAGE_SHIFT));
    9.20 -                                initrd_start = 0;
    9.21 -                        }
    9.22 -                }
    9.23 -        }
    9.24 +	if (xen_start_info.mod_start) {
    9.25 +		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
    9.26 +			/*reserve_bootmem_generic(INITRD_START, INITRD_SIZE);*/
    9.27 +			initrd_start = INITRD_START + PAGE_OFFSET;
    9.28 +			initrd_end = initrd_start+INITRD_SIZE;
    9.29 +			initrd_below_start_ok = 1;
    9.30 +		} else {
    9.31 +			printk(KERN_ERR "initrd extends beyond end of memory "
    9.32 +				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
    9.33 +				(unsigned long)(INITRD_START + INITRD_SIZE),
    9.34 +				(unsigned long)(end_pfn << PAGE_SHIFT));
    9.35 +			initrd_start = 0;
    9.36 +		}
    9.37 +	}
    9.38  #endif
    9.39  	paging_init();
    9.40  #ifdef CONFIG_X86_LOCAL_APIC
    10.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c	Mon Jun 13 13:18:58 2005 +0000
    10.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c	Fri Jun 17 20:47:52 2005 +0000
    10.3 @@ -196,6 +196,36 @@ static int privcmd_ioctl(struct inode *i
    10.4      }
    10.5      break;
    10.6  
    10.7 +    case IOCTL_PRIVCMD_INITDOMAIN_STORE:
    10.8 +    {
    10.9 +        extern int do_xenbus_probe(void*);
   10.10 +
   10.11 +        if (xen_start_info.store_evtchn != 0) {
   10.12 +            ret = -EINVAL;
   10.13 +            break;
   10.14 +        }
   10.15 +
   10.16 +        /* Allocate page. */
   10.17 +        xen_start_info.store_page = get_zeroed_page(GFP_KERNEL);
   10.18 +        if (!xen_start_info.store_page) {
   10.19 +            ret = -ENOMEM;
   10.20 +            break;
   10.21 +        }
   10.22 +
   10.23 +        /* We don't refcnt properly, so set reserved on page.
   10.24 +         * (this allocation is permanent) */
   10.25 +        SetPageReserved(virt_to_page(xen_start_info.store_page));
   10.26 +
   10.27 +        /* Initial connect. Setup channel and page. */
   10.28 +        xen_start_info.store_evtchn = data;
   10.29 +        ret = pfn_to_mfn(virt_to_phys((void *)xen_start_info.store_page) >>
   10.30 +                         PAGE_SHIFT);
   10.31 +
   10.32 +        /* We'll return then this will wait for daemon to answer */
   10.33 +        // kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
   10.34 +    }
   10.35 +    break;
   10.36 +
   10.37      default:
   10.38          ret = -EINVAL;
   10.39          break;
    11.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h	Mon Jun 13 13:18:58 2005 +0000
    11.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h	Fri Jun 17 20:47:52 2005 +0000
    11.3 @@ -8,6 +8,7 @@
    11.4  #include <asm/segment.h>
    11.5  #include <asm/cpufeature.h>
    11.6  #include <asm-xen/hypervisor.h>
    11.7 +#include <asm/smp_alt.h>
    11.8  
    11.9  #ifdef __KERNEL__
   11.10  
   11.11 @@ -251,19 +252,19 @@ static inline unsigned long __cmpxchg(vo
   11.12  	unsigned long prev;
   11.13  	switch (size) {
   11.14  	case 1:
   11.15 -		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
   11.16 +		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
   11.17  				     : "=a"(prev)
   11.18  				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
   11.19  				     : "memory");
   11.20  		return prev;
   11.21  	case 2:
   11.22 -		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
   11.23 +		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
   11.24  				     : "=a"(prev)
   11.25  				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
   11.26  				     : "memory");
   11.27  		return prev;
   11.28  	case 4:
   11.29 -		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
   11.30 +		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
   11.31  				     : "=a"(prev)
   11.32  				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
   11.33  				     : "memory");
   11.34 @@ -427,11 +428,55 @@ struct alt_instr {
   11.35  #endif
   11.36  
   11.37  #ifdef CONFIG_SMP
   11.38 -#define smp_mb()	mb()
   11.39 +#define smp_wmb()	wmb()
   11.40 +#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
   11.41 +#define smp_alt_mb(instr)                                           \
   11.42 +__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
   11.43 +		     ".section __smp_alternatives,\"a\"\n"          \
   11.44 +		     ".long 6667b\n"                                \
   11.45 +                     ".long 6673f\n"                                \
   11.46 +		     ".previous\n"                                  \
   11.47 +		     ".section __smp_replacements,\"a\"\n"          \
   11.48 +		     "6673:.byte 6668b-6667b\n"                     \
   11.49 +		     ".byte 6670f-6669f\n"                          \
   11.50 +		     ".byte 6671f-6670f\n"                          \
   11.51 +                     ".byte 0\n"                                    \
   11.52 +		     ".byte %c0\n"                                  \
   11.53 +		     "6669:lock;addl $0,0(%%esp)\n"                 \
   11.54 +		     "6670:" instr "\n"                             \
   11.55 +		     "6671:\n"                                      \
   11.56 +		     ".previous\n"                                  \
   11.57 +		     :                                              \
   11.58 +		     : "i" (X86_FEATURE_XMM2)                       \
   11.59 +		     : "memory")
   11.60 +#define smp_rmb() smp_alt_mb("lfence")
   11.61 +#define smp_mb()  smp_alt_mb("mfence")
   11.62 +#define set_mb(var, value) do {                                     \
   11.63 +unsigned long __set_mb_temp;                                        \
   11.64 +__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
   11.65 +		     ".section __smp_alternatives,\"a\"\n"          \
   11.66 +		     ".long 6667b\n"                                \
   11.67 +		     ".long 6673f\n"                                \
   11.68 +		     ".previous\n"                                  \
   11.69 +		     ".section __smp_replacements,\"a\"\n"          \
   11.70 +		     "6673: .byte 6668b-6667b\n"                    \
   11.71 +		     ".byte 6670f-6669f\n"                          \
   11.72 +		     ".byte 0\n"                                    \
   11.73 +		     ".byte 6671f-6670f\n"                          \
   11.74 +		     ".byte -1\n"                                   \
   11.75 +		     "6669: xchg %1, %0\n"                          \
   11.76 +		     "6670:movl %1, %0\n"                           \
   11.77 +		     "6671:\n"                                      \
   11.78 +		     ".previous\n"                                  \
   11.79 +		     : "=m" (var), "=r" (__set_mb_temp)             \
   11.80 +		     : "1" (value)                                  \
   11.81 +		     : "memory"); } while (0)
   11.82 +#else
   11.83  #define smp_rmb()	rmb()
   11.84 -#define smp_wmb()	wmb()
   11.85 +#define smp_mb()	mb()
   11.86 +#define set_mb(var, value) do { xchg(&var, value); } while (0)
   11.87 +#endif
   11.88  #define smp_read_barrier_depends()	read_barrier_depends()
   11.89 -#define set_mb(var, value) do { xchg(&var, value); } while (0)
   11.90  #else
   11.91  #define smp_mb()	barrier()
   11.92  #define smp_rmb()	barrier()
    12.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h	Mon Jun 13 13:18:58 2005 +0000
    12.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h	Fri Jun 17 20:47:52 2005 +0000
    12.3 @@ -84,5 +84,7 @@ typedef struct privcmd_blkmsg
    12.4      _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
    12.5  #define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
    12.6      _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
    12.7 +#define IOCTL_PRIVCMD_INITDOMAIN_STORE \
    12.8 +    _IOC(_IOC_READ, 'P', 5, 0)
    12.9  
   12.10  #endif /* __PRIVCMD_H__ */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/patches/linux-2.6.11/smp-alts.patch	Fri Jun 17 20:47:52 2005 +0000
    13.3 @@ -0,0 +1,554 @@
    13.4 +diff -Naur linux-2.6.11/arch/i386/Kconfig linux-2.6.11.post/arch/i386/Kconfig
    13.5 +--- linux-2.6.11/arch/i386/Kconfig	2005-03-02 07:37:49.000000000 +0000
    13.6 ++++ linux-2.6.11.post/arch/i386/Kconfig	2005-06-10 13:42:35.000000000 +0100
    13.7 +@@ -481,6 +481,19 @@
    13.8 + 
    13.9 + 	  If you don't know what to do here, say N.
   13.10 + 
   13.11 ++config SMP_ALTERNATIVES
   13.12 ++	bool "SMP alternatives support (EXPERIMENTAL)"
   13.13 ++	depends on SMP && EXPERIMENTAL
   13.14 ++	help
   13.15 ++	  Try to reduce the overhead of running an SMP kernel on a uniprocessor
   13.16 ++	  host slightly by replacing certain key instruction sequences
   13.17 ++	  according to whether we currently have more than one CPU available.
   13.18 ++	  This should provide a noticeable boost to performance when
   13.19 ++	  running SMP kernels on UP machines, and have negligible impact
   13.20 ++	  when running on an true SMP host.
   13.21 ++
   13.22 ++          If unsure, say N.
   13.23 ++	  
   13.24 + config NR_CPUS
   13.25 + 	int "Maximum number of CPUs (2-255)"
   13.26 + 	range 2 255
   13.27 +diff -Naur linux-2.6.11/arch/i386/kernel/Makefile linux-2.6.11.post/arch/i386/kernel/Makefile
   13.28 +--- linux-2.6.11/arch/i386/kernel/Makefile	2005-03-02 07:37:49.000000000 +0000
   13.29 ++++ linux-2.6.11.post/arch/i386/kernel/Makefile	2005-06-16 11:16:18.555332435 +0100
   13.30 +@@ -32,6 +32,7 @@
   13.31 + obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
   13.32 + obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
   13.33 + obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
   13.34 ++obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
   13.35 + 
   13.36 + EXTRA_AFLAGS   := -traditional
   13.37 + 
   13.38 +diff -Naur linux-2.6.11/arch/i386/kernel/smpalts.c linux-2.6.11.post/arch/i386/kernel/smpalts.c
   13.39 +--- linux-2.6.11/arch/i386/kernel/smpalts.c	1970-01-01 01:00:00.000000000 +0100
   13.40 ++++ linux-2.6.11.post/arch/i386/kernel/smpalts.c	2005-06-16 11:23:39.300902424 +0100
   13.41 +@@ -0,0 +1,76 @@
   13.42 ++#include <linux/kernel.h>
   13.43 ++#include <asm/system.h>
   13.44 ++#include <asm/smp_alt.h>
   13.45 ++#include <asm/processor.h>
   13.46 ++#include <asm/string.h>
   13.47 ++
   13.48 ++struct smp_replacement_record {
   13.49 ++	unsigned char targ_size;
   13.50 ++	unsigned char smp1_size;
   13.51 ++	unsigned char smp2_size;
   13.52 ++	unsigned char up_size;
   13.53 ++	unsigned char feature;
   13.54 ++	unsigned char data[0];
   13.55 ++};
   13.56 ++
   13.57 ++struct smp_alternative_record {
   13.58 ++	void *targ_start;
   13.59 ++	struct smp_replacement_record *repl;
   13.60 ++};
   13.61 ++
   13.62 ++extern struct smp_alternative_record __start_smp_alternatives_table,
   13.63 ++  __stop_smp_alternatives_table;
   13.64 ++
   13.65 ++void prepare_for_smp(void)
   13.66 ++{
   13.67 ++	struct smp_alternative_record *r;
   13.68 ++	printk(KERN_INFO "Enabling SMP...\n");
   13.69 ++	for (r = &__start_smp_alternatives_table;
   13.70 ++	     r != &__stop_smp_alternatives_table;
   13.71 ++	     r++) {
   13.72 ++		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
   13.73 ++		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
   13.74 ++		BUG_ON(r->repl->targ_size < r->repl->up_size);
   13.75 ++		if (r->repl->feature != (unsigned char)-1 &&
   13.76 ++		    boot_cpu_has(r->repl->feature)) {
   13.77 ++			memcpy(r->targ_start,
   13.78 ++			       r->repl->data + r->repl->smp1_size,
   13.79 ++			       r->repl->smp2_size);
   13.80 ++			memset(r->targ_start + r->repl->smp2_size,
   13.81 ++			       0x90,
   13.82 ++			       r->repl->targ_size - r->repl->smp2_size);
   13.83 ++		} else {
   13.84 ++			memcpy(r->targ_start,
   13.85 ++			       r->repl->data,
   13.86 ++			       r->repl->smp1_size);
   13.87 ++			memset(r->targ_start + r->repl->smp1_size,
   13.88 ++			       0x90,
   13.89 ++			       r->repl->targ_size - r->repl->smp1_size);
   13.90 ++		}
   13.91 ++	}
   13.92 ++	/* Paranoia */
   13.93 ++	asm volatile ("jmp 1f\n1:");
   13.94 ++	mb();
   13.95 ++}
   13.96 ++
   13.97 ++void unprepare_for_smp(void)
   13.98 ++{
   13.99 ++	struct smp_alternative_record *r;
  13.100 ++	printk(KERN_INFO "Disabling SMP...\n");
  13.101 ++	for (r = &__start_smp_alternatives_table;
  13.102 ++	     r != &__stop_smp_alternatives_table;
  13.103 ++	     r++) {
  13.104 ++		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
  13.105 ++		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
  13.106 ++		BUG_ON(r->repl->targ_size < r->repl->up_size);
  13.107 ++		memcpy(r->targ_start,
  13.108 ++		       r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
  13.109 ++		       r->repl->up_size);
  13.110 ++		memset(r->targ_start + r->repl->up_size,
  13.111 ++		       0x90,
  13.112 ++		       r->repl->targ_size - r->repl->up_size);
  13.113 ++	}
  13.114 ++	/* Paranoia */
  13.115 ++	asm volatile ("jmp 1f\n1:");
  13.116 ++	mb();
  13.117 ++}
  13.118 +diff -Naur linux-2.6.11/arch/i386/kernel/smpboot.c linux-2.6.11.post/arch/i386/kernel/smpboot.c
  13.119 +--- linux-2.6.11/arch/i386/kernel/smpboot.c	2005-03-02 07:38:09.000000000 +0000
  13.120 ++++ linux-2.6.11.post/arch/i386/kernel/smpboot.c	2005-06-16 11:17:09.287064617 +0100
  13.121 +@@ -1003,6 +1003,11 @@
  13.122 + 		if (max_cpus <= cpucount+1)
  13.123 + 			continue;
  13.124 + 
  13.125 ++#ifdef CONFIG_SMP_ALTERNATIVES
  13.126 ++		if (kicked == 1)
  13.127 ++			prepare_for_smp();
  13.128 ++#endif
  13.129 ++
  13.130 + 		if (do_boot_cpu(apicid))
  13.131 + 			printk("CPU #%d not responding - cannot use it.\n",
  13.132 + 								apicid);
  13.133 +@@ -1118,6 +1123,11 @@
  13.134 + 		return -EIO;
  13.135 + 	}
  13.136 + 
  13.137 ++#ifdef CONFIG_SMP_ALTERNATIVES
  13.138 ++	if (num_online_cpus() == 1)
  13.139 ++		prepare_for_smp();
  13.140 ++#endif
  13.141 ++
  13.142 + 	local_irq_enable();
  13.143 + 	/* Unleash the CPU! */
  13.144 + 	cpu_set(cpu, smp_commenced_mask);
  13.145 +diff -Naur linux-2.6.11/arch/i386/kernel/vmlinux.lds.S linux-2.6.11.post/arch/i386/kernel/vmlinux.lds.S
  13.146 +--- linux-2.6.11/arch/i386/kernel/vmlinux.lds.S	2005-03-02 07:38:37.000000000 +0000
  13.147 ++++ linux-2.6.11.post/arch/i386/kernel/vmlinux.lds.S	2005-06-10 11:14:14.000000000 +0100
  13.148 +@@ -30,6 +30,13 @@
  13.149 +   __ex_table : { *(__ex_table) }
  13.150 +   __stop___ex_table = .;
  13.151 + 
  13.152 ++  . = ALIGN(16);
  13.153 ++  __start_smp_alternatives_table = .;
  13.154 ++  __smp_alternatives : { *(__smp_alternatives) }
  13.155 ++  __stop_smp_alternatives_table = .;
  13.156 ++
  13.157 ++  __smp_replacements : { *(__smp_replacements) }
  13.158 ++
  13.159 +   RODATA
  13.160 + 
  13.161 +   /* writeable */
  13.162 +diff -Naur linux-2.6.11/include/asm-i386/atomic.h linux-2.6.11.post/include/asm-i386/atomic.h
  13.163 +--- linux-2.6.11/include/asm-i386/atomic.h	2005-03-02 07:37:51.000000000 +0000
  13.164 ++++ linux-2.6.11.post/include/asm-i386/atomic.h	2005-06-13 10:10:39.000000000 +0100
  13.165 +@@ -4,18 +4,13 @@
  13.166 + #include <linux/config.h>
  13.167 + #include <linux/compiler.h>
  13.168 + #include <asm/processor.h>
  13.169 ++#include <asm/smp_alt.h>
  13.170 + 
  13.171 + /*
  13.172 +  * Atomic operations that C can't guarantee us.  Useful for
  13.173 +  * resource counting etc..
  13.174 +  */
  13.175 + 
  13.176 +-#ifdef CONFIG_SMP
  13.177 +-#define LOCK "lock ; "
  13.178 +-#else
  13.179 +-#define LOCK ""
  13.180 +-#endif
  13.181 +-
  13.182 + /*
  13.183 +  * Make sure gcc doesn't try to be clever and move things around
  13.184 +  * on us. We need to use _exactly_ the address the user gave us,
  13.185 +diff -Naur linux-2.6.11/include/asm-i386/bitops.h linux-2.6.11.post/include/asm-i386/bitops.h
  13.186 +--- linux-2.6.11/include/asm-i386/bitops.h	2005-03-02 07:38:12.000000000 +0000
  13.187 ++++ linux-2.6.11.post/include/asm-i386/bitops.h	2005-06-13 10:11:54.000000000 +0100
  13.188 +@@ -7,6 +7,7 @@
  13.189 + 
  13.190 + #include <linux/config.h>
  13.191 + #include <linux/compiler.h>
  13.192 ++#include <asm/smp_alt.h>
  13.193 + 
  13.194 + /*
  13.195 +  * These have to be done with inline assembly: that way the bit-setting
  13.196 +@@ -16,12 +17,6 @@
  13.197 +  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  13.198 +  */
  13.199 + 
  13.200 +-#ifdef CONFIG_SMP
  13.201 +-#define LOCK_PREFIX "lock ; "
  13.202 +-#else
  13.203 +-#define LOCK_PREFIX ""
  13.204 +-#endif
  13.205 +-
  13.206 + #define ADDR (*(volatile long *) addr)
  13.207 + 
  13.208 + /**
  13.209 +@@ -41,7 +36,7 @@
  13.210 +  */
  13.211 + static inline void set_bit(int nr, volatile unsigned long * addr)
  13.212 + {
  13.213 +-	__asm__ __volatile__( LOCK_PREFIX
  13.214 ++	__asm__ __volatile__( LOCK
  13.215 + 		"btsl %1,%0"
  13.216 + 		:"=m" (ADDR)
  13.217 + 		:"Ir" (nr));
  13.218 +@@ -76,7 +71,7 @@
  13.219 +  */
  13.220 + static inline void clear_bit(int nr, volatile unsigned long * addr)
  13.221 + {
  13.222 +-	__asm__ __volatile__( LOCK_PREFIX
  13.223 ++	__asm__ __volatile__( LOCK
  13.224 + 		"btrl %1,%0"
  13.225 + 		:"=m" (ADDR)
  13.226 + 		:"Ir" (nr));
  13.227 +@@ -121,7 +116,7 @@
  13.228 +  */
  13.229 + static inline void change_bit(int nr, volatile unsigned long * addr)
  13.230 + {
  13.231 +-	__asm__ __volatile__( LOCK_PREFIX
  13.232 ++	__asm__ __volatile__( LOCK
  13.233 + 		"btcl %1,%0"
  13.234 + 		:"=m" (ADDR)
  13.235 + 		:"Ir" (nr));
  13.236 +@@ -140,7 +135,7 @@
  13.237 + {
  13.238 + 	int oldbit;
  13.239 + 
  13.240 +-	__asm__ __volatile__( LOCK_PREFIX
  13.241 ++	__asm__ __volatile__( LOCK
  13.242 + 		"btsl %2,%1\n\tsbbl %0,%0"
  13.243 + 		:"=r" (oldbit),"=m" (ADDR)
  13.244 + 		:"Ir" (nr) : "memory");
  13.245 +@@ -180,7 +175,7 @@
  13.246 + {
  13.247 + 	int oldbit;
  13.248 + 
  13.249 +-	__asm__ __volatile__( LOCK_PREFIX
  13.250 ++	__asm__ __volatile__( LOCK
  13.251 + 		"btrl %2,%1\n\tsbbl %0,%0"
  13.252 + 		:"=r" (oldbit),"=m" (ADDR)
  13.253 + 		:"Ir" (nr) : "memory");
  13.254 +@@ -231,7 +226,7 @@
  13.255 + {
  13.256 + 	int oldbit;
  13.257 + 
  13.258 +-	__asm__ __volatile__( LOCK_PREFIX
  13.259 ++	__asm__ __volatile__( LOCK
  13.260 + 		"btcl %2,%1\n\tsbbl %0,%0"
  13.261 + 		:"=r" (oldbit),"=m" (ADDR)
  13.262 + 		:"Ir" (nr) : "memory");
  13.263 +diff -Naur linux-2.6.11/include/asm-i386/rwsem.h linux-2.6.11.post/include/asm-i386/rwsem.h
  13.264 +--- linux-2.6.11/include/asm-i386/rwsem.h	2005-03-02 07:38:08.000000000 +0000
  13.265 ++++ linux-2.6.11.post/include/asm-i386/rwsem.h	2005-06-13 10:13:06.000000000 +0100
  13.266 +@@ -40,6 +40,7 @@
  13.267 + 
  13.268 + #include <linux/list.h>
  13.269 + #include <linux/spinlock.h>
  13.270 ++#include <asm/smp_alt.h>
  13.271 + 
  13.272 + struct rwsem_waiter;
  13.273 + 
  13.274 +@@ -99,7 +100,7 @@
  13.275 + {
  13.276 + 	__asm__ __volatile__(
  13.277 + 		"# beginning down_read\n\t"
  13.278 +-LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  13.279 ++LOCK	        "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  13.280 + 		"  js        2f\n\t" /* jump if we weren't granted the lock */
  13.281 + 		"1:\n\t"
  13.282 + 		LOCK_SECTION_START("")
  13.283 +@@ -130,7 +131,7 @@
  13.284 + 		"  movl	     %1,%2\n\t"
  13.285 + 		"  addl      %3,%2\n\t"
  13.286 + 		"  jle	     2f\n\t"
  13.287 +-LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
  13.288 ++LOCK	        "  cmpxchgl  %2,%0\n\t"
  13.289 + 		"  jnz	     1b\n\t"
  13.290 + 		"2:\n\t"
  13.291 + 		"# ending __down_read_trylock\n\t"
  13.292 +@@ -150,7 +151,7 @@
  13.293 + 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
  13.294 + 	__asm__ __volatile__(
  13.295 + 		"# beginning down_write\n\t"
  13.296 +-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  13.297 ++LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  13.298 + 		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
  13.299 + 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
  13.300 + 		"1:\n\t"
  13.301 +@@ -188,7 +189,7 @@
  13.302 + 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
  13.303 + 	__asm__ __volatile__(
  13.304 + 		"# beginning __up_read\n\t"
  13.305 +-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  13.306 ++LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  13.307 + 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  13.308 + 		"1:\n\t"
  13.309 + 		LOCK_SECTION_START("")
  13.310 +@@ -214,7 +215,7 @@
  13.311 + 	__asm__ __volatile__(
  13.312 + 		"# beginning __up_write\n\t"
  13.313 + 		"  movl      %2,%%edx\n\t"
  13.314 +-LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  13.315 ++LOCK	        "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  13.316 + 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
  13.317 + 		"1:\n\t"
  13.318 + 		LOCK_SECTION_START("")
  13.319 +@@ -239,7 +240,7 @@
  13.320 + {
  13.321 + 	__asm__ __volatile__(
  13.322 + 		"# beginning __downgrade_write\n\t"
  13.323 +-LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  13.324 ++LOCK	        "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  13.325 + 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  13.326 + 		"1:\n\t"
  13.327 + 		LOCK_SECTION_START("")
  13.328 +@@ -263,7 +264,7 @@
  13.329 + static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  13.330 + {
  13.331 + 	__asm__ __volatile__(
  13.332 +-LOCK_PREFIX	"addl %1,%0"
  13.333 ++LOCK	          "addl %1,%0"
  13.334 + 		: "=m"(sem->count)
  13.335 + 		: "ir"(delta), "m"(sem->count));
  13.336 + }
  13.337 +@@ -276,7 +277,7 @@
  13.338 + 	int tmp = delta;
  13.339 + 
  13.340 + 	__asm__ __volatile__(
  13.341 +-LOCK_PREFIX	"xadd %0,(%2)"
  13.342 ++LOCK  	          "xadd %0,(%2)"
  13.343 + 		: "+r"(tmp), "=m"(sem->count)
  13.344 + 		: "r"(sem), "m"(sem->count)
  13.345 + 		: "memory");
  13.346 +diff -Naur linux-2.6.11/include/asm-i386/smp_alt.h linux-2.6.11.post/include/asm-i386/smp_alt.h
  13.347 +--- linux-2.6.11/include/asm-i386/smp_alt.h	1970-01-01 01:00:00.000000000 +0100
  13.348 ++++ linux-2.6.11.post/include/asm-i386/smp_alt.h	2005-06-16 11:16:50.109433206 +0100
  13.349 +@@ -0,0 +1,32 @@
  13.350 ++#ifndef __ASM_SMP_ALT_H__
  13.351 ++#define __ASM_SMP_ALT_H__
  13.352 ++
  13.353 ++#include <linux/config.h>
  13.354 ++
  13.355 ++#ifdef CONFIG_SMP
  13.356 ++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  13.357 ++#define LOCK \
  13.358 ++        "6677: nop\n" \
  13.359 ++	".section __smp_alternatives,\"a\"\n" \
  13.360 ++	".long 6677b\n" \
  13.361 ++	".long 6678f\n" \
  13.362 ++	".previous\n" \
  13.363 ++	".section __smp_replacements,\"a\"\n" \
  13.364 ++	"6678: .byte 1\n" \
  13.365 ++	".byte 1\n" \
  13.366 ++	".byte 0\n" \
  13.367 ++        ".byte 1\n" \
  13.368 ++	".byte -1\n" \
  13.369 ++	"lock\n" \
  13.370 ++	"nop\n" \
  13.371 ++	".previous\n"
  13.372 ++void prepare_for_smp(void);
  13.373 ++void unprepare_for_smp(void);
  13.374 ++#else
  13.375 ++#define LOCK "lock ; "
  13.376 ++#endif
  13.377 ++#else
  13.378 ++#define LOCK ""
  13.379 ++#endif
  13.380 ++
  13.381 ++#endif /* __ASM_SMP_ALT_H__ */
  13.382 +diff -Naur linux-2.6.11/include/asm-i386/spinlock.h linux-2.6.11.post/include/asm-i386/spinlock.h
  13.383 +--- linux-2.6.11/include/asm-i386/spinlock.h	2005-03-02 07:37:50.000000000 +0000
  13.384 ++++ linux-2.6.11.post/include/asm-i386/spinlock.h	2005-06-13 14:13:52.000000000 +0100
  13.385 +@@ -6,6 +6,7 @@
  13.386 + #include <asm/page.h>
  13.387 + #include <linux/config.h>
  13.388 + #include <linux/compiler.h>
  13.389 ++#include <asm/smp_alt.h>
  13.390 + 
  13.391 + asmlinkage int printk(const char * fmt, ...)
  13.392 + 	__attribute__ ((format (printf, 1, 2)));
  13.393 +@@ -47,8 +48,9 @@
  13.394 + #define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
  13.395 + 
  13.396 + #define spin_lock_string \
  13.397 +-	"\n1:\t" \
  13.398 +-	"lock ; decb %0\n\t" \
  13.399 ++        "1:\n" \
  13.400 ++	LOCK \
  13.401 ++	"decb %0\n\t" \
  13.402 + 	"jns 3f\n" \
  13.403 + 	"2:\t" \
  13.404 + 	"rep;nop\n\t" \
  13.405 +@@ -58,8 +60,9 @@
  13.406 + 	"3:\n\t"
  13.407 + 
  13.408 + #define spin_lock_string_flags \
  13.409 +-	"\n1:\t" \
  13.410 +-	"lock ; decb %0\n\t" \
  13.411 ++        "1:\n" \
  13.412 ++	LOCK \
  13.413 ++	"decb %0\n\t" \
  13.414 + 	"jns 4f\n\t" \
  13.415 + 	"2:\t" \
  13.416 + 	"testl $0x200, %1\n\t" \
  13.417 +@@ -121,10 +124,34 @@
  13.418 + static inline int _raw_spin_trylock(spinlock_t *lock)
  13.419 + {
  13.420 + 	char oldval;
  13.421 ++#ifdef CONFIG_SMP_ALTERNATIVES
  13.422 + 	__asm__ __volatile__(
  13.423 +-		"xchgb %b0,%1"
  13.424 ++		"1:movb %1,%b0\n"
  13.425 ++		"movb $0,%1\n"
  13.426 ++		"2:"
  13.427 ++		".section __smp_alternatives,\"a\"\n"
  13.428 ++		".long 1b\n"
  13.429 ++		".long 3f\n"
  13.430 ++		".previous\n"
  13.431 ++		".section __smp_replacements,\"a\"\n"
  13.432 ++		"3: .byte 2b - 1b\n"
  13.433 ++		".byte 5f-4f\n"
  13.434 ++		".byte 0\n"
  13.435 ++		".byte 6f-5f\n"
  13.436 ++		".byte -1\n"
  13.437 ++		"4: xchgb %b0,%1\n"
  13.438 ++		"5: movb %1,%b0\n"
  13.439 ++		"movb $0,%1\n"
  13.440 ++		"6:\n"
  13.441 ++		".previous\n"
  13.442 + 		:"=q" (oldval), "=m" (lock->slock)
  13.443 + 		:"0" (0) : "memory");
  13.444 ++#else
  13.445 ++	__asm__ __volatile__(
  13.446 ++		"xchgb %b0,%1\n"
  13.447 ++		:"=q" (oldval), "=m" (lock->slock)
  13.448 ++		:"0" (0) : "memory");
  13.449 ++#endif
  13.450 + 	return oldval > 0;
  13.451 + }
  13.452 + 
  13.453 +@@ -225,8 +252,8 @@
  13.454 + 	__build_write_lock(rw, "__write_lock_failed");
  13.455 + }
  13.456 + 
  13.457 +-#define _raw_read_unlock(rw)		asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
  13.458 +-#define _raw_write_unlock(rw)	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
  13.459 ++#define _raw_read_unlock(rw)	asm volatile(LOCK "incl %0" :"=m" ((rw)->lock) : : "memory")
  13.460 ++#define _raw_write_unlock(rw)	asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
  13.461 + 
  13.462 + static inline int _raw_read_trylock(rwlock_t *lock)
  13.463 + {
  13.464 +diff -Naur linux-2.6.11/include/asm-i386/system.h linux-2.6.11.post/include/asm-i386/system.h
  13.465 +--- linux-2.6.11/include/asm-i386/system.h	2005-03-02 07:37:30.000000000 +0000
  13.466 ++++ linux-2.6.11.post/include/asm-i386/system.h	2005-06-15 13:21:40.000000000 +0100
  13.467 +@@ -5,7 +5,7 @@
  13.468 + #include <linux/kernel.h>
  13.469 + #include <asm/segment.h>
  13.470 + #include <asm/cpufeature.h>
  13.471 +-#include <linux/bitops.h> /* for LOCK_PREFIX */
  13.472 ++#include <asm/smp_alt.h>
  13.473 + 
  13.474 + #ifdef __KERNEL__
  13.475 + 
  13.476 +@@ -249,19 +249,19 @@
  13.477 + 	unsigned long prev;
  13.478 + 	switch (size) {
  13.479 + 	case 1:
  13.480 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
  13.481 ++		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
  13.482 + 				     : "=a"(prev)
  13.483 + 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  13.484 + 				     : "memory");
  13.485 + 		return prev;
  13.486 + 	case 2:
  13.487 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
  13.488 ++		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
  13.489 + 				     : "=a"(prev)
  13.490 + 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  13.491 + 				     : "memory");
  13.492 + 		return prev;
  13.493 + 	case 4:
  13.494 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
  13.495 ++		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
  13.496 + 				     : "=a"(prev)
  13.497 + 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  13.498 + 				     : "memory");
  13.499 +@@ -425,11 +425,55 @@
  13.500 + #endif
  13.501 + 
  13.502 + #ifdef CONFIG_SMP
  13.503 +-#define smp_mb()	mb()
  13.504 +-#define smp_rmb()	rmb()
  13.505 + #define smp_wmb()	wmb()
  13.506 +-#define smp_read_barrier_depends()	read_barrier_depends()
  13.507 ++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  13.508 ++#define smp_alt_mb(instr)                                           \
  13.509 ++__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
  13.510 ++		     ".section __smp_alternatives,\"a\"\n"          \
  13.511 ++		     ".long 6667b\n"                                \
  13.512 ++                     ".long 6673f\n"                                \
  13.513 ++		     ".previous\n"                                  \
  13.514 ++		     ".section __smp_replacements,\"a\"\n"          \
  13.515 ++		     "6673:.byte 6668b-6667b\n"                     \
  13.516 ++		     ".byte 6670f-6669f\n"                          \
  13.517 ++		     ".byte 6671f-6670f\n"                          \
  13.518 ++                     ".byte 0\n"                                    \
  13.519 ++		     ".byte %c0\n"                                  \
  13.520 ++		     "6669:lock;addl $0,0(%%esp)\n"                 \
  13.521 ++		     "6670:" instr "\n"                             \
  13.522 ++		     "6671:\n"                                      \
  13.523 ++		     ".previous\n"                                  \
  13.524 ++		     :                                              \
  13.525 ++		     : "i" (X86_FEATURE_XMM2)                       \
  13.526 ++		     : "memory")
  13.527 ++#define smp_rmb() smp_alt_mb("lfence")
  13.528 ++#define smp_mb()  smp_alt_mb("mfence")
  13.529 ++#define set_mb(var, value) do {                                     \
  13.530 ++unsigned long __set_mb_temp;                                        \
  13.531 ++__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
  13.532 ++		     ".section __smp_alternatives,\"a\"\n"          \
  13.533 ++		     ".long 6667b\n"                                \
  13.534 ++		     ".long 6673f\n"                                \
  13.535 ++		     ".previous\n"                                  \
  13.536 ++		     ".section __smp_replacements,\"a\"\n"          \
  13.537 ++		     "6673: .byte 6668b-6667b\n"                    \
  13.538 ++		     ".byte 6670f-6669f\n"                          \
  13.539 ++		     ".byte 0\n"                                    \
  13.540 ++		     ".byte 6671f-6670f\n"                          \
  13.541 ++		     ".byte -1\n"                                   \
  13.542 ++		     "6669: xchg %1, %0\n"                          \
  13.543 ++		     "6670:movl %1, %0\n"                           \
  13.544 ++		     "6671:\n"                                      \
  13.545 ++		     ".previous\n"                                  \
  13.546 ++		     : "=m" (var), "=r" (__set_mb_temp)             \
  13.547 ++		     : "1" (value)                                  \
  13.548 ++		     : "memory"); } while (0)
  13.549 ++#else
  13.550 ++#define smp_rmb()	rmb()
  13.551 ++#define smp_mb()	mb()
  13.552 + #define set_mb(var, value) do { xchg(&var, value); } while (0)
  13.553 ++#endif
  13.554 ++#define smp_read_barrier_depends()	read_barrier_depends()
  13.555 + #else
  13.556 + #define smp_mb()	barrier()
  13.557 + #define smp_rmb()	barrier()
    14.1 --- a/tools/Makefile	Mon Jun 13 13:18:58 2005 +0000
    14.2 +++ b/tools/Makefile	Fri Jun 17 20:47:52 2005 +0000
    14.3 @@ -10,7 +10,6 @@ SUBDIRS += xentrace
    14.4  SUBDIRS += python
    14.5  SUBDIRS += xcs
    14.6  SUBDIRS += xcutils
    14.7 -SUBDIRS += xenstore
    14.8  SUBDIRS += pygrub
    14.9  SUBDIRS += firmware
   14.10  
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/debugger/pdb/readme	Fri Jun 17 20:47:52 2005 +0000
    15.3 @@ -0,0 +1,84 @@
    15.4 +
    15.5 +PDB 0.3 
    15.6 +http://www.cl.cam.ac.uk/netos/pdb
    15.7 +
    15.8 +Alex Ho  
    15.9 +June 2005
   15.10 +
   15.11 +
   15.12 +This is the latest incarnation of the pervasive debugger.
   15.13 +PDB is a remote stub for GDB.  Running as a user-space
   15.14 +application in domain 0, it can debug any other domain.
   15.15 +
   15.16 +
   15.17 ++------+    tcp/ip    +-------+  
   15.18 +| GDB  |--------------|  PDB  |
   15.19 ++------+              +-------+   +-------+
   15.20 +                      | Dom 0 |   | Dom U |
   15.21 +                      +-------+---+-------+
   15.22 +                      |  Xen              |
   15.23 +                      +-------------------+
   15.24 +
   15.25 +Installation
   15.26 +
   15.27 +- Install OCaml 3.08 in domain 0.
   15.28 +  http://caml.inria.fr/download.en.html  is a good place to start.
   15.29 +
   15.30 +- Build Xen with debugger support
   15.31 +  make domu_debug=y xen
   15.32 +
   15.33 +- (optional)
   15.34 +  Build the target domains with debugging symbols.
   15.35 +  make CONFIG_DEBUG_INFO=true CONFIG_FRAME_POINTER=false linux-2.6-xenU-build
   15.36 +
   15.37 +  You can also change linux-2.6.11-xenU/Makefile
   15.38 +  CONFIG_CC_OPTIMIZE_FOR_SIZE from -O2 to -O
   15.39 +
   15.40 +- Build PDB
   15.41 +  (cd tools/debugger/libxendebug; make install)
   15.42 +  (cd tools/debugger/pdb; make)
   15.43 +
   15.44 +Usage
   15.45 +
   15.46 +- PDB does not currently support SMP.  Please boot xen with "maxcpus=1"
   15.47 +
   15.48 +- Run PDB
   15.49 +  domain-0.xeno# ./pdb <port>
   15.50 +
   15.51 +- Run GDB
   15.52 +  hostname% gdb <xeno.bk>/dist/install/boot/vmlinux-syms-2.6.11.11-xenU
   15.53 +
   15.54 +  (gdb) target remote domain-0.xeno:<port>
   15.55 +
   15.56 +  At this point, you'll get an error message such as:
   15.57 +  Remote debugging using domain-0.xeno:5000
   15.58 +  0x00000000 in ?? ()
   15.59 +  warning: shared library handler failed to enable breakpoint
   15.60 +  Although GDB is connected to PDB, PDB doesn't know which domain
   15.61 +  you'd like to debug, so it's just feeding GDB a bunch of zeros.
   15.62 +
   15.63 +  (gdb) maint packet x context = domain <domid> <vcpu>
   15.64 +
   15.65 +  This tells PDB that we'd like to debug a particular domain & vcpu.
   15.66 +  However, since we're sending the command directly to PDB, GDB doesn't 
   15.67 +  know that we now have a proper target.  We can force GDB to invalidate
   15.68 +  its register cache.  This is optional; the next time the program
   15.69 +  stops GDB will query for the registers automatically.
   15.70 +
   15.71 +  (gdb) flushreg
   15.72 +
   15.73 +  
   15.74 +  the following gdb commands should work :)
   15.75 +
   15.76 +  break
   15.77 +  step,   stepi
   15.78 +  next,   nexti
   15.79 +  continue
   15.80 +  print
   15.81 +
   15.82 +
   15.83 +To Do
   15.84 +
   15.85 +- watchpoints
   15.86 +- support for SMP
   15.87 +- support for user applications
    16.1 --- a/tools/firmware/vmxassist/Makefile	Mon Jun 13 13:18:58 2005 +0000
    16.2 +++ b/tools/firmware/vmxassist/Makefile	Fri Jun 17 20:47:52 2005 +0000
    16.3 @@ -18,6 +18,9 @@
    16.4  # Place - Suite 330, Boston, MA 02111-1307 USA.
    16.5  #
    16.6  
    16.7 +XEN_ROOT = ../../..
    16.8 +include $(XEN_ROOT)/tools/Rules.mk
    16.9 +
   16.10  # The emulator code lives in ROM space
   16.11  TEXTADDR=0x000D0000
   16.12  DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
   16.13 @@ -32,19 +35,24 @@ CPP=cpp -P
   16.14  OBJCOPY=objcopy -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0
   16.15  CFLAGS=${DEFINES} -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
   16.16  
   16.17 +ifeq ($(XEN_COMPILE_ARCH),x86_64)
   16.18 +CFLAGS  += -m32 -march=i686
   16.19 +LDFLAGS += -m elf_i386
   16.20 +endif
   16.21 +
   16.22  OBJECTS = head.o trap.o vm86.o setup.o util.o
   16.23  
   16.24  all: vmxloader
   16.25  
   16.26  vmxloader: roms.h vmxloader.c
   16.27 -	${CC} ${DEFINES} -c vmxloader.c
   16.28 -	$(CC) -o vmxloader.tmp -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o
   16.29 +	${CC} ${CFLAGS} ${DEFINES} -c vmxloader.c
   16.30 +	$(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o
   16.31  	objcopy --change-addresses=0xC0000000 vmxloader.tmp vmxloader
   16.32  	rm -f vmxloader.tmp
   16.33  
   16.34  vmxassist.bin: vmxassist.ld ${OBJECTS}
   16.35  	${CPP} ${DEFINES} vmxassist.ld > vmxassist.tmp
   16.36 -	${LD} -o vmxassist -nostdlib --fatal-warnings -N -T vmxassist.tmp ${OBJECTS}
   16.37 +	${LD} -o vmxassist ${LDFLAGS} -nostdlib --fatal-warnings -N -T vmxassist.tmp ${OBJECTS}
   16.38  	nm -n vmxassist > vmxassist.sym
   16.39  	${OBJCOPY} vmxassist vmxassist.tmp
   16.40  	dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync
    17.1 --- a/tools/firmware/vmxassist/head.S	Mon Jun 13 13:18:58 2005 +0000
    17.2 +++ b/tools/firmware/vmxassist/head.S	Fri Jun 17 20:47:52 2005 +0000
    17.3 @@ -106,6 +106,7 @@ 1:
    17.4   * main and setup our own environment.
    17.5   */
    17.6  	.globl	_start
    17.7 +	.code32
    17.8  _start:
    17.9  	cli
   17.10  
    18.1 --- a/tools/firmware/vmxassist/trap.S	Mon Jun 13 13:18:58 2005 +0000
    18.2 +++ b/tools/firmware/vmxassist/trap.S	Fri Jun 17 20:47:52 2005 +0000
    18.3 @@ -20,7 +20,6 @@
    18.4  #include "machine.h"
    18.5  #include "offsets.h"
    18.6  
    18.7 -
    18.8  /*
    18.9   * All processor exception/faults/interrupts end up here.
   18.10   *
   18.11 @@ -43,6 +42,7 @@ 1:	.if	\error == 0
   18.12  	.endm
   18.13  
   18.14  	.section .rodata
   18.15 +	.code32
   18.16  	.align	4
   18.17  	.global	trap_handlers
   18.18  trap_handlers:
   18.19 @@ -96,6 +96,7 @@ trap_handlers:
   18.20  	TRAP_HANDLER	47, 0	/* irq 15 */
   18.21  
   18.22  	.text
   18.23 +	.code32
   18.24  	.align	16
   18.25  common_trap:				/* common trap handler */
   18.26  	pushl	%gs
    19.1 --- a/tools/libxc/Makefile	Mon Jun 13 13:18:58 2005 +0000
    19.2 +++ b/tools/libxc/Makefile	Fri Jun 17 20:47:52 2005 +0000
    19.3 @@ -44,7 +44,8 @@ DEPS     = .*.d
    19.4  LIB_OBJS := $(patsubst %.c,%.o,$(SRCS))
    19.5  PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS))
    19.6  
    19.7 -LIB      := libxc.a libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
    19.8 +LIB      := libxc.a libxc-pic.a
    19.9 +LIB      += libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
   19.10  
   19.11  all: build
   19.12  build: check-for-zlib mk-symlinks
   19.13 @@ -98,6 +99,9 @@ rpm: build
   19.14  libxc.a: $(LIB_OBJS)
   19.15  	$(AR) rc $@ $^
   19.16  
   19.17 +libxc-pic.a: $(PIC_OBJS)
   19.18 +	$(AR) rc $@ $^
   19.19 +
   19.20  libxc.so: libxc.so.$(MAJOR)
   19.21  	ln -sf $< $@
   19.22  libxc.so.$(MAJOR): libxc.so.$(MAJOR).$(MINOR)
    20.1 --- a/tools/python/setup.py	Mon Jun 13 13:18:58 2005 +0000
    20.2 +++ b/tools/python/setup.py	Fri Jun 17 20:47:52 2005 +0000
    20.3 @@ -17,7 +17,7 @@ library_dirs = [ XEN_ROOT + "/tools/libx
    20.4                   XEN_ROOT + "/tools/xenstore",
    20.5                   ]
    20.6  
    20.7 -libraries = [ "xc", "xenstore" ]
    20.8 +libraries = [ "xc", "xenstore-pic" ]
    20.9  
   20.10  xc = Extension("xc",
   20.11                 extra_compile_args = extra_compile_args,
    21.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Mon Jun 13 13:18:58 2005 +0000
    21.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Fri Jun 17 20:47:52 2005 +0000
    21.3 @@ -1,3 +1,8 @@
    21.4 +/* 
    21.5 +    Python interface to the Xen Store Daemon.
    21.6 +    Copyright (C) 2005 Mike Wray Hewlett-Packard
    21.7 +*/
    21.8 +
    21.9  #include <Python.h>
   21.10  
   21.11  #include <stdio.h>
   21.12 @@ -14,9 +19,9 @@
   21.13   */
   21.14  
   21.15  /* Needed for Python versions earlier than 2.3. */
   21.16 -//#ifndef PyMODINIT_FUNC
   21.17 -//#define PyMODINIT_FUNC DL_EXPORT(void)
   21.18 -//#endif
   21.19 +#ifndef PyMODINIT_FUNC
   21.20 +#define PyMODINIT_FUNC DL_EXPORT(void)
   21.21 +#endif
   21.22  
   21.23  #define PYPKG    "xen.lowlevel.xs"
   21.24  
   21.25 @@ -47,6 +52,53 @@ static inline PyObject *pyvalue_str(char
   21.26              : PyErr_SetFromErrno(PyExc_RuntimeError));
   21.27  }
   21.28  
   21.29 +#define xspy_read_doc "\n"			\
   21.30 +	"Read data from a path.\n"		\
   21.31 +	" path [string]: xenstore path\n"	\
   21.32 +	"\n"					\
   21.33 +	"Returns: [string] data read.\n"	\
   21.34 +	"Raises RuntimeError on error.\n"	\
   21.35 +	"\n"
   21.36 +
   21.37 +static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
   21.38 +{
   21.39 +    static char *kwd_spec[] = { "path", NULL };
   21.40 +    static char *arg_spec = "s|";
   21.41 +    char *path = NULL;
   21.42 +
   21.43 +    struct xs_handle *xh = xshandle(self);
   21.44 +    char *xsval = NULL;
   21.45 +    unsigned int xsval_n = 0;
   21.46 +    PyObject *val = NULL;
   21.47 +
   21.48 +    if (!xh)
   21.49 +	goto exit;
   21.50 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   21.51 +                                     &path))
   21.52 +        goto exit;
   21.53 +    xsval = xs_read(xh, path, &xsval_n);
   21.54 +    if (!xsval) {
   21.55 +        val = pyvalue_int(0);
   21.56 +        goto exit;
   21.57 +    }
   21.58 +    val = PyString_FromStringAndSize(xsval, xsval_n);
   21.59 + exit:
   21.60 +    if (xsval)
   21.61 +	free(xsval);
   21.62 +    return val;
   21.63 +}
   21.64 +
   21.65 +#define xspy_write_doc "\n"					\
   21.66 +	"Write data to a path.\n"				\
   21.67 +	" path   [string] : xenstore path to write to\n."	\
   21.68 +	" data   [string] : data to write.\n"			\
   21.69 +	" create [int]    : create flag, default 0.\n"		\
   21.70 +	" excl   [int]    : exclusive flag, default 0.\n"	\
   21.71 +	"\n"							\
   21.72 +	"Returns: [int] 0 on success.\n"			\
   21.73 +	"Raises RuntimeError on error.\n"			\
   21.74 +	"\n"
   21.75 +
   21.76  static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
   21.77  {
   21.78      static char *kwd_spec[] = { "path", "data", "create", "excl", NULL };
   21.79 @@ -77,53 +129,13 @@ static PyObject *xspy_write(PyObject *se
   21.80      return val;
   21.81  }
   21.82  
   21.83 -static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
   21.84 -{
   21.85 -    static char *kwd_spec[] = { "path", NULL };
   21.86 -    static char *arg_spec = "s|";
   21.87 -    char *path = NULL;
   21.88 -
   21.89 -    struct xs_handle *xh = xshandle(self);
   21.90 -    char *xsval = NULL;
   21.91 -    unsigned int xsval_n = 0;
   21.92 -    PyObject *val = NULL;
   21.93 -
   21.94 -    if (!xh)
   21.95 -	goto exit;
   21.96 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   21.97 -                                     &path))
   21.98 -        goto exit;
   21.99 -    xsval = xs_read(xh, path, &xsval_n);
  21.100 -    if (!xsval) {
  21.101 -        val = pyvalue_int(0);
  21.102 -        goto exit;
  21.103 -    }
  21.104 -    val = PyString_FromStringAndSize(xsval, xsval_n);
  21.105 - exit:
  21.106 -    if (xsval)
  21.107 -	free(xsval);
  21.108 -    return val;
  21.109 -}
  21.110 -
  21.111 -static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
  21.112 -{
  21.113 -    static char *kwd_spec[] = { "path", NULL };
  21.114 -    static char *arg_spec = "s|";
  21.115 -    char *path = NULL;
  21.116 -
  21.117 -    struct xs_handle *xh = xshandle(self);
  21.118 -    PyObject *val = NULL;
  21.119 -    int xsval = 0;
  21.120 -
  21.121 -    if (!xh)
  21.122 -	goto exit;
  21.123 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.124 -        goto exit;
  21.125 -    xsval = xs_mkdir(xh, path);
  21.126 -    val = pyvalue_int(xsval);
  21.127 - exit:
  21.128 -    return val;
  21.129 -}
  21.130 +#define xspy_ls_doc "\n"					\
  21.131 +	"List a directory.\n"					\
  21.132 +	" path [string]: path to list.\n"			\
  21.133 +	"\n"							\
  21.134 +	"Returns: [string array] list of subdirectory names.\n"	\
  21.135 +	"Raises RuntimeError on error.\n"			\
  21.136 +	"\n"
  21.137  
  21.138  static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
  21.139  {
  21.140 @@ -153,6 +165,41 @@ static PyObject *xspy_ls(PyObject *self,
  21.141      return val;
  21.142  }
  21.143  
  21.144 +#define xspy_mkdir_doc "\n"					\
  21.145 +	"Make a directory.\n"					\
  21.146 +	" path [string]: path to directory to create.\n"	\
  21.147 +	"\n"							\
  21.148 +	"Returns: [int] 0 on success.\n"			\
  21.149 +	"Raises RuntimeError on error.\n"			\
  21.150 +	"\n"
  21.151 +
  21.152 +static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
  21.153 +{
  21.154 +    static char *kwd_spec[] = { "path", NULL };
  21.155 +    static char *arg_spec = "s|";
  21.156 +    char *path = NULL;
  21.157 +
  21.158 +    struct xs_handle *xh = xshandle(self);
  21.159 +    PyObject *val = NULL;
  21.160 +    int xsval = 0;
  21.161 +
  21.162 +    if (!xh)
  21.163 +	goto exit;
  21.164 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.165 +        goto exit;
  21.166 +    xsval = xs_mkdir(xh, path);
  21.167 +    val = pyvalue_int(xsval);
  21.168 + exit:
  21.169 +    return val;
  21.170 +}
  21.171 +
  21.172 +#define xspy_rm_doc "\n"			\
  21.173 +	"Remove a path.\n"			\
  21.174 +	" path [string] : path to remove\n"	\
  21.175 +	"Returns: [int] 0 on success.\n"	\
  21.176 +	"Raises RuntimeError on error.\n"	\
  21.177 +	"\n"
  21.178 +
  21.179  static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
  21.180  {
  21.181      static char *kwd_spec[] = { "path", NULL };
  21.182 @@ -173,6 +220,14 @@ static PyObject *xspy_rm(PyObject *self,
  21.183      return val;
  21.184  }
  21.185  
  21.186 +#define xspy_get_permissions_doc "\n"		\
  21.187 +	"Get the permissions for a path\n"	\
  21.188 +	" path [string]: xenstore path.\n"	\
  21.189 +	"\n"					\
  21.190 +	"Returns: permissions array.\n"		\
  21.191 +	"Raises RuntimeError on error.\n"	\
  21.192 +	"\n"
  21.193 +
  21.194  static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
  21.195  				      PyObject *kwds)
  21.196  {
  21.197 @@ -209,6 +264,15 @@ static PyObject *xspy_get_permissions(Py
  21.198      return val;
  21.199  }
  21.200  
  21.201 +#define xspy_set_permissions_doc "\n"		\
  21.202 +	"Set the permissions for a path\n"	\
  21.203 +	" path  [string] : xenstore path.\n"	\
  21.204 +	" perms          : permissions.\n"	\
  21.205 +	"\n"					\
  21.206 +	"Returns: [int] 0 on success.\n"	\
  21.207 +	"Raises RuntimeError on error.\n"	\
  21.208 +	"\n"
  21.209 +
  21.210  static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
  21.211  				      PyObject *kwds)
  21.212  {
  21.213 @@ -275,12 +339,22 @@ static PyObject *xspy_set_permissions(Py
  21.214      return val;
  21.215  }
  21.216  
  21.217 +#define xspy_watch_doc "\n"					\
  21.218 +	"Watch a path, get notifications when it changes.\n"	\
  21.219 +	" path  [string] : xenstore path.\n"			\
  21.220 +	" token [string] : returned in watch notification\n"	\
  21.221 +	"\n"							\
  21.222 +	"Returns: [int] 0 on success.\n"			\
  21.223 +	"Raises RuntimeError on error.\n"			\
  21.224 +	"\n"
  21.225 +
  21.226  static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
  21.227  {
  21.228 -    static char *kwd_spec[] = { "path", "priority", NULL };
  21.229 -    static char *arg_spec = "s|i";
  21.230 +    static char *kwd_spec[] = { "path", "priority", "token", NULL };
  21.231 +    static char *arg_spec = "s|is";
  21.232      char *path = NULL;
  21.233      int priority = 0;
  21.234 +    char *token = "";
  21.235  
  21.236      struct xs_handle *xh = xshandle(self);
  21.237      PyObject *val = NULL;
  21.238 @@ -289,14 +363,22 @@ static PyObject *xspy_watch(PyObject *se
  21.239      if (!xh)
  21.240  	goto exit;
  21.241      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, 
  21.242 -                                     &path, &priority))
  21.243 +                                     &path, &priority, &token))
  21.244          goto exit;
  21.245 -    xsval = xs_watch(xh, path, priority);
  21.246 +    xsval = xs_watch(xh, path, token, priority);
  21.247      val = pyvalue_int(xsval);
  21.248   exit:
  21.249      return val;
  21.250  }
  21.251  
  21.252 +#define xspy_read_watch_doc "\n"		\
  21.253 +	"Read a watch notification.\n"		\
  21.254 +	" path [string]: xenstore path.\n"	\
  21.255 +	"\n"					\
  21.256 +	"Returns: [tuple] (path, token).\n"	\
  21.257 +	"Raises RuntimeError on error.\n"	\
  21.258 +	"\n"
  21.259 +
  21.260  static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
  21.261  				 PyObject *kwds)
  21.262  {
  21.263 @@ -305,25 +387,39 @@ static PyObject *xspy_read_watch(PyObjec
  21.264  
  21.265      struct xs_handle *xh = xshandle(self);
  21.266      PyObject *val = NULL;
  21.267 -    char *xsval = NULL;
  21.268 +    char **xsval = NULL;
  21.269  
  21.270      if (!xh)
  21.271  	goto exit;
  21.272      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
  21.273          goto exit;
  21.274      xsval = xs_read_watch(xh);
  21.275 -    val = pyvalue_str(xsval);
  21.276 +    if (!xsval) {
  21.277 +            val = PyErr_SetFromErrno(PyExc_RuntimeError);
  21.278 +            goto exit;
  21.279 +    }
  21.280 +    /* Create tuple (path, token). */
  21.281 +    val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
  21.282   exit:
  21.283      if (xsval)
  21.284  	free(xsval);
  21.285      return val;
  21.286  }
  21.287  
  21.288 +#define xspy_acknowledge_watch_doc "\n"					\
  21.289 +	"Acknowledge a watch notification that has been read.\n"	\
  21.290 +	" token [string] : returned in watch notification\n"		\
  21.291 +	"\n"								\
  21.292 +	"Returns: [int] 0 on success.\n"				\
  21.293 +	"Raises RuntimeError on error.\n"				\
  21.294 +	"\n"
  21.295 +
  21.296  static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
  21.297  					PyObject *kwds)
  21.298  {
  21.299 -    static char *kwd_spec[] = { NULL };
  21.300 -    static char *arg_spec = "";
  21.301 +    static char *kwd_spec[] = { "token", NULL };
  21.302 +    static char *arg_spec = "s";
  21.303 +    char *token;
  21.304  
  21.305      struct xs_handle *xh = xshandle(self);
  21.306      PyObject *val = NULL;
  21.307 @@ -331,19 +427,29 @@ static PyObject *xspy_acknowledge_watch(
  21.308  
  21.309      if (!xh)
  21.310  	goto exit;
  21.311 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
  21.312 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
  21.313          goto exit;
  21.314 -    xsval = xs_acknowledge_watch(xh);
  21.315 +    xsval = xs_acknowledge_watch(xh, token);
  21.316      val = pyvalue_int(xsval);
  21.317   exit:
  21.318      return val;
  21.319  }
  21.320  
  21.321 +#define xspy_unwatch_doc "\n"				\
  21.322 +	"Stop watching a path.\n"			\
  21.323 +	" path  [string] : xenstore path.\n"		\
  21.324 +	" token [string] : token from the watch.\n"	\
  21.325 +	"\n"						\
  21.326 +	"Returns: [int] 0 on success.\n"		\
  21.327 +	"Raises RuntimeError on error.\n"		\
  21.328 +	"\n"
  21.329 +
  21.330  static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
  21.331  {
  21.332 -    static char *kwd_spec[] = { "path", NULL };
  21.333 -    static char *arg_spec = "s|";
  21.334 +    static char *kwd_spec[] = { "path", "token", NULL };
  21.335 +    static char *arg_spec = "s|s";
  21.336      char *path = NULL;
  21.337 +    char *token = "";
  21.338  
  21.339      struct xs_handle *xh = xshandle(self);
  21.340      PyObject *val = NULL;
  21.341 @@ -351,14 +457,24 @@ static PyObject *xspy_unwatch(PyObject *
  21.342  
  21.343      if (!xh)
  21.344  	goto exit;
  21.345 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.346 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
  21.347 +				     &token))
  21.348          goto exit;
  21.349 -    xsval = xs_unwatch(xh, path);
  21.350 +    xsval = xs_unwatch(xh, path, token);
  21.351      val = pyvalue_int(xsval);
  21.352   exit:
  21.353      return val;
  21.354  }
  21.355  
  21.356 +#define xspy_transaction_start_doc "\n"				\
  21.357 +	"Start a transaction on a path.\n"			\
  21.358 +	"Only one transaction can be active at a time.\n"	\
  21.359 +	" path [string]: xenstore path.\n"			\
  21.360 +	"\n"							\
  21.361 +	"Returns: [int] 0 on success.\n"			\
  21.362 +	"Raises RuntimeError on error.\n"			\
  21.363 +	"\n"
  21.364 +
  21.365  static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
  21.366  					PyObject *kwds)
  21.367  {
  21.368 @@ -380,6 +496,15 @@ static PyObject *xspy_transaction_start(
  21.369      return val;
  21.370  }
  21.371  
  21.372 +#define xspy_transaction_end_doc "\n"					\
  21.373 +	"End the current transaction.\n"				\
  21.374 +	"Attempts to commit the transaction unless abort is true.\n"	\
  21.375 +	" abort [int]: Abort flag..\n"					\
  21.376 +	"\n"								\
  21.377 +	"Returns: [int] 0 on success.\n"				\
  21.378 +	"Raises RuntimeError on error.\n"				\
  21.379 +	"\n"
  21.380 +
  21.381  static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
  21.382  				      PyObject *kwds)
  21.383  {
  21.384 @@ -401,6 +526,17 @@ static PyObject *xspy_transaction_end(Py
  21.385      return val;
  21.386  }
  21.387  
  21.388 +#define xspy_introduce_domain_doc "\n"					\
  21.389 +	"Tell xenstore about a domain so it can talk to it.\n"		\
  21.390 +	" dom  [int]   : domain id\n"					\
  21.391 +	" page [long]  : address of domain's xenstore page\n"		\
  21.392 +	" port [int]   : port the domain is using for xenstore\n"	\
  21.393 +	" path [string]: path to the domain's data in xenstore\n"	\
  21.394 +	"\n"								\
  21.395 +	"Returns: [int] 0 on success.\n"				\
  21.396 +	"Raises RuntimeError on error.\n"				\
  21.397 +	"\n"
  21.398 +
  21.399  static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
  21.400  				       PyObject *kwds)
  21.401  {
  21.402 @@ -429,6 +565,15 @@ static PyObject *xspy_introduce_domain(P
  21.403      return val;
  21.404  }
  21.405  
  21.406 +#define xspy_release_domain_doc "\n"					\
  21.407 +	"Tell xenstore to release its channel to a domain.\n"		\
  21.408 +	"Unless this is done the domain will not be released.\n"	\
  21.409 +	" dom [int]: domain id\n"					\
  21.410 +	"\n"								\
  21.411 +	"Returns: [int] 0 on success.\n"				\
  21.412 +	"Raises RuntimeError on error.\n"				\
  21.413 +	"\n"
  21.414 +
  21.415  static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
  21.416  				     PyObject *kwds)
  21.417  {
  21.418 @@ -453,6 +598,13 @@ static PyObject *xspy_release_domain(PyO
  21.419      return val;
  21.420  }
  21.421  
  21.422 +#define xspy_close_doc "\n"			\
  21.423 +	"Close the connection to xenstore.\n"	\
  21.424 +	"\n"					\
  21.425 +	"Returns: [int] 0 on success.\n"	\
  21.426 +	"Raises RuntimeError on error.\n"	\
  21.427 +	"\n"
  21.428 +
  21.429  static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
  21.430  {
  21.431      static char *kwd_spec[] = { NULL };
  21.432 @@ -473,6 +625,13 @@ static PyObject *xspy_close(PyObject *se
  21.433      return val;
  21.434  }
  21.435  
  21.436 +#define xspy_shutdown_doc "\n"			\
  21.437 +	"Shutdown the xenstore daemon.\n"	\
  21.438 +	"\n"					\
  21.439 +	"Returns: [int] 0 on success.\n"	\
  21.440 +	"Raises RuntimeError on error.\n"	\
  21.441 +	"\n"
  21.442 +
  21.443  static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
  21.444  {
  21.445      static char *kwd_spec[] = { NULL };
  21.446 @@ -492,49 +651,31 @@ static PyObject *xspy_shutdown(PyObject 
  21.447      return val;
  21.448  }
  21.449  
  21.450 -#define XSPY_METH(_name) \
  21.451 -    #_name, \
  21.452 -    (PyCFunction) xspy_ ## _name, \
  21.453 -    (METH_VARARGS | METH_KEYWORDS)
  21.454 -// mtime
  21.455 -// ctime
  21.456 +#define XSPY_METH(_name) {			\
  21.457 +    .ml_name  = #_name,				\
  21.458 +    .ml_meth  = (PyCFunction) xspy_ ## _name,	\
  21.459 +    .ml_flags = (METH_VARARGS | METH_KEYWORDS),	\
  21.460 +    .ml_doc   = xspy_ ## _name ## _doc }
  21.461  
  21.462  static PyMethodDef xshandle_methods[] = {
  21.463 -    { XSPY_METH(read), 
  21.464 -      "read(path) : read data\n" },
  21.465 -    { XSPY_METH(write), 
  21.466 -      "write(path, data, [creat], [excl]): write data\n" },
  21.467 -    { XSPY_METH(ls), 
  21.468 -      "ls(path): list directory.\n" },
  21.469 -    { XSPY_METH(mkdir), 
  21.470 -      "mkdir(path): make a directory.\n" },
  21.471 -    { XSPY_METH(rm),
  21.472 -      "rm(path): remove a path (dir must be empty).\n" },
  21.473 -    { XSPY_METH(get_permissions),
  21.474 -      "get_permissions(path)\n" },
  21.475 -    { XSPY_METH(set_permissions),
  21.476 -      "set_permissions(path)\n" },
  21.477 -    { XSPY_METH(watch), 
  21.478 -      "watch(path)\n" },
  21.479 -    { XSPY_METH(read_watch), 
  21.480 -      "read_watch()\n" },
  21.481 -    { XSPY_METH(acknowledge_watch), 
  21.482 -      "acknowledge_watch()\n" },
  21.483 -    { XSPY_METH(unwatch), 
  21.484 -      "unwatch()\n" },
  21.485 -    { XSPY_METH(transaction_start), 
  21.486 -      "transaction_start()\n" },
  21.487 -    { XSPY_METH(transaction_end), 
  21.488 -      "transaction_end([abort])\n" },
  21.489 -    { XSPY_METH(introduce_domain), 
  21.490 -      "introduce_domain(dom, page, port)\n" },
  21.491 -    { XSPY_METH(release_domain), 
  21.492 -      "release_domain(dom)\n" },
  21.493 -    { XSPY_METH(close), 
  21.494 -      "close()\n" },
  21.495 -    { XSPY_METH(shutdown), 
  21.496 -      "shutdown()\n" },
  21.497 -    { NULL, NULL, 0, NULL }
  21.498 +     XSPY_METH(read),
  21.499 +     XSPY_METH(write),
  21.500 +     XSPY_METH(ls),
  21.501 +     XSPY_METH(mkdir),
  21.502 +     XSPY_METH(rm),
  21.503 +     XSPY_METH(get_permissions),
  21.504 +     XSPY_METH(set_permissions),
  21.505 +     XSPY_METH(watch),
  21.506 +     XSPY_METH(read_watch),
  21.507 +     XSPY_METH(acknowledge_watch),
  21.508 +     XSPY_METH(unwatch),
  21.509 +     XSPY_METH(transaction_start),
  21.510 +     XSPY_METH(transaction_end),
  21.511 +     XSPY_METH(introduce_domain),
  21.512 +     XSPY_METH(release_domain),
  21.513 +     XSPY_METH(close),
  21.514 +     XSPY_METH(shutdown),
  21.515 +     { /* Terminator. */ },
  21.516  };
  21.517  
  21.518  static PyObject *xshandle_getattr(PyObject *self, char *name)
  21.519 @@ -604,8 +745,15 @@ static PyObject *xshandle_open(PyObject 
  21.520  }
  21.521  
  21.522  static PyMethodDef xs_methods[] = {
  21.523 -    { "open", (PyCFunction)xshandle_open, (METH_VARARGS | METH_KEYWORDS), 
  21.524 -      "Open a connection to the xenstore daemon.\n" },
  21.525 +    { .ml_name  = "open",
  21.526 +      .ml_meth  = (PyCFunction)xshandle_open,
  21.527 +      .ml_flags = (METH_VARARGS | METH_KEYWORDS), 
  21.528 +      .ml_doc   = "\n"
  21.529 +      "Open a connection to the xenstore daemon.\n"
  21.530 +      "Returns: xs connection object.\n"
  21.531 +      "Raises RuntimeError on error.\n"
  21.532 +      "\n"
  21.533 +    },
  21.534      { NULL, NULL, 0, NULL }
  21.535  };
  21.536  
    22.1 --- a/tools/python/xen/lowlevel/xu/xu.c	Mon Jun 13 13:18:58 2005 +0000
    22.2 +++ b/tools/python/xen/lowlevel/xu/xu.c	Fri Jun 17 20:47:52 2005 +0000
    22.3 @@ -72,7 +72,7 @@ static void set_cloexec(int fd)
    22.4  
    22.5  static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
    22.6  static int xcs_data_fd = -1; /*    data connection to the xcs server. */
    22.7 -static u32 xcs_session_id = 0;
    22.8 +static unsigned long  xcs_session_id = 0;
    22.9  
   22.10  static int xcs_ctrl_send(xcs_msg_t *msg);
   22.11  static int xcs_ctrl_read(xcs_msg_t *msg);
    23.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 13 13:18:58 2005 +0000
    23.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Jun 17 20:47:52 2005 +0000
    23.3 @@ -157,7 +157,7 @@ class XendDomainInfo:
    23.4          db = parentdb.addChild(uuid)
    23.5          vm = cls(db)
    23.6          vm.construct(config)
    23.7 -        vm.saveDB(sync=True)
    23.8 +        vm.saveToDB(sync=True)
    23.9          return vm
   23.10  
   23.11      create = classmethod(create)
   23.12 @@ -193,7 +193,7 @@ class XendDomainInfo:
   23.13  
   23.14      recreate = classmethod(recreate)
   23.15  
   23.16 -    def restore(cls, parentdb, config, uuid=None):
   23.17 +    def restore(cls, parentdb, config, uuid):
   23.18          """Create a domain and a VM object to do a restore.
   23.19  
   23.20          @param parentdb:  parent db
   23.21 @@ -202,16 +202,20 @@ class XendDomainInfo:
   23.22          """
   23.23          db = parentdb.addChild(uuid)
   23.24          vm = cls(db)
   23.25 -        dom = xc.domain_create()
   23.26 -        vm.setdom(dom)
   23.27 -        vm.dom_construct(vm.id, config)
   23.28 -        vm.saveDB(sync=True)
   23.29 +        id = xc.domain_create()
   23.30 +        vm.setdom(id)
   23.31 +        try:
   23.32 +            vm.restore = True
   23.33 +            vm.construct(config)
   23.34 +        finally:
   23.35 +            vm.restore = False
   23.36 +        vm.exportToDB(save=True, sync=True)
   23.37          return vm
   23.38  
   23.39      restore = classmethod(restore)
   23.40  
   23.41      __exports__ = [
   23.42 -        DBVar('id',            ty='str'),
   23.43 +        DBVar('id',            ty='int'),
   23.44          DBVar('name',          ty='str'),
   23.45          DBVar('uuid',          ty='str'),
   23.46          DBVar('config',        ty='sxpr'),
   23.47 @@ -267,14 +271,17 @@ class XendDomainInfo:
   23.48      def setDB(self, db):
   23.49          self.db = db
   23.50  
   23.51 -    def saveDB(self, save=False, sync=False):
   23.52 +    def saveToDB(self, save=False, sync=False):
   23.53          self.db.saveDB(save=save, sync=sync)
   23.54  
   23.55      def exportToDB(self, save=False, sync=False):
   23.56          if self.channel:
   23.57 -            self.channel.saveToDB(self.db.addChild("channel"))
   23.58 +            self.channel.saveToDB(self.db.addChild("channel"), save=save)
   23.59          if self.store_channel:
   23.60 -            self.store_channel.saveToDB(self.db.addChild("store_channel"))
   23.61 +            self.store_channel.saveToDB(self.db.addChild("store_channel"),
   23.62 +                                        save=save)
   23.63 +        if self.image:
   23.64 +            self.image.exportToDB(save=save, sync=sync)
   23.65          self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
   23.66  
   23.67      def importFromDB(self):
   23.68 @@ -316,7 +323,7 @@ class XendDomainInfo:
   23.69              self.state = state
   23.70              self.state_updated.notifyAll()
   23.71          self.state_updated.release()
   23.72 -        self.saveDB()
   23.73 +        self.saveToDB()
   23.74  
   23.75      def state_wait(self, state):
   23.76          self.state_updated.acquire()
   23.77 @@ -325,14 +332,14 @@ class XendDomainInfo:
   23.78          self.state_updated.release()
   23.79  
   23.80      def __str__(self):
   23.81 -        s = "domain"
   23.82 +        s = "<domain"
   23.83          s += " id=" + str(self.id)
   23.84          s += " name=" + self.name
   23.85          s += " memory=" + str(self.memory)
   23.86          console = self.getConsole()
   23.87          if console:
   23.88              s += " console=" + str(console.console_port)
   23.89 -        s += ""
   23.90 +        s += ">"
   23.91          return s
   23.92  
   23.93      __repr__ = __str__
   23.94 @@ -422,15 +429,19 @@ class XendDomainInfo:
   23.95              sxpr.append(self.channel.sxpr())
   23.96          if self.store_channel:
   23.97              sxpr.append(self.store_channel.sxpr())
   23.98 +        if self.store_mfn:
   23.99 +            sxpr.append(['store_mfn', self.store_mfn])
  23.100          console = self.getConsole()
  23.101          if console:
  23.102              sxpr.append(console.sxpr())
  23.103 +
  23.104          if self.restart_count:
  23.105              sxpr.append(['restart_count', self.restart_count])
  23.106          if self.restart_state:
  23.107              sxpr.append(['restart_state', self.restart_state])
  23.108          if self.restart_time:
  23.109              sxpr.append(['restart_time', str(self.restart_time)])
  23.110 +
  23.111          devs = self.sxpr_devices()
  23.112          if devs:
  23.113              sxpr.append(devs)
  23.114 @@ -546,7 +557,7 @@ class XendDomainInfo:
  23.115          """
  23.116          self.create_channel()
  23.117          self.image.createImage()
  23.118 -        self.image.exportToDB()
  23.119 +        self.exportToDB()
  23.120          #if self.store_channel:
  23.121          #    self.db.introduceDomain(self.id,
  23.122          #                            self.store_mfn,
  23.123 @@ -558,7 +569,7 @@ class XendDomainInfo:
  23.124          if self.dom_get(self.id):
  23.125              return
  23.126          self.id = None
  23.127 -        self.saveDB(sync=True)
  23.128 +        self.saveToDB(sync=True)
  23.129          try:
  23.130              # Todo: eventually will have to wait for devices to signal
  23.131              # destruction before can delete the db.
  23.132 @@ -614,7 +625,7 @@ class XendDomainInfo:
  23.133          """
  23.134          self.cleanup()
  23.135          self.destroy_domain()
  23.136 -        self.saveDB()
  23.137 +        self.saveToDB()
  23.138          return 0
  23.139  
  23.140      def is_terminated(self):
  23.141 @@ -649,14 +660,13 @@ class XendDomainInfo:
  23.142              cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
  23.143          except:
  23.144              raise VmError('invalid cpu')
  23.145 -        dom = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
  23.146 +        id = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
  23.147          log.debug('init_domain> Created domain=%d name=%s memory=%d',
  23.148 -                  dom, self.name, self.memory)
  23.149 -        if not self.restore:
  23.150 -            self.setdom(dom)
  23.151 +                  id, self.name, self.memory)
  23.152 +        self.setdom(id)
  23.153  
  23.154      def openChannel(self, key, local, remote):
  23.155 -        """Create a channel to the domain.
  23.156 +        """Create a control channel to the domain.
  23.157          If saved info is available recreate the channel.
  23.158          
  23.159          @param key db key for the saved data (if any)
  23.160 @@ -670,6 +680,11 @@ class XendDomainInfo:
  23.161          return chan
  23.162  
  23.163      def eventChannel(self, key):
  23.164 +        """Create an event channel to the domain.
  23.165 +        If saved info is available recreate the channel.
  23.166 +        
  23.167 +        @param key db key for the saved data (if any)
  23.168 +        """
  23.169          db = self.db.addChild(key)
  23.170          return EventChannel.restoreFromDB(db, 0, self.id)
  23.171          
  23.172 @@ -833,11 +848,12 @@ class XendDomainInfo:
  23.173              self.state = STATE_VM_OK
  23.174              self.shutdown_pending = None
  23.175              self.restart_check()
  23.176 +            self.exportToDB()
  23.177              self.restart_state = STATE_RESTART_BOOTING
  23.178              if self.bootloader:
  23.179                  self.config = self.bootloader_config()
  23.180              self.construct(self.config)
  23.181 -            self.saveDB()
  23.182 +            self.saveToDB()
  23.183          finally:
  23.184              self.restart_state = None
  23.185  
  23.186 @@ -911,23 +927,6 @@ class XendDomainInfo:
  23.187              backend = blkif.getBackend(0)
  23.188              backend.connect(recreate=self.recreate)
  23.189  
  23.190 -    def dom_construct(self, dom, config):
  23.191 -        """Construct a vm for an existing domain.
  23.192 -
  23.193 -        @param dom: domain id
  23.194 -        @param config: domain configuration
  23.195 -        """
  23.196 -        d = dom_get(dom)
  23.197 -        if not d:
  23.198 -            raise VmError("Domain not found: %d" % dom)
  23.199 -        try:
  23.200 -            self.restore = True
  23.201 -            self.setdom(dom)
  23.202 -            self.memory = d['mem_kb']/1024
  23.203 -            self.construct(config)
  23.204 -        finally:
  23.205 -            self.restore = False
  23.206 -
  23.207      def configure_fields(self):
  23.208          """Process the vm configuration fields using the registered handlers.
  23.209          """
    24.1 --- a/tools/python/xen/xend/image.py	Mon Jun 13 13:18:58 2005 +0000
    24.2 +++ b/tools/python/xen/xend/image.py	Fri Jun 17 20:47:52 2005 +0000
    24.3 @@ -98,8 +98,8 @@ class ImageHandler:
    24.4          self.db = vm.db.addChild('/image')
    24.5          self.config = config
    24.6  
    24.7 -    def exportToDB(self, save=False):
    24.8 -        self.db.exportToDB(self, fields=self.__exports__, save=save)
    24.9 +    def exportToDB(self, save=False, sync=False):
   24.10 +        self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
   24.11  
   24.12      def importFromDB(self):
   24.13          self.db.importFromDB(self, fields=self.__exports__)
    25.1 --- a/tools/python/xen/xend/server/blkif.py	Mon Jun 13 13:18:58 2005 +0000
    25.2 +++ b/tools/python/xen/xend/server/blkif.py	Fri Jun 17 20:47:52 2005 +0000
    25.3 @@ -167,6 +167,7 @@ class BlkDev(Dev):
    25.4          DBVar('params',       ty='str'),
    25.5          DBVar('node',         ty='str'),
    25.6          DBVar('device',       ty='long'),
    25.7 +        DBVar('dev_handle',   ty='long'),
    25.8          DBVar('start_sector', ty='long'),
    25.9          DBVar('nr_sectors',   ty='long'),
   25.10          ]
   25.11 @@ -192,6 +193,13 @@ class BlkDev(Dev):
   25.12          self.backendId = 0
   25.13          self.configure(self.config, recreate=recreate)
   25.14  
   25.15 +    def exportToDB(self, save=False):
   25.16 +        Dev.exportToDB(self, save=save)
   25.17 +        backend = self.getBackend()
   25.18 +        if backend and backend.evtchn:
   25.19 +            db = self.db.addChild("evtchn")
   25.20 +            backend.evtchn.exportToDB(db, save=save)
   25.21 +
   25.22      def init(self, recreate=False, reboot=False):
   25.23          self.frontendDomain = self.getDomain()
   25.24          self.frontendChannel = self.getChannel()
    26.1 --- a/tools/python/xen/xend/server/channel.py	Mon Jun 13 13:18:58 2005 +0000
    26.2 +++ b/tools/python/xen/xend/server/channel.py	Fri Jun 17 20:47:52 2005 +0000
    26.3 @@ -81,7 +81,7 @@ class EventChannel(dict):
    26.4          evtchn_close(self.dom1, self.port1)
    26.5          evtchn_close(self.dom2, self.port2)
    26.6  
    26.7 -    def saveToDB(self, db):
    26.8 +    def saveToDB(self, db, save=False):
    26.9          """Save the event channel to the db so it can be restored later,
   26.10          using restoreFromDB() on the class.
   26.11  
   26.12 @@ -91,7 +91,7 @@ class EventChannel(dict):
   26.13          db['dom2']  = str(self.dom2)
   26.14          db['port1'] = str(self.port1)
   26.15          db['port2'] = str(self.port2)
   26.16 -        db.saveDB()
   26.17 +        db.saveDB(save=save)
   26.18  
   26.19      def sxpr(self):
   26.20          return ['event-channel',
   26.21 @@ -339,7 +339,7 @@ class Channel:
   26.22          # Make sure the port will deliver all the messages.
   26.23          self.port.register(TYPE_WILDCARD)
   26.24  
   26.25 -    def saveToDB(self, db):
   26.26 +    def saveToDB(self, db, save=False):
   26.27          """Save the channel ports to the db so the channel can be restored later,
   26.28          using restoreFromDB() on the factory.
   26.29  
   26.30 @@ -348,7 +348,7 @@ class Channel:
   26.31          if self.closed: return
   26.32          db['local_port'] = str(self.getLocalPort())
   26.33          db['remote_port'] = str(self.getRemotePort())
   26.34 -        db.saveDB()
   26.35 +        db.saveDB(save=save)
   26.36  
   26.37      def getKey(self):
   26.38          """Get the channel key.
    27.1 --- a/tools/python/xen/xend/server/console.py	Mon Jun 13 13:18:58 2005 +0000
    27.2 +++ b/tools/python/xen/xend/server/console.py	Fri Jun 17 20:47:52 2005 +0000
    27.3 @@ -214,7 +214,8 @@ class ConsoleDev(Dev, protocol.ServerFac
    27.4                      self.unix_listener = reactor.listenUNIX(path, self)
    27.5                  if xroot.get_xend_http_server():
    27.6                      interface = xroot.get_console_address()
    27.7 -                    self.tcp_listener = reactor.listenTCP(self.console_port, self, interface=interface)
    27.8 +                    self.tcp_listener = reactor.listenTCP(
    27.9 +                        self.console_port, self, interface=interface)
   27.10          finally:
   27.11              self.lock.release()
   27.12  
    28.1 --- a/tools/python/xen/xend/server/netif.py	Mon Jun 13 13:18:58 2005 +0000
    28.2 +++ b/tools/python/xen/xend/server/netif.py	Fri Jun 17 20:47:52 2005 +0000
    28.3 @@ -66,11 +66,9 @@ class NetDev(Dev):
    28.4          DBVar('be_mac',  ty='mac'),
    28.5          DBVar('bridge',  ty='str'),
    28.6          DBVar('script',  ty='str'),
    28.7 -        #DBVar('ipaddr'),
    28.8          DBVar('credit',  ty='int'),
    28.9          DBVar('period',  ty='int'),
   28.10          DBVar('vifname', ty='str'),
   28.11 -        DBVar('evtchn'),                #todo: export fields (renamed)
   28.12          ]
   28.13  
   28.14      def __init__(self, controller, id, config, recreate=False):
   28.15 @@ -89,9 +87,16 @@ class NetDev(Dev):
   28.16          self.bridge = None
   28.17          self.script = None
   28.18          self.ipaddr = None
   28.19 +        self.mtu = None
   28.20          self.vifname = None
   28.21          self.configure(self.config, recreate=recreate)
   28.22  
   28.23 +    def exportToDB(self, save=False):
   28.24 +        Dev.exportToDB(self, save=save)
   28.25 +        if self.evtchn:
   28.26 +            db = self.db.addChild("evtchn")
   28.27 +            self.evtchn.exportToDB(db, save=save)
   28.28 +
   28.29      def init(self, recreate=False, reboot=False):
   28.30          self.destroyed = False
   28.31          self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
   28.32 @@ -128,6 +133,15 @@ class NetDev(Dev):
   28.33              val = None
   28.34          return val
   28.35  
   28.36 +    def _get_config_mtu(self, config):
   28.37 +        mtu = sxp.child_value(config, 'mtu')
   28.38 +        if not mtu: return None
   28.39 +        try:
   28.40 +            mtu = int(mtu)
   28.41 +        except:
   28.42 +            raise XendError("invalid mtu: %s" & mtu)
   28.43 +        return mtu
   28.44 +
   28.45      def configure(self, config, change=False, recreate=False):
   28.46          if change:
   28.47              return self.reconfigure(config)
   28.48 @@ -152,6 +166,7 @@ class NetDev(Dev):
   28.49          self.bridge = sxp.child_value(config, 'bridge')
   28.50          self.script = sxp.child_value(config, 'script')
   28.51          self.ipaddr = self._get_config_ipaddr(config) or []
   28.52 +        self.mtu = self._get_config_mtu(config)
   28.53          self._config_credit_limit(config)
   28.54          
   28.55          try:
   28.56 @@ -183,6 +198,7 @@ class NetDev(Dev):
   28.57          bridge = sxp.child_value(config, 'bridge')
   28.58          script = sxp.child_value(config, 'script')
   28.59          ipaddr = self._get_config_ipaddr(config)
   28.60 +        mtu = self._get_config_mtu(config)
   28.61          
   28.62          xd = get_component('xen.xend.XendDomain')
   28.63          backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).id
   28.64 @@ -199,6 +215,8 @@ class NetDev(Dev):
   28.65              changes['script'] = script
   28.66          if (ipaddr is not None) and (ipaddr != self.ipaddr):
   28.67              changes['ipaddr'] = ipaddr
   28.68 +        if (mtu is not None) and (mtu != self.mtu):
   28.69 +            changes['mtu'] = mtu
   28.70  
   28.71          if changes:
   28.72              self.vifctl("down")
    29.1 --- a/tools/python/xen/xend/xenstore/xsnode.py	Mon Jun 13 13:18:58 2005 +0000
    29.2 +++ b/tools/python/xen/xend/xenstore/xsnode.py	Fri Jun 17 20:47:52 2005 +0000
    29.3 @@ -2,7 +2,9 @@ import errno
    29.4  import os
    29.5  import os.path
    29.6  import select
    29.7 +import socket
    29.8  import sys
    29.9 +import threading
   29.10  import time
   29.11  
   29.12  from xen.lowlevel import xs
   29.13 @@ -12,18 +14,26 @@ from xen.xend.PrettyPrint import prettyp
   29.14  SELECT_TIMEOUT = 2.0
   29.15  
   29.16  def getEventPath(event):
   29.17 -    return os.path.join("/_event", event)
   29.18 +    if event and event.startswith("/"):
   29.19 +        event = event[1:]
   29.20 +    return os.path.join("/event", event)
   29.21  
   29.22  def getEventIdPath(event):
   29.23 -    return os.path.join(eventPath(event), "@eid")
   29.24 +    return os.path.join(getEventPath(event), "@eid")
   29.25  
   29.26  class Subscription:
   29.27  
   29.28 -    def __init__(self, event, fn, id):
   29.29 -        self.event = event
   29.30 +    def __init__(self, path, fn, sid):
   29.31 +        self.path = path
   29.32          self.watcher = None
   29.33          self.fn = fn
   29.34 -        self.id = id
   29.35 +        self.sid = sid
   29.36 +
   29.37 +    def getPath(self):
   29.38 +        return self.path
   29.39 +
   29.40 +    def getSid(self):
   29.41 +        return self.sid
   29.42  
   29.43      def watch(self, watcher):
   29.44          self.watcher = watcher
   29.45 @@ -34,56 +44,61 @@ class Subscription:
   29.46          if watcher:
   29.47              self.watcher = None
   29.48              watcher.delSubs(self)
   29.49 +        return watcher
   29.50  
   29.51 -    def notify(self, event):
   29.52 +    def notify(self, token, path, val):
   29.53          try:
   29.54 -            self.fn(event, id)
   29.55 -        except SystemExitException:
   29.56 +            self.fn(self, token, path, val)
   29.57 +        except SystemExit:
   29.58              raise
   29.59 -        except:
   29.60 +        except Exception, ex:
   29.61              pass
   29.62  
   29.63  class Watcher:
   29.64  
   29.65 -    def __init__(self, store, event):
   29.66 -        self.path = getEventPath(event)
   29.67 -        self.eidPath = getEventIdPath(event)
   29.68 +    def __init__(self, store, path):
   29.69 +        self.path = path
   29.70          store.mkdirs(self.path)
   29.71 -        if not store.exists(self.eidPath):
   29.72 -            store.writeInt(self.eidPath, 0)
   29.73          self.xs = None
   29.74 -        self.subs = []
   29.75 +        self.subscriptions = []
   29.76  
   29.77 -    def __getattr__(self, k, v):
   29.78 -        if k == "fileno":
   29.79 -            if self.xs:
   29.80 -                return self.xs.fileno
   29.81 -            else:
   29.82 -                return -1
   29.83 +    def fileno(self):
   29.84 +        if self.xs:
   29.85 +            return self.xs.fileno
   29.86          else:
   29.87 -            return self.__dict__.get(k, v)
   29.88 +            return -1
   29.89 +
   29.90 +    def getPath(self):
   29.91 +        return self.path
   29.92 +
   29.93 +    def getToken(self):
   29.94 +        return self.path
   29.95  
   29.96      def addSubs(self, subs):
   29.97 -        self.subs.append(subs)
   29.98 +        self.subscriptions.append(subs)
   29.99          self.watch()
  29.100  
  29.101      def delSubs(self, subs):
  29.102 -        self.subs.remove(subs)
  29.103 -        if len(self.subs) == 0:
  29.104 +        self.subscriptions.remove(subs)
  29.105 +        if len(self.subscriptions) == 0:
  29.106              self.unwatch()
  29.107  
  29.108 -    def getEvent(self):
  29.109 -        return self.event
  29.110 -
  29.111      def watch(self):
  29.112          if self.xs: return
  29.113          self.xs = xs.open()
  29.114 -        self.xs.watch(path)
  29.115 +        self.xs.watch(path=self.getPath(), token=self.getToken())
  29.116  
  29.117      def unwatch(self):
  29.118          if self.xs:
  29.119 -            self.xs.unwatch(self.path)
  29.120 -            self.xs.close()
  29.121 +## Possibly crashes xenstored.
  29.122 +##            try:
  29.123 +##                self.xs.unwatch(path=self.getPath(), token=self.getToken())
  29.124 +##            except Exception, ex:
  29.125 +##                print 'Watcher>unwatch>', ex
  29.126 +            try:
  29.127 +                self.xs.close()
  29.128 +            except Exception, ex:
  29.129 +                pass
  29.130              self.xs = None
  29.131              
  29.132      def watching(self):
  29.133 @@ -91,23 +106,47 @@ class Watcher:
  29.134  
  29.135      def getNotification(self):
  29.136          p = self.xs.read_watch()
  29.137 -        self.xs.acknowledge_watch()
  29.138 -        eid = self.xs.readInt(self.eidPath)
  29.139 +        self.xs.acknowledge_watch(p[1])
  29.140          return p
  29.141  
  29.142 -    def notify(self, subs):
  29.143 -        p = self.getNotification()
  29.144 -        for s in subs:
  29.145 -            s.notify(p)
  29.146 -            
  29.147 +    def notify(self):
  29.148 +        try:
  29.149 +            (path, token) = self.getNotification()
  29.150 +            if path.endswith("@eid"):
  29.151 +                pass
  29.152 +            else:
  29.153 +                val = self.xs.read(path)
  29.154 +                for subs in self.subscriptions:
  29.155 +                    subs.notify(token, path, val)
  29.156 +        except SystemExit:
  29.157 +            raise
  29.158 +        except Exception, ex:
  29.159 +            raise
  29.160 +
  29.161 +class EventWatcher(Watcher):
  29.162 +
  29.163 +    def __init__(self, store, path, event):
  29.164 +        Watcher.__init__(self, store, path)
  29.165 +        self.event = event
  29.166 +        self.eidPath = getEventIdPath(event)
  29.167 +        if not store.exists(self.eidPath):
  29.168 +            store.write(self.eidPath, str(0))
  29.169 +
  29.170 +    def getEvent(self):
  29.171 +        return self.event
  29.172 +
  29.173 +    def getToken(self):
  29.174 +        return self.event
  29.175 +
  29.176  class XenStore:
  29.177  
  29.178 +    xs = None
  29.179 +    watchThread = None
  29.180 +    subscription_id = 1
  29.181 +    
  29.182      def __init__(self):
  29.183 -        self.xs = None
  29.184 -        #self.xs = xs.open()
  29.185 -        self.subscription = {}
  29.186 -        self.subscription_id = 0
  29.187 -        self.events = {}
  29.188 +        self.subscriptions = {}
  29.189 +        self.watchers = {}
  29.190          self.write("/", "")
  29.191  
  29.192      def getxs(self):
  29.193 @@ -118,9 +157,11 @@ class XenStore:
  29.194                      self.xs = xs.open()
  29.195                      ex = None
  29.196                      break
  29.197 +                except SystemExit:
  29.198 +                    raise
  29.199                  except Exception, ex:
  29.200 -                    print >>stderr, "Exception connecting to xsdaemon:", ex
  29.201 -                    print >>stderr, "Trying again..."
  29.202 +                    print >>sys.stderr, "Exception connecting to xenstored:", ex
  29.203 +                    print >>sys.stderr, "Trying again..."
  29.204                      time.sleep(1)
  29.205              else:
  29.206                  raise ex
  29.207 @@ -214,73 +255,91 @@ class XenStore:
  29.208  
  29.209      def write(self, path, data, create=True, excl=False):
  29.210          self.mkdirs(path)
  29.211 -        self.getxs().write(path, data, create=create, excl=excl)
  29.212 +        try:
  29.213 +            self.getxs().write(path, data, create=create, excl=excl)
  29.214 +        except Exception, ex:
  29.215 +            raise
  29.216  
  29.217      def begin(self, path):
  29.218 -        self.getxs().begin_transaction(path)
  29.219 +        self.getxs().transaction_start(path)
  29.220  
  29.221      def commit(self, abandon=False):
  29.222 -        self.getxs().end_transaction(abort=abandon)
  29.223 +        self.getxs().transaction_end(abort=abandon)
  29.224 +
  29.225 +    def watch(self, path, fn):
  29.226 +        watcher = self.watchers.get(path)
  29.227 +        if not watcher:
  29.228 +            watcher = self.addWatcher(Watcher(self, path))
  29.229 +        return self.addSubscription(watcher, fn)
  29.230 +        
  29.231 +    def unwatch(self, sid):
  29.232 +        s = self.subscriptions.get(sid)
  29.233 +        if not s: return
  29.234 +        del self.subscriptions[s.sid]
  29.235 +        watcher = s.unwatch()
  29.236 +        if watcher and not watcher.watching():
  29.237 +            try:
  29.238 +                del self.watchers[watcher.getPath()]
  29.239 +            except:
  29.240 +                pass
  29.241  
  29.242      def subscribe(self, event, fn):
  29.243 -        watcher = self.watchEvent(event)
  29.244 -        self.subscription_id += 1
  29.245 -        subs = Subscription(event, fn, self.subscription_id)
  29.246 -        self.subscription[subs.id] = subs
  29.247 -        subs.watch(watcher)
  29.248 -        return subs.id
  29.249 +        path = getEventPath(event)
  29.250 +        watcher = self.watchers.get(path)
  29.251 +        if not watcher:
  29.252 +            watcher = self.addWatcher(EventWatcher(self, path, event))
  29.253 +        return self.addSubscription(watcher, fn)
  29.254  
  29.255 -    def unsubscribe(self, sid):
  29.256 -        s = self.subscription.get(sid)
  29.257 -        if not s: return
  29.258 -        del self.subscription[s.id]
  29.259 -        s.unwatch()
  29.260 -        unwatchEvent(s.event)
  29.261 +    unsubscribe = unwatch
  29.262  
  29.263      def sendEvent(self, event, data):
  29.264          eventPath = getEventPath(event)
  29.265          eidPath = getEventIdPath(event)
  29.266          try:
  29.267 -            self.begin(eventPath)
  29.268 +            #self.begin(eventPath)
  29.269              self.mkdirs(eventPath)
  29.270 +            eid = 1
  29.271              if self.exists(eidPath):
  29.272 -                eid = self.readInt(eidPath)
  29.273 -                eid += 1
  29.274 -            else:
  29.275 -                eid = 1
  29.276 -            self.writeInt(eidPath, eid)
  29.277 +                try:
  29.278 +                    eid = int(self.read(eidPath))
  29.279 +                    eid += 1
  29.280 +                except Exception, ex:
  29.281 +                    pass
  29.282 +            self.write(eidPath, str(eid))
  29.283              self.write(os.path.join(eventPath, str(eid)), data)
  29.284          finally:
  29.285 -            self.commit()
  29.286 +            #self.commit()
  29.287 +            pass
  29.288  
  29.289 -    def watchEvent(self, event):
  29.290 -        if event in  self.events:
  29.291 -            return
  29.292 -        watcher = Watcher(event)
  29.293 -        self.watchers[watcher.getEvent()] = watcher
  29.294 +    def addWatcher(self, watcher):
  29.295 +        self.watchers[watcher.getPath()] = watcher
  29.296          self.watchStart()
  29.297          return watcher
  29.298  
  29.299 -    def unwatchEvent(self, event):
  29.300 -        watcher = self.watchers.get(event)
  29.301 -        if not watcher:
  29.302 -            return
  29.303 -        if not watcher.watching():
  29.304 -            del self.watchers[event]
  29.305 +    def addSubscription(self, watcher, fn):
  29.306 +        self.subscription_id += 1
  29.307 +        subs = Subscription(watcher.getPath(), fn, self.subscription_id)
  29.308 +        self.subscriptions[subs.sid] = subs
  29.309 +        subs.watch(watcher)
  29.310 +        return subs.sid
  29.311  
  29.312      def watchStart(self):
  29.313          if self.watchThread: return
  29.314 -
  29.315 +        self.watchThread = threading.Thread(name="Watcher",
  29.316 +                                            target=self.watchMain)
  29.317 +        self.watchThread.setDaemon(True)
  29.318 +        self.watchThread.start()
  29.319 +        
  29.320      def watchMain(self):
  29.321          try:
  29.322              while True:
  29.323                  if self.watchThread is None: return
  29.324 -                if not self.events:
  29.325 +                if not self.watchers:
  29.326                      return
  29.327                  rd = self.watchers.values()
  29.328                  try:
  29.329 -                    (rd, wr, er) = select.select(rd, [], [], SELECT_TIMEOUT)
  29.330 -                    for watcher in rd:
  29.331 +                    (srd, swr, ser) = select.select(rd, [], [], SELECT_TIMEOUT)
  29.332 +                    for watcher in srd:
  29.333                          watcher.notify()
  29.334                  except socket.error, ex:
  29.335                      if ex.args[0] in (EAGAIN, EINTR):
  29.336 @@ -304,6 +363,15 @@ def getXenStore():
  29.337          xenstore = XenStore()
  29.338          return xenstore
  29.339  
  29.340 +def sendEvent(event, val):
  29.341 +    getXenStore.sendEvent(event, val)
  29.342 +
  29.343 +def subscribe(event, fn):
  29.344 +    return getXenStore().subscribe(event, fn)
  29.345 +
  29.346 +def unsubscribe(sid):
  29.347 +    getXenStore().unsubscribe(sid)
  29.348 +
  29.349  class XenNode:
  29.350  
  29.351      def __init__(self, path="/", create=True):
  29.352 @@ -315,6 +383,9 @@ class XenNode:
  29.353              else:
  29.354                  raise ValueError("path does not exist: '%s'" % path)
  29.355  
  29.356 +    def getStore(self):
  29.357 +        return self.store
  29.358 +
  29.359      def relPath(self, path=""):
  29.360          if not path:
  29.361              return self.path
  29.362 @@ -344,9 +415,7 @@ class XenNode:
  29.363              return None
  29.364  
  29.365      def setData(self, data, path=""):
  29.366 -        path = self.relPath(path)
  29.367 -        #print 'XenNode>setData>', 'path=', path, 'data=', data
  29.368 -        return self.store.write(path, data)
  29.369 +        return self.store.write(self.relPath(path), data)
  29.370  
  29.371      def getLock(self):
  29.372          return None
  29.373 @@ -376,6 +445,24 @@ class XenNode:
  29.374      def releaseDomain(self, dom):
  29.375          self.store.releaseDomain(dom)
  29.376  
  29.377 +    def watch(self, fn, path=""):
  29.378 +        """Watch a path for changes. The path is relative
  29.379 +        to the node and defaults to the node itself.
  29.380 +        """
  29.381 +        return self.store.watch(self.relPath(path), fn)
  29.382 +
  29.383 +    def unwatch(self, sid):
  29.384 +        return self.store.unwatch(sid)
  29.385 +
  29.386 +    def subscribe(self, event, fn):
  29.387 +        return self.store.subscribe(event, fn)
  29.388 +
  29.389 +    def unsubscribe(self, sid):
  29.390 +        self.store.unsubscribe(sid)
  29.391 +
  29.392 +    def sendEvent(self, event, data):
  29.393 +        return self.store.sendEvent(event, data)
  29.394 +
  29.395      def __repr__(self):
  29.396          return "<XenNode %s>" % self.path
  29.397  
    30.1 --- a/tools/python/xen/xend/xenstore/xsobj.py	Mon Jun 13 13:18:58 2005 +0000
    30.2 +++ b/tools/python/xen/xend/xenstore/xsobj.py	Fri Jun 17 20:47:52 2005 +0000
    30.3 @@ -1,6 +1,8 @@
    30.4  import string
    30.5  import types
    30.6  
    30.7 +from xen.xend.XendLogging import log
    30.8 +
    30.9  from xen.xend import sxp
   30.10  from xsnode import XenNode
   30.11  from xen.util.mac import macToString, macFromString
   30.12 @@ -14,14 +16,19 @@ def hasAttr(obj, attr):
   30.13          return hasattr(obj, attr)
   30.14  
   30.15  def getAttr(obj, attr):
   30.16 -    if isinstance(obj, dict):
   30.17 -        return dict.get(attr)
   30.18 -    else:
   30.19 -        return getattr(obj, attr, None)
   30.20 +    try:
   30.21 +        if isinstance(obj, dict):
   30.22 +            return obj.get(attr)
   30.23 +        else:
   30.24 +            return getattr(obj, attr, None)
   30.25 +    except AttributeError:
   30.26 +        return None
   30.27 +    except LookupError:
   30.28 +        return None
   30.29  
   30.30  def setAttr(obj, attr, val):
   30.31      if isinstance(obj, dict):
   30.32 -        dict[attr] = val
   30.33 +        obj[attr] = val
   30.34      else:
   30.35          setattr(obj, attr, val)
   30.36  
   30.37 @@ -48,15 +55,15 @@ class DBConverter:
   30.38  
   30.39      getConverter = classmethod(getConverter)
   30.40  
   30.41 -    def convertToDB(cls, val, ty=None):
   30.42 -        return cls.getConverter(ty).toDB(val)
   30.43 +    def exportTypeToDB(cls, db, path, val, ty=None):
   30.44 +        return cls.getConverter(ty).exportToDB(db, path, val)
   30.45  
   30.46 -    convertToDB = classmethod(convertToDB)
   30.47 +    exportTypeToDB = classmethod(exportTypeToDB)
   30.48  
   30.49 -    def convertFromDB(cls, val, ty=None):
   30.50 -        return cls.getConverter(ty).fromDB(val)
   30.51 +    def importTypeFromDB(cls, db, path, ty=None):
   30.52 +        return cls.getConverter(ty).importFromDB(db, path)
   30.53  
   30.54 -    convertFromDB = classmethod(convertFromDB)
   30.55 +    importTypeFromDB = classmethod(importTypeFromDB)
   30.56  
   30.57      # Must define in subclass.
   30.58      name = None
   30.59 @@ -69,6 +76,26 @@ class DBConverter:
   30.60              raise ValueError("invalid converter name: '%s'" % self.name)
   30.61          self.converters[self.name] = self
   30.62  
   30.63 +    def exportToDB(self, db, path, val):
   30.64 +        if val is None:
   30.65 +            return
   30.66 +        try:
   30.67 +            data = self.toDB(val)
   30.68 +        except Exception, ex:
   30.69 +            raise
   30.70 +        setattr(db, path, data)
   30.71 +
   30.72 +    def importFromDB(self, db, path):
   30.73 +        data = getAttr(db, path)
   30.74 +        if data is None:
   30.75 +            val = None
   30.76 +        else:
   30.77 +            try:
   30.78 +                val = self.fromDB(data.getData())
   30.79 +            except Exception, ex:
   30.80 +                raise
   30.81 +        return val
   30.82 +        
   30.83      def toDB(self, val):
   30.84          raise NotImplementedError()
   30.85  
   30.86 @@ -178,10 +205,12 @@ class DBVar:
   30.87          self.attr = varpath[-1]
   30.88  
   30.89      def exportToDB(self, db, obj):
   30.90 -        self.setDB(db, self.getObj(obj))
   30.91 +        val = self.getObj(obj)
   30.92 +        DBConverter.exportTypeToDB(db, self.path, val, ty=self.ty)
   30.93  
   30.94      def importFromDB(self, db, obj):
   30.95 -        self.setObj(obj, self.getDB(db))
   30.96 +        val = DBConverter.importTypeFromDB(db, self.path, ty=self.ty)
   30.97 +        self.setObj(obj, val)
   30.98  
   30.99      def getObj(self, obj):
  30.100          o = obj
  30.101 @@ -200,23 +229,6 @@ class DBVar:
  30.102              return
  30.103          setAttr(o, self.attr, val)
  30.104  
  30.105 -    def getDB(self, db):
  30.106 -        try:
  30.107 -            data = getattr(db, self.path)
  30.108 -        except AttributeError:
  30.109 -            return None
  30.110 -        return DBConverter.convertFromDB(data, ty=self.ty)
  30.111 -
  30.112 -    def setDB(self, db, val):
  30.113 -        # Don't set in db if val is None.
  30.114 -        #print 'DBVar>setDB>', self.path, 'val=', val
  30.115 -        if val is None:
  30.116 -            return
  30.117 -        data = DBConverter.convertToDB(val, ty=self.ty)
  30.118 -        #print 'DBVar>setDB>', self.path, 'data=', data
  30.119 -        setattr(db, self.path, data)
  30.120 -        
  30.121 -
  30.122  class DBMap(dict):
  30.123      """A persistent map. Extends dict with persistence.
  30.124      Set and get values using the usual map syntax:
  30.125 @@ -314,6 +326,21 @@ class DBMap(dict):
  30.126              traceback.print_exc()
  30.127              print 'DBMap>releaseDomain>', ex
  30.128              pass # todo: don't ignore
  30.129 +
  30.130 +    def watch(self, fn, path=""):
  30.131 +        return self.__db__.watch(fn, path=path)
  30.132 +
  30.133 +    def unwatch(self, sid):
  30.134 +        return self.__db__.unwatch(sid)
  30.135 +
  30.136 +    def subscribe(self, event, fn):
  30.137 +        return self.__db__.subscribe(event, fn)
  30.138 +
  30.139 +    def unsubscribe(self, sid):
  30.140 +        return self.__db__.unsubscribe(sid)
  30.141 +
  30.142 +    def sendEvent(self, event, val):
  30.143 +        return self.__db__.sendEvent(event, val)
  30.144          
  30.145      def transactionBegin(self):
  30.146          # Begin a transaction.
  30.147 @@ -328,12 +355,6 @@ class DBMap(dict):
  30.148          # We have changed values, what do we do?
  30.149          pass
  30.150  
  30.151 -    def watch(self, fn):
  30.152 -        pass
  30.153 -
  30.154 -    def unwatch(self, watch):
  30.155 -        pass
  30.156 -        
  30.157      def checkName(self, k):
  30.158          if k == "":
  30.159              raise ValueError("invalid key, empty string")
  30.160 @@ -456,6 +477,9 @@ class DBMap(dict):
  30.161              n = n._addChild(x)
  30.162          return n
  30.163  
  30.164 +    def getDB(self):
  30.165 +        return self.__db__
  30.166 +
  30.167      def setDB(self, db):
  30.168          if (db is not None) and not isinstance(db, XenNode):
  30.169              raise ValueError("invalid db")
    31.1 --- a/tools/xcs/xcs_proto.h	Mon Jun 13 13:18:58 2005 +0000
    31.2 +++ b/tools/xcs/xcs_proto.h	Fri Jun 17 20:47:52 2005 +0000
    31.3 @@ -40,7 +40,7 @@
    31.4  #define TYPE_VIRQ      0xfffe
    31.5  
    31.6  typedef struct {
    31.7 -    u32 session_id;
    31.8 +    unsigned long  session_id;
    31.9  } xcs_connect_msg_t;
   31.10  
   31.11  typedef struct {
    32.1 --- a/tools/xenstore/Makefile	Mon Jun 13 13:18:58 2005 +0000
    32.2 +++ b/tools/xenstore/Makefile	Fri Jun 17 20:47:52 2005 +0000
    32.3 @@ -20,17 +20,14 @@ BASECFLAGS+= -I$(XEN_ROOT)/xen/include/p
    32.4  BASECFLAGS+= -I.
    32.5  
    32.6  CFLAGS += $(BASECFLAGS)
    32.7 -ifeq ($(XEN_TARGET_ARCH),x86_64)
    32.8 -CFLAGS += -fPIC
    32.9 -endif
   32.10  LDFLAGS=$(PROFILE) -L$(XEN_LIBXC)
   32.11  TESTDIR=`pwd`/testsuite/tmp
   32.12  TESTFLAGS=-DTESTING
   32.13  TESTENV=XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
   32.14  
   32.15 -all: xen xenstored libxenstore.a
   32.16 +all: xen xenstored libxenstore.a libxenstore-pic.a
   32.17  
   32.18 -testcode: xen xs_test xenstored_test xs_random
   32.19 +testcode: xen xs_test xenstored_test xs_random xs_dom0_test
   32.20  
   32.21  xen:
   32.22  	ln -sf $(XEN_ROOT)/xen/include/public $@
   32.23 @@ -44,8 +41,9 @@ xenstored_test: xenstored_core_test.o xe
   32.24  xs_test: xs_test.o xs_lib.o utils.o
   32.25  xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
   32.26  xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
   32.27 +xs_watch_stress: xs_watch_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
   32.28  
   32.29 -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: CFLAGS=$(BASECFLAGS) $(TESTFLAGS)
   32.30 +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)
   32.31  
   32.32  xenstored_%_test.o: xenstored_%.c
   32.33  	$(COMPILE.c) -o $@ $<
   32.34 @@ -56,10 +54,19 @@ xs_test_lib.o: xs.c
   32.35  talloc_test.o: talloc.c
   32.36  	$(COMPILE.c) -o $@ $<
   32.37  
   32.38 -libxenstore.a: libxenstore.a(xs.o) libxenstore.a(xs_lib.o)
   32.39 +LIB_OBJS     := xs.o xs_lib.o
   32.40 +
   32.41 +LIB_OBJS_A   := $(patsubst %.o,libxenstore.a(%.o),$(LIB_OBJS))
   32.42 +LIB_OBJS_PIC := $(patsubst %.o,libxenstore-pic.a(%.opic),$(LIB_OBJS))
   32.43 +
   32.44 +libxenstore.a: $(LIB_OBJS_A)
   32.45 +
   32.46 +libxenstore-pic.a: $(LIB_OBJS_PIC)
   32.47  
   32.48  clean: testsuite-clean
   32.49 -	rm -f *.o *.a xs_test xenstored xenstored_test xs_random xs_stress xen
   32.50 +	rm -f *.o *.opic *.a
   32.51 +	rm -f xen xenstored xs_random xs_stress xs_watch_stress
   32.52 +	rm -f xs_test xenstored_test xs_dom0_test
   32.53  	-$(RM) $(PROG_DEP)
   32.54  
   32.55  check: testsuite-run randomcheck stresstest
   32.56 @@ -78,9 +85,14 @@ randomcheck: xs_random xenstored_test
   32.57  	$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED)
   32.58  	$(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
   32.59  
   32.60 -stresstest: xs_stress xenstored_test
   32.61 +stresstest: xs_stress xs_watch_stress xenstored_test
   32.62 +	rm -rf $(TESTDIR)/store
   32.63 +	export $(TESTENV); PID=`./xenstored_test --output-pid`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
   32.64  	rm -rf $(TESTDIR)/store
   32.65 -	export $(TESTENV); PID=`./xenstored_test --output-pid`; ./xs_stress 10000; ret=$$?; kill $$PID; exit $$ret
   32.66 +	export $(TESTENV); PID=`./xenstored_test --output-pid`; ./xs_watch_stress; ret=$$?; kill $$PID; exit $$ret
   32.67 +
   32.68 +xs_dom0_test: xs_dom0_test.o utils.o
   32.69 +	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxc -o $@
   32.70  
   32.71  TAGS:
   32.72  	etags `find . -name '*.[ch]'`
   32.73 @@ -88,7 +100,7 @@ TAGS:
   32.74  tarball: clean
   32.75  	cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
   32.76  
   32.77 -install: xenstored libxenstore.a
   32.78 +install: xenstored libxenstore.a libxenstore-pic.a
   32.79  	$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
   32.80  	$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
   32.81  	$(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
   32.82 @@ -96,7 +108,11 @@ install: xenstored libxenstore.a
   32.83  	$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
   32.84  	$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
   32.85  	$(INSTALL_DATA) libxenstore.a $(DESTDIR)/usr/$(LIBDIR)
   32.86 +	$(INSTALL_DATA) libxenstore-pic.a $(DESTDIR)/usr/$(LIBDIR)
   32.87  	$(INSTALL_DATA) xs.h $(DESTDIR)/usr/include
   32.88  	$(INSTALL_DATA) xs_lib.h $(DESTDIR)/usr/include
   32.89  
   32.90  -include $(PROG_DEP)
   32.91 +
   32.92 +# never delete any intermediate files.
   32.93 +.SECONDARY:
    33.1 --- a/tools/xenstore/testsuite/07watch.sh	Mon Jun 13 13:18:58 2005 +0000
    33.2 +++ b/tools/xenstore/testsuite/07watch.sh	Fri Jun 17 20:47:52 2005 +0000
    33.3 @@ -3,30 +3,118 @@
    33.4  # Watch something, write to it, check watch has fired.
    33.5  [ "`echo -e 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    33.6  
    33.7 -[ "`echo -e '1 watch /test 100\n2 write /test create contents2\n1 waitwatch\n1 ackwatch' | ./xs_test 2>&1`" = "1:/test" ]
    33.8 +[ "`echo -e '1 watch /test token 100
    33.9 +2 write /test create contents2
   33.10 +1 waitwatch
   33.11 +1 ackwatch token' | ./xs_test 2>&1`" = "1:/test:token" ]
   33.12  
   33.13  # Check that reads don't set it off.
   33.14 -[ "`echo -e '1 watch /test 100\n2 read /test\n1 waitwatch' | ./xs_test 2>&1`" = "2:contents2
   33.15 +[ "`echo -e '1 watch /test token 100
   33.16 +2 read /test
   33.17 +1 waitwatch' | ./xs_test 2>&1`" = "2:contents2
   33.18  1:waitwatch timeout" ]
   33.19  
   33.20 -# mkdir, setperm and rm should (also /tests watching dirs)
   33.21 +# mkdir, setperm and rm should (also tests watching dirs)
   33.22  [ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
   33.23 -[ "`echo -e '1 watch /dir 100\n2 mkdir /dir/newdir\n1 waitwatch\n1 ackwatch\n2 setperm /dir/newdir 0 READ\n1 waitwatch\n1 ackwatch\n2 rm /dir/newdir\n1 waitwatch\n1 ackwatch' | ./xs_test 2>&1`" = "1:/dir/newdir
   33.24 -1:/dir/newdir
   33.25 -1:/dir/newdir" ]
   33.26 +[ "`echo -e '1 watch /dir token 100
   33.27 +2 mkdir /dir/newdir
   33.28 +1 waitwatch
   33.29 +1 ackwatch token
   33.30 +2 setperm /dir/newdir 0 READ
   33.31 +1 waitwatch
   33.32 +1 ackwatch token
   33.33 +2 rm /dir/newdir
   33.34 +1 waitwatch
   33.35 +1 ackwatch token' | ./xs_test 2>&1`" = "1:/dir/newdir:token
   33.36 +1:/dir/newdir:token
   33.37 +1:/dir/newdir:token" ]
   33.38  
   33.39  # ignore watches while doing commands, should work.
   33.40 -[ "`echo -e 'watch /dir 100\nwrite /dir/test create contents\nread /dir/test\nwaitwatch\nackwatch' | ./xs_test 2>&1`" = "contents
   33.41 -/dir/test" ]
   33.42 +[ "`echo -e 'watch /dir token 100
   33.43 +write /dir/test create contents
   33.44 +read /dir/test
   33.45 +waitwatch
   33.46 +ackwatch token' | ./xs_test 2>&1`" = "contents
   33.47 +/dir/test:token" ]
   33.48  
   33.49  # watch priority /test.
   33.50 -[ "`echo -e '1 watch /dir 1\n3 watch /dir 3\n2 watch /dir 2\nwrite /dir/test create contents\n3 waitwatch\n3 ackwatch\n2 waitwatch\n2 ackwatch\n1 waitwatch\n1 ackwatch' | ./xs_test 2>&1`" = "3:/dir/test
   33.51 -2:/dir/test
   33.52 -1:/dir/test" ]
   33.53 +[ "`echo -e '1 watch /dir token1 1
   33.54 +3 watch /dir token3 3
   33.55 +2 watch /dir token2 2
   33.56 +write /dir/test create contents
   33.57 +3 waitwatch
   33.58 +3 ackwatch token3
   33.59 +2 waitwatch
   33.60 +2 ackwatch token2
   33.61 +1 waitwatch
   33.62 +1 ackwatch token1' | ./xs_test 2>&1`" = "3:/dir/test:token3
   33.63 +2:/dir/test:token2
   33.64 +1:/dir/test:token1" ]
   33.65  
   33.66  # If one dies (without acking), the other should still get ack.
   33.67 -[ "`echo -e '1 watch /dir 0\n2 watch /dir 1\nwrite /dir/test create contents\n2 waitwatch\n2 close\n1 waitwatch\n1 ackwatch' | ./xs_test 2>&1`" = "2:/dir/test
   33.68 -1:/dir/test" ]
   33.69 +[ "`echo -e '1 watch /dir token1 0
   33.70 +2 watch /dir token2 1
   33.71 +write /dir/test create contents
   33.72 +2 waitwatch
   33.73 +2 close
   33.74 +1 waitwatch
   33.75 +1 ackwatch token1' | ./xs_test 2>&1`" = "2:/dir/test:token2
   33.76 +1:/dir/test:token1" ]
   33.77  
   33.78  # If one dies (without reading at all), the other should still get ack.
   33.79 -[ "`echo -e '1 watch /dir 0\n2 watch /dir 1\nwrite /dir/test create contents\n2 close\n1 waitwatch\n1 ackwatch' | ./xs_test 2>&1`" = "1:/dir/test" ]
   33.80 +[ "`echo -e '1 watch /dir token1 0
   33.81 +2 watch /dir token2 1
   33.82 +write /dir/test create contents
   33.83 +2 close
   33.84 +1 waitwatch
   33.85 +1 ackwatch token1' | ./xs_test 2>&1`" = "1:/dir/test:token1" ]
   33.86 +
   33.87 +# unwatch
   33.88 +[ "`echo -e '1 watch /dir token1 0
   33.89 +1 unwatch /dir token1
   33.90 +1 watch /dir token2 0
   33.91 +2 write /dir/test2 create contents
   33.92 +1 waitwatch
   33.93 +1 unwatch /dir token2' | ./xs_test 2>&1`" = "1:/dir/test2:token2" ]
   33.94 +
   33.95 +# unwatch while watch pending.
   33.96 +[ "`echo -e '1 watch /dir token1 0
   33.97 +2 watch /dir token2 1
   33.98 +write /dir/test create contents
   33.99 +2 unwatch /dir token2
  33.100 +1 waitwatch
  33.101 +1 ackwatch token1' | ./xs_test 2>&1`" = "1:/dir/test:token1" ]
  33.102 +
  33.103 +# check we only get notified once.
  33.104 +[ "`echo -e '1 watch /test token 100
  33.105 +2 write /test create contents2
  33.106 +1 waitwatch
  33.107 +1 ackwatch token
  33.108 +1 waitwatch' | ./xs_test 2>&1`" = "1:/test:token
  33.109 +1:waitwatch timeout" ]
  33.110 +
  33.111 +# watches are queued in order.
  33.112 +[ "`echo -e '1 watch / token 100
  33.113 +2 write /test1 create contents
  33.114 +2 write /test2 create contents
  33.115 +2 write /test3 create contents
  33.116 +1 waitwatch
  33.117 +1 ackwatch token
  33.118 +1 waitwatch
  33.119 +1 ackwatch token
  33.120 +1 waitwatch
  33.121 +1 ackwatch token' | ./xs_test 2>&1`" = "1:/test1:token
  33.122 +1:/test2:token
  33.123 +1:/test3:token" ]
  33.124 +
  33.125 +# Creation of subpaths should be covered correctly.
  33.126 +[ "`echo -e '1 watch / token 100
  33.127 +2 write /test/subnode create contents2
  33.128 +2 write /test/subnode/subnode create contents2
  33.129 +1 waitwatch
  33.130 +1 ackwatch token
  33.131 +1 waitwatch
  33.132 +1 ackwatch token
  33.133 +1 waitwatch' | ./xs_test 2>&1`" = "1:/test/subnode:token
  33.134 +1:/test/subnode/subnode:token
  33.135 +1:waitwatch timeout" ]
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/xenstore/testsuite/10domain-homedir.sh	Fri Jun 17 20:47:52 2005 +0000
    34.3 @@ -0,0 +1,12 @@
    34.4 +#! /bin/sh
    34.5 +# Test domain "implicit" paths.
    34.6 +
    34.7 +# Create a domain, write an entry using implicit path, read using implicit
    34.8 +[ "`echo -e 'mkdir /home
    34.9 +introduce 1 100 7 /home
   34.10 +1 write entry1 create contents
   34.11 +read /home/entry1
   34.12 +dir /home' | ./xs_test 2>&1`" = "handle is 1
   34.13 +contents
   34.14 +entry1" ]
   34.15 +
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/xenstore/testsuite/11domain-watch.sh	Fri Jun 17 20:47:52 2005 +0000
    35.3 @@ -0,0 +1,51 @@
    35.4 +#! /bin/sh
    35.5 +# Test watching from a domain.
    35.6 +
    35.7 +# Watch something, write to it, check watch has fired.
    35.8 +[ "`echo -e 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    35.9 +[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
   35.10 +
   35.11 +[ "`echo -e 'introduce 1 100 7 /my/home
   35.12 +1 watch /test token 100
   35.13 +write /test create contents2
   35.14 +1 waitwatch
   35.15 +1 ackwatch token
   35.16 +1 unwatch /test token
   35.17 +release 1' | ./xs_test 2>&1`" = "handle is 1
   35.18 +1:/test:token" ]
   35.19 +
   35.20 +# ignore watches while doing commands, should work.
   35.21 +[ "`echo -e 'introduce 1 100 7 /my/home
   35.22 +1 watch /dir token 100
   35.23 +1 write /dir/test create contents
   35.24 +1 read /dir/test
   35.25 +1 waitwatch
   35.26 +1 ackwatch token
   35.27 +release 1' | ./xs_test 2>&1`" = "handle is 1
   35.28 +1:contents
   35.29 +1:/dir/test:token" ]
   35.30 +
   35.31 +# unwatch
   35.32 +[ "`echo -e 'introduce 1 100 7 /my/home
   35.33 +1 watch /dir token1 0
   35.34 +1 unwatch /dir token1
   35.35 +1 watch /dir token2 0
   35.36 +2 write /dir/test2 create contents
   35.37 +1 waitwatch
   35.38 +1 unwatch /dir token2
   35.39 +release 1' | ./xs_test 2>&1`" = "handle is 1
   35.40 +1:/dir/test2:token2" ]
   35.41 +
   35.42 +# unwatch while watch pending.
   35.43 +[ "`echo -e 'introduce 1 100 7 /my/home
   35.44 +introduce 2 101 8 /my/secondhome
   35.45 +1 watch /dir token1 0
   35.46 +2 watch /dir token2 1
   35.47 +write /dir/test create contents
   35.48 +2 unwatch /dir token2
   35.49 +1 waitwatch
   35.50 +1 ackwatch token1
   35.51 +release 1
   35.52 +release 2' | ./xs_test 2>&1`" = "handle is 1
   35.53 +handle is 2
   35.54 +1:/dir/test:token1" ]
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/xenstore/testsuite/12readonly.sh	Fri Jun 17 20:47:52 2005 +0000
    36.3 @@ -0,0 +1,40 @@
    36.4 +#! /bin/sh
    36.5 +# Test that read only connection can't alter store.
    36.6 +
    36.7 +[ "`echo 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    36.8 +
    36.9 +# These are all valid.
   36.10 +[ "`echo 'dir /
   36.11 +read /test
   36.12 +getperm /test
   36.13 +watch /test token 0
   36.14 +unwatch /test token 
   36.15 +start /
   36.16 +commit
   36.17 +start /
   36.18 +abort' | ./xs_test --readonly 2>&1`" = "test
   36.19 +contents
   36.20 +0 NONE" ]
   36.21 +
   36.22 +# These don't work
   36.23 +[ "`echo 'write /test2 create contents' | ./xs_test --readonly 2>&1`" = "FATAL: write: Read-only file system" ]
   36.24 +[ "`echo 'write /test create contents' | ./xs_test --readonly 2>&1`" = "FATAL: write: Read-only file system" ]
   36.25 +[ "`echo 'setperm /test 100 NONE' | ./xs_test --readonly 2>&1`" = "FATAL: setperm: Read-only file system" ]
   36.26 +[ "`echo 'setperm /test 100 NONE' | ./xs_test --readonly 2>&1`" = "FATAL: setperm: Read-only file system" ]
   36.27 +[ "`echo 'shutdown' | ./xs_test --readonly 2>&1`" = "FATAL: shutdown: Read-only file system" ]
   36.28 +[ "`echo 'introduce 1 100 7 /home' | ./xs_test --readonly 2>&1`" = "FATAL: introduce: Read-only file system" ]
   36.29 +
   36.30 +# Check that watches work like normal.
   36.31 +set -m
   36.32 +[ "`echo 'watch / token 0
   36.33 +waitwatch
   36.34 +ackwatch token' | ./xs_test --readonly 2>&1`" = "/test:token" ] &
   36.35 +
   36.36 +[ "`echo 'write /test create contents' | ./xs_test 2>&1`" = "" ]
   36.37 +if wait; then :; else
   36.38 +    echo Readonly wait test failed: $?
   36.39 +    exit 1
   36.40 +fi
   36.41 +    
   36.42 +    
   36.43 +
    37.1 --- a/tools/xenstore/testsuite/test.sh	Mon Jun 13 13:18:58 2005 +0000
    37.2 +++ b/tools/xenstore/testsuite/test.sh	Fri Jun 17 20:47:52 2005 +0000
    37.3 @@ -9,7 +9,7 @@ run_test()
    37.4      mkdir $XENSTORED_ROOTDIR
    37.5  # Weird failures with this.
    37.6      if type valgrind >/dev/null 2>&1; then
    37.7 -	valgrind -q --logfile-fd=3 ./xenstored_test --output-pid --no-fork 3>testsuite/tmp/vgout > /tmp/pid &
    37.8 +	valgrind -q --logfile-fd=3 ./xenstored_test --output-pid --no-fork 3>testsuite/tmp/vgout > /tmp/pid 2> testsuite/tmp/xenstored_errors &
    37.9  	while [ ! -s /tmp/pid ]; do sleep 0; done
   37.10  	PID=`cat /tmp/pid`
   37.11  	rm /tmp/pid
    38.1 --- a/tools/xenstore/xenstored_core.c	Mon Jun 13 13:18:58 2005 +0000
    38.2 +++ b/tools/xenstore/xenstored_core.c	Fri Jun 17 20:47:52 2005 +0000
    38.3 @@ -122,6 +122,33 @@ void __attribute__((noreturn)) corrupt(s
    38.4  	_exit(2);
    38.5  }
    38.6  
    38.7 +static char *sockmsg_string(enum xsd_sockmsg_type type)
    38.8 +{
    38.9 +	switch (type) {
   38.10 +	case XS_DEBUG: return "DEBUG";
   38.11 +	case XS_SHUTDOWN: return "SHUTDOWN";
   38.12 +	case XS_DIRECTORY: return "DIRECTORY";
   38.13 +	case XS_READ: return "READ";
   38.14 +	case XS_GET_PERMS: return "GET_PERMS";
   38.15 +	case XS_WATCH: return "WATCH";
   38.16 +	case XS_WATCH_ACK: return "WATCH_ACK";
   38.17 +	case XS_UNWATCH: return "UNWATCH";
   38.18 +	case XS_TRANSACTION_START: return "TRANSACTION_START";
   38.19 +	case XS_TRANSACTION_END: return "TRANSACTION_END";
   38.20 +	case XS_INTRODUCE: return "INTRODUCE";
   38.21 +	case XS_RELEASE: return "RELEASE";
   38.22 +	case XS_GETDOMAINPATH: return "GETDOMAINPATH";
   38.23 +	case XS_WRITE: return "WRITE";
   38.24 +	case XS_MKDIR: return "MKDIR";
   38.25 +	case XS_RM: return "RM";
   38.26 +	case XS_SET_PERMS: return "SET_PERMS";
   38.27 +	case XS_WATCH_EVENT: return "WATCH_EVENT";
   38.28 +	case XS_ERROR: return "ERROR";
   38.29 +	default:
   38.30 +		return "**UNKNOWN**";
   38.31 +	}
   38.32 +}
   38.33 +
   38.34  static bool write_message(struct connection *conn)
   38.35  {
   38.36  	int ret;
   38.37 @@ -129,8 +156,9 @@ static bool write_message(struct connect
   38.38  
   38.39  	if (out->inhdr) {
   38.40  		if (verbose)
   38.41 -			xprintf("Writing msg %i out to %p\n",
   38.42 -				out->hdr.msg.type, conn);
   38.43 +			xprintf("Writing msg %s (%s) out to %p\n",
   38.44 +				sockmsg_string(out->hdr.msg.type),
   38.45 +				out->buffer, conn);
   38.46  		ret = conn->write(conn, out->hdr.raw + out->used,
   38.47  				  sizeof(out->hdr) - out->used);
   38.48  		if (ret < 0)
   38.49 @@ -148,9 +176,6 @@ static bool write_message(struct connect
   38.50  			return true;
   38.51  	}
   38.52  
   38.53 -	if (verbose)
   38.54 -		xprintf("Writing data len %i out to %p\n",
   38.55 -			out->hdr.msg.len, conn);
   38.56  	ret = conn->write(conn, out->buffer + out->used,
   38.57  			  out->hdr.msg.len - out->used);
   38.58  
   38.59 @@ -162,10 +187,7 @@ static bool write_message(struct connect
   38.60  		return true;
   38.61  
   38.62  	conn->out = NULL;
   38.63 -
   38.64 -	/* If this was an event, we wait for ack, otherwise we're done. */
   38.65 -	if (!is_watch_event(conn, out))
   38.66 -		talloc_free(out);
   38.67 +	talloc_free(out);
   38.68  
   38.69  	queue_next_event(conn);
   38.70  	return true;
   38.71 @@ -402,7 +424,7 @@ static bool valid_chars(const char *node
   38.72  		       "0123456789-/_@") == strlen(node));
   38.73  }
   38.74  
   38.75 -static bool is_valid_nodename(const char *node)
   38.76 +bool is_valid_nodename(const char *node)
   38.77  {
   38.78  	/* Must start in /. */
   38.79  	if (!strstarts(node, "/"))
   38.80 @@ -601,17 +623,24 @@ static int check_with_parents(struct con
   38.81  	return errnum;
   38.82  }
   38.83  
   38.84 +char *canonicalize(struct connection *conn, const char *node)
   38.85 +{
   38.86 +	const char *prefix;
   38.87 +
   38.88 +	if (!node || strstarts(node, "/"))
   38.89 +		return (char *)node;
   38.90 +	prefix = get_implicit_path(conn);
   38.91 +	if (prefix)
   38.92 +		return talloc_asprintf(node, "%s/%s", prefix, node);
   38.93 +	return (char *)node;
   38.94 +}
   38.95 +
   38.96  bool check_node_perms(struct connection *conn, const char *node,
   38.97  		      enum xs_perm_type perm)
   38.98  {
   38.99  	struct xs_permissions *perms;
  38.100  	unsigned int num;
  38.101  
  38.102 -	if (!node) {
  38.103 -		errno = EINVAL;
  38.104 -		return false;
  38.105 -	}
  38.106 -
  38.107  	if (!node || !is_valid_nodename(node)) {
  38.108  		errno = EINVAL;
  38.109  		return false;
  38.110 @@ -651,6 +680,7 @@ static bool send_directory(struct connec
  38.111  	DIR *dir;
  38.112  	struct dirent *dirent;
  38.113  
  38.114 +	node = canonicalize(conn, node);
  38.115  	if (!check_node_perms(conn, node, XS_PERM_READ))
  38.116  		return send_error(conn, errno);
  38.117  
  38.118 @@ -680,6 +710,7 @@ static bool do_read(struct connection *c
  38.119  	unsigned int size;
  38.120  	int *fd;
  38.121  
  38.122 +	node = canonicalize(conn, node);
  38.123  	if (!check_node_perms(conn, node, XS_PERM_READ))
  38.124  		return send_error(conn, errno);
  38.125  
  38.126 @@ -750,7 +781,7 @@ static bool do_write(struct connection *
  38.127  	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec))
  38.128  		return send_error(conn, EINVAL);
  38.129  
  38.130 -	node = vec[0];
  38.131 +	node = canonicalize(conn, vec[0]);
  38.132  	if (!within_transaction(conn->transaction, node))
  38.133  		return send_error(conn, EROFS);
  38.134  
  38.135 @@ -804,6 +835,7 @@ static bool do_write(struct connection *
  38.136  
  38.137  static bool do_mkdir(struct connection *conn, const char *node)
  38.138  {
  38.139 +	node = canonicalize(conn, node);
  38.140  	if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_CREATE))
  38.141  		return send_error(conn, errno);
  38.142  
  38.143 @@ -826,6 +858,7 @@ static bool do_rm(struct connection *con
  38.144  {
  38.145  	char *tmppath, *path;
  38.146  
  38.147 +	node = canonicalize(conn, node);
  38.148  	if (!check_node_perms(conn, node, XS_PERM_WRITE))
  38.149  		return send_error(conn, errno);
  38.150  
  38.151 @@ -848,6 +881,7 @@ static bool do_rm(struct connection *con
  38.152  
  38.153  	add_change_node(conn->transaction, node);
  38.154  	send_ack(conn, XS_RM);
  38.155 +	/* FIXME: traverse and fire watches for ALL of them! */
  38.156  	fire_watches(conn->transaction, node);
  38.157  	return false;
  38.158  }
  38.159 @@ -858,6 +892,7 @@ static bool do_get_perms(struct connecti
  38.160  	char *strings;
  38.161  	unsigned int len, num;
  38.162  
  38.163 +	node = canonicalize(conn, node);
  38.164  	if (!check_node_perms(conn, node, XS_PERM_READ))
  38.165  		return send_error(conn, errno);
  38.166  
  38.167 @@ -883,7 +918,7 @@ static bool do_set_perms(struct connecti
  38.168  		return send_error(conn, EINVAL);
  38.169  
  38.170  	/* First arg is node name. */
  38.171 -	node = in->buffer;
  38.172 +	node = canonicalize(conn, in->buffer);
  38.173  	in->buffer += strlen(in->buffer) + 1;
  38.174  	num--;
  38.175  
  38.176 @@ -968,10 +1003,10 @@ static bool process_message(struct conne
  38.177  		return do_watch(conn, in);
  38.178  
  38.179  	case XS_WATCH_ACK:
  38.180 -		return do_watch_ack(conn);
  38.181 +		return do_watch_ack(conn, onearg(in));
  38.182  
  38.183  	case XS_UNWATCH:
  38.184 -		return do_unwatch(conn, onearg(in));
  38.185 +		return do_unwatch(conn, in);
  38.186  
  38.187  	case XS_TRANSACTION_START:
  38.188  		return do_transaction_start(conn, onearg(in));
  38.189 @@ -1015,13 +1050,13 @@ static void consider_message(struct conn
  38.190  	}
  38.191  
  38.192  	if (verbose)
  38.193 -		xprintf("Got message %i len %i from %p\n",
  38.194 -			type, conn->in->hdr.msg.len, conn);
  38.195 +		xprintf("Got message %s len %i from %p\n",
  38.196 +			sockmsg_string(type), conn->in->hdr.msg.len, conn);
  38.197  
  38.198  	/* We might get a command while waiting for an ack: this means
  38.199  	 * the other end discarded it: we will re-transmit. */
  38.200  	if (type != XS_WATCH_ACK)
  38.201 -		reset_watch_event(conn);
  38.202 +		conn->waiting_for_ack = false;
  38.203  
  38.204  	/* Careful: process_message may free connection.  We detach
  38.205  	 * "in" beforehand and allocate the new buffer to avoid
  38.206 @@ -1136,7 +1171,6 @@ struct connection *new_connection(connwr
  38.207  
  38.208  	new->blocked = false;
  38.209  	new->out = new->waiting_reply = NULL;
  38.210 -	new->event = NULL;
  38.211  	new->fd = -1;
  38.212  	new->id = 0;
  38.213  	new->domain = NULL;
  38.214 @@ -1203,6 +1237,42 @@ static void time_relative_to_now(struct 
  38.215  	}
  38.216  }
  38.217  
  38.218 +#ifdef TESTING
  38.219 +/* Useful for running under debugger. */
  38.220 +void dump_connection(void)
  38.221 +{
  38.222 +	struct connection *i;
  38.223 +
  38.224 +	list_for_each_entry(i, &connections, list) {
  38.225 +		printf("Connection %p:\n", i);
  38.226 +		if (i->id)
  38.227 +			printf("    id = %i\n", i->id);
  38.228 +		if (i->blocked)
  38.229 +			printf("    blocked on = %s\n", i->blocked);
  38.230 +		if (i->waiting_for_ack)
  38.231 +			printf("    waiting_for_ack TRUE\n");
  38.232 +		if (!i->in->inhdr || i->in->used)
  38.233 +			printf("    got %i bytes of %s\n",
  38.234 +			       i->in->used, i->in->inhdr ? "header" : "data");
  38.235 +		if (i->out)
  38.236 +			printf("    sending message %s (%s) out\n",
  38.237 +			       sockmsg_string(i->out->hdr.msg.type),
  38.238 +			       i->out->buffer);
  38.239 +		if (i->waiting_reply)
  38.240 +			printf("    ... and behind is queued %s (%s)\n",
  38.241 +			       sockmsg_string(i->waiting_reply->hdr.msg.type),
  38.242 +			       i->waiting_reply->buffer);
  38.243 +#if 0
  38.244 +		if (i->transaction)
  38.245 +			dump_transaction(i);
  38.246 +		if (i->domain)
  38.247 +			dump_domain(i);
  38.248 +#endif
  38.249 +		dump_watches(i);
  38.250 +	}
  38.251 +}
  38.252 +#endif
  38.253 +
  38.254  static struct option options[] = { { "no-fork", 0, NULL, 'N' },
  38.255  				   { "verbose", 0, NULL, 'V' },
  38.256  				   { "output-pid", 0, NULL, 'P' },
  38.257 @@ -1314,6 +1384,7 @@ int main(int argc, char *argv[])
  38.258  
  38.259  		timerclear(&tv);
  38.260  		shortest_transaction_timeout(&tv);
  38.261 +		shortest_watch_ack_timeout(&tv);
  38.262  		if (timerisset(&tv)) {
  38.263  			time_relative_to_now(&tv);
  38.264  			tvp = &tv;
  38.265 @@ -1351,8 +1422,15 @@ int main(int argc, char *argv[])
  38.266  			}
  38.267  		}
  38.268  
  38.269 -		if (tvp)
  38.270 +		/* Flush output for domain connections,  */
  38.271 +		list_for_each_entry(i, &connections, list)
  38.272 +			if (i->domain && i->out)
  38.273 +				handle_output(i);
  38.274 +
  38.275 +		if (tvp) {
  38.276  			check_transaction_timeout();
  38.277 +			check_watch_ack_timeout();
  38.278 +		}
  38.279  
  38.280  		/* If transactions ended, we might be able to do more work. */
  38.281  		unblock_connections();
    39.1 --- a/tools/xenstore/xenstored_core.h	Mon Jun 13 13:18:58 2005 +0000
    39.2 +++ b/tools/xenstore/xenstored_core.h	Fri Jun 17 20:47:52 2005 +0000
    39.3 @@ -16,8 +16,10 @@
    39.4      along with this program; if not, write to the Free Software
    39.5      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    39.6  */
    39.7 -#ifndef _XENSTORED_INTERNAL_H
    39.8 -#define _XENSTORED_INTERNAL_H
    39.9 +
   39.10 +#ifndef _XENSTORED_CORE_H
   39.11 +#define _XENSTORED_CORE_H
   39.12 +
   39.13  #include <stdbool.h>
   39.14  #include <stdint.h>
   39.15  #include <errno.h>
   39.16 @@ -59,8 +61,8 @@ struct connection
   39.17  	/* Is this a read-only connection? */
   39.18  	bool can_write;
   39.19  
   39.20 -	/* Our current event.  If all used, we're waiting for ack. */
   39.21 -	struct watch_event *event;
   39.22 +	/* Are we waiting for a watch event ack? */
   39.23 +	bool waiting_for_ack;
   39.24  
   39.25  	/* Buffered incoming data. */
   39.26  	struct buffered_data *in;
   39.27 @@ -105,6 +107,9 @@ bool send_ack(struct connection *conn, e
   39.28  /* Send an error: error is usually "errno". */
   39.29  bool send_error(struct connection *conn, int error);
   39.30  
   39.31 +/* Canonicalize this path if possible. */
   39.32 +char *canonicalize(struct connection *conn, const char *node);
   39.33 +
   39.34  /* Check permissions on this node. */
   39.35  bool check_node_perms(struct connection *conn, const char *node,
   39.36  		      enum xs_perm_type perm);
   39.37 @@ -121,6 +126,10 @@ struct connection *new_connection(connwr
   39.38  void handle_input(struct connection *conn);
   39.39  void handle_output(struct connection *conn);
   39.40  
   39.41 +/* Is this a valid node name? */
   39.42 +bool is_valid_nodename(const char *node);
   39.43 +
   39.44  /* Convenient talloc-style destructor for paths. */
   39.45  int destroy_path(void *path);
   39.46 -#endif /* _XENSTORED_INTERNAL_H */
   39.47 +
   39.48 +#endif /* _XENSTORED_CORE_H */
    40.1 --- a/tools/xenstore/xenstored_domain.c	Mon Jun 13 13:18:58 2005 +0000
    40.2 +++ b/tools/xenstore/xenstored_domain.c	Fri Jun 17 20:47:52 2005 +0000
    40.3 @@ -65,11 +65,6 @@ struct domain
    40.4  
    40.5  static LIST_HEAD(domains);
    40.6  
    40.7 -void domain_set_conn(struct domain *domain, struct connection *conn)
    40.8 -{
    40.9 -	domain->conn = conn;
   40.10 -}
   40.11 -
   40.12  struct ringbuf_head
   40.13  {
   40.14  	u32 write; /* Next place to write to */
   40.15 @@ -268,6 +263,9 @@ bool do_introduce(struct connection *con
   40.16  	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec))
   40.17  		return send_error(conn, EINVAL);
   40.18  
   40.19 +	if (conn->id != 0)
   40.20 +		return send_error(conn, EACCES);
   40.21 +
   40.22  	if (!conn->can_write)
   40.23  		return send_error(conn, EROFS);
   40.24  
   40.25 @@ -275,10 +273,9 @@ bool do_introduce(struct connection *con
   40.26  	domain = talloc(in, struct domain);
   40.27  	domain->domid = atoi(vec[0]);
   40.28  	domain->port = atoi(vec[2]);
   40.29 +	if (!domain->port || !domain->domid || !is_valid_nodename(vec[3]))
   40.30 +		return send_error(conn, EINVAL);
   40.31  	domain->path = talloc_strdup(domain, vec[3]);
   40.32 -	talloc_set_destructor(domain, destroy_domain);
   40.33 -	if (!domain->port || !domain->domid)
   40.34 -		return send_error(conn, EINVAL);
   40.35  	domain->page = xc_map_foreign_range(*xc_handle, domain->domid,
   40.36  					    getpagesize(),
   40.37  					    PROT_READ|PROT_WRITE,
   40.38 @@ -286,6 +283,9 @@ bool do_introduce(struct connection *con
   40.39  	if (!domain->page)
   40.40  		return send_error(conn, errno);
   40.41  
   40.42 +	list_add(&domain->list, &domains);
   40.43 +	talloc_set_destructor(domain, destroy_domain);
   40.44 +
   40.45  	/* One in each half of page. */
   40.46  	domain->input = domain->page;
   40.47  	domain->output = domain->page + getpagesize()/2;
   40.48 @@ -298,7 +298,6 @@ bool do_introduce(struct connection *con
   40.49  	domain->conn->domain = domain;
   40.50  
   40.51  	talloc_steal(domain->conn, domain);
   40.52 -	list_add(&domain->list, &domains);
   40.53  
   40.54  	return send_ack(conn, XS_INTRODUCE);
   40.55  }
   40.56 @@ -327,6 +326,9 @@ bool do_release(struct connection *conn,
   40.57  	if (!domid)
   40.58  		return send_error(conn, EINVAL);
   40.59  
   40.60 +	if (conn->id != 0)
   40.61 +		return send_error(conn, EACCES);
   40.62 +
   40.63  	domain = find_domain_by_domid(domid);
   40.64  	if (!domain)
   40.65  		return send_error(conn, ENOENT);
   40.66 @@ -365,6 +367,14 @@ static int close_xc_handle(void *_handle
   40.67  	return 0;
   40.68  }
   40.69  
   40.70 +/* Returns the implicit path of a connection (only domains have this) */
   40.71 +const char *get_implicit_path(const struct connection *conn)
   40.72 +{
   40.73 +	if (!conn->domain)
   40.74 +		return NULL;
   40.75 +	return conn->domain->path;
   40.76 +}
   40.77 +
   40.78  /* Returns the event channel handle. */
   40.79  int domain_init(void)
   40.80  {
    41.1 --- a/tools/xenstore/xenstored_domain.h	Mon Jun 13 13:18:58 2005 +0000
    41.2 +++ b/tools/xenstore/xenstored_domain.h	Fri Jun 17 20:47:52 2005 +0000
    41.3 @@ -16,6 +16,7 @@
    41.4      along with this program; if not, write to the Free Software
    41.5      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    41.6  */
    41.7 +
    41.8  #ifndef _XENSTORED_DOMAIN_H
    41.9  #define _XENSTORED_DOMAIN_H
   41.10  
   41.11 @@ -33,6 +34,7 @@ bool do_get_domain_path(struct connectio
   41.12  /* Returns the event channel handle */
   41.13  int domain_init(void);
   41.14  
   41.15 -void domain_set_conn(struct domain *domain, struct connection *conn);
   41.16 +/* Returns the implicit path of a connection (only domains have this) */
   41.17 +const char *get_implicit_path(const struct connection *conn);
   41.18  
   41.19  #endif /* _XENSTORED_DOMAIN_H */
    42.1 --- a/tools/xenstore/xenstored_transaction.c	Mon Jun 13 13:18:58 2005 +0000
    42.2 +++ b/tools/xenstore/xenstored_transaction.c	Fri Jun 17 20:47:52 2005 +0000
    42.3 @@ -201,6 +201,7 @@ bool do_transaction_start(struct connect
    42.4  	if (conn->transaction)
    42.5  		return send_error(conn, EBUSY);
    42.6  
    42.7 +	node = canonicalize(conn, node);
    42.8  	if (!check_node_perms(conn, node, XS_PERM_READ))
    42.9  		return send_error(conn, errno);
   42.10  
    43.1 --- a/tools/xenstore/xenstored_watch.c	Mon Jun 13 13:18:58 2005 +0000
    43.2 +++ b/tools/xenstore/xenstored_watch.c	Fri Jun 17 20:47:52 2005 +0000
    43.3 @@ -21,6 +21,8 @@
    43.4  #include <sys/types.h>
    43.5  #include <stdarg.h>
    43.6  #include <stdlib.h>
    43.7 +#include <sys/time.h>
    43.8 +#include <time.h>
    43.9  #include "talloc.h"
   43.10  #include "list.h"
   43.11  #include "xenstored_watch.h"
   43.12 @@ -28,6 +30,8 @@
   43.13  #include "utils.h"
   43.14  #include "xenstored_test.h"
   43.15  
   43.16 +/* FIXME: time out unacked watches. */
   43.17 +
   43.18  /* We create this if anyone is interested "node", then we pass it from
   43.19   * watch to watch as each connection acks it.
   43.20   */
   43.21 @@ -39,7 +43,10 @@ struct watch_event
   43.22  	/* Watch we are currently attached to. */
   43.23  	struct watch *watch;
   43.24  
   43.25 -	struct buffered_data *data;
   43.26 +	struct timeval timeout;
   43.27 +
   43.28 +	/* Name of node which changed. */
   43.29 +	char *node;
   43.30  };
   43.31  
   43.32  struct watch
   43.33 @@ -50,72 +57,63 @@ struct watch
   43.34  	/* Current outstanding events applying to this watch. */
   43.35  	struct list_head events;
   43.36  
   43.37 +	char *token;
   43.38  	char *node;
   43.39  	struct connection *conn;
   43.40  };
   43.41  static LIST_HEAD(watches);
   43.42  
   43.43 -static void reset_event(struct watch_event *event)
   43.44 +static struct watch_event *get_first_event(struct connection *conn)
   43.45  {
   43.46 -	event->data->inhdr = true;
   43.47 -	event->data->used = 0;
   43.48 -}
   43.49 -
   43.50 -/* We received a non-ACK response: re-queue any watch we just sent. */
   43.51 -void reset_watch_event(struct connection *conn)
   43.52 -{
   43.53 -	if (waiting_for_ack(conn))
   43.54 -		reset_event(conn->event);
   43.55 -}
   43.56 +	struct watch *watch;
   43.57 +	struct watch_event *event;
   43.58  
   43.59 -/* We're waiting if we have an event and we sent it all. */
   43.60 -bool waiting_for_ack(struct connection *conn)
   43.61 -{
   43.62 -	if (!conn->event)
   43.63 -		return false;
   43.64 +	/* Find first watch with an event. */
   43.65 +	list_for_each_entry(watch, &watches, list) {
   43.66 +		if (watch->conn != conn)
   43.67 +			continue;
   43.68  
   43.69 -	if (conn->event->data->inhdr)
   43.70 -		return false;
   43.71 -	return conn->event->data->used == conn->event->data->hdr.msg.len;
   43.72 -}
   43.73 -
   43.74 -bool is_watch_event(struct connection *conn, struct buffered_data *out)
   43.75 -{
   43.76 -	return (conn->event && out == conn->event->data);
   43.77 +		event = list_top(&watch->events, struct watch_event, list);
   43.78 +		if (event)
   43.79 +			return event;
   43.80 +	}
   43.81 +	return NULL;
   43.82  }
   43.83  
   43.84  /* Look through our watches: if any of them have an event, queue it. */
   43.85  void queue_next_event(struct connection *conn)
   43.86  {
   43.87 -	struct watch *watch;
   43.88 +	struct watch_event *event;
   43.89 +	char *buffer;
   43.90 +	unsigned int len;
   43.91  
   43.92 -	/* We had a reply queued already?  Send it. */
   43.93 +	/* We had a reply queued already?  Send it: other end will
   43.94 +	 * discard watch. */
   43.95  	if (conn->waiting_reply) {
   43.96  		conn->out = conn->waiting_reply;
   43.97  		conn->waiting_reply = NULL;
   43.98 +		conn->waiting_for_ack = false;
   43.99  		return;
  43.100  	}
  43.101  
  43.102 -	/* If we're waiting for ack, don't queue more. */
  43.103 -	if (waiting_for_ack(conn))
  43.104 +	/* If we're already waiting for ack, don't queue more. */
  43.105 +	if (conn->waiting_for_ack)
  43.106 +		return;
  43.107 +
  43.108 +	event = get_first_event(conn);
  43.109 +	if (!event)
  43.110  		return;
  43.111  
  43.112 -	/* Find a good event to send. */
  43.113 -	if (!conn->event) {
  43.114 -		list_for_each_entry(watch, &watches, list) {
  43.115 -			if (watch->conn != conn)
  43.116 -				continue;
  43.117 +	/* If we decide to cancel, we will reset this. */
  43.118 +	conn->waiting_for_ack = true;
  43.119  
  43.120 -			conn->event = list_top(&watch->events,
  43.121 -					       struct watch_event, list);
  43.122 -			if (conn->event)
  43.123 -				break;
  43.124 -		}
  43.125 -		if (!conn->event)
  43.126 -			return;
  43.127 -	}
  43.128 -
  43.129 -	conn->out = conn->event->data;
  43.130 +	/* Create reply from path and token */
  43.131 +	len = strlen(event->node) + 1 + strlen(event->watch->token) + 1;
  43.132 +	buffer = talloc_array(conn, char, len);
  43.133 +	strcpy(buffer, event->node);
  43.134 +	strcpy(buffer+strlen(event->node)+1, event->watch->token);
  43.135 +	send_reply(conn, XS_WATCH_EVENT, buffer, len);
  43.136 +	talloc_free(buffer);
  43.137  }
  43.138  
  43.139  /* Watch on DIR applies to DIR, DIR/FILE, but not DIRLONG. */
  43.140 @@ -160,14 +158,15 @@ void fire_watches(struct transaction *tr
  43.141  
  43.142  	/* Create and fill in info about event. */
  43.143  	event = talloc(talloc_autofree_context(), struct watch_event);
  43.144 -	event->data = new_buffer(event);
  43.145 -	event->data->hdr.msg.type = XS_WATCH_EVENT;
  43.146 -	event->data->hdr.msg.len = strlen(node) + 1;
  43.147 -	event->data->buffer = talloc_strdup(event->data, node);
  43.148 +	event->node = talloc_strdup(event, node);
  43.149  
  43.150  	/* Tie event to this watch. */
  43.151  	event->watch = watch;
  43.152 -	list_add(&event->list, &watch->events);
  43.153 +	list_add_tail(&event->list, &watch->events);
  43.154 +
  43.155 +	/* Warn if not finished after thirty seconds. */
  43.156 +	gettimeofday(&event->timeout, NULL);
  43.157 +	event->timeout.tv_sec += 30;
  43.158  
  43.159  	/* If connection not doing anything, queue this. */
  43.160  	if (!watch->conn->out)
  43.161 @@ -178,16 +177,15 @@ void fire_watches(struct transaction *tr
  43.162  static void move_event_onwards(struct watch_event *event)
  43.163  {
  43.164  	list_del(&event->list);
  43.165 -	reset_event(event);
  43.166  
  43.167  	/* Remove from this watch, and find next watch to put this on. */
  43.168 -	event->watch = find_next_watch(event->watch, event->data->buffer);
  43.169 +	event->watch = find_next_watch(event->watch, event->node);
  43.170  	if (!event->watch) {
  43.171  		talloc_free(event);
  43.172  		return;
  43.173  	}
  43.174  
  43.175 -	list_add(&event->list, &event->watch->events);
  43.176 +	list_add_tail(&event->list, &event->watch->events);
  43.177  
  43.178  	/* If connection not doing anything, queue this. */
  43.179  	if (!event->watch->conn->out)
  43.180 @@ -199,10 +197,6 @@ static int destroy_watch(void *_watch)
  43.181  	struct watch *watch = _watch;
  43.182  	struct watch_event *event;
  43.183  
  43.184 -	/* Forget about sending out or waiting for acks for this watch.  */
  43.185 -	if (watch->conn->event && watch->conn->event->watch == watch)
  43.186 -		watch->conn->event = NULL;
  43.187 -
  43.188  	/* If we have pending events, pass them on to others. */
  43.189  	while ((event = list_top(&watch->events, struct watch_event, list)))
  43.190  		move_event_onwards(event);
  43.191 @@ -227,21 +221,59 @@ static void insert_watch(struct watch *w
  43.192  	list_add_tail(&watch->list, &watches);
  43.193  }
  43.194  
  43.195 +void shortest_watch_ack_timeout(struct timeval *tv)
  43.196 +{
  43.197 +	struct watch *watch;
  43.198 +
  43.199 +	list_for_each_entry(watch, &watches, list) {
  43.200 +		struct watch_event *i;
  43.201 +		list_for_each_entry(i, &watch->events, list) {
  43.202 +			if (!timerisset(&i->timeout))
  43.203 +				continue;
  43.204 +			if (!timerisset(tv) || timercmp(&i->timeout, tv, <))
  43.205 +				*tv = i->timeout;
  43.206 +		}
  43.207 +	}
  43.208 +}	
  43.209 +
  43.210 +void check_watch_ack_timeout(void)
  43.211 +{
  43.212 +	struct watch *watch;
  43.213 +	struct timeval now;
  43.214 +
  43.215 +	gettimeofday(&now, NULL);
  43.216 +	list_for_each_entry(watch, &watches, list) {
  43.217 +		struct watch_event *i, *tmp;
  43.218 +		list_for_each_entry_safe(i, tmp, &watch->events, list) {
  43.219 +			if (!timerisset(&i->timeout))
  43.220 +				continue;
  43.221 +			if (timercmp(&i->timeout, &now, <)) {
  43.222 +				xprintf("Warning: timeout on watch event %s"
  43.223 +					" token %s\n",
  43.224 +					i->node, watch->token);
  43.225 +				timerclear(&i->timeout);
  43.226 +			}
  43.227 +		}
  43.228 +	}
  43.229 +}
  43.230 +
  43.231  bool do_watch(struct connection *conn, struct buffered_data *in)
  43.232  {
  43.233  	struct watch *watch;
  43.234 -	char *vec[2];
  43.235 +	char *vec[3];
  43.236  
  43.237  	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
  43.238  		return send_error(conn, EINVAL);
  43.239  
  43.240 +	vec[0] = canonicalize(conn, vec[0]);
  43.241  	if (!check_node_perms(conn, vec[0], XS_PERM_READ))
  43.242  		return send_error(conn, errno);
  43.243  
  43.244  	watch = talloc(conn, struct watch);
  43.245  	watch->node = talloc_strdup(watch, vec[0]);
  43.246 +	watch->token = talloc_strdup(watch, vec[1]);
  43.247  	watch->conn = conn;
  43.248 -	watch->priority = strtoul(vec[1], NULL, 0);
  43.249 +	watch->priority = strtoul(vec[2], NULL, 0);
  43.250  	INIT_LIST_HEAD(&watch->events);
  43.251  
  43.252  	insert_watch(watch);
  43.253 @@ -249,31 +281,58 @@ bool do_watch(struct connection *conn, s
  43.254  	return send_ack(conn, XS_WATCH);
  43.255  }
  43.256  
  43.257 -bool do_watch_ack(struct connection *conn)
  43.258 +bool do_watch_ack(struct connection *conn, const char *token)
  43.259  {
  43.260  	struct watch_event *event;
  43.261  
  43.262 -	if (!waiting_for_ack(conn))
  43.263 +	if (!conn->waiting_for_ack)
  43.264  		return send_error(conn, ENOENT);
  43.265  
  43.266 -	/* Remove this watch event. */
  43.267 -	event = conn->event;
  43.268 -	conn->event = NULL;
  43.269 +	event = get_first_event(conn);
  43.270 +	if (!streq(event->watch->token, token))
  43.271 +		return send_error(conn, EINVAL);
  43.272  
  43.273  	move_event_onwards(event);
  43.274 +	conn->waiting_for_ack = false;
  43.275  	return send_ack(conn, XS_WATCH_ACK);
  43.276  }
  43.277  
  43.278 -bool do_unwatch(struct connection *conn, const char *node)
  43.279 +bool do_unwatch(struct connection *conn, struct buffered_data *in)
  43.280  {
  43.281  	struct watch *watch;
  43.282 +	char *node, *vec[2];
  43.283  
  43.284 +	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
  43.285 +		return send_error(conn, EINVAL);
  43.286 +
  43.287 +	node = canonicalize(conn, vec[0]);
  43.288  	list_for_each_entry(watch, &watches, list) {
  43.289 -		if (watch->conn == conn
  43.290 -		    && streq(watch->node, node)) {
  43.291 +		if (watch->conn != conn)
  43.292 +			continue;
  43.293 +
  43.294 +		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
  43.295  			talloc_free(watch);
  43.296  			return send_ack(conn, XS_UNWATCH);
  43.297  		}
  43.298  	}
  43.299  	return send_error(conn, ENOENT);
  43.300  }
  43.301 +
  43.302 +#ifdef TESTING
  43.303 +void dump_watches(struct connection *conn)
  43.304 +{
  43.305 +	struct watch *watch;
  43.306 +	struct watch_event *event;
  43.307 +
  43.308 +	/* Find first watch with an event. */
  43.309 +	list_for_each_entry(watch, &watches, list) {
  43.310 +		if (watch->conn != conn)
  43.311 +			continue;
  43.312 +
  43.313 +		printf("    watch on %s token %s prio %i\n",
  43.314 +		       watch->node, watch->token, watch->priority);
  43.315 +		list_for_each_entry(event, &watch->events, list)
  43.316 +			printf("        event: %s\n", event->node);
  43.317 +	}
  43.318 +}
  43.319 +#endif
    44.1 --- a/tools/xenstore/xenstored_watch.h	Mon Jun 13 13:18:58 2005 +0000
    44.2 +++ b/tools/xenstore/xenstored_watch.h	Fri Jun 17 20:47:52 2005 +0000
    44.3 @@ -16,13 +16,15 @@
    44.4      along with this program; if not, write to the Free Software
    44.5      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    44.6  */
    44.7 +
    44.8  #ifndef _XENSTORED_WATCH_H
    44.9  #define _XENSTORED_WATCH_H
   44.10 +
   44.11  #include "xenstored_core.h"
   44.12  
   44.13  bool do_watch(struct connection *conn, struct buffered_data *in);
   44.14 -bool do_watch_ack(struct connection *conn);
   44.15 -bool do_unwatch(struct connection *conn, const char *node);
   44.16 +bool do_watch_ack(struct connection *conn, const char *token);
   44.17 +bool do_unwatch(struct connection *conn, struct buffered_data *in);
   44.18  
   44.19  /* Is this a watch event message for this connection? */
   44.20  bool is_watch_event(struct connection *conn, struct buffered_data *out);
   44.21 @@ -30,13 +32,15 @@ bool is_watch_event(struct connection *c
   44.22  /* Look through our watches: if any of them have an event, queue it. */
   44.23  void queue_next_event(struct connection *conn);
   44.24  
   44.25 -/* Is this connection waiting for a watch acknowledgement? */
   44.26 -bool waiting_for_ack(struct connection *conn);
   44.27 -
   44.28 -/* Reset event if we were sending one */
   44.29 -void reset_watch_event(struct connection *conn);
   44.30 -
   44.31  /* Fire all watches. */
   44.32  void fire_watches(struct transaction *trans, const char *node);
   44.33  
   44.34 +/* Find shortest timeout: if any, reduce tv (may already be set). */
   44.35 +void shortest_watch_ack_timeout(struct timeval *tv);
   44.36 +
   44.37 +/* Check for watches which may have timed out. */
   44.38 +void check_watch_ack_timeout(void);
   44.39 +
   44.40 +void dump_watches(struct connection *conn);
   44.41 +
   44.42  #endif /* _XENSTORED_WATCH_H */
    45.1 --- a/tools/xenstore/xs.c	Mon Jun 13 13:18:58 2005 +0000
    45.2 +++ b/tools/xenstore/xs.c	Fri Jun 17 20:47:52 2005 +0000
    45.3 @@ -159,8 +159,7 @@ static void *read_reply(int fd, enum xsd
    45.4  
    45.5  /* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
    45.6  static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
    45.7 -		      const struct iovec *iovec,
    45.8 -		      unsigned int num_vecs,
    45.9 +		      const struct iovec *iovec, unsigned int num_vecs,
   45.10  		      unsigned int *len)
   45.11  {
   45.12  	struct xsd_sockmsg msg;
   45.13 @@ -330,8 +329,7 @@ bool xs_rm(struct xs_handle *h, const ch
   45.14   * Returns malloced array, or NULL: call free() after use.
   45.15   */
   45.16  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
   45.17 -					  const char *path,
   45.18 -					  unsigned int *num)
   45.19 +					  const char *path, unsigned int *num)
   45.20  {
   45.21  	char *strings;
   45.22  	unsigned int len;
   45.23 @@ -400,61 +398,75 @@ unwind:
   45.24  
   45.25  /* Watch a node for changes (poll on fd to detect, or call read_watch()).
   45.26   * When the node (or any child) changes, fd will become readable.
   45.27 + * Token is returned when watch is read, to allow matching.
   45.28   * Priority indicates order if multiple watchers: higher is first.
   45.29   * Returns false on failure.
   45.30   */
   45.31 -bool xs_watch(struct xs_handle *h, const char *path, unsigned int priority)
   45.32 +bool xs_watch(struct xs_handle *h, const char *path, const char *token,
   45.33 +	      unsigned int priority)
   45.34  {
   45.35  	char prio[MAX_STRLEN(priority)];
   45.36 -	struct iovec iov[2];
   45.37 +	struct iovec iov[3];
   45.38  
   45.39  	sprintf(prio, "%u", priority);
   45.40  	iov[0].iov_base = (void *)path;
   45.41  	iov[0].iov_len = strlen(path) + 1;
   45.42 -	iov[1].iov_base = prio;
   45.43 -	iov[1].iov_len = strlen(prio) + 1;
   45.44 +	iov[1].iov_base = (void *)token;
   45.45 +	iov[1].iov_len = strlen(token) + 1;
   45.46 +	iov[2].iov_base = prio;
   45.47 +	iov[2].iov_len = strlen(prio) + 1;
   45.48  
   45.49  	return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
   45.50  }
   45.51  
   45.52  /* Find out what node change was on (will block if nothing pending).
   45.53 - * Returns malloced path, or NULL: call free() after use.
   45.54 + * Returns array of two pointers: path and token, or NULL.
   45.55 + * Call free() after use.
   45.56   */
   45.57 -char *xs_read_watch(struct xs_handle *h)
   45.58 +char **xs_read_watch(struct xs_handle *h)
   45.59  {
   45.60  	struct xsd_sockmsg msg;
   45.61 -	char *path;
   45.62 +	char **ret;
   45.63  
   45.64  	if (!read_all(h->fd, &msg, sizeof(msg)))
   45.65  		return NULL;
   45.66  
   45.67  	assert(msg.type == XS_WATCH_EVENT);
   45.68 -	path = malloc(msg.len);
   45.69 -	if (!path)
   45.70 +	ret = malloc(sizeof(char *)*2 + msg.len);
   45.71 +	if (!ret)
   45.72  		return NULL;
   45.73  
   45.74 -	if (!read_all(h->fd, path, msg.len)) {
   45.75 -		free_no_errno(path);
   45.76 +	ret[0] = (char *)(ret + 2);
   45.77 +	if (!read_all(h->fd, ret[0], msg.len)) {
   45.78 +		free_no_errno(ret);
   45.79  		return NULL;
   45.80  	}
   45.81 -	return path;
   45.82 +	ret[1] = ret[0] + strlen(ret[0]) + 1;
   45.83 +	return ret;
   45.84  }
   45.85  
   45.86  /* Acknowledge watch on node.  Watches must be acknowledged before
   45.87   * any other watches can be read.
   45.88   * Returns false on failure.
   45.89   */
   45.90 -bool xs_acknowledge_watch(struct xs_handle *h)
   45.91 +bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
   45.92  {
   45.93 -	return xs_bool(xs_single(h, XS_WATCH_ACK, "OK", NULL));
   45.94 +	return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
   45.95  }
   45.96  
   45.97  /* Remove a watch on a node.
   45.98   * Returns false on failure (no watch on that node).
   45.99   */
  45.100 -bool xs_unwatch(struct xs_handle *h, const char *path)
  45.101 +bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
  45.102  {
  45.103 -	return xs_bool(xs_single(h, XS_UNWATCH, path, NULL));
  45.104 +	struct iovec iov[2];
  45.105 +
  45.106 +	iov[0].iov_base = (char *)path;
  45.107 +	iov[0].iov_len = strlen(path) + 1;
  45.108 +	iov[1].iov_base = (char *)token;
  45.109 +	iov[1].iov_len = strlen(token) + 1;
  45.110 +
  45.111 +	return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
  45.112  }
  45.113  
  45.114  /* Start a transaction: changes by others will not be seen during this
  45.115 @@ -488,11 +500,8 @@ bool xs_transaction_end(struct xs_handle
  45.116   * This tells the store daemon about a shared memory page and event channel
  45.117   * associated with a domain: the domain uses these to communicate.
  45.118   */
  45.119 -bool xs_introduce_domain(struct xs_handle *h,
  45.120 -			 domid_t domid,
  45.121 -			 unsigned long mfn,
  45.122 -			 unsigned int eventchn,
  45.123 -			 const char *path)
  45.124 +bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn,
  45.125 +			 unsigned int eventchn, const char *path)
  45.126  {
  45.127  	char domid_str[MAX_STRLEN(domid)];
  45.128  	char mfn_str[MAX_STRLEN(mfn)];
  45.129 @@ -515,8 +524,7 @@ bool xs_introduce_domain(struct xs_handl
  45.130  	return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
  45.131  }
  45.132  
  45.133 -bool xs_release_domain(struct xs_handle *h,
  45.134 -		       domid_t domid)
  45.135 +bool xs_release_domain(struct xs_handle *h, domid_t domid)
  45.136  {
  45.137  	char domid_str[MAX_STRLEN(domid)];
  45.138  
    46.1 --- a/tools/xenstore/xs.h	Mon Jun 13 13:18:58 2005 +0000
    46.2 +++ b/tools/xenstore/xs.h	Fri Jun 17 20:47:52 2005 +0000
    46.3 @@ -1,5 +1,3 @@
    46.4 -#ifndef _XS_H
    46.5 -#define _XS_H
    46.6  /* 
    46.7      Xen Store Daemon providing simple tree-like database.
    46.8      Copyright (C) 2005 Rusty Russell IBM Corporation
    46.9 @@ -19,11 +17,15 @@
   46.10      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   46.11  */
   46.12  
   46.13 -/* On failure, these routines set errno. */
   46.14 +#ifndef _XS_H
   46.15 +#define _XS_H
   46.16 +
   46.17  #include "xs_lib.h"
   46.18  
   46.19  struct xs_handle;
   46.20  
   46.21 +/* On failure, these routines set errno. */
   46.22 +
   46.23  /* Connect to the xs daemon.
   46.24   * Returns a handle or NULL.
   46.25   */
   46.26 @@ -52,8 +54,8 @@ void *xs_read(struct xs_handle *h, const
   46.27  /* Write the value of a single file.
   46.28   * Returns false on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
   46.29   */
   46.30 -bool xs_write(struct xs_handle *h, const char *path, const void *data, unsigned int len,
   46.31 -	      int createflags);
   46.32 +bool xs_write(struct xs_handle *h, const char *path, const void *data,
   46.33 +	      unsigned int len, int createflags);
   46.34  
   46.35  /* Create a new directory.
   46.36   * Returns false on failure.
   46.37 @@ -69,42 +71,42 @@ bool xs_rm(struct xs_handle *h, const ch
   46.38   * Returns malloced array, or NULL: call free() after use.
   46.39   */
   46.40  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
   46.41 -					  const char *path,
   46.42 -					  unsigned int *num);
   46.43 +					  const char *path, unsigned int *num);
   46.44  
   46.45  /* Set permissions of node (must be owner).
   46.46   * Returns false on failure.
   46.47   */
   46.48 -bool xs_set_permissions(struct xs_handle *h,
   46.49 -			const char *path,
   46.50 -			struct xs_permissions *perms,
   46.51 -			unsigned int num_perms);
   46.52 +bool xs_set_permissions(struct xs_handle *h, const char *path,
   46.53 +			struct xs_permissions *perms, unsigned int num_perms);
   46.54  
   46.55  /* Watch a node for changes (poll on fd to detect, or call read_watch()).
   46.56   * When the node (or any child) changes, fd will become readable.
   46.57 + * Token is returned when watch is read, to allow matching.
   46.58   * Priority indicates order if multiple watchers: higher is first.
   46.59   * Returns false on failure.
   46.60   */
   46.61 -bool xs_watch(struct xs_handle *h, const char *path, unsigned int priority);
   46.62 +bool xs_watch(struct xs_handle *h, const char *path, const char *token,
   46.63 +	      unsigned int priority);
   46.64  
   46.65  /* Return the FD to poll on to see if a watch has fired. */
   46.66  int xs_fileno(struct xs_handle *h);
   46.67  
   46.68  /* Find out what node change was on (will block if nothing pending).
   46.69 - * Returns malloced path, or NULL: call free() after use.
   46.70 + * Returns array of two pointers: path and token, or NULL.
   46.71 + * Call free() after use.
   46.72   */
   46.73 -char *xs_read_watch(struct xs_handle *h);
   46.74 +char **xs_read_watch(struct xs_handle *h);
   46.75  
   46.76  /* Acknowledge watch on node.  Watches must be acknowledged before
   46.77   * any other watches can be read.
   46.78   * Returns false on failure.
   46.79   */
   46.80 -bool xs_acknowledge_watch(struct xs_handle *h);
   46.81 +bool xs_acknowledge_watch(struct xs_handle *h, const char *token);
   46.82  
   46.83  /* Remove a watch on a node.
   46.84   * Returns false on failure (no watch on that node).
   46.85   */
   46.86 -bool xs_unwatch(struct xs_handle *h, const char *path);
   46.87 +bool xs_unwatch(struct xs_handle *h, const char *path, const char *token);
   46.88  
   46.89  /* Start a transaction: changes by others will not be seen during this
   46.90   * transaction, and changes will not be visible to others until end.
   46.91 @@ -125,11 +127,8 @@ bool xs_transaction_end(struct xs_handle
   46.92   * This tells the store daemon about a shared memory page, event channel
   46.93   * and store path associated with a domain: the domain uses these to communicate.
   46.94   */
   46.95 -bool xs_introduce_domain(struct xs_handle *h,
   46.96 -                         domid_t domid,
   46.97 -                         unsigned long mfn,
   46.98 -                         unsigned int eventchn,
   46.99 -                         const char *path);
  46.100 +bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn,
  46.101 +                         unsigned int eventchn, const char *path);
  46.102  
  46.103  /* Release a domain.
  46.104   * Tells the store domain to release the memory page to the domain.
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/xenstore/xs_dom0_test.c	Fri Jun 17 20:47:52 2005 +0000
    47.3 @@ -0,0 +1,43 @@
    47.4 +/* Test introduction of domain 0 */
    47.5 +#include <linux/ioctl.h>
    47.6 +#include <sys/ioctl.h>
    47.7 +#include "xs.h"
    47.8 +#include "utils.h"
    47.9 +#include <xc.h>
   47.10 +#include <xen/linux/privcmd.h>
   47.11 +#include <stdio.h>
   47.12 +#include <unistd.h>
   47.13 +#include <sys/mman.h>
   47.14 +
   47.15 +int main()
   47.16 +{
   47.17 +	int h, local = 0, kernel = 0;
   47.18 +	long err;
   47.19 +	void *page;
   47.20 +
   47.21 +	h = xc_interface_open();
   47.22 +	if (h < 0)
   47.23 +		barf_perror("Failed to open xc");
   47.24 +
   47.25 +	if (xc_evtchn_bind_interdomain(h, DOMID_SELF, 0, &local, &kernel) != 0)
   47.26 +		barf_perror("Failed to bind interdomain");
   47.27 +
   47.28 +	printf("Got ports %i & %i\n", local, kernel);
   47.29 +
   47.30 +	err = ioctl(h, IOCTL_PRIVCMD_INITDOMAIN_STORE, kernel);
   47.31 +	if (err < 0)
   47.32 +		barf_perror("Failed to initialize store");
   47.33 +	printf("Got mfn %li\n", err);
   47.34 +
   47.35 +	page = xc_map_foreign_range(h, 0, getpagesize(), PROT_READ|PROT_WRITE,
   47.36 +				    err);
   47.37 +	if (!page)
   47.38 +		barf_perror("Failed to map page %li", err);
   47.39 +	printf("Mapped page at %p\n", page);
   47.40 +	printf("Page says %s\n", (char *)page);
   47.41 +	munmap(page, getpagesize());
   47.42 +	printf("unmapped\n");
   47.43 +	
   47.44 +	return 0;
   47.45 +}
   47.46 +	
    48.1 --- a/tools/xenstore/xs_lib.c	Mon Jun 13 13:18:58 2005 +0000
    48.2 +++ b/tools/xenstore/xs_lib.c	Fri Jun 17 20:47:52 2005 +0000
    48.3 @@ -67,7 +67,7 @@ bool xs_write_all(int fd, const void *da
    48.4  
    48.5  /* Convert strings to permissions.  False if a problem. */
    48.6  bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
    48.7 -		      const char *strings)
    48.8 +			 const char *strings)
    48.9  {
   48.10  	const char *p;
   48.11  	char *end;
   48.12 @@ -138,4 +138,3 @@ unsigned int xs_count_strings(const char
   48.13  
   48.14  	return num;
   48.15  }
   48.16 -	
    49.1 --- a/tools/xenstore/xs_lib.h	Mon Jun 13 13:18:58 2005 +0000
    49.2 +++ b/tools/xenstore/xs_lib.h	Fri Jun 17 20:47:52 2005 +0000
    49.3 @@ -1,5 +1,3 @@
    49.4 -#ifndef _XR_LIB_H
    49.5 -#define _XR_LIB_H
    49.6  /* 
    49.7      Common routines between Xen store user library and daemon.
    49.8      Copyright (C) 2005 Rusty Russell IBM Corporation
    49.9 @@ -18,6 +16,10 @@
   49.10      along with this program; if not, write to the Free Software
   49.11      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   49.12  */
   49.13 +
   49.14 +#ifndef _XS_LIB_H
   49.15 +#define _XS_LIB_H
   49.16 +
   49.17  #include <stdbool.h>
   49.18  #include <limits.h>
   49.19  #include <xc.h>
   49.20 @@ -52,7 +54,7 @@ bool xs_write_all(int fd, const void *da
   49.21  
   49.22  /* Convert strings to permissions.  False if a problem. */
   49.23  bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
   49.24 -		      const char *strings);
   49.25 +			 const char *strings);
   49.26  
   49.27  /* Convert permissions to a string (up to len MAX_STRLEN(domid_t)+1). */
   49.28  bool xs_perm_to_string(const struct xs_permissions *perm, char *buffer);
    50.1 --- a/tools/xenstore/xs_stress.c	Mon Jun 13 13:18:58 2005 +0000
    50.2 +++ b/tools/xenstore/xs_stress.c	Fri Jun 17 20:47:52 2005 +0000
    50.3 @@ -50,7 +50,7 @@ static void work(unsigned int cycles, un
    50.4  		}
    50.5  		if (streq(lockdir, ""))
    50.6  			strcpy(lockdir, "/");
    50.7 -		
    50.8 +
    50.9  		if (!xs_transaction_start(h, lockdir))
   50.10  			barf_perror("%i: starting transaction %i on %s",
   50.11  				    childnum, i, lockdir);
    51.1 --- a/tools/xenstore/xs_test.c	Mon Jun 13 13:18:58 2005 +0000
    51.2 +++ b/tools/xenstore/xs_test.c	Fri Jun 17 20:47:52 2005 +0000
    51.3 @@ -173,9 +173,9 @@ static void __attribute__((noreturn)) us
    51.4  	     "  getperm <path>\n"
    51.5  	     "  setperm <path> <id> <flags> ...\n"
    51.6  	     "  shutdown\n"
    51.7 -	     "  watch <path> <prio>\n"
    51.8 +	     "  watch <path> <token> <prio>\n"
    51.9  	     "  waitwatch\n"
   51.10 -	     "  ackwatch\n"
   51.11 +	     "  ackwatch <token>\n"
   51.12  	     "  unwatch <path> <token>\n"
   51.13  	     "  close\n"
   51.14  	     "  start <node>\n"
   51.15 @@ -358,36 +358,37 @@ static void do_shutdown(unsigned int han
   51.16  		failed(handle);
   51.17  }
   51.18  
   51.19 -static void do_watch(unsigned int handle, const char *node, const char *pri)
   51.20 +static void do_watch(unsigned int handle, const char *node, const char *token,
   51.21 +		     const char *pri)
   51.22  {
   51.23 -	if (!xs_watch(handles[handle], node, atoi(pri)))
   51.24 +	if (!xs_watch(handles[handle], node, token, atoi(pri)))
   51.25  		failed(handle);
   51.26  }
   51.27  
   51.28  static void do_waitwatch(unsigned int handle)
   51.29  {
   51.30 -	char *node;
   51.31 +	char **vec;
   51.32  
   51.33 -	node = xs_read_watch(handles[handle]);
   51.34 -	if (!node)
   51.35 +	vec = xs_read_watch(handles[handle]);
   51.36 +	if (!vec)
   51.37  		failed(handle);
   51.38  
   51.39  	if (handle)
   51.40 -		printf("%i:%s\n", handle, node);
   51.41 +		printf("%i:%s:%s\n", handle, vec[0], vec[1]);
   51.42  	else
   51.43 -		printf("%s\n", node);
   51.44 -	free(node);
   51.45 +		printf("%s:%s\n", vec[0], vec[1]);
   51.46 +	free(vec);
   51.47  }
   51.48  
   51.49 -static void do_ackwatch(unsigned int handle)
   51.50 +static void do_ackwatch(unsigned int handle, const char *token)
   51.51  {
   51.52 -	if (!xs_acknowledge_watch(handles[handle]))
   51.53 +	if (!xs_acknowledge_watch(handles[handle], token))
   51.54  		failed(handle);
   51.55  }
   51.56  
   51.57 -static void do_unwatch(unsigned int handle, const char *node)
   51.58 +static void do_unwatch(unsigned int handle, const char *node, const char *token)
   51.59  {
   51.60 -	if (!xs_unwatch(handles[handle], node))
   51.61 +	if (!xs_unwatch(handles[handle], node, token))
   51.62  		failed(handle);
   51.63  }
   51.64  
   51.65 @@ -613,13 +614,13 @@ int main(int argc, char *argv[])
   51.66  		else if (streq(command, "shutdown"))
   51.67  			do_shutdown(handle);
   51.68  		else if (streq(command, "watch"))
   51.69 -			do_watch(handle, arg(line, 1), arg(line, 2));
   51.70 +			do_watch(handle, arg(line, 1), arg(line, 2), arg(line, 3));
   51.71  		else if (streq(command, "waitwatch"))
   51.72  			do_waitwatch(handle);
   51.73  		else if (streq(command, "ackwatch"))
   51.74 -			do_ackwatch(handle);
   51.75 +			do_ackwatch(handle, arg(line, 1));
   51.76  		else if (streq(command, "unwatch"))
   51.77 -			do_unwatch(handle, arg(line, 1));
   51.78 +			do_unwatch(handle, arg(line, 1), arg(line, 2));
   51.79  		else if (streq(command, "close")) {
   51.80  			xs_daemon_close(handles[handle]);
   51.81  			handles[handle] = NULL;
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/tools/xenstore/xs_watch_stress.c	Fri Jun 17 20:47:52 2005 +0000
    52.3 @@ -0,0 +1,120 @@
    52.4 +/* Stress test for watch code: two processes communicating by watches */
    52.5 +#include "xs.h"
    52.6 +#include "utils.h"
    52.7 +#include <stdlib.h>
    52.8 +#include <stdio.h>
    52.9 +#include <sys/types.h>
   52.10 +#include <sys/wait.h>
   52.11 +#include <sys/stat.h>
   52.12 +#include <fcntl.h>
   52.13 +#include <unistd.h>
   52.14 +
   52.15 +int main(int argc __attribute__((unused)), char *argv[])
   52.16 +{
   52.17 +	int childpid, status, fds[2];
   52.18 +	bool parent;
   52.19 +	unsigned int i, acks = 0;
   52.20 +	struct xs_handle *h;
   52.21 +	char *data;
   52.22 +	unsigned int len;
   52.23 +	const char *path, *otherpath;
   52.24 +
   52.25 +	pipe(fds);
   52.26 +	childpid = fork();
   52.27 +	if (childpid == -1)
   52.28 +		barf_perror("Failed fork");
   52.29 +	parent = (childpid != 0);
   52.30 +
   52.31 +	h = xs_daemon_open();
   52.32 +	if (!h)
   52.33 +		barf_perror("Could not connect to daemon");
   52.34 +
   52.35 +	if (!xs_watch(h, "/", "token", 0))
   52.36 +		barf_perror("Could not set watch");
   52.37 +
   52.38 +	if (parent) {
   52.39 +		char c;
   52.40 +
   52.41 +		if (read(fds[0], &c, 1) != 1)
   52.42 +			barf("Child exited");
   52.43 +
   52.44 +		path = "/parent";
   52.45 +		otherpath = "/child";
   52.46 +		/* Create initial node. */
   52.47 +		if (!xs_write(h, path, "0", 2, O_CREAT))
   52.48 +			barf_perror("Write to %s failed", path);
   52.49 +	} else {
   52.50 +		path = "/child";
   52.51 +		otherpath = "/parent";
   52.52 +
   52.53 +		if (write(fds[1], "", 1) != 1)
   52.54 +			barf_perror("Write to parent failed");
   52.55 +	}
   52.56 +
   52.57 +	for (i = 0; i < (argv[1] ? (unsigned)atoi(argv[1]) : 100);) {
   52.58 +		char **vec;
   52.59 +
   52.60 +		vec = xs_read_watch(h);
   52.61 +		if (!vec)
   52.62 +			barf_perror("Read watch failed");
   52.63 +
   52.64 +		if (!streq(vec[1], "token"))
   52.65 +			barf("Watch token %s bad", vec[1]);
   52.66 +		if (streq(vec[0], otherpath)) {
   52.67 +			char number[32];
   52.68 +
   52.69 +			data = xs_read(h, otherpath, &len);
   52.70 +			if (!data)
   52.71 +				barf_perror("reading %s", otherpath);
   52.72 +			sprintf(number, "%i", atoi(data) + 1);
   52.73 +			free(data);
   52.74 +			if (!xs_write(h, path, number, strlen(number) + 1,
   52.75 +				      O_CREAT))
   52.76 +				barf_perror("writing %s", path);
   52.77 +			i++;
   52.78 +		} else if (!streq(vec[0], path))
   52.79 +			barf_perror("Watch fired on unknown path %s", vec[0]);
   52.80 +		xs_acknowledge_watch(h, vec[1]);
   52.81 +		acks++;
   52.82 +		free(vec);
   52.83 +	}
   52.84 +
   52.85 +	if (!parent) {
   52.86 +		while (acks != 2 * i - 1) {
   52.87 +			char **vec;
   52.88 +			vec = xs_read_watch(h);
   52.89 +			if (!vec)
   52.90 +				barf_perror("Watch failed");
   52.91 +			if (!streq(vec[0], path))
   52.92 +				barf_perror("Watch fired path %s", vec[0]);
   52.93 +			if (!streq(vec[1], "token"))
   52.94 +				barf("Watch token %s bad", vec[1]);
   52.95 +			free(vec);
   52.96 +
   52.97 +			printf("Expect %i events, only got %i\n",
   52.98 +			       2 * i - 1, acks);
   52.99 +			acks++;
  52.100 +		}
  52.101 +		exit(0);
  52.102 +	}
  52.103 +
  52.104 +	if (acks != 2 * i)
  52.105 +		barf("Parent got %i watch events\n", acks);
  52.106 +
  52.107 +	printf("Waiting for %i\n", childpid);
  52.108 +	if (waitpid(childpid, &status, 0) != childpid)
  52.109 +		barf_perror("Child wait failed");
  52.110 +	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
  52.111 +		barf_perror("Child status %i", status);
  52.112 +
  52.113 +	data = xs_read(h, path, &len);
  52.114 +	if (atoi(data) != 2 * (int)i)
  52.115 +		barf("%s count is %s\n", path, data);
  52.116 +	free(data);
  52.117 +	data = xs_read(h, otherpath, &len);
  52.118 +	if (atoi(data) != 2 * (int)i - 1)
  52.119 +		barf("%s count is %s\n", otherpath, data);
  52.120 +	free(data);
  52.121 +	printf("Success!\n");
  52.122 +	exit(0);
  52.123 +}
    53.1 --- a/xen/drivers/char/serial.c	Mon Jun 13 13:18:58 2005 +0000
    53.2 +++ b/xen/drivers/char/serial.c	Fri Jun 17 20:47:52 2005 +0000
    53.3 @@ -176,11 +176,15 @@ char serial_getc(int handle)
    53.4              if ( port->rxbufp != port->rxbufc )
    53.5              {
    53.6                  c = port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufc++)];
    53.7 +                spin_unlock_irqrestore(&port->lock, flags);
    53.8                  break;
    53.9              }
   53.10              
   53.11              if ( port->driver->getc(port, &c) )
   53.12 +            {
   53.13 +                spin_unlock_irqrestore(&port->lock, flags);
   53.14                  break;
   53.15 +            }
   53.16  
   53.17              spin_unlock_irqrestore(&port->lock, flags);
   53.18