bhyve: simplify restore of kernel structs
Both devices and kernel struct can use the same 'lookup_dev' function instead of having duplicated code. Reviewed by: corvink, rew MFC after: 1 week Sponsored by: vStack Differential Revision: https://reviews.freebsd.org/D40105
This commit is contained in:
committed by
Corvin Köhne
parent
50aef9f62c
commit
ee5023f3c2
+43
-114
@@ -415,51 +415,6 @@ do { \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static void *
|
||||
lookup_struct(enum snapshot_req struct_id, struct restore_state *rstate,
|
||||
size_t *struct_size)
|
||||
{
|
||||
const ucl_object_t *structs = NULL, *obj = NULL;
|
||||
ucl_object_iter_t it = NULL;
|
||||
int64_t snapshot_req, size, file_offset;
|
||||
|
||||
structs = ucl_object_lookup(rstate->meta_root_obj, JSON_KERNEL_ARR_KEY);
|
||||
if (structs == NULL) {
|
||||
fprintf(stderr, "Failed to find '%s' object.\n",
|
||||
JSON_KERNEL_ARR_KEY);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (ucl_object_type(structs) != UCL_ARRAY) {
|
||||
fprintf(stderr, "Object '%s' is not an array.\n",
|
||||
JSON_KERNEL_ARR_KEY);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
while ((obj = ucl_object_iterate(structs, &it, true)) != NULL) {
|
||||
snapshot_req = -1;
|
||||
JSON_GET_INT_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
|
||||
&snapshot_req, NULL);
|
||||
assert(snapshot_req >= 0);
|
||||
if ((enum snapshot_req) snapshot_req == struct_id) {
|
||||
JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
|
||||
&size, NULL);
|
||||
assert(size >= 0);
|
||||
|
||||
JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
|
||||
&file_offset, NULL);
|
||||
assert(file_offset >= 0);
|
||||
assert((uint64_t)file_offset + size <=
|
||||
rstate->kdata_len);
|
||||
|
||||
*struct_size = (size_t)size;
|
||||
return ((uint8_t *)rstate->kdata_map + file_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void *
|
||||
lookup_check_dev(const char *dev_name, struct restore_state *rstate,
|
||||
const ucl_object_t *obj, size_t *data_size)
|
||||
@@ -488,15 +443,15 @@ lookup_check_dev(const char *dev_name, struct restore_state *rstate,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void*
|
||||
lookup_dev(const char *dev_name, struct restore_state *rstate,
|
||||
size_t *data_size)
|
||||
static void *
|
||||
lookup_dev(const char *dev_name, const char *key, struct restore_state *rstate,
|
||||
size_t *data_size)
|
||||
{
|
||||
const ucl_object_t *devs = NULL, *obj = NULL;
|
||||
ucl_object_iter_t it = NULL;
|
||||
void *ret;
|
||||
|
||||
devs = ucl_object_lookup(rstate->meta_root_obj, JSON_DEV_ARR_KEY);
|
||||
devs = ucl_object_lookup(rstate->meta_root_obj, key);
|
||||
if (devs == NULL) {
|
||||
fprintf(stderr, "Failed to find '%s' object.\n",
|
||||
JSON_DEV_ARR_KEY);
|
||||
@@ -861,67 +816,42 @@ restore_vm_mem(struct vmctx *ctx, struct restore_state *rstate)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vm_restore_kern_struct(struct vmctx *ctx, struct restore_state *rstate,
|
||||
const struct vm_snapshot_kern_info *info)
|
||||
{
|
||||
void *struct_ptr;
|
||||
size_t struct_size;
|
||||
int ret;
|
||||
struct vm_snapshot_meta *meta;
|
||||
|
||||
struct_ptr = lookup_struct(info->req, rstate, &struct_size);
|
||||
if (struct_ptr == NULL) {
|
||||
fprintf(stderr, "%s: Failed to lookup struct %s\r\n",
|
||||
__func__, info->struct_name);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (struct_size == 0) {
|
||||
fprintf(stderr, "%s: Kernel struct size was 0 for: %s\r\n",
|
||||
__func__, info->struct_name);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
meta = &(struct vm_snapshot_meta) {
|
||||
.dev_name = info->struct_name,
|
||||
.dev_req = info->req,
|
||||
|
||||
.buffer.buf_start = struct_ptr,
|
||||
.buffer.buf_size = struct_size,
|
||||
|
||||
.buffer.buf = struct_ptr,
|
||||
.buffer.buf_rem = struct_size,
|
||||
|
||||
.op = VM_SNAPSHOT_RESTORE,
|
||||
};
|
||||
|
||||
ret = vm_snapshot_req(ctx, meta);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "%s: Failed to restore struct: %s\r\n",
|
||||
__func__, info->struct_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
for (unsigned i = 0; i < nitems(snapshot_kern_structs); i++) {
|
||||
const struct vm_snapshot_kern_info *info;
|
||||
struct vm_snapshot_meta *meta;
|
||||
void *data;
|
||||
size_t size;
|
||||
|
||||
for (i = 0; i < nitems(snapshot_kern_structs); i++) {
|
||||
ret = vm_restore_kern_struct(ctx, rstate,
|
||||
&snapshot_kern_structs[i]);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
info = &snapshot_kern_structs[i];
|
||||
data = lookup_dev(info->struct_name, JSON_KERNEL_ARR_KEY, rstate, &size);
|
||||
if (data == NULL)
|
||||
errx(EX_DATAERR, "Cannot find kern struct %s",
|
||||
info->struct_name);
|
||||
|
||||
if (size == 0)
|
||||
errx(EX_DATAERR, "data with zero size for %s",
|
||||
info->struct_name);
|
||||
|
||||
meta = &(struct vm_snapshot_meta) {
|
||||
.dev_name = info->struct_name,
|
||||
.dev_req = info->req,
|
||||
|
||||
.buffer.buf_start = data,
|
||||
.buffer.buf_size = size,
|
||||
|
||||
.buffer.buf = data,
|
||||
.buffer.buf_rem = size,
|
||||
|
||||
.op = VM_SNAPSHOT_RESTORE,
|
||||
};
|
||||
|
||||
if (vm_snapshot_req(ctx, meta))
|
||||
err(EX_DATAERR, "Failed to restore %s",
|
||||
info->struct_name);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -934,7 +864,8 @@ vm_restore_user_dev(struct restore_state *rstate,
|
||||
int ret;
|
||||
struct vm_snapshot_meta *meta;
|
||||
|
||||
dev_ptr = lookup_dev(info->dev_name, rstate, &dev_size);
|
||||
dev_ptr = lookup_dev(info->dev_name, JSON_DEV_ARR_KEY, rstate,
|
||||
&dev_size);
|
||||
if (dev_ptr == NULL) {
|
||||
fprintf(stderr, "Failed to lookup dev: %s\r\n", info->dev_name);
|
||||
fprintf(stderr, "Continuing the restore/migration process\r\n");
|
||||
@@ -1027,7 +958,7 @@ vm_resume_user_devs(void)
|
||||
}
|
||||
|
||||
static int
|
||||
vm_snapshot_kern_struct(struct vmctx *ctx, int data_fd, xo_handle_t *xop,
|
||||
vm_save_kern_struct(struct vmctx *ctx, int data_fd, xo_handle_t *xop,
|
||||
const char *array_key, struct vm_snapshot_meta *meta, off_t *offset)
|
||||
{
|
||||
int ret;
|
||||
@@ -1054,9 +985,8 @@ vm_snapshot_kern_struct(struct vmctx *ctx, int data_fd, xo_handle_t *xop,
|
||||
|
||||
/* Write metadata. */
|
||||
xo_open_instance_h(xop, array_key);
|
||||
xo_emit_h(xop, "{:debug_name/%s}\n", meta->dev_name);
|
||||
xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%d}\n",
|
||||
meta->dev_req);
|
||||
xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%s}\n",
|
||||
meta->dev_name);
|
||||
xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
|
||||
xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
|
||||
xo_close_instance_h(xop, JSON_KERNEL_ARR_KEY);
|
||||
@@ -1068,7 +998,7 @@ vm_snapshot_kern_struct(struct vmctx *ctx, int data_fd, xo_handle_t *xop,
|
||||
}
|
||||
|
||||
static int
|
||||
vm_snapshot_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
|
||||
vm_save_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
|
||||
{
|
||||
int ret, error;
|
||||
size_t buf_size, i, offset;
|
||||
@@ -1102,7 +1032,7 @@ vm_snapshot_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
|
||||
meta->buffer.buf = meta->buffer.buf_start;
|
||||
meta->buffer.buf_rem = meta->buffer.buf_size;
|
||||
|
||||
ret = vm_snapshot_kern_struct(ctx, data_fd, xop,
|
||||
ret = vm_save_kern_struct(ctx, data_fd, xop,
|
||||
JSON_DEV_ARR_KEY, meta, &offset);
|
||||
if (ret != 0) {
|
||||
error = -1;
|
||||
@@ -1385,8 +1315,7 @@ vm_checkpoint(struct vmctx *ctx, int fddir, const char *checkpoint_file,
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
ret = vm_snapshot_kern_structs(ctx, kdata_fd, xop);
|
||||
ret = vm_save_kern_structs(ctx, kdata_fd, xop);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to snapshot vm kernel data.\n");
|
||||
error = -1;
|
||||
|
||||
Reference in New Issue
Block a user