Skip to content

Commit 1559fd0

Browse files
committed
wip cow cache rewriting
1 parent c3c9c21 commit 1559fd0

File tree

16 files changed

+828
-337
lines changed

16 files changed

+828
-337
lines changed

block.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
#include "qemu/rcu.h"
5555
#include "block/coroutines.h"
5656

57+
#include "libafl/syx-snapshot/syx-snapshot.h"
58+
5759
#ifdef CONFIG_BSD
5860
#include <sys/ioctl.h>
5961
#include <sys/queue.h>
@@ -1259,6 +1261,34 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
12591261
*child_flags &= ~BDRV_O_NATIVE_AIO;
12601262
}
12611263

1264+
//// --- Begin LibAFL code ---
1265+
1266+
/*
1267+
* Returns the options and flags that a temporary snapshot should get, based on
1268+
* the originally requested flags (the originally requested image will have
1269+
* flags like a backing file)
1270+
*/
1271+
static void bdrv_syx_cow_cache_options(int *child_flags, QDict *child_options,
1272+
int parent_flags, QDict *parent_options)
1273+
{
1274+
GLOBAL_STATE_CODE();
1275+
*child_flags = parent_flags;
1276+
1277+
/* For temporary files, unconditional cache=unsafe is fine */
1278+
qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
1279+
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
1280+
1281+
/* Copy the read-only and discard options from the parent */
1282+
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
1283+
qdict_copy_default(child_options, parent_options, BDRV_OPT_DISCARD);
1284+
1285+
/* aio=native doesn't work for cache.direct=off, so disable it for the
1286+
* temporary snapshot */
1287+
*child_flags &= ~BDRV_O_NATIVE_AIO;
1288+
}
1289+
1290+
//// --- End LibAFL code ---
1291+
12621292
static void GRAPH_WRLOCK bdrv_backing_attach(BdrvChild *c)
12631293
{
12641294
BlockDriverState *parent = c->opaque;
@@ -3870,6 +3900,33 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
38703900
return bs;
38713901
}
38723902

3903+
//// --- Begin LibAFL code ---
3904+
3905+
static BlockDriverState *bdrv_append_syx_cow_cache(BlockDriverState *bs,
3906+
int flags,
3907+
QDict *scc_options,
3908+
Error **errp)
3909+
{
3910+
BlockDriverState* bs_scc = NULL;
3911+
3912+
/* We add a syx-cow-cache layer on top of the node being opened */
3913+
qdict_put_str(scc_options, "driver", "syx-cow-cache");
3914+
qdict_put_str(scc_options, "file", bs->node_name);
3915+
3916+
/* Open the syx cow cache */
3917+
bs_scc = bdrv_open(NULL, NULL, scc_options, flags, errp);
3918+
scc_options = NULL;
3919+
if (!bs_scc) {
3920+
goto out;
3921+
}
3922+
3923+
out:
3924+
qobject_unref(scc_options);
3925+
return bs_scc;
3926+
}
3927+
3928+
//// --- End LibAFL code ---
3929+
38733930
static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
38743931
int flags,
38753932
QDict *snapshot_options,
@@ -3966,6 +4023,14 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
39664023
QDict *snapshot_options = NULL;
39674024
int snapshot_flags = 0;
39684025

4026+
//// --- Begin LibAFL code ---
4027+
4028+
QDict* scc_options = NULL;
4029+
int scc_flags = 0;
4030+
bool attach_syx_continue = false;
4031+
4032+
//// --- End LibAFL code ---
4033+
39694034
assert(!child_class || !flags);
39704035
assert(!child_class == !parent);
39714036
GLOBAL_STATE_CODE();
@@ -4152,6 +4217,24 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
41524217
* (the inverse results in an error message from bdrv_open_common()) */
41534218
assert(!(flags & BDRV_O_PROTOCOL) || !file);
41544219

4220+
//// --- Begin LibAFL code ---
4221+
if (!(flags & BDRV_O_NOSYX) && syx_snapshot_use_scc() && !strcmp(drv->format_name, "file") && bs->open_flags & BDRV_O_RDWR) {
4222+
if (snapshot_flags) {
4223+
error_setg(errp, "Syx snapshots should not be used with any QEMU snapshot option");
4224+
goto close_and_fail;
4225+
}
4226+
4227+
scc_options = qdict_new();
4228+
bdrv_syx_cow_cache_options(&scc_flags, scc_options,
4229+
flags, options);
4230+
4231+
// qdict_put_bool(options, BDRV_OPT_READ_ONLY, true);
4232+
// bs->open_flags &= ~BDRV_O_RDWR;
4233+
4234+
attach_syx_continue = true;
4235+
}
4236+
//// --- End LibAFL code ---
4237+
41554238
/* Open the image */
41564239
ret = bdrv_open_common(bs, file, options, &local_err);
41574240
if (ret < 0) {
@@ -4221,6 +4304,17 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
42214304
bs = snapshot_bs;
42224305
}
42234306

