QEMU-Nyx-fork/nyx/snapshot/block/nyx_block_snapshot.c
Sergej Schumilo cd702b528c Initial Release of Nyx
Co-authored-by: Cornelius Aschermann <cornelius@hexgolems.com>
2021-11-14 22:20:53 +01:00

195 lines
5.2 KiB
C

#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
#include "cpu.h"
#include "qemu/main-loop.h"
#include "sysemu/block-backend.h"
#include "block/qapi.h"
#include "sysemu/runstate.h"
#include "migration/vmstate.h"
#include "nyx/snapshot/block/nyx_block_snapshot.h"
#include "nyx/debug.h"
#include "nyx/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){
debug_printf("%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);
debug_printf("%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){
debug_printf("%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;
}
/*
static void fast_reload_serialize_cow(fast_reload_t* self, const char* folder){
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);
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;
printf("%d -> %s\n", i, (const char*)self->cow_cache_array[i]->filename);
strncpy((char*)&entry.idstr, (const char*)self->cow_cache_array[i]->filename, 256);
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);
}
*/
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;
//printf("%d -> %s\n", i, (const char*)self->cow_cache_array[i]->filename);
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);
}