diff mbox series

[RFC,06/19] fuzz: Add ramfile for fast vmstate/vmload

Message ID 20190725032321.12721-7-alxndr@bu.edu (mailing list archive)
State New, archived
Headers show
Series Add virtual device fuzzing support | expand

Commit Message

Alexander Bulekov July 25, 2019, 3:23 a.m. UTC
The ramfile allows vmstate to be saved and restored directly onto the
heap.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/ramfile.c | 127 +++++++++++++++++++++++++++++++++++++++++++
 tests/fuzz/ramfile.h |  20 +++++++
 2 files changed, 147 insertions(+)
 create mode 100644 tests/fuzz/ramfile.c
 create mode 100644 tests/fuzz/ramfile.h

Comments

Stefan Hajnoczi July 26, 2019, 12:47 p.m. UTC | #1
On Thu, Jul 25, 2019 at 03:23:49AM +0000, Oleinik, Alexander wrote:
> The ramfile allows vmstate to be saved and restored directly onto the
> heap.
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  tests/fuzz/ramfile.c | 127 +++++++++++++++++++++++++++++++++++++++++++
>  tests/fuzz/ramfile.h |  20 +++++++
>  2 files changed, 147 insertions(+)
>  create mode 100644 tests/fuzz/ramfile.c
>  create mode 100644 tests/fuzz/ramfile.h
> 
> diff --git a/tests/fuzz/ramfile.c b/tests/fuzz/ramfile.c
> new file mode 100644
> index 0000000000..8da242e9ee
> --- /dev/null
> +++ b/tests/fuzz/ramfile.c

Please put this in migration/.  This code doesn't do fuzzing and is
general-purpose enough to be used by other parts of QEMU dealing with
live migration.

> @@ -0,0 +1,127 @@
> +/*
> + * =====================================================================================
> + *
> + *       Filename:  ramfile.c
> + *
> + *    Description:  QEMUFile stored in dynamically allocated RAM for fast VMRestore
> + *
> + *         Author:  Alexander Oleinik (), alxndr@bu.edu
> + *   Organization:  
> + *
> + * =====================================================================================
> + */

Please use license headers with all new files that are created.
Fine-grained filename and authorship information is already kept by git
so it's not necessary to duplicate it here.

> +#include <stdlib.h>
> +#include "qemu/osdep.h"

osdep.h already includes stdlib.h.

> +#include "qemu-common.h"
> +#include "exec/memory.h"
> +#include "migration/qemu-file.h"
> +#include "migration/migration.h"
> +#include "migration/savevm.h"
> +#include "ramfile.h"
> +
> +#define INCREMENT 10240
> +#define IO_BUF_SIZE 32768
> +#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
> +
> +struct QEMUFile {
> +    const QEMUFileOps *ops;
> +    const QEMUFileHooks *hooks;
> +    void *opaque;
> +
> +    int64_t bytes_xfer;
> +    int64_t xfer_limit;
> +
> +    int64_t pos; /* start of buffer when writing, end of buffer
> +                    when reading */
> +    int buf_index;
> +    int buf_size; /* 0 when writing */
> +    uint8_t buf[IO_BUF_SIZE];
> +
> +    DECLARE_BITMAP(may_free, MAX_IOV_SIZE);
> +    struct iovec iov[MAX_IOV_SIZE];
> +    unsigned int iovcnt;
> +
> +    int last_error;
> +};

Wait, what?! :)