4307+
if (attach_syx_continue) {
4308+
BlockDriverState* scc_bs;
4309+
scc_bs = bdrv_append_syx_cow_cache(bs, scc_flags, scc_options, &local_err);
4310+
scc_options = NULL;
4311+
if (local_err) {
4312+
goto close_and_fail;
4313+
}
4314+
bdrv_unref(bs);
4315+
bs = scc_bs;
4316+
}
4317+
42244318
return bs;
42254319

42264320
fail:

block/block-backend.c

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@
2828
#include "trace.h"
2929
#include "migration/misc.h"
3030

31-
//// --- Begin LibAFL code ---
32-
#ifdef CONFIG_SOFTMMU
33-
#include "libafl/syx-snapshot/syx-snapshot.h"
34-
#endif
35-
//// --- End LibAFL code ---
36-
3731
/* Number of coroutines to reserve per attached device model */
3832
#define COROUTINE_POOL_RESERVATION 64
3933

@@ -48,9 +42,6 @@ typedef struct BlockBackendAioNotifier {
4842

4943
struct BlockBackend {
5044
char *name;
51-
//// --- Begin LibAFL code ---
52-
guint name_hash;
53-
//// --- End LibAFL code ---
5445
int refcnt;
5546
BdrvChild *root;
5647
AioContext *ctx; /* access with atomic operations only */
@@ -705,12 +696,6 @@ bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
705696
error_setg(errp, "Device with id '%s' already exists", name);
706697
return false;
707698
}
708-
//// --- Begin LibAFL code ---
709-
if (blk_by_name_hash(g_str_hash(name))) {
710-
error_setg(errp, "Device with name hash '%x' already exists", g_str_hash(name));
711-
return false;
712-
}
713-
//// --- End LibAFL code ---
714699
if (bdrv_find_node(name)) {
715700
error_setg(errp,
716701
"Device name '%s' conflicts with an existing node name",
@@ -719,9 +704,6 @@ bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
719704
}
720705

721706
blk->name = g_strdup(name);
722-
//// --- Begin LibAFL code ---
723-
blk->name_hash = g_str_hash(blk->name);
724-
//// --- End LibAFL code ---
725707
QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
726708
return true;
727709
}
@@ -753,14 +735,6 @@ const char *blk_name(const BlockBackend *blk)
753735
return blk->name ?: "";
754736
}
755737

756-
//// --- Begin LibAFL code ---
757-
guint blk_name_hash(const BlockBackend* blk)
758-
{
759-
IO_CODE();
760-
return blk->name_hash;
761-
}
762-
//// --- End LibAFL code ---
763-
764738
/*
765739
* Return the BlockBackend with name @name if it exists, else null.
766740
* @name must not be null.
@@ -779,22 +753,6 @@ BlockBackend *blk_by_name(const char *name)
779753
return NULL;
780754
}
781755

782-
/*
783-
* Return the BlockBackend with name hash @name_hash if it exists, else null.
784-
*/
785-
BlockBackend *blk_by_name_hash(guint name_hash)
786-
{
787-
BlockBackend *blk = NULL;
788-
789-
GLOBAL_STATE_CODE();
790-
while ((blk = blk_next(blk)) != NULL) {
791-
if (name_hash == blk->name_hash) {
792-
return blk;
793-
}
794-
}
795-
return NULL;
796-
}
797-
798756
/*
799757
* Return the BlockDriverState attached to @blk if any, else null.
800758
*/
@@ -1648,21 +1606,8 @@ static void coroutine_fn blk_aio_read_entry(void *opaque)
16481606

16491607
assert(qiov->size == acb->bytes);
16501608

1651-
//// --- Begin LibAFL code ---
1652-
#ifdef CONFIG_SOFTMMU
1653-
if (!syx_snapshot_cow_cache_read_entry(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags)) {
1654-
#endif
1655-
//// --- End LibAFL code ---
1656-
rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov,
1657-
0, rwco->flags);
1658-
//// --- Begin LibAFL code ---
1659-
#ifdef CONFIG_SOFTMMU
1660-
} else {
1661-
rwco->ret = 0;
1662-
}
1663-
#endif
1664-
//// --- End LibAFL code ---
1665-
1609+
rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov,
1610+
0, rwco->flags);
16661611
blk_aio_complete(acb);
16671612
}
16681613

@@ -1674,19 +1619,7 @@ static void coroutine_fn blk_aio_write_entry(void *opaque)
16741619

