On Sun, Feb 26, 2017 at 08:16:18PM +0100, Christian Barthel wrote:
> Hi,
>
> I've added the 'vmctl status' view to systat(1). I am not sure if this
> is of general interest.
>
> Any opinions about it?
>
At the first look, it seems to be a good thing.
But from a technical standpoint I agree with mlarkin here. It doesn't
provide much value and it adds new complexity to systat.
I also have another reason for not putting it into systat: vmd, vmctl,
"vmctl status", and the related imsgs are still under active
development. I don't want to take care of another consumer right now.
Reyk
> Index: usr.bin/systat/Makefile
> ===================================================================
> RCS file: /cvs/src/usr.bin/systat/Makefile,v
> retrieving revision 1.27
> diff -u -p -r1.27 Makefile
> --- usr.bin/systat/Makefile 12 Mar 2015 01:03:00 -0000 1.27
> +++ usr.bin/systat/Makefile 26 Feb 2017 11:21:16 -0000
> @@ -5,13 +5,14 @@ PROG= systat
> .PATH: ${.CURDIR}/../../usr.bin/vmstat
>
> CFLAGS+=-DNOKVM
> +CPPFLAGS+=-I${.CURDIR}/../../usr.sbin/vmd/
> CPPFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
> CPPFLAGS+=-I${.CURDIR}/../../sbin/pfctl
> SRCS= dkstats.c engine.c if.c inetname.c iostat.c main.c mbufs.c
> netstat.c \
> nfs.c pigs.c sensors.c swap.c vmstat.c pftop.c cache.c pf.c \
> - pool.c malloc.c cpu.c
> + pool.c malloc.c cpu.c vmm.c
>
> DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM}
> -LDADD= -lcurses -lm -lkvm
> +LDADD= -lcurses -lm -lkvm -lutil
>
> .include <bsd.prog.mk>
> Index: usr.bin/systat/engine.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/systat/engine.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 engine.c
> --- usr.bin/systat/engine.c 2 Jan 2016 20:01:48 -0000 1.19
> +++ usr.bin/systat/engine.c 26 Feb 2017 11:21:17 -0000
> @@ -1320,6 +1320,7 @@ engine_initialize(void)
> signal(SIGQUIT, sig_close);
> signal(SIGWINCH, sig_resize);
> signal(SIGALRM, sig_alarm);
> + signal(SIGPIPE, SIG_IGN);
> }
>
> void
> Index: usr.bin/systat/main.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/systat/main.c,v
> retrieving revision 1.66
> diff -u -p -r1.66 main.c
> --- usr.bin/systat/main.c 13 Oct 2016 11:22:46 -0000 1.66
> +++ usr.bin/systat/main.c 26 Feb 2017 11:21:17 -0000
> @@ -362,6 +362,7 @@ initialize(void)
> initmalloc();
> initnfs();
> initcpu();
> + initvmm();
> }
>
> void
> Index: usr.bin/systat/vmm.c
> ===================================================================
> RCS file: usr.bin/systat/vmm.c
> diff -N usr.bin/systat/vmm.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ usr.bin/systat/vmm.c 26 Feb 2017 11:21:25 -0000
> @@ -0,0 +1,239 @@
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/signal.h>
> +#include <sys/queue.h>
> +#include <sys/un.h>
> +#include <sys/uio.h>
> +#include <machine/vmmvar.h>
> +
> +#include <imsg.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <err.h>
> +#include <unistd.h>
> +
> +#include "systat.h"
> +#include "vmd.h"
> +
> +#define VMM_IDENT 256
> +
> +int initvmm(void);
> +void print_vmm(void);
> +int read_vmm(void);
> +int vmm_keyboard_callback(int ch);
> +
> +static void connect_vmd(void);
> +static void get_info_vm(uint32_t id, const char *name, int console);
> +static int add_info(struct imsg *imsg, int *ret);
> +
> +static struct vmop_info_result* vir = NULL;
> +static struct imsgbuf *ibuf;
> +static const char *socket_name = SOCKET_NAME;
> +static int is_connected = 0;
> +static int ctl_sock = -1;
> +static size_t ct = 0; /*
> counter for number of VM's */
> +
> +field_def fields_vmm[] = {
> + {"ID", 6, 10, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
> + {"PID", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
> + {"VCPUS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
> + {"MAXMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
> + {"CURMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
> + {"TTY", 5, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
> + {"NAME", 5, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
> +};
> +
> +#define FLD_VMM_ID FIELD_ADDR(fields_vmm,0)
> +#define FLD_VMM_PID FIELD_ADDR(fields_vmm,1)
> +#define FLD_VMM_VCPUS FIELD_ADDR(fields_vmm,2)
> +#define FLD_VMM_MAXMEM FIELD_ADDR(fields_vmm,3)
> +#define FLD_VMM_CURMEM FIELD_ADDR(fields_vmm,4)
> +#define FLD_VMM_TTYNAME FIELD_ADDR(fields_vmm,5)
> +#define FLD_VMM_NAME FIELD_ADDR(fields_vmm,6)
> +
> +/* Define views */
> +field_def *view_vmm_0[] = {
> + FLD_VMM_ID, FLD_VMM_PID, FLD_VMM_VCPUS, FLD_VMM_MAXMEM,
> + FLD_VMM_CURMEM, FLD_VMM_TTYNAME, FLD_VMM_NAME, NULL
> +};
> +
> +/* Define view managers */
> +struct view_manager vmm_mgr = {
> + "VMM", NULL, read_vmm, NULL, print_header,
> + print_vmm, vmm_keyboard_callback, NULL, NULL
> +};
> +
> +field_view views_vmm[] = {
> + {view_vmm_0, "vmm", '6', &vmm_mgr},
> + {NULL, NULL, 0, NULL}
> +};
> +
> +static void
> +connect_vmd(void)
> +{
> + struct sockaddr_un sun;
> +
> + if (ctl_sock != -1) {
> + close(ibuf->fd);
> + free(ibuf);
> + }
> +
> + if ((ctl_sock = socket(AF_UNIX,
> + SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1)
> + err(1, "socket");
> +
> + bzero(&sun, sizeof(sun));
> + sun.sun_family = AF_UNIX;
> + strlcpy(sun.sun_path, socket_name, sizeof(sun.sun_path));
> +
> + if (connect(ctl_sock,
> + (struct sockaddr
> *)&sun, sizeof(sun)) == -1)
> + is_connected = 0;
> + else
> + is_connected = 1;
> +
> + if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
> + err(1, "malloc");
> + imsg_init(ibuf, ctl_sock);
> +}
> +
> +static void
> +get_info_vm(uint32_t id, const char *name, int console)
> +{
> + if (imsg_compose(ibuf, IMSG_VMDOP_GET_INFO_VM_REQUEST,
> + 0, 0, -1, NULL, 0) < 0)
> + errx(1, "imsg_compose");
> +}
> +
> +
> +static int
> +add_info(struct imsg *imsg, int *ret)
> +{
> + if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_DATA) {
> + if ((vir = reallocarray(vir, ct + 1,
> + sizeof(struct vmop_info_result))) == NULL) {
> + *ret = ENOMEM;
> + return (1);
> + }
> + memcpy(&vir[ct], imsg->data, sizeof(struct vmop_info_result));
> + ct++;
> + *ret = 0;
> + return (0);
> + } else if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_END_DATA) {
> + *ret = 0;
> + return (1);
> + } else {
> + *ret = EINVAL;
> + return (1);
> + }
> +}
> +
> +int
> +read_vmm(void)
> +{
> + int n;
> + struct imsg imsg;
> + int ret, done = 0;
> +
> + if (!is_connected)
> + connect_vmd();
> +
> + get_info_vm(0, NULL, 0);
> + while (is_connected && ibuf->w.queued)
> + if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
> + is_connected = 0;
> + ct = 0;
> +
> + while (is_connected && !done) {
> + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
> + errx(1, "imsg_read error");
> + if (n == 0)
> + errx(1, "pipe closed");
> +
> + while (is_connected && !done) {
> + if ((n = imsg_get(ibuf, &imsg)) == -1)
> + errx(1, "imsg_get error");
> + if (n == 0)
> + break;
> +
> + if (imsg.hdr.type == IMSG_CTL_FAIL) {
> + if (IMSG_DATA_SIZE(&imsg) == sizeof(ret)) {
> + memcpy(&ret, imsg.data, sizeof(ret));
> + errno = ret;
> + warn("command failed");
> + } else
> + warn("command failed");
> + done = 1;
> + break;
> + }
> +
> + ret = 0;
> + done = add_info(&imsg, &ret);
> +
> + imsg_free(&imsg);
> + }
> + }
> +
> + return 0;
> +}
> +
> +void
> +print_vmm(void)
> +{
> + char mem[VMM_IDENT];
> + char cmem[VMM_IDENT];
> + char tty[VMM_IDENT];
> + char name[VMM_MAX_NAME_LEN];
> + struct vm_info_result *v;
> + int i;
> +
> + for (i = 0; vir != NULL && i < ct; i++) {
> + v = &vir[i].vir_info;
> + if (v != NULL) {
> + print_fld_uint(FLD_VMM_ID, v->vir_id);
> + print_fld_uint(FLD_VMM_PID, v->vir_creator_pid);
> + print_fld_uint(FLD_VMM_VCPUS, v->vir_ncpus);
> +
> + snprintf(mem, sizeof(mem), "%7zdMB",
> v->vir_memory_size);
> + print_fld_str(FLD_VMM_MAXMEM, mem);
> + snprintf(cmem, sizeof(cmem), "%7zdMB",
> v->vir_used_size/1024/1024);
> + print_fld_str(FLD_VMM_CURMEM, cmem);
> + snprintf(tty, sizeof(tty), "%s", vir[i].vir_ttyname);
> + print_fld_str(FLD_VMM_TTYNAME, tty);
> + snprintf(name, VMM_MAX_NAME_LEN, "%s", v->vir_name);
> + print_fld_str(FLD_VMM_NAME, name);
> +
> + end_line();
> + }
> + }
> + end_line();
> + print_fld_str(FLD_VMM_ID, "Total:");
> + print_fld_uint(FLD_VMM_PID, ct);
> + print_fld_str(FLD_VMM_NAME,
> + (is_connected) ? "connected" : "disconnected");
> +
> + if (vir != NULL)
> + free(vir);
> + vir = NULL;
> +}
> +
> +int
> +vmm_keyboard_callback(int ch)
> +{
> + keyboard_callback(ch);
> + read_vmm();
> +}
> +
> +int
> +initvmm(void)
> +{
> + field_view *v;
> +
> + connect_vmd();
> + for (v = views_vmm; v->name != NULL; v++)
> + add_view(v);
> +
> + return(1);
> +}
>
--