Please add the ram file to qemu-file.c instead of duplicating QEMUFile.
Alexander Bulekov July 26, 2019, 7:36 p.m. UTC | #2
On 7/26/19 8:47 AM, Stefan Hajnoczi wrote:
> On Thu, Jul 25, 2019 at 03:23:49AM +0000, Oleinik, Alexander wrote:
>> The ramfile allows vmstate to be saved and restored directly onto the
>> heap.
>>
>> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
>> ---
>>   tests/fuzz/ramfile.c | 127 +++++++++++++++++++++++++++++++++++++++++++
>>   tests/fuzz/ramfile.h |  20 +++++++
>>   2 files changed, 147 insertions(+)
>>   create mode 100644 tests/fuzz/ramfile.c
>>   create mode 100644 tests/fuzz/ramfile.h
>>
>> diff --git a/tests/fuzz/ramfile.c b/tests/fuzz/ramfile.c
>> new file mode 100644
>> index 0000000000..8da242e9ee
>> --- /dev/null
>> +++ b/tests/fuzz/ramfile.c
> 
> Please put this in migration/.  This code doesn't do fuzzing and is
> general-purpose enough to be used by other parts of QEMU dealing with
> live migration.
> 
>> @@ -0,0 +1,127 @@
>> +/*
>> + * =====================================================================================
>> + *
>> + *       Filename:  ramfile.c
>> + *
>> + *    Description:  QEMUFile stored in dynamically allocated RAM for fast VMRestore
>> + *
>> + *         Author:  Alexander Oleinik (), alxndr@bu.edu
>> + *   Organization:
>> + *
>> + * =====================================================================================
>> + */
> 
> Please use license headers with all new files that are created.
> Fine-grained filename and authorship information is already kept by git
> so it's not necessary to duplicate it here.
> 
>> +#include <stdlib.h>
>> +#include "qemu/osdep.h"
> 
> osdep.h already includes stdlib.h.
> 
>> +#include "qemu-common.h"
>> +#include "exec/memory.h"
>> +#include "migration/qemu-file.h"
>> +#include "migration/migration.h"
>> +#include "migration/savevm.h"
>> +#include "ramfile.h"
>> +
>> +#define INCREMENT 10240
>> +#define IO_BUF_SIZE 32768
>> +#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
>> +
>> +struct QEMUFile {
>> +    const QEMUFileOps *ops;
>> +    const QEMUFileHooks *hooks;
>> +    void *opaque;
>> +
>> +    int64_t bytes_xfer;
>> +    int64_t xfer_limit;
>> +
>> +    int64_t pos; /* start of buffer when writing, end of buffer
>> +                    when reading */
>> +    int buf_index;
>> +    int buf_size; /* 0 when writing */
>> +    uint8_t buf[IO_BUF_SIZE];
>> +
>> +    DECLARE_BITMAP(may_free, MAX_IOV_SIZE);
>> +    struct iovec iov[MAX_IOV_SIZE];
>> +    unsigned int iovcnt;
>> +
>> +    int last_error;
>> +};
> 
> Wait, what?! :)
> 
> Please add the ram file to qemu-file.c instead of duplicating QEMUFile.
> 
I think we should be able to replace all of this simply by using 
memfd_create. Since it acts as a regular file, it will work with the 
existing code (likely with performance gains).
Paolo Bonzini July 26, 2019, 7:54 p.m. UTC | #3
On 26/07/19 21:36, Oleinik, Alexander wrote:
>>
>> Please add the ram file to qemu-file.c instead of duplicating QEMUFile.
>>
> I think we should be able to replace all of this simply by using 
> memfd_create. Since it acts as a regular file, it will work with the 
> existing code (likely with performance gains).

That wouldn't be portable to non-Linux, so having RAMFile is better.

Paolo
diff mbox series

Patch

