Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/snapshot.c
Show First 20 Lines • Show All 1,302 Lines • ▼ Show 20 Lines | vm_vcpu_resume(struct vmctx *ctx) | ||||
pthread_mutex_lock(&vcpu_lock); | pthread_mutex_lock(&vcpu_lock); | ||||
checkpoint_active = false; | checkpoint_active = false; | ||||
pthread_mutex_unlock(&vcpu_lock); | pthread_mutex_unlock(&vcpu_lock); | ||||
vm_resume_all_cpus(ctx); | vm_resume_all_cpus(ctx); | ||||
pthread_cond_broadcast(&vcpus_can_run); | pthread_cond_broadcast(&vcpus_can_run); | ||||
} | } | ||||
static int | static int | ||||
vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) | vm_checkpoint(struct vmctx *ctx, int fddir, const char *checkpoint_file, | ||||
bool stop_vm) | |||||
{ | { | ||||
int fd_checkpoint = 0, kdata_fd = 0; | int fd_checkpoint = 0, kdata_fd = 0, fd_meta; | ||||
int ret = 0; | int ret = 0; | ||||
int error = 0; | int error = 0; | ||||
size_t memsz; | size_t memsz; | ||||
xo_handle_t *xop = NULL; | xo_handle_t *xop = NULL; | ||||
char *meta_filename = NULL; | char *meta_filename = NULL; | ||||
char *kdata_filename = NULL; | char *kdata_filename = NULL; | ||||
FILE *meta_file = NULL; | FILE *meta_file = NULL; | ||||
kdata_filename = strcat_extension(checkpoint_file, ".kern"); | kdata_filename = strcat_extension(checkpoint_file, ".kern"); | ||||
if (kdata_filename == NULL) { | if (kdata_filename == NULL) { | ||||
fprintf(stderr, "Failed to construct kernel data filename.\n"); | fprintf(stderr, "Failed to construct kernel data filename.\n"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
kdata_fd = open(kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); | kdata_fd = openat(fddir, kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); | ||||
if (kdata_fd < 0) { | if (kdata_fd < 0) { | ||||
perror("Failed to open kernel data snapshot file."); | perror("Failed to open kernel data snapshot file."); | ||||
error = -1; | error = -1; | ||||
goto done; | goto done; | ||||
} | } | ||||
fd_checkpoint = open(checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700); | fd_checkpoint = openat(fddir, checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700); | ||||
if (fd_checkpoint < 0) { | if (fd_checkpoint < 0) { | ||||
perror("Failed to create checkpoint file"); | perror("Failed to create checkpoint file"); | ||||
error = -1; | error = -1; | ||||
goto done; | goto done; | ||||
} | } | ||||
meta_filename = strcat_extension(checkpoint_file, ".meta"); | meta_filename = strcat_extension(checkpoint_file, ".meta"); | ||||
if (meta_filename == NULL) { | if (meta_filename == NULL) { | ||||
fprintf(stderr, "Failed to construct vm metadata filename.\n"); | fprintf(stderr, "Failed to construct vm metadata filename.\n"); | ||||
goto done; | goto done; | ||||
} | } | ||||
meta_file = fopen(meta_filename, "w"); | fd_meta = openat(fddir, meta_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); | ||||
if (fd_meta != -1) | |||||
meta_file = fdopen(fd_meta, "w"); | |||||
if (meta_file == NULL) { | if (meta_file == NULL) { | ||||
perror("Failed to open vm metadata snapshot file."); | perror("Failed to open vm metadata snapshot file."); | ||||
close(fd_meta); | |||||
goto done; | goto done; | ||||
} | } | ||||
emaste: Is it OK to pass -1 to fdopen? | |||||
Done Inline Actions@emaste fdopen() will fail with EBADF. If you think it needs additional check, I can add it. gusev.vitaliy_gmail.com: @emaste `fdopen()` will fail with EBADF. If you think it needs additional check, I can add… | |||||
Done Inline ActionsI think so, otherwise the EBADF could be used by perror below and result in a confusing message. meta_file is initialized to NULL already so it should be enough to just do if (fd_meta != -1) meta_file = ...? emaste: I think so, otherwise the EBADF could be used by `perror` below and result in a confusing… | |||||
Done Inline ActionsGood point. Corrected. gusev.vitaliy_gmail.com: Good point. Corrected. | |||||
xop = xo_create_to_file(meta_file, XO_STYLE_JSON, XOF_PRETTY); | xop = xo_create_to_file(meta_file, XO_STYLE_JSON, XOF_PRETTY); | ||||
if (xop == NULL) { | if (xop == NULL) { | ||||
perror("Failed to get libxo handle on metadata file."); | perror("Failed to get libxo handle on metadata file."); | ||||
goto done; | goto done; | ||||
} | } | ||||
vm_vcpu_pause(ctx); | vm_vcpu_pause(ctx); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
vm_do_checkpoint(struct vmctx *ctx, const nvlist_t *nvl) | vm_do_checkpoint(struct vmctx *ctx, const nvlist_t *nvl) | ||||
{ | { | ||||
int error; | int error; | ||||
if (!nvlist_exists_string(nvl, "filename") || | if (!nvlist_exists_string(nvl, "filename") || | ||||
!nvlist_exists_bool(nvl, "suspend")) | !nvlist_exists_bool(nvl, "suspend") || | ||||
!nvlist_exists_descriptor(nvl, "fddir")) | |||||
error = EINVAL; | error = EINVAL; | ||||
else | else | ||||
error = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"), | error = vm_checkpoint(ctx, | ||||
nvlist_get_descriptor(nvl, "fddir"), | |||||
nvlist_get_string(nvl, "filename"), | |||||
nvlist_get_bool(nvl, "suspend")); | nvlist_get_bool(nvl, "suspend")); | ||||
return (error); | return (error); | ||||
} | } | ||||
IPC_COMMAND(ipc_cmd_set, checkpoint, vm_do_checkpoint); | IPC_COMMAND(ipc_cmd_set, checkpoint, vm_do_checkpoint); | ||||
void | void | ||||
init_snapshot(void) | init_snapshot(void) | ||||
▲ Show 20 Lines • Show All 214 Lines • Show Last 20 Lines |
Is it OK to pass -1 to fdopen?