16751620
assert(!qiov || qiov->size == acb->bytes);
16761621

1677-
//// --- Begin LibAFL code ---
1678-
#ifdef CONFIG_SOFTMMU
1679-
if (!syx_snapshot_cow_cache_write_entry(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags)) {
1680-
#endif
1681-
//// --- End LibAFL code ---
1682-
rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags);
1683-
//// --- Begin LibAFL code ---
1684-
#ifdef CONFIG_SOFTMMU
1685-
} else {
1686-
rwco->ret = 0;
1687-
}
1688-
#endif
1689-
//// --- End LibAFL code ---
1622+
rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags);
16901623

16911624
blk_aio_complete(acb);
16921625
}

include/block/block-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ typedef enum {
226226
writes in a snapshot */
227227
#define BDRV_O_TEMPORARY 0x0010 /* delete the file after use */
228228
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
229+
#define BDRV_O_NOSYX 0x0040
229230
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the
230231
thread pool */
231232
#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */

include/libafl/exit.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,22 @@ struct libafl_exit_reason_breakpoint {
3636
};
3737

3838
// A synchronous exit has been triggered.
39-
struct libafl_exit_reason_sync_exit {};
39+
struct libafl_exit_reason_sync_exit {
40+
};
4041

4142
// A timeout occured and we were asked to exit on timeout
42-
struct libafl_exit_reason_timeout {};
43+
struct libafl_exit_reason_timeout {
44+
};
4345

4446
struct libafl_exit_reason {
4547
enum libafl_exit_reason_kind kind;
4648
CPUState* cpu; // CPU that triggered an exit.
4749
vaddr next_pc; // The PC that should be stored in the CPU when re-entering.
4850
union {
49-
struct libafl_exit_reason_internal internal; // kind == INTERNAL
50-
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
51-
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
52-
struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT
51+
struct libafl_exit_reason_internal internal; // kind == INTERNAL
52+
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
53+
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
54+
struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT
5355
} data;
5456
};
5557

include/libafl/syx-snapshot/syx-cow-cache.h

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
#define INITIAL_NB_CHUNKS_PER_DEVICE (1024 * 64)
1212

1313
typedef struct SyxCowCacheDevice {
14-
GArray* data;
15-
GHashTable* positions; // blk_offset -> data_position
14+
GArray* data; // [u8]
15+
GHashTable* positions; // blkdev offset (must be aligned on chunk_size) ->
16+
// data offset
1617
} SyxCowCacheDevice;
1718

18-
typedef struct SyxCowCacheLayer SyxCowCacheLayer;
19-
2019
typedef struct SyxCowCacheLayer {
21-
GHashTable* cow_cache_devices; // H(device) -> SyxCowCacheDevice
20+
GArray* blks; // [SyxCowCacheDevice]
21+
2222
uint64_t chunk_size;
2323
uint64_t max_nb_chunks;
2424

@@ -31,21 +31,15 @@ typedef struct SyxCowCache {
3131

3232
SyxCowCache* syx_cow_cache_new(void);
3333

34-
// lhs <- rhs
35-
// rhs is freed and nulled.
36-
void syx_cow_cache_move(SyxCowCache* lhs, SyxCowCache** rhs);
34+
// Returns a SyxCowCache with a new layer on top.
35+
// Other layers from scc are still present.
36+
SyxCowCache* syx_cow_cache_push(SyxCowCache* scc, uint64_t chunk_size,
37+
uint64_t max_size);
3738

38-
void syx_cow_cache_push_layer(SyxCowCache* scc, uint64_t chunk_size,
39-
uint64_t max_size);
40-
void syx_cow_cache_pop_layer(SyxCowCache* scc);
39+
void syx_cow_cache_pop(SyxCowCache* scc);
4140

42-
void syx_cow_cache_flush_highest_layer(SyxCowCache* scc);
41+
// void syx_cow_cache_pop_layer(SyxCowCache* scc);
4342

44-
void syx_cow_cache_read_entry(SyxCowCache* scc, BlockBackend* blk,
45-
int64_t offset, int64_t bytes, QEMUIOVector* qiov,
46-
size_t qiov_offset, BdrvRequestFlags flags);
43+
void syx_cow_cache_flush_highest_layer(SyxCowCache* scc);
4744

48-
bool syx_cow_cache_write_entry(SyxCowCache* scc, BlockBackend* blk,
49-
int64_t offset, int64_t bytes,
50-
QEMUIOVector* qiov, size_t qiov_offset,
51-
BdrvRequestFlags flags);
45+
void syx_cow_cache_check_files_ro(void);

0 commit comments

Comments
 (0)