167 lines
4.4 KiB
C
167 lines
4.4 KiB
C
#include "qemu/osdep.h"
|
|
|
|
#include "block/qapi.h"
|
|
#include "migration/vmstate.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "sysemu/runstate.h"
|
|
#include "sysemu/sysemu.h"
|
|
|
|
#include "nyx/debug.h"
|
|
#include "nyx/snapshot/block/nyx_block_snapshot.h"
|
|
#include "nyx/state/state.h"
|
|
|
|
typedef struct fast_reload_cow_entry_s {
|
|
uint32_t id;
|
|
char idstr[256];
|
|
} fast_reload_cow_entry_t;
|
|
|
|
|
|
nyx_block_t *nyx_block_snapshot_init_from_file(const char *folder, bool pre_snapshot)
|
|
{
|
|
nyx_block_t *self = malloc(sizeof(nyx_block_t));
|
|
memset(self, 0, sizeof(nyx_block_t));
|
|
|
|
BlockBackend *blk;
|
|
fast_reload_cow_entry_t entry;
|
|
|
|
char *tmp1;
|
|
char *tmp2;
|
|
|
|
assert(asprintf(&tmp1, "%s/fs_cache.meta", folder) != -1);
|
|
assert(asprintf(&tmp2, "%s/fs_drv", folder) != -1);
|
|
|
|
|
|
self->cow_cache_array_size = 0;
|
|
|
|
FILE *f = fopen(tmp1, "r");
|
|
assert(f != NULL);
|
|
|
|
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
if (blk && blk->cow_cache) {
|
|
nyx_debug("%p %s\n", blk->cow_cache, blk->cow_cache->filename);
|
|
self->cow_cache_array_size++;
|
|
}
|
|
}
|
|
|
|
uint32_t temp_cow_cache_array_size;
|
|
|
|
assert(fread(&temp_cow_cache_array_size, sizeof(uint32_t), 1, f) == 1);
|
|
|
|
nyx_debug("%d vs %x\n", temp_cow_cache_array_size, self->cow_cache_array_size);
|
|
assert(self->cow_cache_array_size == temp_cow_cache_array_size);
|
|
|
|
self->cow_cache_array =
|
|
(cow_cache_t **)malloc(sizeof(cow_cache_t *) * self->cow_cache_array_size);
|
|
|
|
uint32_t i = 0;
|
|
uint32_t id = 0;
|
|
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
if (blk && blk->cow_cache) {
|
|
self->cow_cache_array[i++] = blk->cow_cache;
|
|
assert(fread(&entry, sizeof(fast_reload_cow_entry_t), 1, f) == 1);
|
|
|
|
assert(!strcmp(entry.idstr, blk->cow_cache->filename));
|
|
assert(entry.id == id);
|
|
}
|
|
id++;
|
|
}
|
|
|
|
|
|
fclose(f);
|
|
|
|
for (i = 0; i < self->cow_cache_array_size; i++) {
|
|
read_primary_buffer(self->cow_cache_array[i], tmp2, !pre_snapshot);
|
|
}
|
|
|
|
free(tmp1);
|
|
free(tmp2);
|
|
return self;
|
|
}
|
|
|
|
nyx_block_t *nyx_block_snapshot_init(void)
|
|
{
|
|
nyx_block_t *self = malloc(sizeof(nyx_block_t));
|
|
memset(self, 0, sizeof(nyx_block_t));
|
|
|
|
BlockBackend *blk;
|
|
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
if (blk && blk->cow_cache) {
|
|
nyx_debug("%p %s\n", blk->cow_cache, blk->cow_cache->filename);
|
|
self->cow_cache_array_size++;
|
|
}
|
|
}
|
|
|
|
self->cow_cache_array =
|
|
(cow_cache_t **)malloc(sizeof(cow_cache_t *) * self->cow_cache_array_size);
|
|
|
|
uint32_t i = 0;
|
|
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
if (blk && blk->cow_cache) {
|
|
self->cow_cache_array[i++] = blk->cow_cache;
|
|
}
|
|
}
|
|
|
|
|
|
for (i = 0; i < self->cow_cache_array_size; i++) {
|
|
switch_to_fuzz_mode(self->cow_cache_array[i]);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
void nyx_block_snapshot_flush(nyx_block_t *self)
|
|
{
|
|
GET_GLOBAL_STATE()->cow_cache_full = false;
|
|
}
|
|
|
|
void nyx_block_snapshot_switch_incremental(nyx_block_t *self)
|
|
{
|
|
for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
|
|
cow_cache_enable_tmp_mode(self->cow_cache_array[i]);
|
|
}
|
|
nyx_block_snapshot_flush(self);
|
|
}
|
|
|
|
void nyx_block_snapshot_disable_incremental(nyx_block_t *self)
|
|
{
|
|
for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
|
|
cow_cache_disable_tmp_mode(self->cow_cache_array[i]);
|
|
}
|
|
}
|
|
|
|
void nyx_block_snapshot_reset(nyx_block_t *self)
|
|
{
|
|
for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
|
|
cow_cache_reset(self->cow_cache_array[i]);
|
|
}
|
|
}
|
|
|
|
void nyx_block_snapshot_serialize(nyx_block_t *self, const char *snapshot_folder)
|
|
{
|
|
fast_reload_cow_entry_t entry;
|
|
|
|
char *tmp1;
|
|
char *tmp2;
|
|
|
|
assert(asprintf(&tmp1, "%s/fs_cache.meta", snapshot_folder) != -1);
|
|
assert(asprintf(&tmp2, "%s/fs_drv", snapshot_folder) != -1);
|
|
|
|
|
|
FILE *f = fopen(tmp1, "w");
|
|
|
|
fwrite(&(self->cow_cache_array_size), sizeof(uint32_t), 1, f);
|
|
|
|
for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
|
|
entry.id = i;
|
|
strncpy((char *)&entry.idstr,
|
|
(const char *)self->cow_cache_array[i]->filename, 255);
|
|
fwrite(&entry, sizeof(fast_reload_cow_entry_t), 1, f);
|
|
|
|
dump_primary_buffer(self->cow_cache_array[i], tmp2);
|
|
}
|
|
fclose(f);
|
|
|
|
free(tmp1);
|
|
free(tmp2);
|
|
}
|