# HG changeset patch # User root@procyon # Node ID a9e921cf08212ad25ec8966314530482f4bcbf8f # Parent ec03b24a2d83273ec62db8596506b80577a0e41e xm dump command add on xm dump-core [-L|--live][-C| --crash] [output path] -L| --live Live dump: By default, xm dump does an xm pause, unpause before and after taking the dump, respectively. This option disables the pause/unpause and simply takes the dump. -C :| --crash crash dump: This executes an xm destroy after the dump file is complete. The output path is optional, and if it is not specified, the path will be /var/xen/dump/..core This command uses the existant dumpCore(), which has been used for coredump when a domU crashed. In this patch, the xc_domain_dumpcore_via_callback() in xc_core.c of libxc is also modified. Previously, the xc_domain_dumpcore_via_callback() did not respond to error when copy_from_domain_page() failed. In other words, the dump core remained silent even if mapping the domain memory failed and its page could not be copied. When this happened, erroneous data had been dumped to the file without the user realizing it. Now, it has been modified so that if copy_from_domain_page fails, this fact is recorded in the logfile. However even in such cases, the dumping will continue as before. Signed-off-by: Ken Hironaka Signed-off-by: Akio Takebe diff -r ec03b24a2d83 -r a9e921cf0821 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Tue Aug 15 19:53:55 2006 +0100 +++ b/tools/libxc/xc_core.c Fri Aug 18 09:57:23 2006 +0900 @@ -37,6 +37,7 @@ xc_domain_dumpcore_via_callback(int xc_h char dummy[PAGE_SIZE]; int dummy_len; int sts; + unsigned int cpy_err_cnt = 0; if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL ) { @@ -103,7 +104,13 @@ xc_domain_dumpcore_via_callback(int xc_h for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ ) { - copy_from_domain_page(xc_handle, domid, page_array[i], dump_mem); + sts = copy_from_domain_page(xc_handle, domid, page_array[i], dump_mem); + + if( sts != 0 ){ + memset(dump_mem, 0, PAGE_SIZE); + cpy_err_cnt++; + } + dump_mem += PAGE_SIZE; if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) ) { @@ -112,6 +119,10 @@ xc_domain_dumpcore_via_callback(int xc_h goto error_out; dump_mem = dump_mem_start; } + } + if( cpy_err_cnt != 0 ){ + IPRINTF("Could not copy from domid=%d (%d)pages\n", domid, cpy_err_cnt); + goto error_out; } free(dump_mem_start); diff -r ec03b24a2d83 -r a9e921cf0821 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Tue Aug 15 19:53:55 2006 +0100 +++ b/tools/python/xen/xend/XendDomain.py Fri Aug 18 09:57:23 2006 +0900 @@ -390,6 +390,22 @@ class XendDomain: except Exception, ex: raise XendError(str(ex)) + def domain_dump(self, domid, filename, live, crash): + """Dump domain 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 core for privileged domain %s" % domid) + + try: + log.info("Domain core dump requested for domain %s (%d) live=%d crash=%d.", + dominfo.getName(), dominfo.getDomid(), live, crash) + return dominfo.dumpCore(filename) + except Exception, ex: + raise XendError(str(ex)) def domain_destroy(self, domid): """Terminate domain immediately.""" diff -r ec03b24a2d83 -r a9e921cf0821 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Aug 15 19:53:55 2006 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Aug 18 09:57:23 2006 +0900 @@ -967,11 +967,12 @@ class XendDomainInfo: self.restart(True) - def dumpCore(self): + def dumpCore(self,corefile=None): """Create a core dump for this domain. Nothrow guarantee.""" try: - corefile = "/var/xen/dump/%s.%s.core" % (self.info['name'], + if not corefile: + corefile = "/var/xen/dump/%s.%s.core" % (self.info['name'], self.domid) xc.domain_dumpcore(self.domid, corefile) diff -r ec03b24a2d83 -r a9e921cf0821 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Aug 15 19:53:55 2006 +0100 +++ b/tools/python/xen/xm/main.py Fri Aug 18 09:57:23 2006 +0900 @@ -57,6 +57,9 @@ create_help = """create [-c] [Name=Value].. Create a domain based on Config File""" destroy_help = "destroy Terminate a domain immediately" +dump_core_help = """dump-core [-L|--live][-C|--crash] + [FileName] Dump core of the specified domain""" + help_help = "help Display this message" list_help = "list [--long] [DomId, ...] List information about domains" list_label_help = "list [--label] [DomId, ...] List information about domains including their labels" @@ -140,6 +143,7 @@ short_command_list = [ "console", "create", "destroy", + "dump-core", "help", "list", "mem-set", @@ -161,6 +165,7 @@ domain_commands = [ "destroy", "domid", "domname", + "dump-core", "list", "list_label", "mem-max", @@ -593,6 +598,43 @@ def xm_unpause(args): server.xend.domain.unpause(dom) +def xm_dump_core(args): + arg_check(args, "dump-core",1,3) + live = False + crash = False + import getopt + (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash']) + + for (k, v) in options: + if k in ['-L', '--live']: + live = True + if k in ['-C', '--crash']: + crash = True + + if len(params) == 0 or len(params) > 2: + err("invalid number of parameters") + usage("dump-core") + + dom = params[0] + if len(params) == 2: + filename = os.path.abspath(params[1]) + else: + filename = None + + if not live: + server.xend.domain.pause(dom) + + try: + print "dumping core of domain:%s ..." % str(dom) + server.xend.domain.dump(dom, filename, live, crash) + finally: + if not live: + server.xend.domain.unpause(dom) + + if crash: + print "destroying domain:%s ..." % str(dom) + server.xend.domain.destroy(dom) + def xm_rename(args): arg_check(args, "rename", 2) @@ -1170,6 +1212,7 @@ commands = { "destroy": xm_destroy, "domid": xm_domid, "domname": xm_domname, + "dump-core": xm_dump_core, "rename": xm_rename, "restore": xm_restore, "save": xm_save,