ia64/xen-unstable

changeset 9098:385ddb11971d

Merge xen-ia64-unstable.hg
author kaf24@firebug.cl.cam.ac.uk
date Thu Mar 02 10:49:19 2006 +0100 (2006-03-02)
parents b4f1084177cc 34b7dd72aa55
children eeac4fdf02ed
files
line diff
     1.1 --- a/.hgignore	Wed Mar 01 15:06:24 2006 -0700
     1.2 +++ b/.hgignore	Thu Mar 02 10:49:19 2006 +0100
     1.3 @@ -166,6 +166,7 @@
     1.4  ^tools/xenstore/xenstore-read$
     1.5  ^tools/xenstore/xenstore-rm$
     1.6  ^tools/xenstore/xenstore-write$
     1.7 +^tools/xenstore/xenstore-control$
     1.8  ^tools/xenstore/xenstore-ls$
     1.9  ^tools/xenstore/xenstored$
    1.10  ^tools/xenstore/xenstored_test$
     2.1 --- a/linux-2.6-xen-sparse/include/xen/public/xenstored.h	Wed Mar 01 15:06:24 2006 -0700
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,89 +0,0 @@
     2.4 -/*
     2.5 - * Simple prototyle Xen Store Daemon providing simple tree-like database.
     2.6 - * Copyright (C) 2005 Rusty Russell IBM Corporation
     2.7 - *
     2.8 - * This file may be distributed separately from the Linux kernel, or
     2.9 - * incorporated into other software packages, subject to the following license:
    2.10 - * 
    2.11 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.12 - * of this source file (the "Software"), to deal in the Software without
    2.13 - * restriction, including without limitation the rights to use, copy, modify,
    2.14 - * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    2.15 - * and to permit persons to whom the Software is furnished to do so, subject to
    2.16 - * the following conditions:
    2.17 - * 
    2.18 - * The above copyright notice and this permission notice shall be included in
    2.19 - * all copies or substantial portions of the Software.
    2.20 - * 
    2.21 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.22 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.23 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.24 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.25 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    2.26 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    2.27 - * IN THE SOFTWARE.
    2.28 - */
    2.29 -
    2.30 -#ifndef _XENSTORED_H
    2.31 -#define _XENSTORED_H
    2.32 -
    2.33 -enum xsd_sockmsg_type
    2.34 -{
    2.35 -	XS_DEBUG,
    2.36 -	XS_SHUTDOWN,
    2.37 -	XS_DIRECTORY,
    2.38 -	XS_READ,
    2.39 -	XS_GET_PERMS,
    2.40 -	XS_WATCH,
    2.41 -	XS_WATCH_ACK,
    2.42 -	XS_UNWATCH,
    2.43 -	XS_TRANSACTION_START,
    2.44 -	XS_TRANSACTION_END,
    2.45 -	XS_OP_READ_ONLY = XS_TRANSACTION_END,
    2.46 -	XS_INTRODUCE,
    2.47 -	XS_RELEASE,
    2.48 -	XS_GET_DOMAIN_PATH,
    2.49 -	XS_WRITE,
    2.50 -	XS_MKDIR,
    2.51 -	XS_RM,
    2.52 -	XS_SET_PERMS,
    2.53 -	XS_WATCH_EVENT,
    2.54 -	XS_ERROR,
    2.55 -};
    2.56 -
    2.57 -#define XS_WRITE_NONE "NONE"
    2.58 -#define XS_WRITE_CREATE "CREATE"
    2.59 -#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
    2.60 -
    2.61 -/* We hand errors as strings, for portability. */
    2.62 -struct xsd_errors
    2.63 -{
    2.64 -	int errnum;
    2.65 -	const char *errstring;
    2.66 -};
    2.67 -#define XSD_ERROR(x) { x, #x }
    2.68 -static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
    2.69 -	XSD_ERROR(EINVAL),
    2.70 -	XSD_ERROR(EACCES),
    2.71 -	XSD_ERROR(EEXIST),
    2.72 -	XSD_ERROR(EISDIR),
    2.73 -	XSD_ERROR(ENOENT),
    2.74 -	XSD_ERROR(ENOMEM),
    2.75 -	XSD_ERROR(ENOSPC),
    2.76 -	XSD_ERROR(EIO),
    2.77 -	XSD_ERROR(ENOTEMPTY),
    2.78 -	XSD_ERROR(ENOSYS),
    2.79 -	XSD_ERROR(EROFS),
    2.80 -	XSD_ERROR(EBUSY),
    2.81 -	XSD_ERROR(EAGAIN),
    2.82 -	XSD_ERROR(EISCONN),
    2.83 -};
    2.84 -struct xsd_sockmsg
    2.85 -{
    2.86 -	u32 type;
    2.87 -	u32 len; 		/* Length of data following this. */
    2.88 -
    2.89 -	/* Generally followed by nul-terminated string(s). */
    2.90 -};
    2.91 -
    2.92 -#endif /* _XENSTORED_H */
     3.1 --- a/tools/examples/block	Wed Mar 01 15:06:24 2006 -0700
     3.2 +++ b/tools/examples/block	Thu Mar 02 10:49:19 2006 +0100
     3.3 @@ -129,7 +129,14 @@ check_sharing()
     3.4  same_vm()
     3.5  {
     3.6    local otherdom="$1"
     3.7 -  local othervm=$(xenstore-read "/local/domain/$otherdom/vm")
     3.8 +  # Note that othervm can be MISSING here, because Xend will be racing with
     3.9 +  # the hotplug scripts -- the entries in /local/domain can be removed by
    3.10 +  # Xend before the hotplug scripts have removed the entry in
    3.11 +  # /local/domain/0/backend/.  In this case, we want to pretend that the
    3.12 +  # VM is the same as FRONTEND_UUID, because that way the 'sharing' will be
    3.13 +  # allowed.
    3.14 +  local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm"         \
    3.15 +                  "$FRONTEND_UUID")
    3.16  
    3.17    [ "$FRONTEND_UUID" == "$othervm" ]
    3.18  }
     4.1 --- a/tools/examples/xen-hotplug-cleanup	Wed Mar 01 15:06:24 2006 -0700
     4.2 +++ b/tools/examples/xen-hotplug-cleanup	Thu Mar 02 10:49:19 2006 +0100
     4.3 @@ -12,10 +12,11 @@ dir=$(dirname "$0")
     4.4  claim_lock "block"
     4.5  
     4.6  # remove device frontend store entries
     4.7 -xenstore-rm -t $(xenstore-read "$XENBUS_PATH/frontend") || true
     4.8 +xenstore-rm -t \
     4.9 +  $(xenstore-read "$XENBUS_PATH/frontend" 2>/dev/null) 2>/dev/null || true
    4.10  
    4.11  # remove device backend store entries
    4.12 -xenstore-rm -t "$XENBUS_PATH"       || true
    4.13 -xenstore-rm -t "error/$XENBUS_PATH" || true
    4.14 +xenstore-rm -t "$XENBUS_PATH"        2>/dev/null || true
    4.15 +xenstore-rm -t "error/$XENBUS_PATH"  2>/dev/null || true
    4.16  
    4.17  release_lock "block"
     5.1 --- a/tools/xenstore/Makefile	Wed Mar 01 15:06:24 2006 -0700
     5.2 +++ b/tools/xenstore/Makefile	Thu Mar 02 10:49:19 2006 +0100
     5.3 @@ -27,7 +27,10 @@ CLIENTS := xenstore-exists xenstore-list
     5.4  CLIENTS += xenstore-write
     5.5  CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
     5.6  
     5.7 -all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-ls
     5.8 +all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
     5.9 +
    5.10 +test_interleaved_transactions: test_interleaved_transactions.o
    5.11 +	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
    5.12  
    5.13  testcode: xs_test xenstored_test xs_random
    5.14  
    5.15 @@ -35,13 +38,16 @@ xenstored: xenstored_core.o xenstored_wa
    5.16  	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
    5.17  
    5.18  $(CLIENTS): xenstore-%: xenstore_%.o libxenstore.so
    5.19 -	$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
    5.20 +	$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
    5.21  
    5.22  $(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
    5.23  	$(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
    5.24  
    5.25 +xenstore-control: xenstore_control.o libxenstore.so
    5.26 +	$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
    5.27 +
    5.28  xenstore-ls: xsls.o libxenstore.so
    5.29 -	$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
    5.30 +	$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
    5.31  
    5.32  xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
    5.33  	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
    5.34 @@ -77,7 +83,8 @@ libxenstore.so: xs.opic xs_lib.opic
    5.35  clean: testsuite-clean
    5.36  	rm -f *.o *.opic *.so
    5.37  	rm -f xenstored xs_random xs_stress xs_crashme
    5.38 -	rm -f xs_test xenstored_test xs_tdb_dump xenstore-ls $(CLIENTS)
    5.39 +	rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
    5.40 +	rm -f $(CLIENTS)
    5.41  	$(RM) $(PROG_DEP)
    5.42  
    5.43  print-dir:
    5.44 @@ -129,7 +136,7 @@ TAGS:
    5.45  tarball: clean
    5.46  	cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
    5.47  
    5.48 -install: libxenstore.so xenstored xenstore-ls $(CLIENTS)
    5.49 +install: all
    5.50  	$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
    5.51  	$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
    5.52  	$(INSTALL_DIR) -p $(DESTDIR)/usr/bin
    5.53 @@ -137,6 +144,7 @@ install: libxenstore.so xenstored xensto
    5.54  	$(INSTALL_DIR) -p $(DESTDIR)/usr/include
    5.55  	$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
    5.56  	$(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
    5.57 +	$(INSTALL_PROG) xenstore-control $(DESTDIR)/usr/bin
    5.58  	$(INSTALL_PROG) xenstore-ls $(DESTDIR)/usr/bin
    5.59  	$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
    5.60  	$(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/xenstore/xenstore_control.c	Thu Mar 02 10:49:19 2006 +0100
     6.3 @@ -0,0 +1,30 @@
     6.4 +#include <stdio.h>
     6.5 +#include <stdlib.h>
     6.6 +#include <string.h>
     6.7 +
     6.8 +#include "xs.h"
     6.9 +
    6.10 +
    6.11 +int main(int argc, char **argv)
    6.12 +{
    6.13 +  struct xs_handle * xsh;
    6.14 +
    6.15 +  if (argc < 2 ||
    6.16 +      strcmp(argv[1], "check"))
    6.17 +  {
    6.18 +    fprintf(stderr,
    6.19 +            "Usage:\n"
    6.20 +            "\n"
    6.21 +            "       %s check\n"
    6.22 +            "\n", argv[0]);
    6.23 +    return 2;
    6.24 +  }
    6.25 +
    6.26 +  xsh = xs_daemon_open();
    6.27 +
    6.28 +  xs_debug_command(xsh, argv[1], NULL, 0);
    6.29 +
    6.30 +  xs_daemon_close(xsh);
    6.31 +
    6.32 +  return 0;
    6.33 +}
     7.1 --- a/tools/xenstore/xenstored_core.c	Wed Mar 01 15:06:24 2006 -0700
     7.2 +++ b/tools/xenstore/xenstored_core.c	Thu Mar 02 10:49:19 2006 +0100
     7.3 @@ -60,6 +60,18 @@ static int reopen_log_pipe[2];
     7.4  static char *tracefile = NULL;
     7.5  static TDB_CONTEXT *tdb_ctx;
     7.6  
     7.7 +static void corrupt(struct connection *conn, const char *fmt, ...);
     7.8 +static void check_store();
     7.9 +
    7.10 +#define log(...)							\
    7.11 +	do {								\
    7.12 +		char *s = talloc_asprintf(NULL, __VA_ARGS__);		\
    7.13 +		trace("%s\n", s);					\
    7.14 +		syslog(LOG_ERR, "%s",  s);				\
    7.15 +		talloc_free(s);						\
    7.16 +	} while (0)
    7.17 +
    7.18 +
    7.19  #ifdef TESTING
    7.20  static bool failtest = false;
    7.21  
    7.22 @@ -104,33 +116,6 @@ int test_mkdir(const char *dir, int perm
    7.23  
    7.24  #include "xenstored_test.h"
    7.25  
    7.26 -/* FIXME: Ideally, this should never be called.  Some can be eliminated. */
    7.27 -/* Something is horribly wrong: shutdown immediately. */
    7.28 -void __attribute__((noreturn)) corrupt(struct connection *conn,
    7.29 -				       const char *fmt, ...)
    7.30 -{
    7.31 -	va_list arglist;
    7.32 -	char *str;
    7.33 -	int saved_errno = errno;
    7.34 -
    7.35 -	va_start(arglist, fmt);
    7.36 -	str = talloc_vasprintf(NULL, fmt, arglist);
    7.37 -	va_end(arglist);
    7.38 -
    7.39 -	trace("xenstored corruption: connection id %i: err %s: %s",
    7.40 -		conn ? (int)conn->id : -1, strerror(saved_errno), str);
    7.41 -	eprintf("xenstored corruption: connection id %i: err %s: %s",
    7.42 -		conn ? (int)conn->id : -1, strerror(saved_errno), str);
    7.43 -#ifdef TESTING
    7.44 -	/* Allow them to attach debugger. */
    7.45 -	sleep(30);
    7.46 -#endif
    7.47 -	syslog(LOG_DAEMON,
    7.48 -	       "xenstored corruption: connection id %i: err %s: %s",
    7.49 -	       conn ? (int)conn->id : -1, strerror(saved_errno), str);
    7.50 -	_exit(2);
    7.51 -}
    7.52 -
    7.53  TDB_CONTEXT *tdb_context(struct connection *conn)
    7.54  {
    7.55  	/* conn = NULL used in manual_node at setup. */
    7.56 @@ -216,8 +201,9 @@ static void trace_io(const struct connec
    7.57  	now = time(NULL);
    7.58  	tm = localtime(&now);
    7.59  
    7.60 -	trace("%s %p %02d:%02d:%02d %s (", prefix, conn,
    7.61 -	      tm->tm_hour, tm->tm_min, tm->tm_sec,
    7.62 +	trace("%s %p %p %04d%02d%02d %02d:%02d:%02d %s (", prefix, conn,
    7.63 +	      conn->transaction, tm->tm_year + 1900, tm->tm_mon + 1,
    7.64 +	      tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
    7.65  	      sockmsg_string(data->hdr.msg.type));
    7.66  	
    7.67  	for (i = 0; i < data->hdr.msg.len; i++)
    7.68 @@ -837,8 +823,6 @@ static int destroy_node(void *_node)
    7.69  	return 0;
    7.70  }
    7.71  
    7.72 -/* Be careful: create heirarchy, put entry in existing parent *last*.
    7.73 - * This helps fsck if we die during this. */
    7.74  static struct node *create_node(struct connection *conn, 
    7.75  				const char *name,
    7.76  				void *data, unsigned int datalen)
    7.77 @@ -939,8 +923,9 @@ static void delete_node(struct connectio
    7.78  {
    7.79  	unsigned int i;
    7.80  
    7.81 -	/* Delete self, then delete children.  If something goes wrong,
    7.82 -	 * consistency check will clean up this way. */
    7.83 +	/* Delete self, then delete children.  If we crash, then the worst
    7.84 +	   that can happen is the children will continue to take up space, but
    7.85 +	   will otherwise be unreachable. */
    7.86  	delete_node_single(conn, node);
    7.87  
    7.88  	/* Delete children, too. */
    7.89 @@ -950,9 +935,14 @@ static void delete_node(struct connectio
    7.90  		child = read_node(conn, 
    7.91  				  talloc_asprintf(node, "%s/%s", node->name,
    7.92  						  node->children + i));
    7.93 -		if (!child)
    7.94 -			corrupt(conn, "No child '%s' found", child);
    7.95 -		delete_node(conn, child);
    7.96 +		if (child) {
    7.97 +			delete_node(conn, child);
    7.98 +		}
    7.99 +		else {
   7.100 +			trace("delete_node: No child '%s/%s' found!\n",
   7.101 +			      node->name, node->children + i);
   7.102 +			/* Skip it, we've already deleted the parent. */
   7.103 +		}
   7.104  	}
   7.105  }
   7.106  
   7.107 @@ -976,12 +966,15 @@ static bool delete_child(struct connecti
   7.108  		}
   7.109  	}
   7.110  	corrupt(conn, "Can't find child '%s' in %s", childname, node->name);
   7.111 +	return false;
   7.112  }
   7.113  
   7.114  
   7.115  static int _rm(struct connection *conn, struct node *node, const char *name)
   7.116  {
   7.117 -	/* Delete from parent first, then if something explodes fsck cleans. */
   7.118 +	/* Delete from parent first, then if we crash, the worst that can
   7.119 +	   happen is the child will continue to take up space, but will
   7.120 +	   otherwise be unreachable. */
   7.121  	struct node *parent = read_node(conn, get_parent(name));
   7.122  	if (!parent) {
   7.123  		send_error(conn, EINVAL);
   7.124 @@ -1000,10 +993,11 @@ static int _rm(struct connection *conn, 
   7.125  
   7.126  static void internal_rm(const char *name)
   7.127  {
   7.128 -	char *tname = talloc_strdup(talloc_autofree_context(), name);
   7.129 +	char *tname = talloc_strdup(NULL, name);
   7.130  	struct node *node = read_node(NULL, tname);
   7.131  	if (node)
   7.132  		_rm(NULL, node, tname);
   7.133 +	talloc_free(tname);
   7.134  }
   7.135  
   7.136  
   7.137 @@ -1149,18 +1143,19 @@ static void process_message(struct conne
   7.138  	case XS_DEBUG:
   7.139  		if (streq(in->buffer, "print"))
   7.140  			xprintf("debug: %s", in->buffer + get_string(in, 0));
   7.141 +		if (streq(in->buffer, "check"))
   7.142 +			check_store();
   7.143  #ifdef TESTING
   7.144  		/* For testing, we allow them to set id. */
   7.145  		if (streq(in->buffer, "setid")) {
   7.146  			conn->id = atoi(in->buffer + get_string(in, 0));
   7.147 -			send_ack(conn, XS_DEBUG);
   7.148  		} else if (streq(in->buffer, "failtest")) {
   7.149  			if (get_string(in, 0) < in->used)
   7.150  				srandom(atoi(in->buffer + get_string(in, 0)));
   7.151 -			send_ack(conn, XS_DEBUG);
   7.152  			failtest = true;
   7.153  		}
   7.154  #endif /* TESTING */
   7.155 +		send_ack(conn, XS_DEBUG);
   7.156  		break;
   7.157  
   7.158  	case XS_WATCH:
   7.159 @@ -1258,7 +1253,7 @@ static void handle_input(struct connecti
   7.160  
   7.161  		if (in->hdr.msg.len > PATH_MAX) {
   7.162  #ifndef TESTING
   7.163 -			syslog(LOG_DAEMON, "Client tried to feed us %i",
   7.164 +			syslog(LOG_ERR, "Client tried to feed us %i",
   7.165  			       in->hdr.msg.len);
   7.166  #endif
   7.167  			goto bad_client;
   7.168 @@ -1425,10 +1420,16 @@ static void setup_structure(void)
   7.169  		   balloon driver will pick up stale entries.  In the case of
   7.170  		   the balloon driver, this can be fatal.
   7.171  		*/
   7.172 -		char *tlocal = talloc_strdup(talloc_autofree_context(),
   7.173 -					     "/local");
   7.174 +		char *tlocal = talloc_strdup(NULL, "/local");
   7.175 +
   7.176 +		check_store();
   7.177 +
   7.178  		internal_rm("/local");
   7.179  		create_node(NULL, tlocal, NULL, 0);
   7.180 +
   7.181 +		talloc_free(tlocal);
   7.182 +
   7.183 +		check_store();
   7.184  	}
   7.185  	else {
   7.186  		tdb_ctx = tdb_open(tdbname, 7919, TDB_FLAGS, O_RDWR|O_CREAT,
   7.187 @@ -1439,11 +1440,93 @@ static void setup_structure(void)
   7.188  		manual_node("/", "tool");
   7.189  		manual_node("/tool", "xenstored");
   7.190  		manual_node("/tool/xenstored", NULL);
   7.191 +
   7.192 +		check_store();
   7.193  	}
   7.194 +}
   7.195 +
   7.196 +static char *child_name(const char *s1, const char *s2)
   7.197 +{
   7.198 +	if (strcmp(s1, "/")) {
   7.199 +		return talloc_asprintf(NULL, "%s/%s", s1, s2);
   7.200 +	}
   7.201 +	else {
   7.202 +		return talloc_asprintf(NULL, "/%s", s2);
   7.203 +	}
   7.204 +}
   7.205 +
   7.206 +static void check_store_(const char *name)
   7.207 +{
   7.208 +	struct node *node = read_node(NULL, name);
   7.209 +
   7.210 +	if (node) {
   7.211 +		size_t i = 0;
   7.212 +
   7.213 +		while (i < node->childlen) {
   7.214 +			size_t childlen = strlen(node->children + i);
   7.215 +			char * childname = child_name(node->name,
   7.216 +						      node->children + i);
   7.217 +			struct node *childnode = read_node(NULL, childname);
   7.218 +			
   7.219 +			if (childnode) {
   7.220 +				check_store_(childname);
   7.221 +				i += childlen + 1;
   7.222 +			}
   7.223 +			else {
   7.224 +				log("check_store: No child '%s' found!\n",
   7.225 +				    childname);
   7.226 +
   7.227 +				memdel(node->children, i, childlen + 1,
   7.228 +				       node->childlen);
   7.229 +				node->childlen -= childlen + 1;
   7.230 +				write_node(NULL, node);
   7.231 +			}
   7.232  
   7.233 -	/* FIXME: Fsck */
   7.234 +			talloc_free(childname);
   7.235 +		}
   7.236 +	}
   7.237 +	else {
   7.238 +		/* Impossible, because no database should ever be without the
   7.239 +		   root, and otherwise, we've just checked in our caller
   7.240 +		   (which made a recursive call to get here). */
   7.241 +		   
   7.242 +		log("check_store: No child '%s' found: impossible!", name);
   7.243 +	}
   7.244 +}
   7.245 +
   7.246 +
   7.247 +static void check_store()
   7.248 +{
   7.249 +	char * root = talloc_strdup(NULL, "/");
   7.250 +	log("Checking store ...");
   7.251 +	check_store_(root);
   7.252 +	log("Checking store complete.");
   7.253 +	talloc_free(root);
   7.254  }
   7.255  
   7.256 +
   7.257 +/* Something is horribly wrong: check the store. */
   7.258 +static void corrupt(struct connection *conn, const char *fmt, ...)
   7.259 +{
   7.260 +	va_list arglist;
   7.261 +	char *str;
   7.262 +	int saved_errno = errno;
   7.263 +
   7.264 +	va_start(arglist, fmt);
   7.265 +	str = talloc_vasprintf(NULL, fmt, arglist);
   7.266 +	va_end(arglist);
   7.267 +
   7.268 +	log("corruption detected by connection %i: err %s: %s",
   7.269 +	    conn ? (int)conn->id : -1, strerror(saved_errno), str);
   7.270 +
   7.271 +#ifdef TESTING
   7.272 +	/* Allow them to attach debugger. */
   7.273 +	sleep(30);
   7.274 +#endif
   7.275 +	check_store();
   7.276 +}
   7.277 +
   7.278 +
   7.279  static void write_pidfile(const char *pidfile)
   7.280  {
   7.281  	char buf[100];
     8.1 --- a/tools/xenstore/xenstored_core.h	Wed Mar 01 15:06:24 2006 -0700
     8.2 +++ b/tools/xenstore/xenstored_core.h	Thu Mar 02 10:49:19 2006 +0100
     8.3 @@ -148,10 +148,6 @@ int destroy_tdb(void *_tdb);
     8.4  /* Replace the tdb: required for transaction code */
     8.5  bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb);
     8.6  
     8.7 -/* Fail due to excessive corruption, capitalist pigdogs! */
     8.8 -void __attribute__((noreturn)) corrupt(struct connection *conn,
     8.9 -				       const char *fmt, ...);
    8.10 -
    8.11  struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
    8.12  
    8.13  
     9.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Mar 01 15:06:24 2006 -0700
     9.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Thu Mar 02 10:49:19 2006 +0100
     9.3 @@ -247,6 +247,7 @@ void svm_load_msrs(void)
     9.4  void svm_restore_msrs(struct vcpu *v)
     9.5  {
     9.6  }
     9.7 +#endif
     9.8  
     9.9  #define IS_CANO_ADDRESS(add) 1
    9.10  
    9.11 @@ -297,8 +298,13 @@ static inline int long_mode_do_msr_read(
    9.12          return 0;
    9.13      }
    9.14  
    9.15 +#ifdef __x86_64__
    9.16      HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", 
    9.17              msr_content);
    9.18 +#else
    9.19 +    HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %llx\n", 
    9.20 +            msr_content);
    9.21 +#endif
    9.22  
    9.23      regs->eax = msr_content & 0xffffffff;
    9.24      regs->edx = msr_content >> 32;
    9.25 @@ -311,12 +317,18 @@ static inline int long_mode_do_msr_write
    9.26      struct vcpu *vc = current;
    9.27      struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
    9.28  
    9.29 +#ifdef __x86_64__
    9.30      HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n", 
    9.31                  regs->ecx, msr_content);
    9.32 +#else
    9.33 +    HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %x msr_content %llx\n", 
    9.34 +                regs->ecx, msr_content);
    9.35 +#endif
    9.36  
    9.37      switch (regs->ecx)
    9.38      {
    9.39      case MSR_EFER:
    9.40 +#ifdef __x86_64__
    9.41          if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
    9.42                                                  &vc->arch.hvm_svm.cpu_state))
    9.43          {
    9.44 @@ -337,6 +349,7 @@ static inline int long_mode_do_msr_write
    9.45          if ((msr_content ^ vmcb->efer) & EFER_LME)
    9.46              msr_content &= ~EFER_LME;  
    9.47          /* No update for LME/LMA since it have no effect */
    9.48 +#endif
    9.49          vmcb->efer = msr_content | EFER_SVME;
    9.50          break;
    9.51  
    9.52 @@ -383,18 +396,6 @@ static inline int long_mode_do_msr_write
    9.53      return 1;
    9.54  }
    9.55  
    9.56 -#else
    9.57 -static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
    9.58 -{
    9.59 -    return 0;
    9.60 -}
    9.61 -
    9.62 -static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
    9.63 -{
    9.64 -    return 0;
    9.65 -}
    9.66 -#endif
    9.67 -
    9.68  void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
    9.69  {
    9.70      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    9.71 @@ -937,10 +938,8 @@ static void svm_vmexit_do_cpuid(struct v
    9.72  
    9.73      if (input == 1)
    9.74      {
    9.75 -#ifndef __x86_64__
    9.76          if ( hvm_apic_support(v->domain) &&
    9.77                  !vlapic_global_enabled((VLAPIC(v))) )
    9.78 -#endif
    9.79              clear_bit(X86_FEATURE_APIC, &edx);
    9.80  	    
    9.81  #if CONFIG_PAGING_LEVELS < 3
    10.1 --- a/xen/arch/x86/hvm/svm/x86_32/exits.S	Wed Mar 01 15:06:24 2006 -0700
    10.2 +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S	Thu Mar 02 10:49:19 2006 +0100
    10.3 @@ -88,9 +88,6 @@
    10.4  #define STGI   .byte 0x0F,0x01,0xDC
    10.5  #define CLGI   .byte 0x0F,0x01,0xDD
    10.6  
    10.7 -#define DO_TSC_OFFSET 0
    10.8 -#define DO_FPUSAVE    0
    10.9 -        
   10.10  ENTRY(svm_asm_do_launch)
   10.11          sti
   10.12          CLGI                
   10.13 @@ -101,36 +98,6 @@ ENTRY(svm_asm_do_launch)
   10.14          movl VCPU_svm_hsa_pa(%ebx), %eax
   10.15          VMSAVE
   10.16  
   10.17 -#if DO_FPUSAVE
   10.18 -        mov      %cr0, %eax     
   10.19 -        push %eax
   10.20 -        clts
   10.21 -        lea     VCPU_arch_guest_fpu_ctxt(%ebx), %eax
   10.22 -        fxrstor (%eax)
   10.23 -        pop      %eax
   10.24 -        mov      %eax, %cr0
   10.25 -#endif
   10.26 -
   10.27 -#if (DO_TSC_OFFSET)
   10.28 -        pushl %edx /* eax and edx get trashed by rdtsc */
   10.29 -        pushl %eax
   10.30 -        rdtsc
   10.31 -        subl VCPU_svm_vmexit_tsc(%ebx),%eax   /* tsc's from    */
   10.32 -        sbbl VCPU_svm_vmexit_tsc+4(%ebx),%edx /* last #VMEXIT? */
   10.33 -        subl %eax,VMCB_tsc_offset(%ecx)  /* subtract from running TSC_OFFSET */
   10.34 -        sbbl %edx,VMCB_tsc_offset+4(%ecx)
   10.35 -        subl $20000,VMCB_tsc_offset(%ecx)  /* fudge factor for VMXXX calls  */
   10.36 -        sbbl $0,VMCB_tsc_offset+4(%ecx)
   10.37 -
   10.38 -        /* 
   10.39 -         * TODO: may need to add a kludge factor to account for all the cycles 
   10.40 -         * burned in VMLOAD, VMSAVE, VMRUN...
   10.41 -         */
   10.42 -
   10.43 -        popl %eax
   10.44 -        popl %edx
   10.45 -        #endif
   10.46 -
   10.47          movl VCPU_svm_vmcb_pa(%ebx), %eax
   10.48          popl %ebx
   10.49          popl %ecx
   10.50 @@ -150,31 +117,7 @@ ENTRY(svm_asm_do_launch)
   10.51          VMSAVE
   10.52          /* eax is the only register we're allowed to touch here... */
   10.53  
   10.54 -#if DO_FPUSAVE
   10.55 -        mov  %cr0, %eax
   10.56 -        push %eax
   10.57 -        clts
   10.58          GET_CURRENT(%eax)
   10.59 -        lea     VCPU_arch_guest_fpu_ctxt(%eax), %eax
   10.60 -        fxsave (%eax)
   10.61 -        fnclex
   10.62 -        pop  %eax
   10.63 -        mov  %eax, %cr0
   10.64 -#endif
   10.65 -        
   10.66 -        GET_CURRENT(%eax)
   10.67 -
   10.68 -#if (DO_TSC_OFFSET)
   10.69 -        pushl %edx
   10.70 -        pushl %ebx
   10.71 -        movl %eax,%ebx
   10.72 -        rdtsc
   10.73 -        movl %eax,VCPU_svm_vmexit_tsc(%ebx)
   10.74 -        movl %edx,VCPU_svm_vmexit_tsc+4(%ebx)
   10.75 -        movl %ebx,%eax
   10.76 -        popl %ebx
   10.77 -        popl %edx
   10.78 -#endif
   10.79  
   10.80          movl VCPU_svm_hsa_pa(%eax), %eax
   10.81          VMLOAD
    11.1 --- a/xen/arch/x86/mm.c	Wed Mar 01 15:06:24 2006 -0700
    11.2 +++ b/xen/arch/x86/mm.c	Thu Mar 02 10:49:19 2006 +0100
    11.3 @@ -506,7 +506,6 @@ get_page_from_l2e(
    11.4      vaddr <<= PGT_va_shift;
    11.5      rc = get_page_and_type_from_pagenr(
    11.6          l2e_get_pfn(l2e), PGT_l1_page_table | vaddr, d);
    11.7 -
    11.8  #if CONFIG_PAGING_LEVELS == 2
    11.9      if ( unlikely(!rc) )
   11.10          rc = get_linear_pagetable(l2e, pfn, d);
   11.11 @@ -3187,8 +3186,8 @@ static int ptwr_emulated_update(
   11.12          ptwr_flush(d, PTWR_PT_INACTIVE);
   11.13  
   11.14      /* Read the PTE that maps the page being updated. */
   11.15 -    if (__copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)],
   11.16 -                         sizeof(pte)))
   11.17 +    if ( __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)],
   11.18 +                          sizeof(pte)) )
   11.19      {
   11.20          MEM_LOG("ptwr_emulate: Cannot read thru linear_pg_table");
   11.21          return X86EMUL_UNHANDLEABLE;
   11.22 @@ -3198,15 +3197,10 @@ static int ptwr_emulated_update(
   11.23      page = mfn_to_page(pfn);
   11.24  
   11.25      /* We are looking only for read-only mappings of p.t. pages. */
   11.26 -    if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
   11.27 -         ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
   11.28 -         (page_get_owner(page) != d) )
   11.29 -    {
   11.30 -        MEM_LOG("ptwr_emulate: Page is mistyped or bad pte "
   11.31 -                "(%lx, %" PRtype_info ")",
   11.32 -                l1e_get_pfn(pte), page->u.inuse.type_info);
   11.33 -        return X86EMUL_UNHANDLEABLE;
   11.34 -    }
   11.35 +    ASSERT((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) == _PAGE_PRESENT);
   11.36 +    ASSERT((page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table);
   11.37 +    ASSERT((page->u.inuse.type_info & PGT_count_mask) != 0);
   11.38 +    ASSERT(page_get_owner(page) == d);
   11.39  
   11.40      /* Check the new PTE. */
   11.41      nl1e = l1e_from_intpte(val);
   11.42 @@ -3266,8 +3260,11 @@ static int ptwr_emulated_cmpxchg8b(
   11.43      unsigned long new,
   11.44      unsigned long new_hi)
   11.45  {
   11.46 -    return ptwr_emulated_update(
   11.47 -        addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1);
   11.48 +    if ( CONFIG_PAGING_LEVELS == 2 )
   11.49 +        return X86EMUL_UNHANDLEABLE;
   11.50 +    else
   11.51 +        return ptwr_emulated_update(
   11.52 +            addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1);
   11.53  }
   11.54  
   11.55  static struct x86_mem_emulator ptwr_mem_emulator = {
    12.1 --- a/xen/arch/x86/shadow.c	Wed Mar 01 15:06:24 2006 -0700
    12.2 +++ b/xen/arch/x86/shadow.c	Thu Mar 02 10:49:19 2006 +0100
    12.3 @@ -279,8 +279,8 @@ alloc_shadow_page(struct domain *d,
    12.4               psh_type == PGT_l4_shadow )      /* allocated for PAE PDP page */
    12.5              page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA);
    12.6          else if ( d->arch.ops->guest_paging_levels == PAGING_L3 &&
    12.7 -                  psh_type == PGT_l3_shadow ) /* allocated for PAE PDP page */
    12.8 -            page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA);
    12.9 +                  (psh_type == PGT_l3_shadow || psh_type == PGT_l4_shadow) )
   12.10 +            page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); /* allocated for PAE PDP page */
   12.11          else
   12.12              page = alloc_domheap_page(NULL);
   12.13  #endif
    13.1 --- a/xen/arch/x86/x86_32/domain_page.c	Wed Mar 01 15:06:24 2006 -0700
    13.2 +++ b/xen/arch/x86/x86_32/domain_page.c	Thu Mar 02 10:49:19 2006 +0100
    13.3 @@ -11,15 +11,40 @@
    13.4  #include <xen/mm.h>
    13.5  #include <xen/perfc.h>
    13.6  #include <xen/domain_page.h>
    13.7 +#include <xen/shadow.h>
    13.8  #include <asm/current.h>
    13.9  #include <asm/flushtlb.h>
   13.10  #include <asm/hardirq.h>
   13.11  
   13.12 +static inline struct vcpu *mapcache_current_vcpu(void)
   13.13 +{
   13.14 +    struct vcpu *v;
   13.15 +
   13.16 +    /* In the common case we use the mapcache of the running VCPU. */
   13.17 +    v = current;
   13.18 +
   13.19 +    /*
   13.20 +     * If guest_table is NULL, and we are running a paravirtualised guest,
   13.21 +     * then it means we are running on the idle domain's page table and must
   13.22 +     * therefore use its mapcache.
   13.23 +     */
   13.24 +    if ( unlikely(!pagetable_get_pfn(v->arch.guest_table)) && !HVM_DOMAIN(v) )
   13.25 +    {
   13.26 +        /* If we really are idling, perform lazy context switch now. */
   13.27 +        if ( (v = idle_vcpu[smp_processor_id()]) == current )
   13.28 +            __sync_lazy_execstate();
   13.29 +        /* We must now be running on the idle page table. */
   13.30 +        ASSERT(read_cr3() == __pa(idle_pg_table));
   13.31 +    }
   13.32 +
   13.33 +    return v;
   13.34 +}
   13.35 +
   13.36  void *map_domain_page(unsigned long pfn)
   13.37  {
   13.38      unsigned long va;
   13.39 -    unsigned int idx, i, vcpu = current->vcpu_id;
   13.40 -    struct domain *d;
   13.41 +    unsigned int idx, i, vcpu;
   13.42 +    struct vcpu *v;
   13.43      struct mapcache *cache;
   13.44      struct vcpu_maphash_entry *hashent;
   13.45  
   13.46 @@ -27,12 +52,10 @@ void *map_domain_page(unsigned long pfn)
   13.47  
   13.48      perfc_incrc(map_domain_page_count);
   13.49  
   13.50 -    /* If we are the idle domain, ensure that we run on our own page tables. */
   13.51 -    d = current->domain;
   13.52 -    if ( unlikely(is_idle_domain(d)) )
   13.53 -        __sync_lazy_execstate();
   13.54 +    v = mapcache_current_vcpu();
   13.55  
   13.56 -    cache = &d->arch.mapcache;
   13.57 +    vcpu  = v->vcpu_id;
   13.58 +    cache = &v->domain->arch.mapcache;
   13.59  
   13.60      hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)];
   13.61      if ( hashent->pfn == pfn )
   13.62 @@ -93,7 +116,8 @@ void *map_domain_page(unsigned long pfn)
   13.63  void unmap_domain_page(void *va)
   13.64  {
   13.65      unsigned int idx;
   13.66 -    struct mapcache *cache = &current->domain->arch.mapcache;
   13.67 +    struct vcpu *v;
   13.68 +    struct mapcache *cache;
   13.69      unsigned long pfn;
   13.70      struct vcpu_maphash_entry *hashent;
   13.71  
   13.72 @@ -102,9 +126,13 @@ void unmap_domain_page(void *va)
   13.73      ASSERT((void *)MAPCACHE_VIRT_START <= va);
   13.74      ASSERT(va < (void *)MAPCACHE_VIRT_END);
   13.75  
   13.76 +    v = mapcache_current_vcpu();
   13.77 +
   13.78 +    cache = &v->domain->arch.mapcache;
   13.79 +
   13.80      idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT;
   13.81      pfn = l1e_get_pfn(cache->l1tab[idx]);
   13.82 -    hashent = &cache->vcpu_maphash[current->vcpu_id].hash[MAPHASH_HASHFN(pfn)];
   13.83 +    hashent = &cache->vcpu_maphash[v->vcpu_id].hash[MAPHASH_HASHFN(pfn)];
   13.84  
   13.85      if ( hashent->idx == idx )
   13.86      {