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?
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);
+}