xen-vtx-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
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
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