# HG changeset patch
# User root@procyon
# Node ID a16cc49dbd01e9c3f78fb5041d782025c2bda2fa
# Parent  10b05c2e79475f90330fa061b46d6df7e71a41c5
Support "xm dump" command.
xc_domain_dump() only call __domain_crash().
After __domain_crash(), xend start dumpcore 
because shutdown status is crash.
(When enabel-dump in xend-cofig.sxp is yes)

The xm dump usage is below.
1. vi /etc/xen/xend-config.sxp
   (enable-dump yes)
2. xend start
3. xm create domU
4. xm dump domU
5. coredump is created in /var/xen/dump/

Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>

diff -r 10b05c2e7947 -r a16cc49dbd01 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/libxc/xc_domain.c	Thu Aug 03 09:20:16 2006 +0900
@@ -28,6 +28,14 @@ int xc_domain_create(int xc_handle,
     return 0;
 }
 
+int xc_domain_dump(int xc_handle,
+                    uint32_t domid)
+{
+    DECLARE_DOM0_OP;
+    op.cmd = DOM0_DUMPDOMAIN;
+    op.u.dumpdomain.domain = (domid_t)domid;
+    return do_dom0_op(xc_handle, &op);
+}
 
 int xc_domain_pause(int xc_handle,
                     uint32_t domid)
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/libxc/xenctrl.h	Thu Aug 03 09:20:16 2006 +0900
@@ -202,6 +202,17 @@ int xc_domain_unpause(int xc_handle,
                       uint32_t domid);
 
 /**
+ * This function dump a domain. A domain_dump only crash domain.
+ * after crash domain, xc_domain_dumpcore dump domain memory.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain id to pause
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_dump(int xc_handle,
+                    uint32_t domid);
+
+/**
  * This function will destroy a domain.  Destroying a domain removes the domain
  * completely from memory.  This function should be called after sending the
  * domain a SHUTDOWN control message to free up the domain resources.
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c	Thu Aug 03 09:20:16 2006 +0900
@@ -117,6 +117,11 @@ static PyObject *pyxc_domain_max_vcpus(X
     
     Py_INCREF(zero);
     return zero;
+}
+
+static PyObject *pyxc_domain_dump(XcObject *self, PyObject *args)
+{
+    return dom_op(self, args, xc_domain_dump);
 }
 
 static PyObject *pyxc_domain_pause(XcObject *self, PyObject *args)
@@ -945,6 +950,13 @@ static PyMethodDef pyxc_methods[] = {
       "Dump core of a domain.\n"
       " dom [int]: Identifier of domain to dump core of.\n"
       " corefile [string]: Name of corefile to be created.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_dump", 
+      (PyCFunction)pyxc_domain_dump, 
+      METH_VARARGS, "\n"
+      "Dump of a domain.\n"
+      " dom [int]: Identifier of domain to dump core of.\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
     { "domain_pause", 
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/python/xen/xend/XendDomain.py	Thu Aug 03 09:20:16 2006 +0900
@@ -355,6 +355,23 @@ class XendDomain:
             self.domains_lock.release()
 
  
+    def domain_dump(self, domid):
+        """dump domain's core."""
+
+        dominfo = self.domain_lookup_by_name_or_id_nr(domid)
+        if not dominfo:
+            raise XendInvalidDomain(str(domid))
+
+        if dominfo.getDomid() == PRIV_DOMAIN:
+            raise XendError("Cannot dump privileged domain %s" % domid)
+
+        try:
+            log.info("Domain %s (%d) coredump.", dominfo.getName(),
+                     dominfo.getDomid())
+            return dominfo.dump()
+        except Exception, ex:
+            raise XendError(str(ex))
+
     def domain_unpause(self, domid):
         """Unpause domain execution."""
 
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Aug 03 09:20:16 2006 +0900
@@ -1546,6 +1546,8 @@ class XendDomainInfo:
     def unpause(self):
         xc.domain_unpause(self.domid)
 
+    def dump(self):
+        xc.domain_dump(self.domid)
 
     ## private:
 
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/python/xen/xend/server/SrvDomain.py	Thu Aug 03 09:20:16 2006 +0900
@@ -43,6 +43,10 @@ class SrvDomain(SrvDir):
                      ['config', 'sxpr']])
         return fn(req.args, {'dom': self.dom.domid})
 
+    def op_dump(self, _1, _2):
+        val = self.xd.domain_dump(self.dom.domid)
+        return val
+        
     def op_unpause(self, _1, _2):
         val = self.xd.domain_unpause(self.dom.domid)
         return val
diff -r 10b05c2e7947 -r a16cc49dbd01 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py	Tue Aug 01 18:08:01 2006 +0100
+++ b/tools/python/xen/xm/main.py	Thu Aug 03 09:20:16 2006 +0900
@@ -70,6 +70,7 @@ shutdown_help ="shutdown <DomId> [-w][-a
 shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
 top_help =     "top                              Monitor system and domains in real-time"
 unpause_help = "unpause <DomId>                  Unpause a paused domain"
+dump_help =    "dump <DomId>                     dump domain's core"
 
 help_spacer = """
    """
@@ -148,6 +149,7 @@ short_command_list = [
     "top",
     "unpause",
     "vcpu-set",
+    "dump",
     ]
 
 domain_commands = [
@@ -173,6 +175,7 @@ domain_commands = [
     "vcpu-list",
     "vcpu-pin",
     "vcpu-set",
+    "dump",
     ]
 
 host_commands = [
@@ -585,6 +588,12 @@ def xm_unpause(args):
     dom = args[0]
 
     server.xend.domain.unpause(dom)
+
+def xm_dump(args):
+    arg_check(args, "dump", 1)
+    dom = args[0]
+
+    server.xend.domain.dump(dom)
 
 def xm_rename(args):
     arg_check(args, "rename", 2)
@@ -1126,6 +1135,7 @@ commands = {
     # special
     "pause": xm_pause,
     "unpause": xm_unpause,
+    "dump": xm_dump,
     # host commands
     "dmesg": xm_dmesg,
     "info": xm_info,
diff -r 10b05c2e7947 -r a16cc49dbd01 xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c	Tue Aug 01 18:08:01 2006 +0100
+++ b/xen/common/dom0_ops.c	Thu Aug 03 09:20:16 2006 +0900
@@ -164,6 +164,23 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op
     }
     break;
 
+    case DOM0_DUMPDOMAIN:
+    {
+        struct domain *d = find_domain_by_id(op->u.dumpdomain.domain);
+        ret = -ESRCH;
+        if ( d != NULL )
+        {
+            ret = -EINVAL;
+            if ( d != current->domain )
+            {
+                __domain_crash(d);
+                ret = 0;
+            }
+            put_domain(d);
+        }
+    }
+    break;
+
     case DOM0_PAUSEDOMAIN:
     {
         struct domain *d = find_domain_by_id(op->u.pausedomain.domain);
diff -r 10b05c2e7947 -r a16cc49dbd01 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h	Tue Aug 01 18:08:01 2006 +0100
+++ b/xen/include/public/dom0_ops.h	Thu Aug 03 09:20:16 2006 +0900
@@ -539,6 +539,14 @@ struct dom0_settimeoffset {
 };
 typedef struct dom0_settimeoffset dom0_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(dom0_settimeoffset_t);
+
+#define DOM0_DUMPDOMAIN    51
+struct dom0_dumpdomain {
+    /* IN parameters. */
+    domid_t domain;
+};
+typedef struct dom0_dumpdomain dom0_dumpdomain_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_dumpdomain_t);
 
 struct dom0_op {
     uint32_t cmd;
@@ -583,6 +591,7 @@ struct dom0_op {
         struct dom0_hypercall_init    hypercall_init;
         struct dom0_domain_setup      domain_setup;
         struct dom0_settimeoffset     settimeoffset;
+        struct dom0_dumpdomain        dumpdomain;
         uint8_t                       pad[128];
     } u;
 };
