Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115695013
D35590.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
D35590.diff
View Options
diff --git a/usr.sbin/bhyve/atkbdc.h b/usr.sbin/bhyve/atkbdc.h
--- a/usr.sbin/bhyve/atkbdc.h
+++ b/usr.sbin/bhyve/atkbdc.h
@@ -30,14 +30,9 @@
#define _ATKBDC_H_
struct atkbdc_softc;
-struct vm_snapshot_meta;
struct vmctx;
void atkbdc_init(struct vmctx *ctx);
void atkbdc_event(struct atkbdc_softc *sc, int iskbd);
-#ifdef BHYVE_SNAPSHOT
-int atkbdc_snapshot(struct vm_snapshot_meta *meta);
-#endif
-
#endif /* _ATKBDC_H_ */
diff --git a/usr.sbin/bhyve/atkbdc.c b/usr.sbin/bhyve/atkbdc.c
--- a/usr.sbin/bhyve/atkbdc.c
+++ b/usr.sbin/bhyve/atkbdc.c
@@ -56,6 +56,10 @@
#include "ps2kbd.h"
#include "ps2mouse.h"
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#define KBD_DATA_PORT 0x60
#define KBD_STS_CTL_PORT 0x64
@@ -138,10 +142,6 @@
struct aux_dev aux;
};
-#ifdef BHYVE_SNAPSHOT
-static struct atkbdc_softc *atkbdc_sc = NULL;
-#endif
-
static void
atkbdc_assert_kbd_intr(struct atkbdc_softc *sc)
{
@@ -511,6 +511,14 @@
pthread_mutex_unlock(&sc->mtx);
}
+#ifdef BHYVE_SNAPSHOT
+extern int atkbdc_snapshot(struct vm_snapshot_meta *, void *);
+
+static struct snapshot_ops atkbdc_snapshot_ops = {
+ .snapshot_cb = atkbdc_snapshot,
+};
+#endif
+
void
atkbdc_init(struct vmctx *ctx)
{
@@ -555,42 +563,40 @@
sc->ps2mouse_sc = ps2mouse_init(sc);
#ifdef BHYVE_SNAPSHOT
- assert(atkbdc_sc == NULL);
- atkbdc_sc = sc;
+ register_snapshot_dev("atkbdc", &atkbdc_snapshot_ops, sc);
#endif
}
#ifdef BHYVE_SNAPSHOT
int
-atkbdc_snapshot(struct vm_snapshot_meta *meta)
+atkbdc_snapshot(struct vm_snapshot_meta *meta, void *cbdata)
{
int ret;
-
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->status, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->outport, meta, ret, done);
- SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->ram,
- sizeof(atkbdc_sc->ram), meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->curcmd, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->ctrlbyte, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd, meta, ret, done);
-
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq_active, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq, meta, ret, done);
- SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->kbd.buffer,
- sizeof(atkbdc_sc->kbd.buffer), meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.brd, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bwr, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bcnt, meta, ret, done);
-
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq_active, meta, ret, done);
- SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq, meta, ret, done);
-
- ret = ps2kbd_snapshot(atkbdc_sc->ps2kbd_sc, meta);
- if (ret != 0)
- goto done;
-
- ret = ps2mouse_snapshot(atkbdc_sc->ps2mouse_sc, meta);
-
+ struct atkbdc_softc *sc = (struct atkbdc_softc *)cbdata;
+
+ assert(sc != NULL);
+
+ SNAPSHOT_VAR_OR_LEAVE(sc->status, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->outport, meta, ret, done);
+ SNAPSHOT_BUF_OR_LEAVE(sc->ram, sizeof (sc->ram), meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->curcmd, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->ctrlbyte, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd, meta, ret, done);
+
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd.irq_active, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd.irq, meta, ret, done);
+ SNAPSHOT_BUF_OR_LEAVE(sc->kbd.buffer,
+ sizeof (sc->kbd.buffer), meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd.brd, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd.bwr, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->kbd.bcnt, meta, ret, done);
+
+ SNAPSHOT_VAR_OR_LEAVE(sc->aux.irq_active, meta, ret, done);
+ SNAPSHOT_VAR_OR_LEAVE(sc->aux.irq, meta, ret, done);
+
+ ret = ps2kbd_snapshot(sc->ps2kbd_sc, meta);
+ if (ret == 0)
+ ret = ps2mouse_snapshot(sc->ps2mouse_sc, meta);
done:
return (ret);
}
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -1498,7 +1498,7 @@
}
fprintf(stdout, "Pausing pci devs...\r\n");
- if (vm_pause_user_devs() != 0) {
+ if (vm_pause_devices() != 0) {
fprintf(stderr, "Failed to pause PCI device state.\n");
exit(1);
}
@@ -1510,7 +1510,7 @@
}
fprintf(stdout, "Restoring pci devs...\r\n");
- if (vm_restore_user_devs(ctx, &rstate) != 0) {
+ if (vm_restore_devices(ctx, &rstate) != 0) {
fprintf(stderr, "Failed to restore PCI device state.\n");
exit(1);
}
@@ -1522,7 +1522,7 @@
}
fprintf(stdout, "Resuming pci devs...\r\n");
- if (vm_resume_user_devs() != 0) {
+ if (vm_resume_devices() != 0) {
fprintf(stderr, "Failed to resume PCI device state.\n");
exit(1);
}
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -80,7 +80,6 @@
int (*pe_snapshot)(struct vm_snapshot_meta *meta);
int (*pe_pause)(struct pci_devinst *pi);
int (*pe_resume)(struct pci_devinst *pi);
-
};
#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x);
@@ -259,11 +258,6 @@
void pci_write_dsdt(void);
uint64_t pci_ecfg_base(void);
int pci_bus_configured(int bus);
-#ifdef BHYVE_SNAPSHOT
-int pci_snapshot(struct vm_snapshot_meta *meta);
-int pci_pause(const char *dev_name);
-int pci_resume(const char *dev_name);
-#endif
static __inline void
pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -62,6 +62,10 @@
#include "pci_irq.h"
#include "pci_lpc.h"
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#define CONF1_ADDR_PORT 0x0cf8
#define CONF1_DATA_PORT 0x0cfc
@@ -985,7 +989,9 @@
pdi->pi_lintr.pirq_pin = 0;
pdi->pi_lintr.ioapic_irq = 0;
pdi->pi_d = pde;
- snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot);
+
+ snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d-%d-%d", pde->pe_emu, bus,
+ slot, func);
/* Disable legacy interrupts */
pci_set_cfgdata8(pdi, PCIR_INTLINE, 255);
@@ -1322,6 +1328,18 @@
#define BUSMEM32_ROUNDUP (1024 * 1024)
#define BUSMEM64_ROUNDUP (512 * 1024 * 1024)
+#ifdef BHYVE_SNAPSHOT
+static int pci_snapshot(struct vm_snapshot_meta *, void *);
+static int pci_pause(void *);
+static int pci_resume(void *);
+
+static struct snapshot_ops pci_snapshot_ops = {
+ .snapshot_cb = pci_snapshot,
+ .pause_cb = pci_pause,
+ .resume_cb = pci_resume,
+};
+#endif
+
int
init_pci(struct vmctx *ctx)
{
@@ -1400,6 +1418,10 @@
func, fi);
if (error)
return (error);
+#ifdef BHYVE_SNAPSHOT
+ register_snapshot_dev(fi->fi_devi->pi_name,
+ &pci_snapshot_ops, fi->fi_devi);
+#endif
}
}
@@ -2321,58 +2343,15 @@
}
static int
-pci_find_slotted_dev(const char *dev_name, struct pci_devemu **pde,
- struct pci_devinst **pdi)
-{
- struct businfo *bi;
- struct slotinfo *si;
- struct funcinfo *fi;
- int bus, slot, func;
-
- assert(dev_name != NULL);
- assert(pde != NULL);
- assert(pdi != NULL);
-
- for (bus = 0; bus < MAXBUSES; bus++) {
- if ((bi = pci_businfo[bus]) == NULL)
- continue;
-
- for (slot = 0; slot < MAXSLOTS; slot++) {
- si = &bi->slotinfo[slot];
- for (func = 0; func < MAXFUNCS; func++) {
- fi = &si->si_funcs[func];
- if (fi->fi_pde == NULL)
- continue;
- if (strcmp(dev_name, fi->fi_pde->pe_emu) != 0)
- continue;
-
- *pde = fi->fi_pde;
- *pdi = fi->fi_devi;
- return (0);
- }
- }
- }
-
- return (EINVAL);
-}
-
-int
-pci_snapshot(struct vm_snapshot_meta *meta)
+pci_snapshot(struct vm_snapshot_meta *meta, void *cbdata)
{
struct pci_devemu *pde;
- struct pci_devinst *pdi;
+ struct pci_devinst *pdi = (struct pci_devinst *)cbdata;
int ret;
- assert(meta->dev_name != NULL);
-
- ret = pci_find_slotted_dev(meta->dev_name, &pde, &pdi);
- if (ret != 0) {
- fprintf(stderr, "%s: no such name: %s\r\n",
- __func__, meta->dev_name);
- memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
- return (0);
- }
+ assert(pdi != NULL);
+ pde = pdi->pi_d;
meta->dev_data = pdi;
if (pde->pe_snapshot == NULL) {
@@ -2383,8 +2362,8 @@
ret = pci_snapshot_pci_dev(meta);
if (ret != 0) {
- fprintf(stderr, "%s: failed to snapshot pci dev\r\n",
- __func__);
+ fprintf(stderr, "%s: failed to snapshot pci dev %s: %d\n",
+ __func__, meta->dev_name, ret);
return (-1);
}
@@ -2393,58 +2372,40 @@
return (ret);
}
-int
-pci_pause(const char *dev_name)
+static int
+pci_pause(void *cbdata)
{
struct pci_devemu *pde;
- struct pci_devinst *pdi;
- int ret;
+ struct pci_devinst *pdi = (struct pci_devinst *)cbdata;
- assert(dev_name != NULL);
+ assert(pdi != NULL);
- ret = pci_find_slotted_dev(dev_name, &pde, &pdi);
- if (ret != 0) {
- /*
- * It is possible to call this function without
- * checking that the device is inserted first.
- */
- fprintf(stderr, "%s: no such name: %s\n", __func__, dev_name);
- return (0);
- }
+ pde = pdi->pi_d;
if (pde->pe_pause == NULL) {
/* The pause/resume functionality is optional. */
fprintf(stderr, "%s: not implemented for: %s\n",
- __func__, dev_name);
+ __func__, pdi->pi_name);
return (0);
}
return (*pde->pe_pause)(pdi);
}
-int
-pci_resume(const char *dev_name)
+static int
+pci_resume(void *cbdata)
{
struct pci_devemu *pde;
- struct pci_devinst *pdi;
- int ret;
+ struct pci_devinst *pdi = (struct pci_devinst *)cbdata;
- assert(dev_name != NULL);
+ assert(pdi != NULL);
- ret = pci_find_slotted_dev(dev_name, &pde, &pdi);
- if (ret != 0) {
- /*
- * It is possible to call this function without
- * checking that the device is inserted first.
- */
- fprintf(stderr, "%s: no such name: %s\n", __func__, dev_name);
- return (0);
- }
+ pde = pdi->pi_d;
if (pde->pe_resume == NULL) {
/* The pause/resume functionality is optional. */
fprintf(stderr, "%s: not implemented for: %s\n",
- __func__, dev_name);
+ __func__, pdi->pi_name);
return (0);
}
diff --git a/usr.sbin/bhyve/pci_hostbridge.c b/usr.sbin/bhyve/pci_hostbridge.c
--- a/usr.sbin/bhyve/pci_hostbridge.c
+++ b/usr.sbin/bhyve/pci_hostbridge.c
@@ -64,6 +64,14 @@
return (0);
}
+#ifdef BHYVE_SNAPSHOT
+static int
+pci_hostbridge_snapshot(struct vm_snapshot_meta *meta __unused)
+{
+ return (0);
+}
+#endif
+
static int
pci_amd_hostbridge_legacy_config(nvlist_t *nvl, const char *opts __unused)
{
@@ -77,11 +85,17 @@
.pe_emu = "amd_hostbridge",
.pe_legacy_config = pci_amd_hostbridge_legacy_config,
.pe_alias = "hostbridge",
+#ifdef BHYVE_SNAPSHOT
+ .pe_snapshot = pci_hostbridge_snapshot,
+#endif
};
PCI_EMUL_SET(pci_de_amd_hostbridge);
static const struct pci_devemu pci_de_hostbridge = {
.pe_emu = "hostbridge",
.pe_init = pci_hostbridge_init,
+#ifdef BHYVE_SNAPSHOT
+ .pe_snapshot = pci_hostbridge_snapshot,
+#endif
};
PCI_EMUL_SET(pci_de_hostbridge);
diff --git a/usr.sbin/bhyve/snapshot.h b/usr.sbin/bhyve/snapshot.h
--- a/usr.sbin/bhyve/snapshot.h
+++ b/usr.sbin/bhyve/snapshot.h
@@ -65,22 +65,25 @@
int socket_fd;
};
-typedef int (*vm_snapshot_dev_cb)(struct vm_snapshot_meta *);
-typedef int (*vm_pause_dev_cb) (const char *);
-typedef int (*vm_resume_dev_cb) (const char *);
-
-struct vm_snapshot_dev_info {
- const char *dev_name; /* device name */
- vm_snapshot_dev_cb snapshot_cb; /* callback for device snapshot */
- vm_pause_dev_cb pause_cb; /* callback for device pause */
- vm_resume_dev_cb resume_cb; /* callback for device resume */
+typedef int (*snapshot_dev_cb)(struct vm_snapshot_meta *meta, void *cbdata);
+typedef int (*pause_dev_cb)(void *cbdata);
+typedef int (*resume_dev_cb)(void *cbdata);
+
+struct snapshot_ops {
+ snapshot_dev_cb snapshot_cb; /* callback for device save/restore */
+ pause_dev_cb pause_cb; /* callback for device pause (optional) */
+ resume_dev_cb resume_cb; /* callback for device resume (optional) */
};
struct vm_snapshot_kern_info {
- const char *struct_name; /* kernel structure name*/
+ const char *dev_name; /* kernel device name */
enum snapshot_req req; /* request type */
};
+struct snapshot_ops;
+
+void register_snapshot_dev(const char *devname, struct snapshot_ops *ops,
+ void *cbdata);
void destroy_restore_state(struct restore_state *rstate);
const char *lookup_vmname(struct restore_state *rstate);
@@ -95,9 +98,9 @@
int restore_vm_mem(struct vmctx *ctx, struct restore_state *rstate);
int vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate);
-int vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate);
-int vm_pause_user_devs(void);
-int vm_resume_user_devs(void);
+int vm_restore_devices(struct vmctx *ctx, struct restore_state *rstate);
+int vm_pause_devices(void);
+int vm_resume_devices(void);
int get_checkpoint_msg(int conn_fd, struct vmctx *ctx);
void *checkpoint_thread(void *param);
diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c
--- a/usr.sbin/bhyve/snapshot.c
+++ b/usr.sbin/bhyve/snapshot.c
@@ -119,12 +119,12 @@
#define SNAPSHOT_BUFFER_SIZE (20 * MB)
-#define JSON_STRUCT_ARR_KEY "structs"
+#define JSON_KERNEL_ARR_KEY "kern_structs"
#define JSON_DEV_ARR_KEY "devices"
-#define JSON_BASIC_METADATA_KEY "basic metadata"
-#define JSON_SNAPSHOT_REQ_KEY "snapshot_req"
+#define JSON_BASIC_METADATA_KEY "basic metadata"
+#define JSON_SNAPSHOT_REQ_KEY "device"
#define JSON_SIZE_KEY "size"
-#define JSON_FILE_OFFSET_KEY "file_offset"
+#define JSON_FILE_OFFSET_KEY "file_offset"
#define JSON_NCPUS_KEY "ncpus"
#define JSON_VMNAME_KEY "vmname"
@@ -138,20 +138,6 @@
_a < _b ? _a : _b; \
})
-static const struct vm_snapshot_dev_info snapshot_devs[] = {
- { "atkbdc", atkbdc_snapshot, NULL, NULL },
- { "virtio-net", pci_snapshot, pci_pause, pci_resume },
- { "virtio-blk", pci_snapshot, pci_pause, pci_resume },
- { "virtio-rnd", pci_snapshot, NULL, NULL },
- { "lpc", pci_snapshot, NULL, NULL },
- { "fbuf", pci_snapshot, NULL, NULL },
- { "xhci", pci_snapshot, NULL, NULL },
- { "e1000", pci_snapshot, NULL, NULL },
- { "ahci", pci_snapshot, pci_pause, pci_resume },
- { "ahci-hd", pci_snapshot, pci_pause, pci_resume },
- { "ahci-cd", pci_snapshot, pci_pause, pci_resume },
-};
-
static const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
{ "vhpet", STRUCT_VHPET },
{ "vm", STRUCT_VM },
@@ -169,6 +155,31 @@
static pthread_cond_t vcpus_idle, vcpus_can_run;
static bool checkpoint_active;
+struct snapshot_dev {
+ LIST_ENTRY(snapshot_dev) dev_link;
+ const char *dev_name;
+ struct snapshot_ops *dev_ops;
+ void *dev_cbdata;
+};
+
+static LIST_HEAD(, snapshot_dev) snapshot_devices;
+
+void
+register_snapshot_dev(const char *name, struct snapshot_ops *ops,
+ void *cbdata)
+{
+ struct snapshot_dev *dev;
+
+ assert(ops != NULL && ops->snapshot_cb != NULL);
+
+ dev = calloc(1, sizeof (struct snapshot_dev));
+
+ dev->dev_name = name;
+ dev->dev_ops = ops;
+ dev->dev_cbdata = cbdata;
+ LIST_INSERT_HEAD(&snapshot_devices, dev, dev_link);
+}
+
/*
* TODO: Harden this function and all of its callers since 'base_str' is a user
* provided string.
@@ -415,50 +426,6 @@
} \
} 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_STRUCT_ARR_KEY);
- if (structs == NULL) {
- fprintf(stderr, "Failed to find '%s' object.\n",
- JSON_STRUCT_ARR_KEY);
- return (NULL);
- }
-
- if (ucl_object_type(structs) != UCL_ARRAY) {
- fprintf(stderr, "Object '%s' is not an array.\n",
- JSON_STRUCT_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,
@@ -489,14 +456,14 @@
}
static void*
-lookup_dev(const char *dev_name, struct restore_state *rstate,
- size_t *data_size)
+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,97 +828,71 @@
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;
- }
-
- 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) {
- .ctx = ctx,
- .dev_name = info->struct_name,
- .dev_req = info->req,
- .buffer.buf_start = struct_ptr,
- .buffer.buf_size = struct_size,
+ 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;
- .buffer.buf = struct_ptr,
- .buffer.buf_rem = struct_size,
+ info = &snapshot_kern_structs[i];
+ data = lookup_dev(info->dev_name, JSON_KERNEL_ARR_KEY, rstate, &size);
+ if (data == NULL)
+ errx(EX_DATAERR, "Cannot find kern struct %s", info->dev_name);
- .op = VM_SNAPSHOT_RESTORE,
- };
+ if (size == 0) {
+ warnx("data with zero size for %s", info->dev_name);
+ return (1);
+ }
+ meta = &(struct vm_snapshot_meta) {
+ .ctx = ctx,
+ .dev_name = info->dev_name,
+ .dev_req = info->req,
- ret = vm_snapshot_req(meta);
- if (ret != 0) {
- fprintf(stderr, "%s: Failed to restore struct: %s\r\n",
- __func__, info->struct_name);
- goto done;
- }
+ .buffer.buf_start = data,
+ .buffer.buf_size = size,
-done:
- return (ret);
-}
+ .buffer.buf = data,
+ .buffer.buf_rem = size,
-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)
+ ret = vm_snapshot_req(meta);
+ if (ret != 0) {
+ warnx("%s: Failed to restore %s", __func__,
+ info->dev_name);
return (ret);
+ }
}
- return (0);
+ return (ret);
}
-static int
-vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate,
- const struct vm_snapshot_dev_info *info)
+static void
+vm_restore_device(struct vmctx *ctx, struct restore_state *rstate,
+ struct snapshot_dev *dev)
{
void *dev_ptr;
size_t dev_size;
int ret;
struct vm_snapshot_meta *meta;
- dev_ptr = lookup_dev(info->dev_name, 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");
- return (0);
- }
+ dev_ptr = lookup_dev(dev->dev_name, JSON_DEV_ARR_KEY, rstate, &dev_size);
+ if (dev_ptr == NULL)
+ err(EX_DATAERR, "Failed to lookup dev: %s\r\n", dev->dev_name);
- if (dev_size == 0) {
- fprintf(stderr, "%s: Device size is 0. "
- "Assuming %s is not used\r\n",
- __func__, info->dev_name);
- return (0);
- }
+ if (dev_size == 0)
+ err(EX_DATAERR, "%s: device size is 0: %s\n", __func__,
+ dev->dev_name);
meta = &(struct vm_snapshot_meta) {
.ctx = ctx,
- .dev_name = info->dev_name,
+ .dev_name = dev->dev_name,
.buffer.buf_start = dev_ptr,
.buffer.buf_size = dev_size,
@@ -962,74 +903,62 @@
.op = VM_SNAPSHOT_RESTORE,
};
- ret = (*info->snapshot_cb)(meta);
- if (ret != 0) {
- fprintf(stderr, "Failed to restore dev: %s\r\n",
- info->dev_name);
- return (-1);
- }
-
- return (0);
+ ret = (dev->dev_ops->snapshot_cb)(meta, dev->dev_cbdata);
+ if (ret != 0)
+ err(EX_DATAERR, "Failed to restore dev: %s", dev->dev_name);
}
int
-vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
+vm_restore_devices(struct vmctx *ctx, struct restore_state *rstate)
{
- size_t i;
- int ret;
+ struct snapshot_dev *dev;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- ret = vm_restore_user_dev(ctx, rstate, &snapshot_devs[i]);
- if (ret != 0)
- return (ret);
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ vm_restore_device(ctx, rstate, dev);
}
return 0;
}
int
-vm_pause_user_devs(void)
+vm_pause_devices()
{
- const struct vm_snapshot_dev_info *info;
- size_t i;
- int ret;
+ struct snapshot_dev *dev;
+ int err;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->pause_cb == NULL)
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ if (!dev->dev_ops->pause_cb)
continue;
- ret = info->pause_cb(info->dev_name);
- if (ret != 0)
- return (ret);
+ err = dev->dev_ops->pause_cb(dev->dev_cbdata);
+ if (err != 0)
+ return (err);
}
return (0);
}
int
-vm_resume_user_devs(void)
+vm_resume_devices()
{
- const struct vm_snapshot_dev_info *info;
- size_t i;
- int ret;
+ struct snapshot_dev *dev;
+ int err;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->resume_cb == NULL)
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ if (!dev->dev_ops->resume_cb)
continue;
- ret = info->resume_cb(info->dev_name);
- if (ret != 0)
- return (ret);
+ err = dev->dev_ops->resume_cb(dev->dev_cbdata);
+ if (err != 0)
+ return (err);
}
return (0);
}
static int
-vm_snapshot_kern_struct(int data_fd, xo_handle_t *xop, const char *array_key,
+vm_save_kern_struct(int data_fd, xo_handle_t *xop, const char *array_key,
struct vm_snapshot_meta *meta, off_t *offset)
{
int ret;
@@ -1056,12 +985,10 @@
/* 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_STRUCT_ARR_KEY);
+ xo_close_instance_h(xop, JSON_KERNEL_ARR_KEY);
*offset += data_size;
@@ -1070,7 +997,7 @@
}
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;
@@ -1097,23 +1024,23 @@
.op = VM_SNAPSHOT_SAVE,
};
- xo_open_list_h(xop, JSON_STRUCT_ARR_KEY);
+ xo_open_list_h(xop, JSON_KERNEL_ARR_KEY);
for (i = 0; i < nitems(snapshot_kern_structs); i++) {
- meta->dev_name = snapshot_kern_structs[i].struct_name;
+ meta->dev_name = snapshot_kern_structs[i].dev_name;
meta->dev_req = snapshot_kern_structs[i].req;
memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
meta->buffer.buf = meta->buffer.buf_start;
meta->buffer.buf_rem = meta->buffer.buf_size;
- ret = vm_snapshot_kern_struct(data_fd, xop, JSON_DEV_ARR_KEY,
+ ret = vm_save_kern_struct(data_fd, xop, JSON_DEV_ARR_KEY,
meta, &offset);
if (ret != 0) {
error = -1;
goto err_vm_snapshot_kern_data;
}
}
- xo_close_list_h(xop, JSON_STRUCT_ARR_KEY);
+ xo_close_list_h(xop, JSON_KERNEL_ARR_KEY);
err_vm_snapshot_kern_data:
if (buffer != NULL)
@@ -1122,7 +1049,7 @@
}
static int
-vm_snapshot_basic_metadata(struct vmctx *ctx, xo_handle_t *xop, size_t memsz)
+vm_save_basic_metadata(struct vmctx *ctx, xo_handle_t *xop, size_t memsz)
{
xo_open_container_h(xop, JSON_BASIC_METADATA_KEY);
@@ -1164,16 +1091,20 @@
}
static int
-vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info,
- int data_fd, xo_handle_t *xop,
- struct vm_snapshot_meta *meta, off_t *offset)
+vm_save_device(struct snapshot_dev *dev,
+ int data_fd, xo_handle_t *xop,
+ struct vm_snapshot_meta *meta, off_t *offset)
{
int ret;
- ret = (*info->snapshot_cb)(meta);
+ meta->dev_name = dev->dev_name;
+ memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
+ meta->buffer.buf = meta->buffer.buf_start;
+ meta->buffer.buf_rem = meta->buffer.buf_size;
+
+ ret = (dev->dev_ops->snapshot_cb)(meta, dev->dev_cbdata);
if (ret != 0) {
- fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n",
- meta->dev_name, ret);
+ warnx("Failed to snapshot %s: ret=%d", meta->dev_name, ret);
return (ret);
}
@@ -1186,13 +1117,14 @@
}
static int
-vm_snapshot_user_devs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
+vm_save_devices(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
{
int ret;
off_t offset;
void *buffer;
- size_t buf_size, i;
+ size_t buf_size;
struct vm_snapshot_meta *meta;
+ struct snapshot_dev *dev;
buf_size = SNAPSHOT_BUFFER_SIZE;
@@ -1221,15 +1153,8 @@
xo_open_list_h(xop, JSON_DEV_ARR_KEY);
/* Restore other devices that support this feature */
- for (i = 0; i < nitems(snapshot_devs); i++) {
- meta->dev_name = snapshot_devs[i].dev_name;
-
- memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
- meta->buffer.buf = meta->buffer.buf_start;
- meta->buffer.buf_rem = meta->buffer.buf_size;
-
- ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop,
- meta, &offset);
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ ret = vm_save_device(dev, data_fd, xop, meta, &offset);
if (ret != 0)
goto snapshot_err;
}
@@ -1366,7 +1291,7 @@
vm_vcpu_pause(ctx);
- ret = vm_pause_user_devs();
+ ret = vm_pause_devices();
if (ret != 0) {
fprintf(stderr, "Could not pause devices\r\n");
error = ret;
@@ -1380,22 +1305,21 @@
goto done;
}
- ret = vm_snapshot_basic_metadata(ctx, xop, memsz);
+ ret = vm_save_basic_metadata(ctx, xop, memsz);
if (ret != 0) {
fprintf(stderr, "Failed to snapshot vm basic metadata.\n");
error = -1;
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;
goto done;
}
- ret = vm_snapshot_user_devs(ctx, kdata_fd, xop);
+ ret = vm_save_devices(ctx, kdata_fd, xop);
if (ret != 0) {
fprintf(stderr, "Failed to snapshot device state.\n");
error = -1;
@@ -1410,7 +1334,7 @@
}
done:
- ret = vm_resume_user_devs();
+ ret = vm_resume_devices();
if (ret != 0)
fprintf(stderr, "Could not resume devices\r\n");
vm_vcpu_resume(ctx);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 28, 6:46 AM (14 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17826612
Default Alt Text
D35590.diff (26 KB)
Attached To
Mode
D35590: bhyve: multiple devices support for suspend/checkpoint/resume
Attached
Detach File
Event Timeline
Log In to Comment