From 74e66f34f91176433ecea2fa3e06a4dba0a052ae Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Mon, 7 Jul 2025 11:32:59 +0200 Subject: [PATCH] libxc/PM: Retry get_pxstat if data is incomplete If the total returned by Xen is more than the number of elements allocated, it means that the buffer was too small and so the data is incomplete. Retry to get all the data. Signed-off-by: Ross Lagerwall Reviewed-by: Anthony PERARD master commit: 1ff7f87e8f4ffff97901126927549ae7b7a7340d master date: 2025-06-11 11:07:00 +0200 --- tools/misc/xenpm.c | 49 +++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index de319329e6..d5387f5f06 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -312,29 +312,42 @@ static int get_pxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_px_ int ret = 0; int max_px_num = 0; - ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num); - if ( ret ) - return -errno; - if ( !pxstat) return -EINVAL; - pxstat->total = max_px_num; - pxstat->trans_pt = malloc(max_px_num * max_px_num * - sizeof(uint64_t)); - if ( !pxstat->trans_pt ) - return -ENOMEM; - pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); - if ( !pxstat->pt ) + for ( ; ; ) { - free(pxstat->trans_pt); - return -ENOMEM; - } + ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num); + if ( ret ) + return -errno; - ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat); - if( ret ) - { - ret = -errno; + pxstat->total = max_px_num; + pxstat->trans_pt = malloc(max_px_num * max_px_num * + sizeof(uint64_t)); + if ( !pxstat->trans_pt ) + return -ENOMEM; + pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); + if ( !pxstat->pt ) + { + free(pxstat->trans_pt); + return -ENOMEM; + } + + ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat); + if ( ret ) + { + ret = -errno; + free(pxstat->trans_pt); + free(pxstat->pt); + pxstat->trans_pt = NULL; + pxstat->pt = NULL; + break; + } + + if ( pxstat->total <= max_px_num ) + break; + + /* get_max_px changed under our feet so the data is incomplete. */ free(pxstat->trans_pt); free(pxstat->pt); pxstat->trans_pt = NULL;