]>
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 | --- |
f1eed34a | 16 | migration/qemu-file.c | 50 +++++++++++++++++++++++++++------------- |
5b15e2ec FE |
17 | migration/qemu-file.h | 2 ++ |
18 | migration/savevm-async.c | 5 ++-- | |
f1eed34a | 19 | 3 files changed, 39 insertions(+), 18 deletions(-) |
abc9e57f WB |
20 | |
21 | diff --git a/migration/qemu-file.c b/migration/qemu-file.c | |
4fbd50e2 | 22 | index a10882d47f..19c1de0472 100644 |
abc9e57f WB |
23 | --- a/migration/qemu-file.c |
24 | +++ b/migration/qemu-file.c | |
4fbd50e2 | 25 | @@ -35,8 +35,8 @@ |
f1eed34a | 26 | #include "rdma.h" |
4fbd50e2 | 27 | #include "io/channel-file.h" |
abc9e57f WB |
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 { | |
f1eed34a | 35 | QIOChannel *ioc; |
4fbd50e2 | 36 | @@ -44,7 +44,8 @@ struct QEMUFile { |
5b15e2ec | 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]; | |
4fbd50e2 | 46 | @@ -101,7 +102,9 @@ int qemu_file_shutdown(QEMUFile *f) |
10e10933 | 47 | return 0; |
abc9e57f WB |
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 | ||
4fbd50e2 | 57 | @@ -110,6 +113,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 | } | |
4fbd50e2 | 66 | @@ -120,17 +125,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 | 95 | |
f1eed34a | 96 | /* |
4fbd50e2 | 97 | @@ -328,7 +343,7 @@ static ssize_t coroutine_mixed_fn 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()) { | |
4fbd50e2 | 106 | @@ -368,6 +383,9 @@ int qemu_fclose(QEMUFile *f) |
f1eed34a | 107 | ret = ret2; |
abc9e57f | 108 | } |
5b15e2ec | 109 | g_clear_pointer(&f->ioc, object_unref); |
f1eed34a | 110 | + |
abc9e57f WB |
111 | + free(f->buf); |
112 | + | |
f1eed34a FE |
113 | error_free(f->last_error_obj); |
114 | g_free(f); | |
115 | trace_qemu_file_fclose(); | |
4fbd50e2 | 116 | @@ -416,7 +434,7 @@ static void add_buf_to_iovec(QEMUFile *f, size_t len) |
abc9e57f WB |
117 | { |
118 | if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) { | |
119 | f->buf_index += len; | |
120 | - if (f->buf_index == IO_BUF_SIZE) { | |
121 | + if (f->buf_index == f->buf_allocated_size) { | |
122 | qemu_fflush(f); | |
123 | } | |
124 | } | |
4fbd50e2 | 125 | @@ -441,7 +459,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) |
abc9e57f WB |
126 | } |
127 | ||
128 | while (size > 0) { | |
129 | - l = IO_BUF_SIZE - f->buf_index; | |
130 | + l = f->buf_allocated_size - f->buf_index; | |
131 | if (l > size) { | |
132 | l = size; | |
133 | } | |
4fbd50e2 | 134 | @@ -587,8 +605,8 @@ size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t si |
abc9e57f WB |
135 | size_t index; |
136 | ||
137 | assert(!qemu_file_is_writable(f)); | |
138 | - assert(offset < IO_BUF_SIZE); | |
139 | - assert(size <= IO_BUF_SIZE - offset); | |
140 | + assert(offset < f->buf_allocated_size); | |
141 | + assert(size <= f->buf_allocated_size - offset); | |
142 | ||
143 | /* The 1st byte to read from */ | |
144 | index = f->buf_index + offset; | |
4fbd50e2 | 145 | @@ -638,7 +656,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size |
abc9e57f WB |
146 | size_t res; |
147 | uint8_t *src; | |
148 | ||
149 | - res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0); | |
150 | + res = qemu_peek_buffer(f, &src, MIN(pending, f->buf_allocated_size), 0); | |
151 | if (res == 0) { | |
152 | return done; | |
153 | } | |
4fbd50e2 | 154 | @@ -672,7 +690,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size |
abc9e57f | 155 | */ |
10e10933 | 156 | size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size) |
abc9e57f WB |
157 | { |
158 | - if (size < IO_BUF_SIZE) { | |
159 | + if (size < f->buf_allocated_size) { | |
160 | size_t res; | |
8dca018b | 161 | uint8_t *src = NULL; |
abc9e57f | 162 | |
4fbd50e2 | 163 | @@ -697,7 +715,7 @@ int coroutine_mixed_fn qemu_peek_byte(QEMUFile *f, int offset) |
abc9e57f WB |
164 | int index = f->buf_index + offset; |
165 | ||
166 | assert(!qemu_file_is_writable(f)); | |
167 | - assert(offset < IO_BUF_SIZE); | |
168 | + assert(offset < f->buf_allocated_size); | |
169 | ||
170 | if (index >= f->buf_size) { | |
171 | qemu_fill_buffer(f); | |
4fbd50e2 | 172 | @@ -811,7 +829,7 @@ static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len, |
abc9e57f WB |
173 | ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream, |
174 | const uint8_t *p, size_t size) | |
175 | { | |
176 | - ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t); | |
177 | + ssize_t blen = f->buf_allocated_size - f->buf_index - sizeof(int32_t); | |
178 | ||
179 | if (blen < compressBound(size)) { | |
180 | return -1; | |
181 | diff --git a/migration/qemu-file.h b/migration/qemu-file.h | |
4fbd50e2 | 182 | index 32fd4a34fd..36a0cd8cc8 100644 |
abc9e57f WB |
183 | --- a/migration/qemu-file.h |
184 | +++ b/migration/qemu-file.h | |
f1eed34a FE |
185 | @@ -30,7 +30,9 @@ |
186 | #include "io/channel.h" | |
abc9e57f | 187 | |
5b15e2ec FE |
188 | QEMUFile *qemu_file_new_input(QIOChannel *ioc); |
189 | +QEMUFile *qemu_file_new_input_sized(QIOChannel *ioc, size_t buffer_size); | |
190 | QEMUFile *qemu_file_new_output(QIOChannel *ioc); | |
191 | +QEMUFile *qemu_file_new_output_sized(QIOChannel *ioc, size_t buffer_size); | |
abc9e57f | 192 | int qemu_fclose(QEMUFile *f); |
5b15e2ec | 193 | |
f1eed34a | 194 | /* |
817b7667 | 195 | diff --git a/migration/savevm-async.c b/migration/savevm-async.c |
4fbd50e2 | 196 | index 779e4e2a78..bf36fc06d2 100644 |
817b7667 SR |
197 | --- a/migration/savevm-async.c |
198 | +++ b/migration/savevm-async.c | |
4fbd50e2 | 199 | @@ -379,7 +379,7 @@ void qmp_savevm_start(const char *statefile, Error **errp) |
abc9e57f | 200 | |
5b15e2ec FE |
201 | QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target, |
202 | &snap_state.bs_pos)); | |
203 | - snap_state.file = qemu_file_new_output(ioc); | |
204 | + snap_state.file = qemu_file_new_output_sized(ioc, 4 * 1024 * 1024); | |
abc9e57f WB |
205 | |
206 | if (!snap_state.file) { | |
207 | error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile); | |
4fbd50e2 | 208 | @@ -496,7 +496,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp) |
abc9e57f WB |
209 | blk_op_block_all(be, blocker); |
210 | ||
211 | /* restore the VM state */ | |
5b15e2ec FE |
212 | - f = qemu_file_new_input(QIO_CHANNEL(qio_channel_savevm_async_new(be, &bs_pos))); |
213 | + f = qemu_file_new_input_sized(QIO_CHANNEL(qio_channel_savevm_async_new(be, &bs_pos)), | |
214 | + 4 * 1024 * 1024); | |
abc9e57f WB |
215 | if (!f) { |
216 | error_setg(errp, "Could not open VM state file"); | |
217 | goto the_end; |