]>
Commit | Line | Data |
---|---|---|
abc9e57f WB |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Mon, 4 May 2020 11:05:08 +0200 | |
817b7667 | 4 | Subject: [PATCH] PVE: add optional buffer size to QEMUFile |
abc9e57f WB |
5 | |
6 | So we can use a 4M buffer for savevm-async which should | |
7 | increase performance storing the state onto ceph. | |
8 | ||
9 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
817b7667 SR |
10 | [increase max IOV count in QEMUFile to actually write more data] |
11 | Signed-off-by: Stefan Reiter <s.reiter@proxmox.com> | |
ddbf7a87 | 12 | Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com> |
5b15e2ec FE |
13 | [FE: adapt to removal of QEMUFileOps] |
14 | Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> | |
abc9e57f | 15 | --- |
5b15e2ec FE |
16 | migration/qemu-file.c | 49 +++++++++++++++++++++++++++------------- |
17 | migration/qemu-file.h | 2 ++ | |
18 | migration/savevm-async.c | 5 ++-- | |
19 | 3 files changed, 38 insertions(+), 18 deletions(-) | |
abc9e57f WB |
20 | |
21 | diff --git a/migration/qemu-file.c b/migration/qemu-file.c | |
d03e1b3c | 22 | index 2d5f74ffc2..9fd97e6fe1 100644 |
abc9e57f WB |
23 | --- a/migration/qemu-file.c |
24 | +++ b/migration/qemu-file.c | |
dc9827a6 | 25 | @@ -31,8 +31,8 @@ |
abc9e57f WB |
26 | #include "trace.h" |
27 | #include "qapi/error.h" | |
28 | ||
29 | -#define IO_BUF_SIZE 32768 | |
817b7667 | 30 | -#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64) |
abc9e57f | 31 | +#define DEFAULT_IO_BUF_SIZE 32768 |
817b7667 | 32 | +#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 256) |
abc9e57f WB |
33 | |
34 | struct QEMUFile { | |
5b15e2ec FE |
35 | const QEMUFileHooks *hooks; |
36 | @@ -55,7 +55,8 @@ struct QEMUFile { | |
37 | ||
abc9e57f WB |
38 | int buf_index; |
39 | int buf_size; /* 0 when writing */ | |
40 | - uint8_t buf[IO_BUF_SIZE]; | |
41 | + size_t buf_allocated_size; | |
42 | + uint8_t *buf; | |
43 | ||
44 | DECLARE_BITMAP(may_free, MAX_IOV_SIZE); | |
45 | struct iovec iov[MAX_IOV_SIZE]; | |
d03e1b3c | 46 | @@ -127,7 +128,9 @@ bool qemu_file_mode_is_not_valid(const char *mode) |
abc9e57f WB |
47 | return false; |
48 | } | |
49 | ||
5b15e2ec FE |
50 | -static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable) |
51 | +static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, | |
52 | + bool is_writable, | |
53 | + size_t buffer_size) | |
abc9e57f WB |
54 | { |
55 | QEMUFile *f; | |
56 | ||
d03e1b3c | 57 | @@ -136,6 +139,8 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable) |
5b15e2ec FE |
58 | object_ref(ioc); |
59 | f->ioc = ioc; | |
60 | f->is_writable = is_writable; | |
abc9e57f WB |
61 | + f->buf_allocated_size = buffer_size; |
62 | + f->buf = malloc(buffer_size); | |
5b15e2ec | 63 | |
abc9e57f WB |
64 | return f; |
65 | } | |
d03e1b3c | 66 | @@ -146,17 +151,27 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable) |
5b15e2ec FE |
67 | */ |
68 | QEMUFile *qemu_file_get_return_path(QEMUFile *f) | |
69 | { | |
70 | - return qemu_file_new_impl(f->ioc, !f->is_writable); | |
71 | + return qemu_file_new_impl(f->ioc, !f->is_writable, DEFAULT_IO_BUF_SIZE); | |
72 | } | |
abc9e57f | 73 | |
5b15e2ec FE |
74 | QEMUFile *qemu_file_new_output(QIOChannel *ioc) |
75 | { | |
76 | - return qemu_file_new_impl(ioc, true); | |
77 | + return qemu_file_new_impl(ioc, true, DEFAULT_IO_BUF_SIZE); | |
78 | +} | |
79 | + | |
80 | +QEMUFile *qemu_file_new_output_sized(QIOChannel *ioc, size_t buffer_size) | |
abc9e57f | 81 | +{ |
5b15e2ec FE |
82 | + return qemu_file_new_impl(ioc, true, buffer_size); |
83 | } | |
84 | ||
85 | QEMUFile *qemu_file_new_input(QIOChannel *ioc) | |
86 | { | |
87 | - return qemu_file_new_impl(ioc, false); | |
88 | + return qemu_file_new_impl(ioc, false, DEFAULT_IO_BUF_SIZE); | |
abc9e57f WB |
89 | +} |
90 | + | |
5b15e2ec FE |
91 | +QEMUFile *qemu_file_new_input_sized(QIOChannel *ioc, size_t buffer_size) |
92 | +{ | |
93 | + return qemu_file_new_impl(ioc, false, buffer_size); | |
94 | } | |
abc9e57f WB |
95 | |
96 | void qemu_file_set_hooks(QEMUFile *f, const QEMUFileHooks *hooks) | |
d03e1b3c | 97 | @@ -414,7 +429,7 @@ static ssize_t qemu_fill_buffer(QEMUFile *f) |
5b15e2ec FE |
98 | do { |
99 | len = qio_channel_read(f->ioc, | |
100 | (char *)f->buf + pending, | |
101 | - IO_BUF_SIZE - pending, | |
102 | + f->buf_allocated_size - pending, | |
103 | &local_error); | |
104 | if (len == QIO_CHANNEL_ERR_BLOCK) { | |
105 | if (qemu_in_coroutine()) { | |
d03e1b3c | 106 | @@ -464,6 +479,8 @@ int qemu_fclose(QEMUFile *f) |
abc9e57f | 107 | } |
5b15e2ec | 108 | g_clear_pointer(&f->ioc, object_unref); |
abc9e57f | 109 | |
abc9e57f WB |
110 | + free(f->buf); |
111 | + | |
112 | /* If any error was spotted before closing, we should report it | |
113 | * instead of the close() return value. | |
114 | */ | |
d03e1b3c | 115 | @@ -518,7 +535,7 @@ static void add_buf_to_iovec(QEMUFile *f, size_t len) |
abc9e57f WB |
116 | { |
117 | if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) { | |
118 | f->buf_index += len; | |
119 | - if (f->buf_index == IO_BUF_SIZE) { | |
120 | + if (f->buf_index == f->buf_allocated_size) { | |
121 | qemu_fflush(f); | |
122 | } | |
123 | } | |
d03e1b3c | 124 | @@ -544,7 +561,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) |
abc9e57f WB |
125 | } |
126 | ||
127 | while (size > 0) { | |
128 | - l = IO_BUF_SIZE - f->buf_index; | |
129 | + l = f->buf_allocated_size - f->buf_index; | |
130 | if (l > size) { | |
131 | l = size; | |
132 | } | |
d03e1b3c | 133 | @@ -591,8 +608,8 @@ size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset) |
abc9e57f WB |
134 | size_t index; |
135 | ||
136 | assert(!qemu_file_is_writable(f)); | |
137 | - assert(offset < IO_BUF_SIZE); | |
138 | - assert(size <= IO_BUF_SIZE - offset); | |
139 | + assert(offset < f->buf_allocated_size); | |
140 | + assert(size <= f->buf_allocated_size - offset); | |
141 | ||
142 | /* The 1st byte to read from */ | |
143 | index = f->buf_index + offset; | |
d03e1b3c | 144 | @@ -642,7 +659,7 @@ size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size) |
abc9e57f WB |
145 | size_t res; |
146 | uint8_t *src; | |
147 | ||
148 | - res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0); | |
149 | + res = qemu_peek_buffer(f, &src, MIN(pending, f->buf_allocated_size), 0); | |
150 | if (res == 0) { | |
151 | return done; | |
152 | } | |
d03e1b3c | 153 | @@ -676,7 +693,7 @@ size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size) |
abc9e57f WB |
154 | */ |
155 | size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size) | |
156 | { | |
157 | - if (size < IO_BUF_SIZE) { | |
158 | + if (size < f->buf_allocated_size) { | |
159 | size_t res; | |
8dca018b | 160 | uint8_t *src = NULL; |
abc9e57f | 161 | |
d03e1b3c | 162 | @@ -701,7 +718,7 @@ int qemu_peek_byte(QEMUFile *f, int offset) |
abc9e57f WB |
163 | int index = f->buf_index + offset; |
164 | ||
165 | assert(!qemu_file_is_writable(f)); | |
166 | - assert(offset < IO_BUF_SIZE); | |
167 | + assert(offset < f->buf_allocated_size); | |
168 | ||
169 | if (index >= f->buf_size) { | |
170 | qemu_fill_buffer(f); | |
d03e1b3c | 171 | @@ -853,7 +870,7 @@ static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len, |
abc9e57f WB |
172 | ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream, |
173 | const uint8_t *p, size_t size) | |
174 | { | |
175 | - ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t); | |
176 | + ssize_t blen = f->buf_allocated_size - f->buf_index - sizeof(int32_t); | |
177 | ||
178 | if (blen < compressBound(size)) { | |
179 | return -1; | |
180 | diff --git a/migration/qemu-file.h b/migration/qemu-file.h | |
5b15e2ec | 181 | index fa13d04d78..914f1a63a8 100644 |
abc9e57f WB |
182 | --- a/migration/qemu-file.h |
183 | +++ b/migration/qemu-file.h | |
5b15e2ec | 184 | @@ -63,7 +63,9 @@ typedef struct QEMUFileHooks { |
abc9e57f WB |
185 | } QEMUFileHooks; |
186 | ||
5b15e2ec FE |
187 | QEMUFile *qemu_file_new_input(QIOChannel *ioc); |
188 | +QEMUFile *qemu_file_new_input_sized(QIOChannel *ioc, size_t buffer_size); | |
189 | QEMUFile *qemu_file_new_output(QIOChannel *ioc); | |
190 | +QEMUFile *qemu_file_new_output_sized(QIOChannel *ioc, size_t buffer_size); | |
abc9e57f | 191 | void qemu_file_set_hooks(QEMUFile *f, const QEMUFileHooks *hooks); |
abc9e57f | 192 | int qemu_fclose(QEMUFile *f); |
5b15e2ec | 193 | |
817b7667 | 194 | diff --git a/migration/savevm-async.c b/migration/savevm-async.c |
eee064d9 | 195 | index dc30558713..a38e7351c1 100644 |
817b7667 SR |
196 | --- a/migration/savevm-async.c |
197 | +++ b/migration/savevm-async.c | |
eee064d9 | 198 | @@ -374,7 +374,7 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp) |
abc9e57f | 199 | |
5b15e2ec FE |
200 | QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target, |
201 | &snap_state.bs_pos)); | |
202 | - snap_state.file = qemu_file_new_output(ioc); | |
203 | + snap_state.file = qemu_file_new_output_sized(ioc, 4 * 1024 * 1024); | |
abc9e57f WB |
204 | |
205 | if (!snap_state.file) { | |
206 | error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile); | |
eee064d9 | 207 | @@ -507,7 +507,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp) |
abc9e57f WB |
208 | blk_op_block_all(be, blocker); |
209 | ||
210 | /* restore the VM state */ | |
5b15e2ec FE |
211 | - f = qemu_file_new_input(QIO_CHANNEL(qio_channel_savevm_async_new(be, &bs_pos))); |
212 | + f = qemu_file_new_input_sized(QIO_CHANNEL(qio_channel_savevm_async_new(be, &bs_pos)), | |
213 | + 4 * 1024 * 1024); | |
abc9e57f WB |
214 | if (!f) { |
215 | error_setg(errp, "Could not open VM state file"); | |
216 | goto the_end; |