Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/snapshot.c
Show All 12 Lines | |||||
err(EX_DATAERR, "Failed to restore %s", | err(EX_DATAERR, "Failed to restore %s", | ||||
info->struct_name); | info->struct_name); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vm_restore_user_dev(struct restore_state *rstate, | vm_restore_device(struct restore_state *rstate, | ||||
const struct vm_snapshot_dev_info *info) | const struct vm_snapshot_dev_info *info) | ||||
{ | { | ||||
void *dev_ptr; | void *dev_ptr; | ||||
size_t dev_size; | size_t dev_size; | ||||
int ret; | int ret; | ||||
struct vm_snapshot_meta *meta; | struct vm_snapshot_meta *meta; | ||||
dev_ptr = lookup_dev(info->dev_name, JSON_DEV_ARR_KEY, rstate, | dev_ptr = lookup_dev(info->dev_name, JSON_DEV_ARR_KEY, rstate, | ||||
Show All 24 Lines | |||||
fprintf(stderr, "Failed to restore dev: %s\r\n", | fprintf(stderr, "Failed to restore dev: %s\r\n", | ||||
info->dev_name); | info->dev_name); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vm_restore_user_devs(struct restore_state *rstate) | vm_restore_devices(struct restore_state *rstate) | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
int ret; | int ret; | ||||
for (i = 0; i < nitems(snapshot_devs); i++) { | for (i = 0; i < nitems(snapshot_devs); i++) { | ||||
ret = vm_restore_user_dev(rstate, &snapshot_devs[i]); | ret = vm_restore_device(rstate, &snapshot_devs[i]); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (ret); | return (ret); | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
int | int | ||||
vm_pause_user_devs(void) | vm_pause_devices(void) | ||||
{ | { | ||||
const struct vm_snapshot_dev_info *info; | const struct vm_snapshot_dev_info *info; | ||||
size_t i; | size_t i; | ||||
int ret; | int ret; | ||||
for (i = 0; i < nitems(snapshot_devs); i++) { | for (i = 0; i < nitems(snapshot_devs); i++) { | ||||
info = &snapshot_devs[i]; | info = &snapshot_devs[i]; | ||||
if (info->pause_cb == NULL) | if (info->pause_cb == NULL) | ||||
continue; | continue; | ||||
ret = info->pause_cb(info->dev_name); | ret = info->pause_cb(info->dev_name); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (ret); | return (ret); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vm_resume_user_devs(void) | vm_resume_devices(void) | ||||
{ | { | ||||
const struct vm_snapshot_dev_info *info; | const struct vm_snapshot_dev_info *info; | ||||
size_t i; | size_t i; | ||||
int ret; | int ret; | ||||
for (i = 0; i < nitems(snapshot_devs); i++) { | for (i = 0; i < nitems(snapshot_devs); i++) { | ||||
info = &snapshot_devs[i]; | info = &snapshot_devs[i]; | ||||
if (info->resume_cb == NULL) | if (info->resume_cb == NULL) | ||||
Show All 24 Lines | |||||
xo_close_instance_h(xop, array_key); | xo_close_instance_h(xop, array_key); | ||||
*offset += data_size; | *offset += data_size; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info, | vm_snapshot_device(const struct vm_snapshot_dev_info *info, | ||||
int data_fd, xo_handle_t *xop, | int data_fd, xo_handle_t *xop, | ||||
struct vm_snapshot_meta *meta, off_t *offset) | struct vm_snapshot_meta *meta, off_t *offset) | ||||
{ | { | ||||
int ret; | int ret; | ||||
ret = (*info->snapshot_cb)(meta); | ret = (*info->snapshot_cb)(meta); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n", | fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n", | ||||
meta->dev_name, ret); | meta->dev_name, ret); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
ret = vm_snapshot_dev_write_data(data_fd, xop, JSON_DEV_ARR_KEY, meta, | ret = vm_snapshot_dev_write_data(data_fd, xop, JSON_DEV_ARR_KEY, meta, | ||||
offset); | offset); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (ret); | return (ret); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vm_snapshot_user_devs(int data_fd, xo_handle_t *xop) | vm_snapshot_devices(int data_fd, xo_handle_t *xop) | ||||
{ | { | ||||
int ret; | int ret; | ||||
off_t offset; | off_t offset; | ||||
void *buffer; | void *buffer; | ||||
size_t buf_size, i; | size_t buf_size, i; | ||||
struct vm_snapshot_meta *meta; | struct vm_snapshot_meta *meta; | ||||
buf_size = SNAPSHOT_BUFFER_SIZE; | buf_size = SNAPSHOT_BUFFER_SIZE; | ||||
Show All 23 Lines | |||||
/* Restore other devices that support this feature */ | /* Restore other devices that support this feature */ | ||||
for (i = 0; i < nitems(snapshot_devs); i++) { | for (i = 0; i < nitems(snapshot_devs); i++) { | ||||
meta->dev_name = snapshot_devs[i].dev_name; | meta->dev_name = snapshot_devs[i].dev_name; | ||||
memset(meta->buffer.buf_start, 0, meta->buffer.buf_size); | memset(meta->buffer.buf_start, 0, meta->buffer.buf_size); | ||||
meta->buffer.buf = meta->buffer.buf_start; | meta->buffer.buf = meta->buffer.buf_start; | ||||
meta->buffer.buf_rem = meta->buffer.buf_size; | meta->buffer.buf_rem = meta->buffer.buf_size; | ||||
ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop, | ret = vm_snapshot_device(&snapshot_devs[i], data_fd, xop, | ||||
meta, &offset); | meta, &offset); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto snapshot_err; | goto snapshot_err; | ||||
} | } | ||||
xo_close_list_h(xop, JSON_DEV_ARR_KEY); | xo_close_list_h(xop, JSON_DEV_ARR_KEY); | ||||
snapshot_err: | snapshot_err: | ||||
Show All 24 Lines | |||||
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); | ||||
ret = vm_pause_user_devs(); | ret = vm_pause_devices(); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "Could not pause devices\r\n"); | fprintf(stderr, "Could not pause devices\r\n"); | ||||
error = ret; | error = ret; | ||||
goto done; | goto done; | ||||
} | } | ||||
memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true); | memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true); | ||||
if (memsz == 0) { | if (memsz == 0) { | ||||
Show All 11 Lines | |||||
ret = vm_save_kern_structs(ctx, kdata_fd, xop); | ret = vm_save_kern_structs(ctx, kdata_fd, xop); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "Failed to snapshot vm kernel data.\n"); | fprintf(stderr, "Failed to snapshot vm kernel data.\n"); | ||||
error = -1; | error = -1; | ||||
goto done; | goto done; | ||||
} | } | ||||
ret = vm_snapshot_user_devs(kdata_fd, xop); | ret = vm_snapshot_devices(kdata_fd, xop); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "Failed to snapshot device state.\n"); | fprintf(stderr, "Failed to snapshot device state.\n"); | ||||
error = -1; | error = -1; | ||||
goto done; | goto done; | ||||
} | } | ||||
xo_finish_h(xop); | xo_finish_h(xop); | ||||
if (stop_vm) { | if (stop_vm) { | ||||
vm_destroy(ctx); | vm_destroy(ctx); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
done: | done: | ||||
ret = vm_resume_user_devs(); | ret = vm_resume_devices(); | ||||
if (ret != 0) | if (ret != 0) | ||||
fprintf(stderr, "Could not resume devices\r\n"); | fprintf(stderr, "Could not resume devices\r\n"); | ||||
vm_vcpu_resume(ctx); | vm_vcpu_resume(ctx); | ||||
if (fd_checkpoint > 0) | if (fd_checkpoint > 0) | ||||
close(fd_checkpoint); | close(fd_checkpoint); | ||||
if (meta_filename != NULL) | if (meta_filename != NULL) | ||||
free(meta_filename); | free(meta_filename); | ||||
if (kdata_filename != NULL) | if (kdata_filename != NULL) | ||||
Show All 12 Lines |