Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145555834
D35590.id107366.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D35590.id107366.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
@@ -1489,9 +1489,10 @@
#ifdef BHYVE_SNAPSHOT
if (restore_file != NULL) {
- fprintf(stdout, "Pausing pci devs...\r\n");
- if (vm_pause_user_devs(ctx) != 0) {
- fprintf(stderr, "Failed to pause PCI device state.\n");
+ fprintf(stdout, "Pausing devices...\n");
+ if ((error = vm_pause_devices(ctx)) != 0) {
+ fprintf(stderr, "Failed to pause device state: %d\n",
+ error);
exit(1);
}
@@ -1501,21 +1502,24 @@
exit(1);
}
- fprintf(stdout, "Restoring pci devs...\r\n");
- if (vm_restore_user_devs(ctx, &rstate) != 0) {
- fprintf(stderr, "Failed to restore PCI device state.\n");
+ fprintf(stdout, "Restoring devices...\n");
+ if ((error = vm_restore_devices(ctx, &rstate)) != 0) {
+ fprintf(stderr, "Failed to restore devices state: %d\n",
+ error);
exit(1);
}
- fprintf(stdout, "Restoring kernel structs...\r\n");
- if (vm_restore_kern_structs(ctx, &rstate) != 0) {
- fprintf(stderr, "Failed to restore kernel structs.\n");
+ fprintf(stdout, "Restoring kernel data...\n");
+ if ((error = vm_restore_kern_structs(ctx, &rstate)) != 0) {
+ fprintf(stderr, "Failed to restore kernel data: %d\n",
+ error);
exit(1);
}
- fprintf(stdout, "Resuming pci devs...\r\n");
- if (vm_resume_user_devs(ctx) != 0) {
- fprintf(stderr, "Failed to resume PCI device state.\n");
+ fprintf(stdout, "Resuming devices...\r\n");
+ if ((error = vm_resume_devices(ctx)) != 0) {
+ fprintf(stderr, "Cannot resume devices: %d\n",
+ error);
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
@@ -264,11 +264,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(struct vmctx *ctx, const char *dev_name);
-int pci_resume(struct vmctx *ctx, 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
@@ -981,7 +985,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);
@@ -1316,6 +1322,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(struct vmctx *, void *);
+static int pci_resume(struct vmctx *, 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)
{
@@ -1394,6 +1412,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
}
}
@@ -2317,58 +2339,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) {
@@ -2379,8 +2358,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);
}
@@ -2389,58 +2368,40 @@
return (ret);
}
-int
-pci_pause(struct vmctx *ctx, const char *dev_name)
+static int
+pci_pause(struct vmctx *ctx, 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)(ctx, pdi);
}
-int
-pci_resume(struct vmctx *ctx, const char *dev_name)
+static int
+pci_resume(struct vmctx *ctx, 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);
}
@@ -2618,10 +2579,9 @@
}
#ifdef BHYVE_SNAPSHOT
-int
+static int
pci_emul_snapshot(struct vm_snapshot_meta *meta)
{
-
return (0);
}
#endif
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
@@ -74,15 +74,29 @@
return (0);
}
+#ifdef BHYVE_SNAPSHOT
+static int
+pci_hostbridge_snapshot(struct vm_snapshot_meta *meta)
+{
+ return (0);
+}
+#endif
+
struct pci_devemu pci_de_amd_hostbridge = {
.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);
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,15 +65,14 @@
int socket_fd;
};
-typedef int (*vm_snapshot_dev_cb)(struct vm_snapshot_meta *);
-typedef int (*vm_pause_dev_cb) (struct vmctx *, const char *);
-typedef int (*vm_resume_dev_cb) (struct vmctx *, 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)(struct vmctx *ctx, void *cbdata);
+typedef int (*resume_dev_cb)(struct vmctx *ctx, 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 {
@@ -81,6 +80,8 @@
enum snapshot_req req; /* request type */
};
+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 +96,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(struct vmctx *ctx);
-int vm_resume_user_devs(struct vmctx *ctx);
+int vm_restore_devices(struct vmctx *ctx, struct restore_state *rstate);
+int vm_pause_devices(struct vmctx *ctx);
+int vm_resume_devices(struct vmctx *ctx);
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; \
})
-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 },
-};
-
const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
{ "vhpet", STRUCT_VHPET },
{ "vm", STRUCT_VM },
@@ -170,6 +156,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.
@@ -423,16 +434,16 @@
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);
+ structs = ucl_object_lookup(rstate->meta_root_obj, JSON_KERNEL_ARR_KEY);
if (structs == NULL) {
fprintf(stderr, "Failed to find '%s' object.\n",
- JSON_STRUCT_ARR_KEY);
+ JSON_KERNEL_ARR_KEY);
return (NULL);
}
if (ucl_object_type((ucl_object_t *)structs) != UCL_ARRAY) {
fprintf(stderr, "Object '%s' is not an array.\n",
- JSON_STRUCT_ARR_KEY);
+ JSON_KERNEL_ARR_KEY);
return (NULL);
}
@@ -926,31 +937,30 @@
}
int
-vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate,
- const struct vm_snapshot_dev_info *info)
+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);
+ dev_ptr = lookup_dev(dev->dev_name, rstate, &dev_size);
if (dev_ptr == NULL) {
- fprintf(stderr, "Failed to lookup dev: %s\r\n", info->dev_name);
+ fprintf(stderr, "Failed to lookup dev: %s\n", dev->dev_name);
fprintf(stderr, "Continuing the restore/migration process\r\n");
return (0);
}
if (dev_size == 0) {
- fprintf(stderr, "%s: Device size is 0. "
- "Assuming %s is not used\r\n",
- __func__, info->dev_name);
+ fprintf(stderr, "%s: Device size is 0. Assume %s is not used\n",
+ __func__, dev->dev_name);
return (0);
}
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,
@@ -961,25 +971,24 @@
.op = VM_SNAPSHOT_RESTORE,
};
- ret = (*info->snapshot_cb)(meta);
+ ret = (dev->dev_ops->snapshot_cb)(meta, dev->dev_cbdata);
if (ret != 0) {
- fprintf(stderr, "Failed to restore dev: %s\r\n",
- info->dev_name);
+ fprintf(stderr, "Failed to restore %s: %d\n",
+ dev->dev_name, ret);
return (-1);
}
return (0);
}
-
int
-vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
+vm_restore_devices(struct vmctx *ctx, struct restore_state *rstate)
{
+ struct snapshot_dev *dev;
int ret;
- int i;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- ret = vm_restore_user_dev(ctx, rstate, &snapshot_devs[i]);
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ ret = vm_restore_device(ctx, rstate, dev);
if (ret != 0)
return (ret);
}
@@ -988,47 +997,39 @@
}
int
-vm_pause_user_devs(struct vmctx *ctx)
+vm_pause_devices(struct vmctx *ctx)
{
- const struct vm_snapshot_dev_info *info;
- int ret;
- int i;
-
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->pause_cb == NULL)
- continue;
+ struct snapshot_dev *dev;
+ int err;
- ret = info->pause_cb(ctx, info->dev_name);
- if (ret != 0)
- return (ret);
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ if (dev->dev_ops->pause_cb)
+ err = dev->dev_ops->pause_cb(ctx, dev->dev_cbdata);
+ if (err != 0)
+ return (err);
}
return (0);
}
int
-vm_resume_user_devs(struct vmctx *ctx)
+vm_resume_devices(struct vmctx *ctx)
{
- const struct vm_snapshot_dev_info *info;
- int ret;
- int i;
-
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->resume_cb == NULL)
- continue;
+ struct snapshot_dev *dev;
+ int err;
- ret = info->resume_cb(ctx, info->dev_name);
- if (ret != 0)
- return (ret);
+ LIST_FOREACH(dev, &snapshot_devices, dev_link) {
+ if (dev->dev_ops->resume_cb)
+ err = dev->dev_ops->resume_cb(ctx, 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;
@@ -1059,7 +1060,7 @@
meta->dev_req);
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;
@@ -1068,7 +1069,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, i, error;
size_t offset, buf_size;
@@ -1076,9 +1077,14 @@
struct vm_snapshot_meta *meta;
error = 0;
- offset = 0;
buf_size = SNAPSHOT_BUFFER_SIZE;
+ offset = lseek(data_fd, 0, SEEK_CUR);
+ if (offset < 0) {
+ perror("Failed to get data file current offset.");
+ return (-1);
+ }
+
buffer = malloc(SNAPSHOT_BUFFER_SIZE * sizeof(char));
if (buffer == NULL) {
error = ENOMEM;
@@ -1095,7 +1101,7 @@
.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_req = snapshot_kern_structs[i].req;
@@ -1104,14 +1110,14 @@
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)
@@ -1120,7 +1126,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);
@@ -1161,15 +1167,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",
+ fprintf(stderr, "Failed to snapshot %s: %d\n",
meta->dev_name, ret);
return (ret);
}
@@ -1183,13 +1194,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, i;
+ int ret;
off_t offset;
void *buffer;
size_t buf_size;
struct vm_snapshot_meta *meta;
+ struct snapshot_dev *dev;
buf_size = SNAPSHOT_BUFFER_SIZE;
@@ -1218,15 +1230,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;
}
@@ -1363,7 +1368,7 @@
vm_vcpu_pause(ctx);
- ret = vm_pause_user_devs(ctx);
+ ret = vm_pause_devices(ctx);
if (ret != 0) {
fprintf(stderr, "Could not pause devices\r\n");
error = ret;
@@ -1377,22 +1382,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;
@@ -1407,7 +1411,7 @@
}
done:
- ret = vm_resume_user_devs(ctx);
+ ret = vm_resume_devices(ctx);
if (ret != 0)
fprintf(stderr, "Could not resume devices\r\n");
vm_vcpu_resume(ctx);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 22, 10:33 AM (2 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28935953
Default Alt Text
D35590.id107366.diff (24 KB)
Attached To
Mode
D35590: bhyve: multiple devices support for suspend/checkpoint/resume
Attached
Detach File
Event Timeline
Log In to Comment