Extend the VMM stats interface to support a dynamic count of statistics.
- Add a starting index to 'struct vmstats' and change the VM_STATS ioctl to fetch the 64 stats starting at that index. A compat shim for <= 13 continues to fetch only the first 64 stats. - Extend vm_get_stats() in libvmmapi to use a loop and a static thread local buffer which grows to hold the stats needed. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D27463
This commit is contained in:
parent
3f3e4f3c74
commit
6426978617
@ -1066,19 +1066,44 @@ uint64_t *
|
||||
vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
|
||||
int *ret_entries)
|
||||
{
|
||||
int error;
|
||||
|
||||
static struct vm_stats vmstats;
|
||||
static _Thread_local uint64_t *stats_buf;
|
||||
static _Thread_local u_int stats_count;
|
||||
uint64_t *new_stats;
|
||||
struct vm_stats vmstats;
|
||||
u_int count, index;
|
||||
bool have_stats;
|
||||
|
||||
have_stats = false;
|
||||
vmstats.cpuid = vcpu;
|
||||
count = 0;
|
||||
for (index = 0;; index += nitems(vmstats.statbuf)) {
|
||||
vmstats.index = index;
|
||||
if (ioctl(ctx->fd, VM_STATS, &vmstats) != 0)
|
||||
break;
|
||||
if (stats_count < index + vmstats.num_entries) {
|
||||
new_stats = realloc(stats_buf,
|
||||
(index + vmstats.num_entries) * sizeof(uint64_t));
|
||||
if (new_stats == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
stats_count = index + vmstats.num_entries;
|
||||
stats_buf = new_stats;
|
||||
}
|
||||
memcpy(stats_buf + index, vmstats.statbuf,
|
||||
vmstats.num_entries * sizeof(uint64_t));
|
||||
count += vmstats.num_entries;
|
||||
have_stats = true;
|
||||
|
||||
error = ioctl(ctx->fd, VM_STATS, &vmstats);
|
||||
if (error == 0) {
|
||||
if (vmstats.num_entries != nitems(vmstats.statbuf))
|
||||
break;
|
||||
}
|
||||
if (have_stats) {
|
||||
if (ret_entries)
|
||||
*ret_entries = vmstats.num_entries;
|
||||
*ret_entries = count;
|
||||
if (ret_tv)
|
||||
*ret_tv = vmstats.tv;
|
||||
return (vmstats.statbuf);
|
||||
return (stats_buf);
|
||||
} else
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -174,6 +174,7 @@ struct vm_nmi {
|
||||
#define MAX_VM_STATS 64
|
||||
struct vm_stats {
|
||||
int cpuid; /* in */
|
||||
int index; /* in */
|
||||
int num_entries; /* out */
|
||||
struct timeval tv;
|
||||
uint64_t statbuf[MAX_VM_STATS];
|
||||
|
@ -69,6 +69,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include "io/vhpet.h"
|
||||
#include "io/vrtc.h"
|
||||
|
||||
#ifdef COMPAT_FREEBSD13
|
||||
struct vm_stats_old {
|
||||
int cpuid; /* in */
|
||||
int num_entries; /* out */
|
||||
struct timeval tv;
|
||||
uint64_t statbuf[MAX_VM_STATS];
|
||||
};
|
||||
|
||||
#define VM_STATS_OLD \
|
||||
_IOWR('v', IOCNUM_VM_STATS, struct vm_stats_old)
|
||||
#endif
|
||||
|
||||
struct devmem_softc {
|
||||
int segid;
|
||||
char *name;
|
||||
@ -376,6 +388,9 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
struct vm_pptdev_msi *pptmsi;
|
||||
struct vm_pptdev_msix *pptmsix;
|
||||
struct vm_nmi *vmnmi;
|
||||
#ifdef COMPAT_FREEBSD13
|
||||
struct vm_stats_old *vmstats_old;
|
||||
#endif
|
||||
struct vm_stats *vmstats;
|
||||
struct vm_stat_desc *statdesc;
|
||||
struct vm_x2apic *x2apic;
|
||||
@ -501,11 +516,21 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
statdesc->desc, sizeof(statdesc->desc));
|
||||
break;
|
||||
}
|
||||
#ifdef COMPAT_FREEBSD13
|
||||
case VM_STATS_OLD:
|
||||
vmstats_old = (struct vm_stats_old *)data;
|
||||
getmicrotime(&vmstats_old->tv);
|
||||
error = vmm_stat_copy(sc->vm, vmstats_old->cpuid, 0,
|
||||
nitems(vmstats_old->statbuf),
|
||||
&vmstats_old->num_entries,
|
||||
vmstats_old->statbuf);
|
||||
break;
|
||||
#endif
|
||||
case VM_STATS: {
|
||||
CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_ELEMS);
|
||||
vmstats = (struct vm_stats *)data;
|
||||
getmicrotime(&vmstats->tv);
|
||||
error = vmm_stat_copy(sc->vm, vmstats->cpuid,
|
||||
error = vmm_stat_copy(sc->vm, vmstats->cpuid, vmstats->index,
|
||||
nitems(vmstats->statbuf),
|
||||
&vmstats->num_entries, vmstats->statbuf);
|
||||
break;
|
||||
}
|
||||
|
@ -82,15 +82,29 @@ vmm_stat_register(void *arg)
|
||||
}
|
||||
|
||||
int
|
||||
vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
|
||||
vmm_stat_copy(struct vm *vm, int vcpu, int index, int count, int *num_stats,
|
||||
uint64_t *buf)
|
||||
{
|
||||
struct vmm_stat_type *vst;
|
||||
uint64_t *stats;
|
||||
int i;
|
||||
int i, tocopy;
|
||||
|
||||
if (vcpu < 0 || vcpu >= vm_get_maxcpus(vm))
|
||||
return (EINVAL);
|
||||
|
||||
if (index < 0 || count < 0)
|
||||
return (EINVAL);
|
||||
|
||||
if (index > vst_num_elems)
|
||||
return (ENOENT);
|
||||
|
||||
if (index == vst_num_elems) {
|
||||
*num_stats = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
tocopy = min(vst_num_elems - index, count);
|
||||
|
||||
/* Let stats functions update their counters */
|
||||
for (i = 0; i < vst_num_types; i++) {
|
||||
vst = vsttab[i];
|
||||
@ -100,9 +114,8 @@ vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
|
||||
|
||||
/* Copy over the stats */
|
||||
stats = vcpu_stats(vm, vcpu);
|
||||
for (i = 0; i < vst_num_elems; i++)
|
||||
buf[i] = stats[i];
|
||||
*num_stats = vst_num_elems;
|
||||
memcpy(buf, stats + index, tocopy * sizeof(stats[0]));
|
||||
*num_stats = tocopy;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,8 @@ void *vmm_stat_alloc(void);
|
||||
void vmm_stat_init(void *vp);
|
||||
void vmm_stat_free(void *vp);
|
||||
|
||||
/*
|
||||
* 'buf' should be at least fit 'MAX_VMM_STAT_TYPES' entries
|
||||
*/
|
||||
int vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf);
|
||||
int vmm_stat_copy(struct vm *vm, int vcpu, int index, int count,
|
||||
int *num_stats, uint64_t *buf);
|
||||
int vmm_stat_desc_copy(int index, char *buf, int buflen);
|
||||
|
||||
static void __inline
|
||||
|
Loading…
x
Reference in New Issue
Block a user