Page MenuHomeFreeBSD

D35590.id107366.diff
No OneTemporary

D35590.id107366.diff

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

Mime Type
text/plain
Expires
Sun, Feb 22, 10:32 AM (7 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28935953
Default Alt Text
D35590.id107366.diff (24 KB)

Event Timeline