ia64/xen-unstable

changeset 5099:187e3a02e0d5

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>
author cl349@firebug.cl.cam.ac.uk
date Mon May 23 22:34:18 2005 +0000 (2005-05-23)
parents 2d1acc84d984
children 18001959ba29
files .rootkeys BitKeeper/etc/ignore tools/Makefile tools/libxc/xc_linux_restore.c tools/python/xen/lowlevel/xc/xc.c tools/python/xen/util/xpopen.py tools/python/xen/xend/XendDomain.py tools/xcutils/Makefile tools/xcutils/xc_restore.c
line diff
     1.1 --- a/.rootkeys	Mon May 23 15:22:15 2005 +0000
     1.2 +++ b/.rootkeys	Mon May 23 22:34:18 2005 +0000
     1.3 @@ -863,6 +863,7 @@ 40c9c468IienauFHQ_xJIcqnPJ8giQ tools/pyt
     1.4  41dde8b0yuJX-S79w4xJKxBQ-Mhp1A tools/python/xen/util/memmap.py
     1.5  4288c6fcB1kUAqX0gzU85GGxmamS4Q tools/python/xen/util/process.py
     1.6  4059c6a0pnxhG8hwSOivXybbGOwuXw tools/python/xen/util/tempfile.py
     1.7 +4292565fDy2PaatawinIckKB0cKusg tools/python/xen/util/xpopen.py
     1.8  4267a9b16u4IEPhjRryesk6A17sobA tools/python/xen/web/SrvBase.py
     1.9  4267a9b1FfCUjW7m9anLERcx9lwhJg tools/python/xen/web/SrvDir.py
    1.10  4267a9b1uMXIfzB6-81ZLqMCyTgJmw tools/python/xen/web/__init__.py
    1.11 @@ -1029,6 +1030,8 @@ 41d58ba6x9KO1CQBT7kKOKq_pJYC3g tools/xcs
    1.12  41d58ba6R6foSMtSFEcu-yxWFrT8VQ tools/xcs/xcs.h
    1.13  41d58ba6qyr2BkTcH2WlNBYLRyl2Yw tools/xcs/xcs_proto.h
    1.14  41d58ba6ijEF6fedqRO5vFu7uCirZg tools/xcs/xcsdump.c
    1.15 +4292540couq-V0TPwyQ6bspNEWNcvw tools/xcutils/Makefile
    1.16 +42925407VysDb9O06OK_RUzTZxfLoA tools/xcutils/xc_restore.c
    1.17  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.18  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
    1.19  420d52d2_znVbT4JAPIU36vQOme83g tools/xentrace/xenctx.c
     2.1 --- a/BitKeeper/etc/ignore	Mon May 23 15:22:15 2005 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Mon May 23 22:34:18 2005 +0000
     2.3 @@ -125,6 +125,7 @@ tools/web-shutdown.tap
     2.4  tools/x2d2/minixend
     2.5  tools/xcs/xcs
     2.6  tools/xcs/xcsdump
     2.7 +tools/xcutils/xc_restore
     2.8  tools/xentrace/xentrace
     2.9  tools/xfrd/xfrd
    2.10  xen/BLOG
     3.1 --- a/tools/Makefile	Mon May 23 15:22:15 2005 +0000
     3.2 +++ b/tools/Makefile	Mon May 23 22:34:18 2005 +0000
     3.3 @@ -10,6 +10,7 @@ SUBDIRS += xentrace
     3.4  SUBDIRS += python
     3.5  SUBDIRS += xfrd
     3.6  SUBDIRS += xcs
     3.7 +SUBDIRS += xcutils
     3.8  SUBDIRS += pygrub
     3.9  
    3.10  .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
     4.1 --- a/tools/libxc/xc_linux_restore.c	Mon May 23 15:22:15 2005 +0000
     4.2 +++ b/tools/libxc/xc_linux_restore.c	Mon May 23 22:34:18 2005 +0000
     4.3 @@ -11,7 +11,7 @@
     4.4  
     4.5  #define MAX_BATCH_SIZE 1024
     4.6  
     4.7 -#define DEBUG 0
     4.8 +#define DEBUG 01
     4.9  
    4.10  #if 1
    4.11  #define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
    4.12 @@ -20,7 +20,7 @@
    4.13  #endif
    4.14  
    4.15  #if DEBUG
    4.16 -#define DPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
    4.17 +#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a )
    4.18  #else
    4.19  #define DPRINTF(_f, _a...) ((void)0)
    4.20  #endif
     5.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon May 23 15:22:15 2005 +0000
     5.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Mon May 23 22:34:18 2005 +0000
     5.3 @@ -63,6 +63,13 @@ static PyObject *pyxc_domain_dumpcore(Py
     5.4      return NULL;
     5.5  }
     5.6  
     5.7 +static PyObject *pyxc_handle(PyObject *self)
     5.8 +{
     5.9 +    XcObject *xc = (XcObject *)self;
    5.10 +
    5.11 +    return PyInt_FromLong(xc->xc_handle);
    5.12 +}
    5.13 +
    5.14  static PyObject *pyxc_domain_create(PyObject *self,
    5.15                                      PyObject *args,
    5.16                                      PyObject *kwds)
    5.17 @@ -334,36 +341,6 @@ static PyObject *pyxc_linux_save(PyObjec
    5.18      return val;
    5.19  }
    5.20  
    5.21 -static PyObject *pyxc_linux_restore(PyObject *self,
    5.22 -                                    PyObject *args,
    5.23 -                                    PyObject *kwds)
    5.24 -{
    5.25 -    XcObject *xc = (XcObject *)self;
    5.26 -    PyObject *val = NULL;
    5.27 -    int rc =-1;
    5.28 -    int io_fd, dom;
    5.29 -    unsigned long nr_pfns;
    5.30 -
    5.31 -    static char *kwd_list[] = { "fd", "dom", "pfns", NULL };
    5.32 -
    5.33 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iil", kwd_list,
    5.34 -                                      &io_fd, &dom, &nr_pfns) )
    5.35 -        goto exit;
    5.36 -
    5.37 -    rc = xc_linux_restore(xc->xc_handle, io_fd, dom, nr_pfns);
    5.38 -    if ( rc != 0 )
    5.39 -    {
    5.40 -        PyErr_SetFromErrno(xc_error);
    5.41 -        goto exit;
    5.42 -    }
    5.43 -
    5.44 -    Py_INCREF(zero);
    5.45 -    val = zero;
    5.46 -
    5.47 -  exit:
    5.48 -    return val;
    5.49 -}
    5.50 -
    5.51  static PyObject *pyxc_linux_build(PyObject *self,
    5.52                                    PyObject *args,
    5.53                                    PyObject *kwds)
    5.54 @@ -938,6 +915,11 @@ static PyObject *pyxc_domain_memory_incr
    5.55  
    5.56  
    5.57  static PyMethodDef pyxc_methods[] = {
    5.58 +    { "handle",
    5.59 +      (PyCFunction)pyxc_handle,
    5.60 +      0, "\n"
    5.61 +      "Query the xc control interface file descriptor.\n\n"
    5.62 +      "Returns: [int] file descriptor\n" },
    5.63      { "domain_create", 
    5.64        (PyCFunction)pyxc_domain_create, 
    5.65        METH_VARARGS | METH_KEYWORDS, "\n"
    5.66 @@ -1026,14 +1008,6 @@ static PyMethodDef pyxc_methods[] = {
    5.67        " progress   [int, 1]: Bool - display a running progress indication?\n\n"
    5.68        "Returns: [int] 0 on success; -1 on error.\n" },
    5.69  
    5.70 -    { "linux_restore", 
    5.71 -      (PyCFunction)pyxc_linux_restore, 
    5.72 -      METH_VARARGS | METH_KEYWORDS, "\n"
    5.73 -      "Restore the CPU and memory state of a Linux guest OS.\n"
    5.74 -      " dom        [int]:    Identifier of domain to be restored.\n"
    5.75 -      " pfns       [int]:    Number of pages domain uses.\n"
    5.76 -      "Returns: [int] new domain identifier on success; -1 on error.\n" },
    5.77 -
    5.78      { "linux_build", 
    5.79        (PyCFunction)pyxc_linux_build, 
    5.80        METH_VARARGS | METH_KEYWORDS, "\n"
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/python/xen/util/xpopen.py	Mon May 23 22:34:18 2005 +0000
     6.3 @@ -0,0 +1,112 @@
     6.4 +"""Spawn a command with pipes to its stdin, stdout, and optionally stderr.
     6.5 +
     6.6 +The normal os.popen(cmd, mode) call spawns a shell command and provides a
     6.7 +file interface to just the input or output of the process depending on
     6.8 +whether mode is 'r' or 'w'.  This module provides the functions xpopen2(cmd)
     6.9 +and xpopen3(cmd) which return two or three pipes to the spawned command.
    6.10 +Optionally exclude a list of file descriptors from being closed, allowing
    6.11 +access to those file descriptors from the command.
    6.12 +"""
    6.13 +
    6.14 +import os
    6.15 +import sys
    6.16 +
    6.17 +try:
    6.18 +    MAXFD = os.sysconf('SC_OPEN_MAX')
    6.19 +except (AttributeError, ValueError):
    6.20 +    MAXFD = 256
    6.21 +
    6.22 +_active = []
    6.23 +
    6.24 +def _cleanup():
    6.25 +    for inst in _active[:]:
    6.26 +        inst.poll()
    6.27 +
    6.28 +class xPopen3:
    6.29 +    """Class representing a child process.  Normally instances are created
    6.30 +    by the factory functions popen2() and popen3()."""
    6.31 +
    6.32 +    sts = -1                    # Child not completed yet
    6.33 +
    6.34 +    def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=()):
    6.35 +        """The parameter 'cmd' is the shell command to execute in a
    6.36 +        sub-process.  The 'capturestderr' flag, if true, specifies that
    6.37 +        the object should capture standard error output of the child process.
    6.38 +        The default is false.  If the 'bufsize' parameter is specified, it
    6.39 +        specifies the size of the I/O buffers to/from the child process."""
    6.40 +        _cleanup()
    6.41 +        self.passfd = passfd
    6.42 +        p2cread, p2cwrite = os.pipe()
    6.43 +        c2pread, c2pwrite = os.pipe()
    6.44 +        if capturestderr:
    6.45 +            errout, errin = os.pipe()
    6.46 +        self.pid = os.fork()
    6.47 +        if self.pid == 0:
    6.48 +            # Child
    6.49 +            os.dup2(p2cread, 0)
    6.50 +            os.dup2(c2pwrite, 1)
    6.51 +            if capturestderr:
    6.52 +                os.dup2(errin, 2)
    6.53 +            self._run_child(cmd)
    6.54 +        os.close(p2cread)
    6.55 +        self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
    6.56 +        os.close(c2pwrite)
    6.57 +        self.fromchild = os.fdopen(c2pread, 'r', bufsize)
    6.58 +        if capturestderr:
    6.59 +            os.close(errin)
    6.60 +            self.childerr = os.fdopen(errout, 'r', bufsize)
    6.61 +        else:
    6.62 +            self.childerr = None
    6.63 +        _active.append(self)
    6.64 +
    6.65 +    def _run_child(self, cmd):
    6.66 +        if isinstance(cmd, basestring):
    6.67 +            cmd = ['/bin/sh', '-c', cmd]
    6.68 +        for i in range(3, MAXFD):
    6.69 +            if i in self.passfd:
    6.70 +                continue
    6.71 +            try:
    6.72 +                os.close(i)
    6.73 +            except OSError:
    6.74 +                pass
    6.75 +        try:
    6.76 +            os.execvp(cmd[0], cmd)
    6.77 +        finally:
    6.78 +            os._exit(1)
    6.79 +
    6.80 +    def poll(self):
    6.81 +        """Return the exit status of the child process if it has finished,
    6.82 +        or -1 if it hasn't finished yet."""
    6.83 +        if self.sts < 0:
    6.84 +            try:
    6.85 +                pid, sts = os.waitpid(self.pid, os.WNOHANG)
    6.86 +                if pid == self.pid:
    6.87 +                    self.sts = sts
    6.88 +                    _active.remove(self)
    6.89 +            except os.error:
    6.90 +                pass
    6.91 +        return self.sts
    6.92 +
    6.93 +    def wait(self):
    6.94 +        """Wait for and return the exit status of the child process."""
    6.95 +        if self.sts < 0:
    6.96 +            pid, sts = os.waitpid(self.pid, 0)
    6.97 +            if pid == self.pid:
    6.98 +                self.sts = sts
    6.99 +                _active.remove(self)
   6.100 +        return self.sts
   6.101 +
   6.102 +
   6.103 +def xpopen2(cmd, bufsize=-1, mode='t', passfd=[]):
   6.104 +    """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
   6.105 +    specified, it sets the buffer size for the I/O pipes.  The file objects
   6.106 +    (child_stdout, child_stdin) are returned."""
   6.107 +    inst = xPopen3(cmd, False, bufsize, passfd)
   6.108 +    return inst.fromchild, inst.tochild
   6.109 +
   6.110 +def xpopen3(cmd, bufsize=-1, mode='t', passfd=[]):
   6.111 +    """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
   6.112 +    specified, it sets the buffer size for the I/O pipes.  The file objects
   6.113 +    (child_stdout, child_stdin, child_stderr) are returned."""
   6.114 +    inst = xPopen3(cmd, True, bufsize, passfd)
   6.115 +    return inst.fromchild, inst.tochild, inst.childerr
     7.1 --- a/tools/python/xen/xend/XendDomain.py	Mon May 23 15:22:15 2005 +0000
     7.2 +++ b/tools/python/xen/xend/XendDomain.py	Mon May 23 22:34:18 2005 +0000
     7.3 @@ -25,7 +25,11 @@ from xen.xend.server import channel
     7.4  
     7.5  
     7.6  import errno
     7.7 +import os
     7.8 +import select
     7.9 +from string import join
    7.10  from struct import pack, unpack, calcsize
    7.11 +from xen.util.xpopen import xPopen3
    7.12  
    7.13  __all__ = [ "XendDomain" ]
    7.14  
    7.15 @@ -325,6 +329,7 @@ class XendDomain:
    7.16          sizeof_int = calcsize("i")
    7.17          sizeof_unsigned_long = calcsize("L")
    7.18          PAGE_SIZE = 4096
    7.19 +        PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
    7.20  
    7.21          class XendFile(file):
    7.22              def read_exact(self, size, error_msg):
    7.23 @@ -367,7 +372,29 @@ class XendDomain:
    7.24              #             underlying file descriptor
    7.25              ignore = fd.tell()
    7.26  
    7.27 -            xc.linux_restore(fd.fileno(), int(dominfo.id), nr_pfns)
    7.28 +            cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd.fileno()),
    7.29 +                   dominfo.id, str(nr_pfns)]
    7.30 +            log.info("[xc_restore] " + join(cmd))
    7.31 +            child = xPopen3(cmd, True, -1, [fd.fileno(), xc.handle()])
    7.32 +            child.tochild.close()
    7.33 +
    7.34 +            lasterr = ""
    7.35 +            p = select.poll()
    7.36 +            p.register(child.fromchild.fileno())
    7.37 +            p.register(child.childerr.fileno())
    7.38 +            while True:
    7.39 +                r = p.poll()
    7.40 +                for l in child.childerr.readlines():
    7.41 +                    log.error(l.rstrip())
    7.42 +                    lasterr = l.rstrip()
    7.43 +                for l in child.fromchild.readlines():
    7.44 +                    log.info(l.rstrip())
    7.45 +                if filter(lambda (fd, event): event & select.POLLHUP, r):
    7.46 +                    break
    7.47 +
    7.48 +            if child.wait() != 0:
    7.49 +                raise XendError("xc_restore failed: %s" % lasterr)
    7.50 +            
    7.51              return dominfo
    7.52  
    7.53          except IOError, ex:
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/xcutils/Makefile	Mon May 23 22:34:18 2005 +0000
     8.3 @@ -0,0 +1,62 @@
     8.4 +#
     8.5 +# tools/xcutils/Makefile
     8.6 +#
     8.7 +# This file is subject to the terms and conditions of the GNU General
     8.8 +# Public License.  See the file "COPYING" in the main directory of
     8.9 +# this archive for more details.
    8.10 +#
    8.11 +# Copyright (C) 2005 by Christian Limpach
    8.12 +#
    8.13 +
    8.14 +INSTALL		= install
    8.15 +INSTALL_PROG	= $(INSTALL) -m0755
    8.16 +INSTALL_DIR	= $(INSTALL) -d -m0755
    8.17 +
    8.18 +XEN_ROOT	= ../..
    8.19 +include $(XEN_ROOT)/tools/Rules.mk
    8.20 +
    8.21 +PROGRAMS_INSTALL_DIR	= /usr/libexec/xen
    8.22 +
    8.23 +vpath %.h      $(XEN_LIBXC)
    8.24 +INCLUDES += -I $(XEN_LIBXC)
    8.25 +
    8.26 +CC := gcc
    8.27 +
    8.28 +CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
    8.29 +CFLAGS += $(INCLUDES)
    8.30 +
    8.31 +# Make gcc generate dependencies.
    8.32 +CFLAGS += -Wp,-MD,.$(@F).d
    8.33 +PROG_DEP = .*.d
    8.34 +
    8.35 +PROGRAMS		= xc_restore
    8.36 +
    8.37 +xc_restore_OBJS		= xc_restore.o
    8.38 +xc_restore_LIBS		= xc
    8.39 +
    8.40 +.PHONY: all
    8.41 +all: build
    8.42 +build: $(PROGRAMS)
    8.43 +
    8.44 +define PROGRAM_template
    8.45 + $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
    8.46 + ALL_OBJS	+= $$($(1)_OBJS)
    8.47 +endef
    8.48 +
    8.49 +$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
    8.50 +
    8.51 +$(PROGRAMS):
    8.52 +	$(LINK.o) $^ $(LDLIBS) -o $@
    8.53 +
    8.54 +.PHONY: install
    8.55 +install: build
    8.56 +	[ -d $(DESTDIR)$(PROGRAMS_INSTALL_DIR) ] || \
    8.57 +		$(INSTALL_DIR) $(DESTDIR)$(PROGRAMS_INSTALL_DIR)
    8.58 +	$(INSTALL_PROG) $(PROGRAMS) $(DESTDIR)$(PROGRAMS_INSTALL_DIR)
    8.59 +
    8.60 +
    8.61 +clean:
    8.62 +	$(RM) $(ALL_OBJS) $(PROGRAMS)
    8.63 +	$(RM) $(PROG_DEP)
    8.64 +
    8.65 +-include $(PROG_DEP)
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/xcutils/xc_restore.c	Mon May 23 22:34:18 2005 +0000
     9.3 @@ -0,0 +1,30 @@
     9.4 +/* 
     9.5 + * This file is subject to the terms and conditions of the GNU General
     9.6 + * Public License.  See the file "COPYING" in the main directory of
     9.7 + * this archive for more details.
     9.8 + *
     9.9 + * Copyright (C) 2005 by Christian Limpach
    9.10 + *
    9.11 + */
    9.12 +
    9.13 +#include <stdlib.h>
    9.14 +#include <stdio.h>
    9.15 +#include <err.h>
    9.16 +
    9.17 +#include <xc.h>
    9.18 +
    9.19 +int
    9.20 +main(int argc, char **argv)
    9.21 +{
    9.22 +    unsigned int xc_fd, io_fd, domid, nr_pfns;
    9.23 +
    9.24 +    if (argc != 5)
    9.25 +	errx(1, "usage: %s xcfd iofd domid nr_pfns", argv[0]);
    9.26 +
    9.27 +    xc_fd = atoi(argv[1]);
    9.28 +    io_fd = atoi(argv[2]);
    9.29 +    domid = atoi(argv[3]);
    9.30 +    nr_pfns = atoi(argv[4]);
    9.31 +
    9.32 +    return xc_linux_restore(xc_fd, io_fd, domid, nr_pfns);
    9.33 +}