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:
Vitaliy Gusev 2023-05-15 14:27:29 +00:00 committed by Corvin Köhne
parent 50aef9f62c
commit ee5023f3c2
No known key found for this signature in database
GPG Key ID: D854DA56315E026A

View File

@ -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;