Mike Larkin <[email protected]> writes:
> 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?
>
> I don't know what to think about systat using imsg to talk to other
> daemons.
>
> Is there a reason vmctl's current output isn't sufficient for this
> purpose?
Thanks for your answer!
I thought it might be useful to see that output under the hood of
systat (printing various system statistics). But I agree with you, it
adds some complexity, is not strictly necessary because same
functionality is there with vmctl/while loop and even worse, the code is
very similar to that of vmctl.
>>
>> 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);
>> +}
>>
>