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;
openSUSE Build Service is sponsored by