git: ee5023f3c2f4 - main - bhyve: simplify restore of kernel structs

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Mon, 19 Jun 2023 05:57:58 UTC
The branch main has been updated by corvink:

URL: https://cgit.FreeBSD.org/src/commit/?id=ee5023f3c2f46987fd051de2696c1743e4226a37

commit ee5023f3c2f46987fd051de2696c1743e4226a37
Author:     Vitaliy Gusev <gusev.vitaliy@gmail.com>
AuthorDate: 2023-05-15 14:27:29 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-06-19 05:51:33 +0000

    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
---
 usr.sbin/bhyve/snapshot.c | 149 ++++++++++++----------------------------------
 1 file changed, 39 insertions(+), 110 deletions(-)

diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c
index 7e635c13ef31..dfe341c598b8 100644
--- a/usr.sbin/bhyve/snapshot.c
+++ b/usr.sbin/bhyve/snapshot.c
@@ -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)
+int
+vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate)
 {
-	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;
-	}
+	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;
 
-	if (struct_size == 0) {
-		fprintf(stderr, "%s: Kernel struct size was 0 for: %s\r\n",
-			__func__, info->struct_name);
-		ret = -1;
-		goto done;
-	}
+		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);
 
-	meta = &(struct vm_snapshot_meta) {
-		.dev_name = info->struct_name,
-		.dev_req  = info->req,
-
-		.buffer.buf_start = struct_ptr,
-		.buffer.buf_size = struct_size,
+		if (size == 0)
+			errx(EX_DATAERR, "data with zero size for %s",
+			    info->struct_name);
 
-		.buffer.buf = struct_ptr,
-		.buffer.buf_rem = struct_size,
+		meta = &(struct vm_snapshot_meta) {
+			.dev_name = info->struct_name,
+			.dev_req  = info->req,
 
-		.op = VM_SNAPSHOT_RESTORE,
-	};
+			.buffer.buf_start = data,
+			.buffer.buf_size = size,
 
-	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;
-	}
+			.buffer.buf = data,
+			.buffer.buf_rem = size,
 
-done:
-	return (ret);
-}
-
-int
-vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate)
-{
-	size_t i;
-	int ret;
+			.op = VM_SNAPSHOT_RESTORE,
+		};
 
-	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);
+		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 @@ done:
 }
 
 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;