aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-05-23 22:34:18 +0000
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-05-23 22:34:18 +0000
commit35db9d71b6f65c80fce40a110d0e8a58af8437b5 (patch)
tree9f765d6fd0353c76c8f13cf4459471e671eea95a
parentdad197b071e41ba1a969fe10fc6fda20d5b46fef (diff)
downloadxen-35db9d71b6f65c80fce40a110d0e8a58af8437b5.tar.gz
xen-35db9d71b6f65c80fce40a110d0e8a58af8437b5.tar.bz2
xen-35db9d71b6f65c80fce40a110d0e8a58af8437b5.zip
bitkeeper revision 1.1513.1.1 (42925a6aSZSwfyaVsNzV4psPmpZwZg)
Execute xc_linux_restore in a seperate process so that it can't crash xend. Also handle errors passed from xc_linux_restore and log info messages from xc_linux_restore. XendDomain.py: Popen xc_restore instead of calling xc_linux_restore directly. xc.c: Add pyxc_handle exporting the file descriptor to the control interface. Remove xc_linux_restore -- replaced by popen of xc_restore directly from python. xc_linux_restore.c: Enable debug output. xpopen.py: Add xpopen functionality: Optionally exclude a list of file descriptors from being closed, allowing access to those file descriptors from the command. Remove unused parts. xpopen.py, Makefile, xc_restore.c: new file Makefile: Add xcutils subdir. ignore: Add tools/xcutils/xc_restore. Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
-rw-r--r--.rootkeys3
-rw-r--r--BitKeeper/etc/ignore1
-rw-r--r--tools/Makefile1
-rw-r--r--tools/libxc/xc_linux_restore.c4
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c50
-rw-r--r--tools/python/xen/util/xpopen.py112
-rw-r--r--tools/python/xen/xend/XendDomain.py29
-rw-r--r--tools/xcutils/Makefile62
-rw-r--r--tools/xcutils/xc_restore.c30
9 files changed, 251 insertions, 41 deletions
diff --git a/.rootkeys b/.rootkeys
index 4ba4305d4b..8492df053d 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -863,6 +863,7 @@
41dde8b0yuJX-S79w4xJKxBQ-Mhp1A tools/python/xen/util/memmap.py
4288c6fcB1kUAqX0gzU85GGxmamS4Q tools/python/xen/util/process.py
4059c6a0pnxhG8hwSOivXybbGOwuXw tools/python/xen/util/tempfile.py
+4292565fDy2PaatawinIckKB0cKusg tools/python/xen/util/xpopen.py
4267a9b16u4IEPhjRryesk6A17sobA tools/python/xen/web/SrvBase.py
4267a9b1FfCUjW7m9anLERcx9lwhJg tools/python/xen/web/SrvDir.py
4267a9b1uMXIfzB6-81ZLqMCyTgJmw tools/python/xen/web/__init__.py
@@ -1029,6 +1030,8 @@
41d58ba6R6foSMtSFEcu-yxWFrT8VQ tools/xcs/xcs.h
41d58ba6qyr2BkTcH2WlNBYLRyl2Yw tools/xcs/xcs_proto.h
41d58ba6ijEF6fedqRO5vFu7uCirZg tools/xcs/xcsdump.c
+4292540couq-V0TPwyQ6bspNEWNcvw tools/xcutils/Makefile
+42925407VysDb9O06OK_RUzTZxfLoA tools/xcutils/xc_restore.c
403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
420d52d2_znVbT4JAPIU36vQOme83g tools/xentrace/xenctx.c
diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore
index 08995a6ab9..8ffdcf5028 100644
--- a/BitKeeper/etc/ignore
+++ b/BitKeeper/etc/ignore
@@ -125,6 +125,7 @@ tools/web-shutdown.tap
tools/x2d2/minixend
tools/xcs/xcs
tools/xcs/xcsdump
+tools/xcutils/xc_restore
tools/xentrace/xentrace
tools/xfrd/xfrd
xen/BLOG
diff --git a/tools/Makefile b/tools/Makefile
index 52ddb9f24b..9e6c159050 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -10,6 +10,7 @@ SUBDIRS += xentrace
SUBDIRS += python
SUBDIRS += xfrd
SUBDIRS += xcs
+SUBDIRS += xcutils
SUBDIRS += pygrub
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
index 7d6aec2859..c679e9dd5a 100644
--- a/tools/libxc/xc_linux_restore.c
+++ b/tools/libxc/xc_linux_restore.c
@@ -11,7 +11,7 @@
#define MAX_BATCH_SIZE 1024
-#define DEBUG 0
+#define DEBUG 01
#if 1
#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
@@ -20,7 +20,7 @@
#endif
#if DEBUG
-#define DPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
+#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a )
#else
#define DPRINTF(_f, _a...) ((void)0)
#endif
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 9e6396c75b..8132ff1047 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -63,6 +63,13 @@ static PyObject *pyxc_domain_dumpcore(PyObject *self,
return NULL;
}
+static PyObject *pyxc_handle(PyObject *self)
+{
+ XcObject *xc = (XcObject *)self;
+
+ return PyInt_FromLong(xc->xc_handle);
+}
+
static PyObject *pyxc_domain_create(PyObject *self,
PyObject *args,
PyObject *kwds)
@@ -334,36 +341,6 @@ static PyObject *pyxc_linux_save(PyObject *self,
return val;
}
-static PyObject *pyxc_linux_restore(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- PyObject *val = NULL;
- int rc =-1;
- int io_fd, dom;
- unsigned long nr_pfns;
-
- static char *kwd_list[] = { "fd", "dom", "pfns", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iil", kwd_list,
- &io_fd, &dom, &nr_pfns) )
- goto exit;
-
- rc = xc_linux_restore(xc->xc_handle, io_fd, dom, nr_pfns);
- if ( rc != 0 )
- {
- PyErr_SetFromErrno(xc_error);
- goto exit;
- }
-
- Py_INCREF(zero);
- val = zero;
-
- exit:
- return val;
-}
-
static PyObject *pyxc_linux_build(PyObject *self,
PyObject *args,
PyObject *kwds)
@@ -938,6 +915,11 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
static PyMethodDef pyxc_methods[] = {
+ { "handle",
+ (PyCFunction)pyxc_handle,
+ 0, "\n"
+ "Query the xc control interface file descriptor.\n\n"
+ "Returns: [int] file descriptor\n" },
{ "domain_create",
(PyCFunction)pyxc_domain_create,
METH_VARARGS | METH_KEYWORDS, "\n"
@@ -1026,14 +1008,6 @@ static PyMethodDef pyxc_methods[] = {
" progress [int, 1]: Bool - display a running progress indication?\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
- { "linux_restore",
- (PyCFunction)pyxc_linux_restore,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Restore the CPU and memory state of a Linux guest OS.\n"
- " dom [int]: Identifier of domain to be restored.\n"
- " pfns [int]: Number of pages domain uses.\n"
- "Returns: [int] new domain identifier on success; -1 on error.\n" },
-
{ "linux_build",
(PyCFunction)pyxc_linux_build,
METH_VARARGS | METH_KEYWORDS, "\n"
diff --git a/tools/python/xen/util/xpopen.py b/tools/python/xen/util/xpopen.py
new file mode 100644
index 0000000000..6b15121f09
--- /dev/null
+++ b/tools/python/xen/util/xpopen.py
@@ -0,0 +1,112 @@
+"""Spawn a command with pipes to its stdin, stdout, and optionally stderr.
+
+The normal os.popen(cmd, mode) call spawns a shell command and provides a
+file interface to just the input or output of the process depending on
+whether mode is 'r' or 'w'. This module provides the functions xpopen2(cmd)
+and xpopen3(cmd) which return two or three pipes to the spawned command.
+Optionally exclude a list of file descriptors from being closed, allowing
+access to those file descriptors from the command.
+"""
+
+import os
+import sys
+
+try:
+ MAXFD = os.sysconf('SC_OPEN_MAX')
+except (AttributeError, ValueError):
+ MAXFD = 256
+
+_active = []
+
+def _cleanup():
+ for inst in _active[:]:
+ inst.poll()
+
+class xPopen3:
+ """Class representing a child process. Normally instances are created
+ by the factory functions popen2() and popen3()."""
+
+ sts = -1 # Child not completed yet
+
+ def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=()):
+ """The parameter 'cmd' is the shell command to execute in a
+ sub-process. The 'capturestderr' flag, if true, specifies that
+ the object should capture standard error output of the child process.
+ The default is false. If the 'bufsize' parameter is specified, it
+ specifies the size of the I/O buffers to/from the child process."""
+ _cleanup()
+ self.passfd = passfd
+ p2cread, p2cwrite = os.pipe()
+ c2pread, c2pwrite = os.pipe()
+ if capturestderr:
+ errout, errin = os.pipe()
+ self.pid = os.fork()
+ if self.pid == 0:
+ # Child
+ os.dup2(p2cread, 0)
+ os.dup2(c2pwrite, 1)
+ if capturestderr:
+ os.dup2(errin, 2)
+ self._run_child(cmd)
+ os.close(p2cread)
+ self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
+ os.close(c2pwrite)
+ self.fromchild = os.fdopen(c2pread, 'r', bufsize)
+ if capturestderr:
+ os.close(errin)
+ self.childerr = os.fdopen(errout, 'r', bufsize)
+ else:
+ self.childerr = None
+ _active.append(self)
+
+ def _run_child(self, cmd):
+ if isinstance(cmd, basestring):
+ cmd = ['/bin/sh', '-c', cmd]
+ for i in range(3, MAXFD):
+ if i in self.passfd:
+ continue
+ try:
+ os.close(i)
+ except OSError:
+ pass
+ try:
+ os.execvp(cmd[0], cmd)
+ finally:
+ os._exit(1)
+
+ def poll(self):
+ """Return the exit status of the child process if it has finished,
+ or -1 if it hasn't finished yet."""
+ if self.sts < 0:
+ try:
+ pid, sts = os.waitpid(self.pid, os.WNOHANG)
+ if pid == self.pid:
+ self.sts = sts
+ _active.remove(self)
+ except os.error:
+ pass
+ return self.sts
+
+ def wait(self):
+ """Wait for and return the exit status of the child process."""
+ if self.sts < 0:
+ pid, sts = os.waitpid(self.pid, 0)
+ if pid == self.pid:
+ self.sts = sts
+ _active.remove(self)
+ return self.sts
+
+
+def xpopen2(cmd, bufsize=-1, mode='t', passfd=[]):
+ """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
+ specified, it sets the buffer size for the I/O pipes. The file objects
+ (child_stdout, child_stdin) are returned."""
+ inst = xPopen3(cmd, False, bufsize, passfd)
+ return inst.fromchild, inst.tochild
+
+def xpopen3(cmd, bufsize=-1, mode='t', passfd=[]):
+ """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
+ specified, it sets the buffer size for the I/O pipes. The file objects
+ (child_stdout, child_stdin, child_stderr) are returned."""
+ inst = xPopen3(cmd, True, bufsize, passfd)
+ return inst.fromchild, inst.tochild, inst.childerr
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index d45a3547df..2320e8758d 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -25,7 +25,11 @@ from xen.xend.server import channel
import errno
+import os
+import select
+from string import join
from struct import pack, unpack, calcsize
+from xen.util.xpopen import xPopen3
__all__ = [ "XendDomain" ]
@@ -325,6 +329,7 @@ class XendDomain:
sizeof_int = calcsize("i")
sizeof_unsigned_long = calcsize("L")
PAGE_SIZE = 4096
+ PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
class XendFile(file):
def read_exact(self, size, error_msg):
@@ -367,7 +372,29 @@ class XendDomain:
# underlying file descriptor
ignore = fd.tell()
- xc.linux_restore(fd.fileno(), int(dominfo.id), nr_pfns)
+ cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd.fileno()),
+ dominfo.id, str(nr_pfns)]
+ log.info("[xc_restore] " + join(cmd))
+ child = xPopen3(cmd, True, -1, [fd.fileno(), xc.handle()])
+ child.tochild.close()
+
+ lasterr = ""
+ p = select.poll()
+ p.register(child.fromchild.fileno())
+ p.register(child.childerr.fileno())
+ while True:
+ r = p.poll()
+ for l in child.childerr.readlines():
+ log.error(l.rstrip())
+ lasterr = l.rstrip()
+ for l in child.fromchild.readlines():
+ log.info(l.rstrip())
+ if filter(lambda (fd, event): event & select.POLLHUP, r):
+ break
+
+ if child.wait() != 0:
+ raise XendError("xc_restore failed: %s" % lasterr)
+
return dominfo
except IOError, ex:
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
new file mode 100644
index 0000000000..dbdc45d496
--- /dev/null
+++ b/tools/xcutils/Makefile
@@ -0,0 +1,62 @@
+#
+# tools/xcutils/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General
+# Public License. See the file "COPYING" in the main directory of
+# this archive for more details.
+#
+# Copyright (C) 2005 by Christian Limpach
+#
+
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+PROGRAMS_INSTALL_DIR = /usr/libexec/xen
+
+vpath %.h $(XEN_LIBXC)
+INCLUDES += -I $(XEN_LIBXC)
+
+CC := gcc
+
+CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
+CFLAGS += $(INCLUDES)
+
+# Make gcc generate dependencies.
+CFLAGS += -Wp,-MD,.$(@F).d
+PROG_DEP = .*.d
+
+PROGRAMS = xc_restore
+
+xc_restore_OBJS = xc_restore.o
+xc_restore_LIBS = xc
+
+.PHONY: all
+all: build
+build: $(PROGRAMS)
+
+define PROGRAM_template
+ $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
+ ALL_OBJS += $$($(1)_OBJS)
+endef
+
+$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
+
+$(PROGRAMS):
+ $(LINK.o) $^ $(LDLIBS) -o $@
+
+.PHONY: install
+install: build
+ [ -d $(DESTDIR)$(PROGRAMS_INSTALL_DIR) ] || \
+ $(INSTALL_DIR) $(DESTDIR)$(PROGRAMS_INSTALL_DIR)
+ $(INSTALL_PROG) $(PROGRAMS) $(DESTDIR)$(PROGRAMS_INSTALL_DIR)
+
+
+clean:
+ $(RM) $(ALL_OBJS) $(PROGRAMS)
+ $(RM) $(PROG_DEP)
+
+-include $(PROG_DEP)
diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c
new file mode 100644
index 0000000000..ebba6d698f
--- /dev/null
+++ b/tools/xcutils/xc_restore.c
@@ -0,0 +1,30 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 by Christian Limpach
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include <xc.h>
+
+int
+main(int argc, char **argv)
+{
+ unsigned int xc_fd, io_fd, domid, nr_pfns;
+
+ if (argc != 5)
+ errx(1, "usage: %s xcfd iofd domid nr_pfns", argv[0]);
+
+ xc_fd = atoi(argv[1]);
+ io_fd = atoi(argv[2]);
+ domid = atoi(argv[3]);
+ nr_pfns = atoi(argv[4]);
+
+ return xc_linux_restore(xc_fd, io_fd, domid, nr_pfns);
+}