File xen.sr-save-stats.patch of Package xen
From: Olaf Hering <olaf@aepfle.de>
Date: Thu, 10 Aug 2023 20:42:13 +0000
Subject: sr save stats
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/libs/guest/xg_sr_common.h | 12 ++
tools/libs/guest/xg_sr_restore.c | 1 +
tools/libs/guest/xg_sr_save.c | 67 ++++++++-
xen/common/domctl.c | 1 +
xen/include/public/domctl.h | 1 +
5 files changed, 81 insertions(+), 1 deletion(-)
--- a/tools/libs/guest/xg_sr_common.h
+++ b/tools/libs/guest/xg_sr_common.h
@@ -319,24 +319,36 @@ struct xc_sr_context
xen_pfn_t *batch_pfns;
xen_pfn_t *mfns;
xen_pfn_t *types;
int *errors;
struct iovec *iov;
uint64_t *rec_pfns;
void **guest_data;
unsigned int nr_batch_pfns;
unsigned long *deferred_pages;
unsigned long nr_deferred_pages;
xc_hypercall_buffer_t dirty_bitmap_hbuf;
+ unsigned int pfinfo_broken;
+ unsigned int pfinfo_l1pintab;
+ unsigned int pfinfo_l1tab;
+ unsigned int pfinfo_l2pintab;
+ unsigned int pfinfo_l2tab;
+ unsigned int pfinfo_l3pintab;
+ unsigned int pfinfo_l3tab;
+ unsigned int pfinfo_l4pintab;
+ unsigned int pfinfo_l4tab;
+ unsigned int pfinfo_notab;
+ unsigned int pfinfo_xalloc;
+ unsigned int pfinfo_xtab;
} save;
struct /* Restore data. */
{
struct xc_sr_restore_ops ops;
struct restore_callbacks *callbacks;
xen_pfn_t *pfns;
uint32_t *types;
xen_pfn_t *mfns;
int *map_errs;
xen_pfn_t *pp_pfns;
xen_pfn_t *pp_mfns;
--- a/tools/libs/guest/xg_sr_restore.c
+++ b/tools/libs/guest/xg_sr_restore.c
@@ -863,24 +863,25 @@ static void cleanup(struct xc_sr_context *ctx)
}
/*
* Restore a domain.
*/
static int restore(struct xc_sr_context *ctx)
{
xc_interface *xch = ctx->xch;
struct xc_sr_rhdr rhdr;
int rc, saved_rc = 0, saved_errno = 0;
SUSEINFO("domid %u: %s %s start", ctx->domid, ctx->uuid, __func__);
+ SUSEINFO("domid %u: %lu tot_pages %lu max_pages %lu outstanding_pages %lu extra_pages %lu shr_pages %lu p2m_size", ctx->domid, ctx->dominfo.tot_pages, ctx->dominfo.max_pages, ctx->dominfo.outstanding_pages, ctx->dominfo.extra_pages, ctx->dominfo.shr_pages, ctx->restore.p2m_size);
IPRINTF("Restoring domain");
rc = setup(ctx);
if ( rc )
goto err;
do
{
rc = read_record_header(ctx, ctx->fd, &rhdr);
if ( rc )
{
if ( ctx->restore.buffer_all_records )
--- a/tools/libs/guest/xg_sr_save.c
+++ b/tools/libs/guest/xg_sr_save.c
@@ -115,24 +115,62 @@ static int write_batch(struct xc_sr_context *ctx)
}
rc = xc_get_pfn_type_batch(xch, ctx->domid, nr_pfns, ctx->save.types);
if ( rc )
{
PERROR("Failed to get types for pfn batch");
goto err;
}
rc = -1;
for ( i = 0; i < nr_pfns; ++i )
{
+ switch (ctx->save.types[i]) {
+ case XEN_DOMCTL_PFINFO_NOTAB:
+ ctx->save.pfinfo_notab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L1TAB:
+ ctx->save.pfinfo_l1tab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L1TAB | XEN_DOMCTL_PFINFO_LPINTAB:
+ ctx->save.pfinfo_l1pintab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L2TAB:
+ ctx->save.pfinfo_l2tab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L2TAB | XEN_DOMCTL_PFINFO_LPINTAB:
+ ctx->save.pfinfo_l2pintab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L3TAB:
+ ctx->save.pfinfo_l3tab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L3TAB | XEN_DOMCTL_PFINFO_LPINTAB:
+ ctx->save.pfinfo_l3pintab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L4TAB:
+ ctx->save.pfinfo_l4tab++;
+ break;
+ case XEN_DOMCTL_PFINFO_L4TAB | XEN_DOMCTL_PFINFO_LPINTAB:
+ ctx->save.pfinfo_l4pintab++;
+ break;
+ case XEN_DOMCTL_PFINFO_XTAB:
+ ctx->save.pfinfo_xtab++;
+ break;
+ case XEN_DOMCTL_PFINFO_XALLOC:
+ ctx->save.pfinfo_xalloc++;
+ break;
+ case XEN_DOMCTL_PFINFO_BROKEN:
+ ctx->save.pfinfo_broken++;
+ break;
+ }
if ( !is_known_page_type(ctx->save.types[i]) )
{
ERROR("Unknown type %#"PRIpfn" for pfn %#"PRIpfn,
ctx->save.types[i], ctx->save.mfns[i]);
goto err;
}
if ( !page_type_has_stream_data(ctx->save.types[i]) )
continue;
ctx->save.mfns[nr_pages++] = ctx->save.mfns[i];
}
@@ -859,40 +897,66 @@ static void cleanup(struct xc_sr_context *ctx)
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
NRPAGES(bitmap_size(ctx->save.p2m_size)));
free(ctx->save.deferred_pages);
free(ctx->save.guest_data);
free(ctx->save.rec_pfns);
free(ctx->save.iov);
free(ctx->save.errors);
free(ctx->save.types);
free(ctx->save.mfns);
free(ctx->save.batch_pfns);
}
+static void save_show_stats(struct xc_sr_context *ctx)
+{
+#define do_stat(_str,_mbr) if(ctx->save._mbr){c+=ctx->save._mbr;l+=snprintf(s+l,sizeof(s)-l-1,"%s %u ",_str,ctx->save._mbr);}
+ xc_interface *xch = ctx->xch;
+ char s[321];
+ unsigned int c = 0;
+ int l = 0;
+ s[0] = '\0';
+
+ do_stat("notab", pfinfo_notab);
+ do_stat("broken", pfinfo_broken);
+ do_stat("l1pintab", pfinfo_l1pintab);
+ do_stat("l1tab", pfinfo_l1tab);
+ do_stat("l2pintab", pfinfo_l2pintab);
+ do_stat("l2tab", pfinfo_l2tab);
+ do_stat("l3pintab", pfinfo_l3pintab);
+ do_stat("l3tab", pfinfo_l3tab);
+ do_stat("l4pintab", pfinfo_l4pintab);
+ do_stat("l4tab", pfinfo_l4tab);
+ do_stat("xalloc", pfinfo_xalloc);
+ do_stat("xtab", pfinfo_xtab);
+ SUSEINFO("domid %u: %s, total %u", ctx->domid, s, c);
+#undef do_stat
+}
+
/*
* Save a domain.
*/
static int save(struct xc_sr_context *ctx, uint16_t guest_type)
{
xc_interface *xch = ctx->xch;
int rc, saved_rc = 0, saved_errno = 0;
SUSEINFO("domid %u: %s %s start, %lu pages allocated", ctx->domid, ctx->uuid, __func__, ctx->dominfo.tot_pages);
+ SUSEINFO("domid %u: %lu tot_pages %lu max_pages %lu outstanding_pages %lu extra_pages %lu shr_pages", ctx->domid, ctx->dominfo.tot_pages, ctx->dominfo.max_pages, ctx->dominfo.outstanding_pages, ctx->dominfo.extra_pages, ctx->dominfo.shr_pages);
IPRINTF("Saving domain %d, type %s",
ctx->domid, dhdr_type_to_str(guest_type));
rc = setup(ctx);
if ( rc )
goto err;
- SUSEINFO("domid %u: p2m_size %lx", ctx->domid, ctx->save.p2m_size);
+ SUSEINFO("domid %u: p2m_size %lu", ctx->domid, ctx->save.p2m_size);
xc_report_progress_single(xch, "Start of stream");
rc = write_headers(ctx, guest_type);
if ( rc )
goto err;
rc = ctx->save.ops.static_data(ctx);
if ( rc )
goto err;
rc = write_static_data_end_record(ctx);
@@ -988,24 +1052,25 @@ static int save(struct xc_sr_context *ctx, uint16_t guest_type)
if ( rc )
goto err;
xc_report_progress_single(xch, "Complete");
goto done;
err:
saved_errno = errno;
saved_rc = rc;
PERROR("Save failed");
done:
+ save_show_stats(ctx);
SUSEINFO("domid %u: %s done", ctx->domid, __func__);
cleanup(ctx);
if ( saved_rc )
{
rc = saved_rc;
errno = saved_errno;
}
return rc;
};
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -98,24 +98,25 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
info->flags = (info->nr_online_vcpus ? flags : 0) |
((d->is_dying == DOMDYING_dead) ? XEN_DOMINF_dying : 0) |
(d->is_shut_down ? XEN_DOMINF_shutdown : 0) |
(d->controller_pause_count > 0 ? XEN_DOMINF_paused : 0) |
(d->debugger_attached ? XEN_DOMINF_debugged : 0) |
(is_xenstore_domain(d) ? XEN_DOMINF_xs_domain : 0) |
(is_hvm_domain(d) ? XEN_DOMINF_hvm_guest : 0) |
d->shutdown_code << XEN_DOMINF_shutdownshift;
xsm_security_domaininfo(d, info);
info->tot_pages = domain_tot_pages(d);
+ info->extra_pages = d->extra_pages;
info->max_pages = d->max_pages;
info->outstanding_pages = d->outstanding_pages;
#ifdef CONFIG_MEM_SHARING
info->shr_pages = atomic_read(&d->shr_pages);
#endif
#ifdef CONFIG_MEM_PAGING
info->paged_pages = atomic_read(&d->paged_pages);
#endif
info->shared_info_frame =
gfn_x(mfn_to_gfn(d, _mfn(virt_to_mfn(d->shared_info))));
BUG_ON(SHARED_M2P(info->shared_info_frame));
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -123,24 +123,25 @@ struct xen_domctl_getdomaininfo {
#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged)
/* domain is a xenstore domain */
#define _XEN_DOMINF_xs_domain 7
#define XEN_DOMINF_xs_domain (1U<<_XEN_DOMINF_xs_domain)
/* domain has hardware assisted paging */
#define _XEN_DOMINF_hap 8
#define XEN_DOMINF_hap (1U<<_XEN_DOMINF_hap)
/* XEN_DOMINF_shutdown guest-supplied code. */
#define XEN_DOMINF_shutdownmask 255
#define XEN_DOMINF_shutdownshift 16
uint32_t flags; /* XEN_DOMINF_* */
uint64_aligned_t tot_pages;
+ uint64_aligned_t extra_pages;
uint64_aligned_t max_pages;
uint64_aligned_t outstanding_pages;
uint64_aligned_t shr_pages;
uint64_aligned_t paged_pages;
uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
uint64_aligned_t cpu_time;
uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */
uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
uint32_t ssidref;
xen_domain_handle_t handle;
uint32_t cpupool;