bhyve/snapshot: switch to nvlist for snapshot requests
Switch to using an nvlist with nvlist_send()/nvlist_recv() to communicate from bhyvectl(8) to bhyve(8). The idea is that a bhyve process receives a command with with a set of arguments. The nvlist here is structured to reflect that premise. For example, to snapshot the vm, the expected nvlist looks like: { cmd=START_CHECKPOINT, filename="filename" } Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D33977
This commit is contained in:
parent
a35bdd4489
commit
edfb339d38
@ -1325,7 +1325,7 @@ vm_vcpu_resume(struct vmctx *ctx)
|
||||
}
|
||||
|
||||
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 @@ vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, bool stop_vm)
|
||||
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 @@ handle_message(struct ipc_message *imsg, struct vmctx *ctx)
|
||||
if (err != 0)
|
||||
EPRINTLN("Unable to perform the requested operation\n");
|
||||
|
||||
nvlist_destroy(nvl);
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -1469,25 +1476,18 @@ handle_message(struct ipc_message *imsg, struct vmctx *ctx)
|
||||
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);
|
||||
|
@ -60,31 +60,12 @@ struct restore_state {
|
||||
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;
|
||||
|
@ -17,6 +17,7 @@ WARNS?= 3
|
||||
CFLAGS+= -I${SRCTOP}/sys/amd64/vmm
|
||||
|
||||
.if ${MK_BHYVE_SNAPSHOT} != "no"
|
||||
LIBADD+= nv
|
||||
CFLAGS+= -DBHYVE_SNAPSHOT
|
||||
|
||||
# usr.sbin/bhyve/snapshot.h needs ucl header
|
||||
|
@ -33,10 +33,13 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/nv.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -57,9 +60,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/vmm_dev.h>
|
||||
#include <vmmapi.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "amd/vmcb.h"
|
||||
#include "intel/vmcs.h"
|
||||
|
||||
@ -1684,10 +1684,9 @@ show_memseg(struct vmctx *ctx)
|
||||
|
||||
#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 @@ send_message(struct vmctx *ctx, void *data, size_t len)
|
||||
|
||||
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 @@ send_message(struct vmctx *ctx, void *data, size_t len)
|
||||
static int
|
||||
snapshot_request(struct vmctx *ctx, const char *file, enum ipc_opcode code)
|
||||
{
|
||||
struct ipc_message imsg;
|
||||
size_t length;
|
||||
nvlist_t *nvl;
|
||||
|
||||
imsg.code = code;
|
||||
strlcpy(imsg.data.op.snapshot_filename, file, MAX_SNAPSHOT_FILENAME);
|
||||
nvl = nvlist_create(0);
|
||||
nvlist_add_number(nvl, "cmd", code);
|
||||
nvlist_add_string(nvl, "filename", file);
|
||||
|
||||
length = offsetof(struct ipc_message, data) + sizeof(imsg.data.op);
|
||||
|
||||
return (send_message(ctx, (void *)&imsg, length));
|
||||
return (send_message(ctx, nvl));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user