Changeset View
Standalone View
usr.sbin/bhyve/ipc.c
- This file was added.
/*- | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2016 Flavius Anton | |||||
* Copyright (c) 2016 Mihai Tiganus | |||||
* Copyright (c) 2016-2019 Mihai Carabas | |||||
* Copyright (c) 2017-2019 Darius Mihai | |||||
* Copyright (c) 2017-2019 Elena Mihailescu | |||||
* Copyright (c) 2018-2019 Sergiu Weisz | |||||
* All rights reserved. | |||||
* The bhyve-snapshot feature was developed under sponsorships | |||||
* from Matthew Grooms. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/socket.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/un.h> | |||||
#include <errno.h> | |||||
#include <pthread.h> | |||||
#include <pthread_np.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <unistd.h> | |||||
#include <machine/vmm.h> | |||||
#include <vmmapi.h> | |||||
#include "ipc.h" | |||||
#include "snapshot.h" | |||||
static int | |||||
handle_message(struct ipc_message *imsg, struct vmctx *ctx) | |||||
{ | |||||
int err; | |||||
switch (imsg->code) { | |||||
case START_CHECKPOINT: | |||||
err = vm_checkpoint(ctx, imsg->data.op.snapshot_filename, false); | |||||
break; | |||||
case START_SUSPEND: | |||||
err = vm_checkpoint(ctx, imsg->data.op.snapshot_filename, true); | |||||
break; | |||||
default: | |||||
fprintf(stderr, "Unrecognized message operation.\n"); | |||||
err = -1; | |||||
} | |||||
if (err != 0) | |||||
perror("Unable to perform requested operation"); | |||||
return (err); | |||||
} | |||||
static void * | |||||
ipc_thread(void *arg) | |||||
{ | |||||
struct vmctx *ctx; | |||||
struct ipc_message imsg; | |||||
struct sockaddr_un addr; | |||||
int bytes, socket_fd; | |||||
char vmname[MAX_VMNAME]; | |||||
pthread_set_name_np(pthread_self(), "ipc thread"); | |||||
ctx = (struct vmctx *)arg; | |||||
if (vm_get_name(ctx, vmname, MAX_VMNAME - 1) != 0) { | |||||
perror("Failed to get VM name"); | |||||
return (NULL); | |||||
} | |||||
socket_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | |||||
if (socket_fd < 0) { | |||||
perror("Socket creation failed (IPC with bhyvectl"); | |||||
return (NULL); | |||||
} | |||||
/* | |||||
* Note, BHYVE_RUN_DIR + vmname should be < SUNPATHLEN (104) | |||||
* which allows for a vmname of 88 characters. | |||||
*/ | |||||
jhb: Maybe rename this to `ipc_thread`?
In fact, I would rename several things in here to… | |||||
memset(&addr, 0, sizeof(addr)); | |||||
addr.sun_family = AF_UNIX; | |||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s", | |||||
BHYVE_RUN_DIR, vmname); | |||||
addr.sun_len = SUN_LEN(&addr); | |||||
unlink(addr.sun_path); | |||||
if (bind(socket_fd, (struct sockaddr *)&addr, addr.sun_len) != 0) { | |||||
perror("Failed to bind socket (IPC with bhyvectl)"); | |||||
close(socket_fd); | |||||
return (NULL); | |||||
} | |||||
for (;;) { | |||||
bytes = recvfrom(socket_fd, &imsg, sizeof(imsg), 0, NULL, 0); | |||||
if (bytes >= sizeof(imsg.code)) | |||||
handle_message(&imsg, ctx); | |||||
} | |||||
unlink(addr.sun_path); | |||||
close(socket_fd); | |||||
return (NULL); | |||||
} | |||||
/* | |||||
* Start a thread to handle IPC messages. | |||||
*/ | |||||
int | |||||
init_ipc(struct vmctx *ctx) | |||||
{ | |||||
pthread_t ipc_pthread; | |||||
return (pthread_create(&ipc_pthread, NULL, ipc_thread, ctx)); | |||||
} | |||||
Done Inline ActionsI would like to get rid of this and instead add /var/run/bhyve to BSD.mtree.var instead. You would they just leave off the mkdir entirely and just call bind(). jhb: I would like to get rid of this and instead add /var/run/bhyve to BSD.mtree.var instead. You… | |||||
Done Inline ActionsPerhaps as a followup, I think we want to change this to be a SOCK_DGRAM or SOCK_SEQPACKET socket, and we will want to define a common base structure for messages (with probably just an integer holding the message type) and then message-specific structures that actually get written to the socket. The checkpoint messages would use a message struct that includes the filename. I think checkpoint_op currently includes the vmname, but it isn't used and can be removed. jhb: Perhaps as a followup, I think we want to change this to be a SOCK_DGRAM or SOCK_SEQPACKET… | |||||
Not Done Inline ActionsAs the socket is currently used, it seems SOCK_DGRAM would suffice - bhyvectl sends a message; bhyve receives the message and does the thing. I'm curious, are there scenarios where a bhyve process would want to carry a conversation with another process? I have a diff (based off this review) that uses SOCK_DGRAM instead: https://reviews.freebsd.org/differential/diff/82812/ rew: As the socket is currently used, it seems SOCK_DGRAM would suffice - bhyvectl sends a message… |
Maybe rename this to ipc_thread?
In fact, I would rename several things in here to s/checkpoint/ipc/ except for the checkpoint-specific commands.