Konrad Rzeszutek Wilk
2013-Mar-15 20:01 UTC
[PATCH v12] claim and its friends for allocating multiple self-ballooning guests (v12).
Changes since v11: - Removed most of the libxl_types.idl changes, - Rewrote most of the comments, - Added support for dealing with out-of-sync hypervisors,,,, - claim_mode is now a boolean, - xl info will print outstanding_pages if claim_mode is set to 1, - Addressed all (I hope?) Ian''s comments. The patch (mmu: Introduce XENMEM_claim_pages (subop of memory ops) is already in the hypervisor and described in details the problem/solution/alternative solutions. This builds upon that new hypercall to expand the toolstack to use it. The patches follow the normal code-flow - the patch to implement the two hypercalls: XENMEM_claim_pages and XENMEM_get_outstanding_pages. Then the patches to utilize them in the libxc. The hypercall''s are only utilized if the toolstack (libxl) sets the claim_mode to 1 (true). Then the toolstack (libxl + xl) patches. They revolve around two different changes: 1). Add ''claim_mode=0|1'' global configuration value that determines whether the claim hypercall should be used as part of guest creation. 2). As part of ''xl info'' output how many pages are claimed by different guests. This is more of a diagnostic patch. Note that these two pages: [PATCH 2/4] xc: export outstanding_pages value in xc_dominfo [PATCH 3/4] xl: export ''outstanding_pages'' value from xcinfo could very well be squashed together. I don''t know whather that is OK with the maintainers or not so I left them as two seperate ones. I am OK with them being squashed. docs/man/xl.conf.pod.5 | 41 +++++++++++++++++++++++++++++++++++++++++ tools/examples/xl.conf | 6 ++++++ tools/libxc/xc_domain.c | 1 + tools/libxc/xenctrl.h | 1 + tools/libxl/libxl.c | 13 +++++++++++++ tools/libxl/libxl.h | 2 +- tools/libxl/libxl_dom.c | 3 ++- tools/libxl/libxl_types.idl | 3 ++- tools/libxl/xl.c | 5 +++++ tools/libxl/xl.h | 1 + tools/libxl/xl_cmdimpl.c | 26 ++++++++++++++++++++++++++ 11 files changed, 99 insertions(+), 3 deletions(-) Dan Magenheimer (1): xc: export outstanding_pages value in xc_dominfo structure. Konrad Rzeszutek Wilk (3): xl: Implement XENMEM_claim_pages support via ''claim_mode'' global config xl: export ''outstanding_pages'' value from xcinfo xl: ''xl info'' print outstanding claims if enabled (claim_mode=1 in xl.conf)
Konrad Rzeszutek Wilk
2013-Mar-15 20:01 UTC
[PATCH 1/4] xl: Implement XENMEM_claim_pages support via ''claim_mode'' global config
The XENMEM_claim_pages hypercall operates per domain and it should be used system wide. As such this patch introduces a global configuration option ''claim_mode'' that by default is disabled. If this option is enabled then when a guest is created there will be an guarantee that there is memory available for the guest. This is an particularly acute problem on hosts with memory over-provisioned guests that use tmem and have self-balloon enabled (which is the default option for them). The self-balloon mechanism can deflate/inflate the balloon quickly and the amount of free memory (which ''xl info'' can show) is stale the moment it is printed. When claim is enabled a reservation for the amount of memory (''memory'' in guest config) is set, which is then reduced as the domain''s memory is populated and eventually reaches zero. If the reservation cannot be meet the guest creation fails immediately instead of taking seconds/minutes (depending on the size of the guest) while the guest is populated. Note that to enable tmem type guest, one need to provide ''tmem'' on the Xen hypervisor argument and as well on the Linux kernel command line. There are two boolean options: (off) No claim is made. Memory population during guest creation will be attempted as normal and may fail due to memory exhaustion. (on) Normal memory and freeable pool of ephemeral pages (tmem) is used when calculating whether there is enough memory free to launch a guest. This guarantees immediate feedback whether the guest can be launched due to memory exhaustion (which can take a long time to find out if launching massively huge guests) and in parallel. [v1: Removed own claim_mode type, using just bool, improved docs, all per Ian''s suggestion] [v2: Updated the comments] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- docs/man/xl.conf.pod.5 | 41 +++++++++++++++++++++++++++++++++++++++++ tools/examples/xl.conf | 6 ++++++ tools/libxl/libxl.h | 1 - tools/libxl/libxl_dom.c | 3 ++- tools/libxl/libxl_types.idl | 2 +- tools/libxl/xl.c | 5 +++++ tools/libxl/xl.h | 1 + tools/libxl/xl_cmdimpl.c | 2 ++ 8 files changed, 58 insertions(+), 3 deletions(-) diff --git a/docs/man/xl.conf.pod.5 b/docs/man/xl.conf.pod.5 index 82c6b20..118cbae 100644 --- a/docs/man/xl.conf.pod.5 +++ b/docs/man/xl.conf.pod.5 @@ -98,6 +98,47 @@ Configures the name of the first block device to be used for temporary block device allocations by the toolstack. The default choice is "xvda". +=item B<claim_mode=BOOLEAN> + +If this option is enabled then when a guest is created there will be an +guarantee that there is memory available for the guest. This is an particularly +acute problem on hosts with memory over-provisioned guests that use +tmem and have self-balloon enabled (which is the default option). +The self-balloon mechanism can deflate/inflate the balloon quickly and the +amount of free memory (which C<xl info> can show) is stale the moment +it is printed. When claim is enabled a reservation for the amount of +memory (see ''memory'' in xl.conf(5)) is set, which is then reduced as the +domain''s memory is populated and eventually reaches zero. + +If the reservation cannot be meet the guest creation fails immediately instead +of taking seconds/minutes (depending on the size of the guest) while the guest +is populated. + +Note that to enable tmem type guest, one need to provide C<tmem> on the +Xen hypervisor argument and as well on the Linux kernel command line. + +Note that the claim call is not attempted if C<superpages> option is +used in the guest config (see xl.cfg(5)). + +Default: C<0> + +=over 4 + +=item C<0> + +No claim is made. Memory population during guest creation will be +attempted as normal and may fail due to memory exhaustion. + +=item C<1> + +Normal memory and freeable pool of ephemeral pages (tmem) is used when +calculating whether there is enough memory free to launch a guest. +This guarantees immediate feedback whether the guest can be launched due +to memory exhaustion (which can take a long time to find out if launching +massively huge guests). + +=back + =back =head1 SEE ALSO diff --git a/tools/examples/xl.conf b/tools/examples/xl.conf index 28ab796..e393471 100644 --- a/tools/examples/xl.conf +++ b/tools/examples/xl.conf @@ -20,3 +20,9 @@ # if disabled the old behaviour will be used, and hotplug scripts will be # launched by udev. #run_hotplug_scripts=1 + +# Reserve a claim of memory when launching a guest. This guarantees immediate +# feedback whether the guest can be launched due to memory exhaustion +# (which can take a long time to find out if launching huge guests). +# see xl.conf(5) for details. +#claim_mode=0 diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 030aa86..c4ad58b 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -579,7 +579,6 @@ int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t memory_k /* wait for the memory target of a domain to be reached */ int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs); - int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass); int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_type type); /* libxl_primary_console_exec finds the domid and console number diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index de555ee..cffa0d6 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -367,6 +367,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, dom->console_domid = state->console_domid; dom->xenstore_evtchn = state->store_port; dom->xenstore_domid = state->store_domid; + dom->claim_enabled = libxl_defbool_val(info->claim_mode); if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) { LOGE(ERROR, "xc_dom_boot_xen_init failed"); @@ -601,7 +602,7 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, */ args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10; args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10; - + args.claim_enabled = libxl_defbool_val(info->claim_mode); if (libxl__domain_firmware(gc, info, &args)) { LOG(ERROR, "initializing domain firmware failed"); goto out; diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 5b080ed..2c8d7b9 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -293,7 +293,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("ioports", Array(libxl_ioport_range, "num_ioports")), ("irqs", Array(uint32, "num_irqs")), ("iomem", Array(libxl_iomem_range, "num_iomem")), - + ("claim_mode", libxl_defbool), ("u", KeyedUnion(None, libxl_domain_type, "type", [("hvm", Struct(None, [("firmware", string), ("bios", libxl_bios_type), diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c index ecbcd3b..76639c9 100644 --- a/tools/libxl/xl.c +++ b/tools/libxl/xl.c @@ -44,6 +44,7 @@ char *lockfile; char *default_vifscript = NULL; char *default_bridge = NULL; enum output_format default_output_format = OUTPUT_FORMAT_JSON; +int global_claim_mode = 0; static xentoollog_level minmsglevel = XTL_PROGRESS; @@ -102,6 +103,10 @@ static void parse_global_config(const char *configfile, } if (!xlu_cfg_get_string (config, "blkdev_start", &buf, 0)) blkdev_start = strdup(buf); + + if (!xlu_cfg_get_long (config, "claim_mode", &l, 0)) + global_claim_mode = 1; + xlu_cfg_destroy(config); } diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h index be6f38b..b0cb777 100644 --- a/tools/libxl/xl.h +++ b/tools/libxl/xl.h @@ -145,6 +145,7 @@ int xl_child_pid(xlchildnum); /* returns 0 if child struct is not in use */ extern int autoballoon; extern int run_hotplug_scripts; extern int dryrun_only; +extern int global_claim_mode; extern char *lockfile; extern char *default_vifscript; extern char *default_bridge; diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 87b5536..85fc401 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -757,6 +757,8 @@ static void parse_config_data(const char *config_source, if (!xlu_cfg_get_long (config, "maxmem", &l, 0)) b_info->max_memkb = l * 1024; + libxl_defbool_set(&b_info->claim_mode, global_claim_mode); + if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0)) buf = "destroy"; if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) { -- 1.8.0.2
Konrad Rzeszutek Wilk
2013-Mar-15 20:02 UTC
[PATCH 2/4] xc: export outstanding_pages value in xc_dominfo structure.
From: Dan Magenheimer <dan.magenheimer@oracle.com> This patch provides the value of the currently outstanding pages claimed for a specific domain. This is a value that influences the global outstanding claims value (See patch: "xl: ''xl info'' print outstanding claims if enabled") returned via xc_domain_get_outstanding_pages hypercall. This domain value decrements as the memory is populated for the guest and eventually reaches zero. This patch is neccessary for "xl: export ''outstanding_pages'' value from xcinfo" patch. Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com> [v2: s/unclaimed_pages/outstanding_pages/ per Tim''s suggestion] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- tools/libxc/xc_domain.c | 1 + tools/libxc/xenctrl.h | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 299c907..1676bd7 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -234,6 +234,7 @@ int xc_domain_getinfo(xc_interface *xch, info->ssidref = domctl.u.getdomaininfo.ssidref; info->nr_pages = domctl.u.getdomaininfo.tot_pages; + info->nr_outstanding_pages = domctl.u.getdomaininfo.outstanding_pages; info->nr_shared_pages = domctl.u.getdomaininfo.shr_pages; info->nr_paged_pages = domctl.u.getdomaininfo.paged_pages; info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10); diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index e695456..2a4d4df 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -364,6 +364,7 @@ typedef struct xc_dominfo { hvm:1, debugged:1; unsigned int shutdown_reason; /* only meaningful if shutdown==1 */ unsigned long nr_pages; /* current number, not maximum */ + unsigned long nr_outstanding_pages; unsigned long nr_shared_pages; unsigned long nr_paged_pages; unsigned long shared_info_frame; -- 1.8.0.2
Konrad Rzeszutek Wilk
2013-Mar-15 20:02 UTC
[PATCH 3/4] xl: export ''outstanding_pages'' value from xcinfo
This patch provides the value of the currently outstanding pages claimed for a specific domain. This is a value that influences the global outstanding claims value (See patch: "xl: ''xl info'' print outstanding claims if enabled") returned via xc_domain_get_outstanding_pages hypercall. This domain value decrements as the memory is populated for the guest and eventually reaches zero. With this patch it is possible to utilize this field. Acked-by: Ian Campbell <ian.campbell@citrix.com> [v2: s/unclaimed/outstanding/ per Tim''s suggestion] [v3: Don''t use SXP printout file per Ian''s suggestion] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- tools/libxl/libxl.c | 1 + tools/libxl/libxl_types.idl | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index a09c0fa..f9ed235 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -528,6 +528,7 @@ static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo, else xlinfo->shutdown_reason = ~0; + xlinfo->outstanding_memkb = PAGE_TO_MEMKB(xcinfo->outstanding_pages); xlinfo->current_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages); xlinfo->shared_memkb = PAGE_TO_MEMKB(xcinfo->shr_pages); xlinfo->paged_memkb = PAGE_TO_MEMKB(xcinfo->paged_pages); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 2c8d7b9..7d289e0 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -196,6 +196,7 @@ libxl_dominfo = Struct("dominfo",[ # Otherwise set to a value guaranteed not to clash with any valid # LIBXL_SHUTDOWN_REASON_* constant. ("shutdown_reason", libxl_shutdown_reason), + ("outstanding_memkb", MemKB), ("current_memkb", MemKB), ("shared_memkb", MemKB), ("paged_memkb", MemKB), -- 1.8.0.2
Konrad Rzeszutek Wilk
2013-Mar-15 20:02 UTC
[PATCH 4/4] xl: ''xl info'' print outstanding claims if enabled (claim_mode=1 in xl.conf)
This patch provides the value of the currently outstanding pages claimed for all domains. This is a total global value that influences the hypervisors'' MM system. When a claim call is done, a reservation for a specific amount of pages is set and also a global value is incremented. This global value is then reduced as the domain''s memory is populated and eventually reaches zero. The toolstack can also choose to set the domain''s claim to zero which cancels the reservation and decrements the global value by the amount of claim that has not been satisfied. If the reservation cannot be meet the guest creation fails immediately instead of taking seconds or minutes (depending on the size of the guest) while the toolstack populates memory. See patch: "xl: Implement XENMEM_claim_pages support via ''claim_mode'' global config" for details on how it is implemented. The value fluctuates quite often so the value is stale once it is provided to the user-space. However it is useful for diagnostic purposes. It is only printed when the global "claim_mode" option in xl.conf(5) is set to enabled. [v1: s/unclaimed/outstanding/] [v2: Made libxl_get_claiminfo return just MemKB suggested by Ian] [v3: Made libxl_get_claininfo return MemMB to conform to the other values printed] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- tools/libxl/libxl.c | 12 ++++++++++++ tools/libxl/libxl.h | 1 + tools/libxl/xl_cmdimpl.c | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index f9ed235..e9942c5 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -4054,6 +4054,18 @@ libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr) return ret; } +uint64_t libxl_get_claiminfo(libxl_ctx *ctx) +{ + long l; + + l = xc_domain_get_outstanding_pages(ctx->xch); + if (l < 0) + return l; + + /* In MB */ + return (l >> 8); +} + const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx) { union { diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index c4ad58b..5dab24b 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -579,6 +579,7 @@ int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t memory_k /* wait for the memory target of a domain to be reached */ int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs); +uint64_t libxl_get_claiminfo(libxl_ctx *ctx); int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass); int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_type type); /* libxl_primary_console_exec finds the domid and console number diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 85fc401..ce3a8e1 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -4637,6 +4637,29 @@ static void output_topologyinfo(void) return; } +static void output_claim(void) +{ + long l; + + /* + * Note that the xl.c (which calls us) has already read from the + * global configuration the ''claim_mode'' value. + */ + if (!global_claim_mode) + return; + + l = libxl_get_claiminfo(ctx); + if (l < 0) { + fprintf(stderr, "libxl_get_claiminfo failed. errno: %d (%s)\n", + errno, strerror(errno)); + return; + } + + printf("outstanding_claims : %ld\n", l); + + return; +} + static void print_info(int numa) { output_nodeinfo(); @@ -4647,6 +4670,7 @@ static void print_info(int numa) output_topologyinfo(); output_numainfo(); } + output_claim(); output_xeninfo(); -- 1.8.0.2