diff --git a/usr.sbin/bhyve/snapshot.h b/usr.sbin/bhyve/snapshot.h --- a/usr.sbin/bhyve/snapshot.h +++ b/usr.sbin/bhyve/snapshot.h @@ -60,31 +60,12 @@ ucl_object_t *meta_root_obj; }; -/* Filename that will be used for save/restore */ -struct checkpoint_op { - char snapshot_filename[MAX_SNAPSHOT_FILENAME]; -}; - /* Messages that a bhyve process understands. */ enum ipc_opcode { START_CHECKPOINT, START_SUSPEND, }; -/* - * The type of message and associated data to - * send to a bhyve process. - */ -struct ipc_message { - enum ipc_opcode code; - union { - /* - * message specific structures - */ - struct checkpoint_op op; - } data; -}; - struct checkpoint_thread_info { struct vmctx *ctx; int socket_fd; diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c --- a/usr.sbin/bhyve/snapshot.c +++ b/usr.sbin/bhyve/snapshot.c @@ -1325,7 +1325,7 @@ } static int -vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, bool stop_vm) +vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) { int fd_checkpoint = 0, kdata_fd = 0; int ret = 0; @@ -1440,17 +1440,23 @@ return (error); } -int -handle_message(struct ipc_message *imsg, struct vmctx *ctx) +static int +handle_message(struct vmctx *ctx, nvlist_t *nvl) { - int err; + int err, cmd; - switch (imsg->code) { - case START_CHECKPOINT: - err = vm_checkpoint(ctx, imsg->data.op.snapshot_filename, false); - break; + if (!nvlist_exists_number(nvl, "cmd")) + return (-1); + + cmd = nvlist_get_number(nvl, "cmd"); + switch (cmd) { case START_SUSPEND: - err = vm_checkpoint(ctx, imsg->data.op.snapshot_filename, true); + case START_CHECKPOINT: + if (!nvlist_exists_string(nvl, "filename")) + err = -1; + else + err = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"), + cmd == START_SUSPEND ? true : false); break; default: EPRINTLN("Unrecognized checkpoint operation\n"); @@ -1460,6 +1466,7 @@ if (err != 0) EPRINTLN("Unable to perform the requested operation\n"); + nvlist_destroy(nvl); return (err); } @@ -1469,25 +1476,18 @@ void * checkpoint_thread(void *param) { - struct ipc_message imsg; struct checkpoint_thread_info *thread_info; - ssize_t n; + nvlist_t *nvl; pthread_set_name_np(pthread_self(), "checkpoint thread"); thread_info = (struct checkpoint_thread_info *)param; for (;;) { - n = recvfrom(thread_info->socket_fd, &imsg, sizeof(imsg), 0, NULL, 0); - - /* - * slight sanity check: see if there's enough data to at - * least determine the type of message. - */ - if (n >= sizeof(imsg.code)) - handle_message(&imsg, thread_info->ctx); + nvl = nvlist_recv(thread_info->socket_fd, 0); + if (nvl != NULL) + handle_message(thread_info->ctx, nvl); else - EPRINTLN("Failed to receive message: %s\n", - n == -1 ? strerror(errno) : "unknown error"); + EPRINTLN("nvlist_recv() failed: %s", strerror(errno)); } return (NULL); diff --git a/usr.sbin/bhyvectl/Makefile b/usr.sbin/bhyvectl/Makefile --- a/usr.sbin/bhyvectl/Makefile +++ b/usr.sbin/bhyvectl/Makefile @@ -17,6 +17,7 @@ CFLAGS+= -I${SRCTOP}/sys/amd64/vmm .if ${MK_BHYVE_SNAPSHOT} != "no" +LIBADD+= nv CFLAGS+= -DBHYVE_SNAPSHOT # usr.sbin/bhyve/snapshot.h needs ucl header diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -33,10 +33,13 @@ #include #include -#include +#include #include #include -#include +#include +#include +#include +#include #include #include @@ -57,9 +60,6 @@ #include #include -#include -#include - #include "amd/vmcb.h" #include "intel/vmcs.h" @@ -1684,10 +1684,9 @@ #ifdef BHYVE_SNAPSHOT static int -send_message(struct vmctx *ctx, void *data, size_t len) +send_message(struct vmctx *ctx, nvlist_t *nvl) { struct sockaddr_un addr; - ssize_t len_sent; int err, socket_fd; char vmname_buf[MAX_VMNAME]; @@ -1709,14 +1708,16 @@ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s", BHYVE_RUN_DIR, vmname_buf); - len_sent = sendto(socket_fd, data, len, 0, - (struct sockaddr *)&addr, sizeof(struct sockaddr_un)); - - if (len_sent < 0) { - perror("Failed to send message to bhyve vm"); - err = -1; + if (connect(socket_fd, (struct sockaddr *)&addr, SUN_LEN(&addr)) != 0) { + perror("connect() failed"); + err = errno; + goto done; } + if (nvlist_send(socket_fd, nvl) < 0) + perror("nvlist_send() failed"); + nvlist_destroy(nvl); + done: if (socket_fd > 0) close(socket_fd); @@ -1726,15 +1727,13 @@ static int snapshot_request(struct vmctx *ctx, const char *file, enum ipc_opcode code) { - struct ipc_message imsg; - size_t length; - - imsg.code = code; - strlcpy(imsg.data.op.snapshot_filename, file, MAX_SNAPSHOT_FILENAME); + nvlist_t *nvl; - length = offsetof(struct ipc_message, data) + sizeof(imsg.data.op); + nvl = nvlist_create(0); + nvlist_add_number(nvl, "cmd", code); + nvlist_add_string(nvl, "filename", file); - return (send_message(ctx, (void *)&imsg, length)); + return (send_message(ctx, nvl)); } #endif