]> git.proxmox.com Git - mirror_qemu.git/blame - migration/qemu-file-unix.c
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20160311.0' into...
[mirror_qemu.git] / migration / qemu-file-unix.c
CommitLineData
bee223ba
EH
1/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
1393a485 24#include "qemu/osdep.h"
bee223ba 25#include "qemu-common.h"
3e4097b5 26#include "qemu/error-report.h"
bee223ba
EH
27#include "qemu/iov.h"
28#include "qemu/sockets.h"
10817bf0 29#include "qemu/coroutine.h"
bee223ba 30#include "migration/qemu-file.h"
e1a8c9b6 31#include "migration/qemu-file-internal.h"
bee223ba
EH
32
33typedef struct QEMUFileSocket {
34 int fd;
35 QEMUFile *file;
36} QEMUFileSocket;
37
38static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
39 int64_t pos)
40{
41 QEMUFileSocket *s = opaque;
42 ssize_t len;
43 ssize_t size = iov_size(iov, iovcnt);
3e4097b5
DDAG
44 ssize_t offset = 0;
45 int err;
bee223ba 46
3e4097b5
DDAG
47 while (size > 0) {
48 len = iov_send(s->fd, iov, iovcnt, offset, size);
49
50 if (len > 0) {
51 size -= len;
52 offset += len;
53 }
54
55 if (size > 0) {
b16a44e1 56 if (errno != EAGAIN && errno != EWOULDBLOCK) {
3e4097b5 57 error_report("socket_writev_buffer: Got err=%d for (%zu/%zu)",
b16a44e1 58 errno, (size_t)size, (size_t)len);
3e4097b5
DDAG
59 /*
60 * If I've already sent some but only just got the error, I
61 * could return the amount validly sent so far and wait for the
62 * next call to report the error, but I'd rather flag the error
63 * immediately.
64 */
b16a44e1 65 return -errno;
3e4097b5
DDAG
66 }
67
68 /* Emulate blocking */
69 GPollFD pfd;
70
71 pfd.fd = s->fd;
72 pfd.events = G_IO_OUT | G_IO_ERR;
73 pfd.revents = 0;
4e39f57c
MA
74 TFR(err = g_poll(&pfd, 1, -1 /* no timeout */));
75 /* Errors other than EINTR intentionally ignored */
3e4097b5
DDAG
76 }
77 }
78
79 return offset;
bee223ba
EH
80}
81
82static int socket_get_fd(void *opaque)
83{
84 QEMUFileSocket *s = opaque;
85
86 return s->fd;
87}
88
a202a4c0
DDAG
89static ssize_t socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
90 size_t size)
bee223ba
EH
91{
92 QEMUFileSocket *s = opaque;
93 ssize_t len;
94
95 for (;;) {
96 len = qemu_recv(s->fd, buf, size, 0);
97 if (len != -1) {
98 break;
99 }
b16a44e1 100 if (errno == EAGAIN) {
bee223ba 101 yield_until_fd_readable(s->fd);
b16a44e1 102 } else if (errno != EINTR) {
bee223ba
EH
103 break;
104 }
105 }
106
107 if (len == -1) {
b16a44e1 108 len = -errno;
bee223ba
EH
109 }
110 return len;
111}
112
113static int socket_close(void *opaque)
114{
115 QEMUFileSocket *s = opaque;
116 closesocket(s->fd);
117 g_free(s);
118 return 0;
119}
120
e1a8c9b6
DDAG
121static int socket_shutdown(void *opaque, bool rd, bool wr)
122{
123 QEMUFileSocket *s = opaque;
124
125 if (shutdown(s->fd, rd ? (wr ? SHUT_RDWR : SHUT_RD) : SHUT_WR)) {
126 return -errno;
127 } else {
128 return 0;
129 }
130}
131
adc468e9
DDAG
132static int socket_return_close(void *opaque)
133{
134 QEMUFileSocket *s = opaque;
135 /*
136 * Note: We don't close the socket, that should be done by the forward
137 * path.
138 */
139 g_free(s);
140 return 0;
141}
142
143static const QEMUFileOps socket_return_read_ops = {
144 .get_fd = socket_get_fd,
145 .get_buffer = socket_get_buffer,
146 .close = socket_return_close,
147 .shut_down = socket_shutdown,
148};
149
150static const QEMUFileOps socket_return_write_ops = {
151 .get_fd = socket_get_fd,
152 .writev_buffer = socket_writev_buffer,
153 .close = socket_return_close,
154 .shut_down = socket_shutdown,
155};
156
157/*
158 * Give a QEMUFile* off the same socket but data in the opposite
159 * direction.
160 */
161static QEMUFile *socket_get_return_path(void *opaque)
162{
163 QEMUFileSocket *forward = opaque;
164 QEMUFileSocket *reverse;
165
166 if (qemu_file_get_error(forward->file)) {
167 /* If the forward file is in error, don't try and open a return */
168 return NULL;
169 }
170
171 reverse = g_malloc0(sizeof(QEMUFileSocket));
172 reverse->fd = forward->fd;
173 /* I don't think there's a better way to tell which direction 'this' is */
174 if (forward->file->ops->get_buffer != NULL) {
175 /* being called from the read side, so we need to be able to write */
176 return qemu_fopen_ops(reverse, &socket_return_write_ops);
177 } else {
178 return qemu_fopen_ops(reverse, &socket_return_read_ops);
179 }
180}
181
bee223ba
EH
182static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
183 int64_t pos)
184{
185 QEMUFileSocket *s = opaque;
186 ssize_t len, offset;
187 ssize_t size = iov_size(iov, iovcnt);
188 ssize_t total = 0;
189
190 assert(iovcnt > 0);
191 offset = 0;
192 while (size > 0) {
193 /* Find the next start position; skip all full-sized vector elements */
194 while (offset >= iov[0].iov_len) {
195 offset -= iov[0].iov_len;
196 iov++, iovcnt--;
197 }
198
199 /* skip `offset' bytes from the (now) first element, undo it on exit */
200 assert(iovcnt > 0);
201 iov[0].iov_base += offset;
202 iov[0].iov_len -= offset;
203
204 do {
205 len = writev(s->fd, iov, iovcnt);
206 } while (len == -1 && errno == EINTR);
207 if (len == -1) {
208 return -errno;
209 }
210
211 /* Undo the changes above */
212 iov[0].iov_base -= offset;
213 iov[0].iov_len += offset;
214
215 /* Prepare for the next iteration */
216 offset += len;
217 total += len;
218 size -= len;
219 }
220
221 return total;
222}
223
a202a4c0
DDAG
224static ssize_t unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
225 size_t size)
bee223ba
EH
226{
227 QEMUFileSocket *s = opaque;
228 ssize_t len;
229
230 for (;;) {
231 len = read(s->fd, buf, size);
232 if (len != -1) {
233 break;
234 }
235 if (errno == EAGAIN) {
236 yield_until_fd_readable(s->fd);
237 } else if (errno != EINTR) {
238 break;
239 }
240 }
241
242 if (len == -1) {
243 len = -errno;
244 }
245 return len;
246}
247
248static int unix_close(void *opaque)
249{
250 QEMUFileSocket *s = opaque;
251 close(s->fd);
252 g_free(s);
253 return 0;
254}
255
256static const QEMUFileOps unix_read_ops = {
257 .get_fd = socket_get_fd,
258 .get_buffer = unix_get_buffer,
259 .close = unix_close
260};
261
262static const QEMUFileOps unix_write_ops = {
263 .get_fd = socket_get_fd,
264 .writev_buffer = unix_writev_buffer,
265 .close = unix_close
266};
267
268QEMUFile *qemu_fdopen(int fd, const char *mode)
269{
270 QEMUFileSocket *s;
271
272 if (mode == NULL ||
273 (mode[0] != 'r' && mode[0] != 'w') ||
274 mode[1] != 'b' || mode[2] != 0) {
275 fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
276 return NULL;
277 }
278
97f3ad35 279 s = g_new0(QEMUFileSocket, 1);
bee223ba
EH
280 s->fd = fd;
281
282 if (mode[0] == 'r') {
283 s->file = qemu_fopen_ops(s, &unix_read_ops);
284 } else {
285 s->file = qemu_fopen_ops(s, &unix_write_ops);
286 }
287 return s->file;
288}
289
290static const QEMUFileOps socket_read_ops = {
adc468e9
DDAG
291 .get_fd = socket_get_fd,
292 .get_buffer = socket_get_buffer,
293 .close = socket_close,
294 .shut_down = socket_shutdown,
295 .get_return_path = socket_get_return_path
bee223ba
EH
296};
297
298static const QEMUFileOps socket_write_ops = {
adc468e9
DDAG
299 .get_fd = socket_get_fd,
300 .writev_buffer = socket_writev_buffer,
301 .close = socket_close,
302 .shut_down = socket_shutdown,
303 .get_return_path = socket_get_return_path
bee223ba
EH
304};
305
306QEMUFile *qemu_fopen_socket(int fd, const char *mode)
307{
308 QEMUFileSocket *s;
309
310 if (qemu_file_mode_is_not_valid(mode)) {
311 return NULL;
312 }
313
97f3ad35 314 s = g_new0(QEMUFileSocket, 1);
bee223ba
EH
315 s->fd = fd;
316 if (mode[0] == 'w') {
317 qemu_set_block(s->fd);
318 s->file = qemu_fopen_ops(s, &socket_write_ops);
319 } else {
320 s->file = qemu_fopen_ops(s, &socket_read_ops);
321 }
322 return s->file;
323}