195 lines
5.2 KiB
C
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);
|
|
}
|