Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyvectl/bhyvectl.c
Show All 32 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/errno.h> | #include <sys/errno.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/cpuset.h> | #include <sys/cpuset.h> | ||||
#include <stddef.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <libgen.h> | #include <libgen.h> | ||||
#include <libutil.h> | #include <libutil.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
Show All 9 Lines | |||||
#include <vmmapi.h> | #include <vmmapi.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/un.h> | #include <sys/un.h> | ||||
#include "amd/vmcb.h" | #include "amd/vmcb.h" | ||||
#include "intel/vmcs.h" | #include "intel/vmcs.h" | ||||
#ifdef BHYVE_SNAPSHOT | |||||
#include "ipc.h" | |||||
#endif | |||||
#define MB (1UL << 20) | #define MB (1UL << 20) | ||||
#define GB (1UL << 30) | #define GB (1UL << 30) | ||||
#define REQ_ARG required_argument | #define REQ_ARG required_argument | ||||
#define NO_ARG no_argument | #define NO_ARG no_argument | ||||
#define OPT_ARG optional_argument | #define OPT_ARG optional_argument | ||||
#define CHECKPOINT_RUN_DIR "/var/run/bhyve/checkpoint" | |||||
#define MAX_VMNAME 100 | |||||
static const char *progname; | static const char *progname; | ||||
static void | static void | ||||
usage(bool cpu_intel) | usage(bool cpu_intel) | ||||
{ | { | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"Usage: %s --vm=<vmname>\n" | "Usage: %s --vm=<vmname>\n" | ||||
▲ Show 20 Lines • Show All 1,592 Lines • ▼ Show 20 Lines | if (seglen) { | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
segid++; | segid++; | ||||
} | } | ||||
} | } | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
static int | static int | ||||
send_checkpoint_op_req(struct vmctx *ctx, struct checkpoint_op *op) | send_message(struct vmctx *ctx, void *data, size_t len) | ||||
{ | { | ||||
struct sockaddr_un addr; | struct sockaddr_un addr; | ||||
int socket_fd, len, len_sent, total_sent; | int socket_fd, bytes, err; | ||||
int err = 0; | char vmname[MAX_VMNAME]; | ||||
char vmname_buf[MAX_VMNAME]; | |||||
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); | err = vm_get_name(ctx, vmname, MAX_VMNAME - 1); | ||||
if (err != 0) { | |||||
perror("Failed to get VM name"); | |||||
return (err); | |||||
} | |||||
socket_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | |||||
if (socket_fd < 0) { | if (socket_fd < 0) { | ||||
perror("Error creating bhyvectl socket"); | perror("Error creating bhyvectl socket"); | ||||
err = -1; | return (-1); | ||||
goto done; | |||||
} | } | ||||
memset(&addr, 0, sizeof(struct sockaddr_un)); | memset(&addr, 0, sizeof(struct sockaddr_un)); | ||||
addr.sun_family = AF_UNIX; | addr.sun_family = AF_UNIX; | ||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s", BHYVE_RUN_DIR, vmname); | |||||
err = vm_get_name(ctx, vmname_buf, MAX_VMNAME - 1); | bytes = sendto(socket_fd, (char *)data, len, 0, | ||||
if (err != 0) { | (struct sockaddr *)&addr, sizeof(struct sockaddr_un)); | ||||
perror("Failed to get VM name"); | |||||
goto done; | |||||
} | |||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", CHECKPOINT_RUN_DIR, vmname_buf); | if (bytes < 0) { | ||||
perror("Failed to send message to bhyve vm"); | |||||
if (connect(socket_fd, (struct sockaddr *)&addr, | |||||
sizeof(struct sockaddr_un)) != 0) { | |||||
perror("Connect to VM socket failed"); | |||||
err = -1; | err = -1; | ||||
goto done; | |||||
} | } | ||||
len = sizeof(*op); | |||||
total_sent = 0; | |||||
while ((len_sent = send(socket_fd, (char *)op + total_sent, len - total_sent, 0)) > 0) { | |||||
total_sent += len_sent; | |||||
} | |||||
if (len_sent < 0) { | |||||
perror("Failed to send checkpoint operation request"); | |||||
err = -1; | |||||
} | |||||
done: | |||||
if (socket_fd > 0) | |||||
close(socket_fd); | close(socket_fd); | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
send_start_checkpoint(struct vmctx *ctx, const char *checkpoint_file) | snapshot_request(struct vmctx *ctx, const char *file, enum ipc_opcode code) | ||||
{ | { | ||||
struct checkpoint_op op; | struct ipc_message imsg; | ||||
size_t length; | |||||
op.op = START_CHECKPOINT; | imsg.code = code; | ||||
strncpy(op.snapshot_filename, checkpoint_file, MAX_SNAPSHOT_VMNAME); | |||||
op.snapshot_filename[MAX_SNAPSHOT_VMNAME - 1] = 0; | |||||
return (send_checkpoint_op_req(ctx, &op)); | strlcpy(imsg.data.op.snapshot_filename, file, MAX_SNAPSHOT_FILENAME); | ||||
} | |||||
static int | length = offsetof(struct ipc_message, data) + sizeof(imsg.data.op); | ||||
send_start_suspend(struct vmctx *ctx, const char *suspend_file) | |||||
{ | |||||
struct checkpoint_op op; | |||||
op.op = START_SUSPEND; | return (send_message(ctx, (void *)&imsg, length)); | ||||
strncpy(op.snapshot_filename, suspend_file, MAX_SNAPSHOT_VMNAME); | |||||
op.snapshot_filename[MAX_SNAPSHOT_VMNAME - 1] = 0; | |||||
return (send_checkpoint_op_req(ctx, &op)); | |||||
} | } | ||||
#endif | #endif | ||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
char *vmname; | char *vmname; | ||||
int error, ch, vcpu, ptenum; | int error, ch, vcpu, ptenum; | ||||
▲ Show 20 Lines • Show All 645 Lines • ▼ Show 20 Lines | #endif | ||||
if (error) | if (error) | ||||
printf("errno = %d\n", errno); | printf("errno = %d\n", errno); | ||||
if (!error && destroy) | if (!error && destroy) | ||||
vm_destroy(ctx); | vm_destroy(ctx); | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
if (!error && vm_checkpoint_opt) | if (!error && vm_checkpoint_opt) | ||||
error = send_start_checkpoint(ctx, checkpoint_file); | error = snapshot_request(ctx, checkpoint_file, START_CHECKPOINT); | ||||
if (!error && vm_suspend_opt) | if (!error && vm_suspend_opt) | ||||
error = send_start_suspend(ctx, suspend_file); | error = snapshot_request(ctx, suspend_file, START_SUSPEND); | ||||
#endif | #endif | ||||
free (opts); | free (opts); | ||||
exit(error); | exit(error); | ||||
} | } |