diff --git a/tests/fuzz/ramfile.c b/tests/fuzz/ramfile.c
new file mode 100644
index 0000000000..8da242e9ee
--- /dev/null
+++ b/tests/fuzz/ramfile.c
@@ -0,0 +1,127 @@ 
+/*
+ * =====================================================================================
+ *
+ *       Filename:  ramfile.c
+ *
+ *    Description:  QEMUFile stored in dynamically allocated RAM for fast VMRestore
+ *
+ *         Author:  Alexander Oleinik (), alxndr@bu.edu
+ *   Organization:  
+ *
+ * =====================================================================================
+ */
+#include <stdlib.h>
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/memory.h"
+#include "migration/qemu-file.h"
+#include "migration/migration.h"
+#include "migration/savevm.h"
+#include "ramfile.h"
+
+#define INCREMENT 10240
+#define IO_BUF_SIZE 32768
+#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
+
+struct QEMUFile {
+    const QEMUFileOps *ops;
+    const QEMUFileHooks *hooks;
+    void *opaque;
+
+    int64_t bytes_xfer;
+    int64_t xfer_limit;
+
+    int64_t pos; /* start of buffer when writing, end of buffer
+                    when reading */
+    int buf_index;
+    int buf_size; /* 0 when writing */
+    uint8_t buf[IO_BUF_SIZE];
+
+    DECLARE_BITMAP(may_free, MAX_IOV_SIZE);
+    struct iovec iov[MAX_IOV_SIZE];
+    unsigned int iovcnt;
+
+    int last_error;
+};
+
+static ssize_t ram_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
+                                  int64_t pos)
+{
+	ram_disk *rd = (ram_disk*)opaque;
+	gsize newsize;
+	ssize_t total_size = 0;
+	int i;
+	if(!rd->base) {
+		rd->base = g_malloc(INCREMENT);
+		rd->len = INCREMENT;
+	}
+	for(i = 0; i< iovcnt; i++)
+	{
+		if(pos+iov[i].iov_len >= rd->len ){
+			newsize = ((pos + iov[i].iov_len)/INCREMENT + 1) * INCREMENT;
+			rd->base = g_realloc(rd->base, newsize);
+			rd->len = newsize;
+		}
+		/* for(int j =0; j<iov[i].iov_len; j++){ */
+		/* 	printf("%hhx",*((char*)iov[i].iov_base+j)); */
+		/* } */
+		memcpy(rd->base + pos, iov[i].iov_base, iov[i].iov_len);
+		pos += iov[i].iov_len;
+		total_size += iov[i].iov_len;
+	}
+	return total_size;
+}
+
+static ssize_t ram_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
+                                   size_t size)
+{
+	ram_disk *rd = (ram_disk*)opaque;
+	if(pos+size>rd->len){
+		if(rd->len-pos>=0){
+			memcpy(buf, rd->base + pos, rd->len-pos);
+			size = rd->len-pos;
+		}
+	}
+	else
+		memcpy(buf, rd->base + pos, size);
+	return size;
+}
+
+static int ram_fclose(void *opaque)
+{
+	return 0;
+}
+
+static const QEMUFileOps ram_read_ops = {
+    .get_buffer = ram_get_buffer,
+    .close =      ram_fclose
+};
+
+static const QEMUFileOps ram_write_ops = {
+    .writev_buffer = ram_writev_buffer,
+    .close =      ram_fclose
+};
+
+QEMUFile *qemu_fopen_ram(ram_disk **return_rd) {
+	ram_disk *rd = g_new0(ram_disk, 1);
+	*return_rd=rd;
+	return qemu_fopen_ops(rd, &ram_write_ops);
+}
+
+QEMUFile *qemu_fopen_ro_ram(ram_disk* rd) {
+    return qemu_fopen_ops(rd, &ram_read_ops);
+}
+
+void qemu_freopen_ro_ram(QEMUFile* f) {
+	void *rd = f->opaque;
+	f->bytes_xfer=0;
+	f->xfer_limit=0;
+	f->last_error=0;
+	f->iovcnt=0;
+	f->buf_index=0;
+	f->buf_size=0;
+	f->pos=0;
+	f->ops = &ram_read_ops;
+	f->opaque = rd;
+	return;
+}
diff --git a/tests/fuzz/ramfile.h b/tests/fuzz/ramfile.h
new file mode 100644
index 0000000000..b51cc72950
--- /dev/null
+++ b/tests/fuzz/ramfile.h
@@ -0,0 +1,20 @@ 
+#ifndef RAMFILE_H
+#define RAMFILE_H
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "migration/qemu-file.h"
+
+typedef struct ram_disk {
+	void *base;
+	gsize len;
+} ram_disk;
+
+QEMUFile *qemu_fopen_ram(ram_disk **rd);
+QEMUFile *qemu_fopen_ro_ram(ram_disk* rd);
+void qemu_freopen_ro_ram(QEMUFile* f);
+
+#endif