xref: /openbmc/qemu/io/channel.c (revision 37677d7d)
1 /*
2  * QEMU I/O channels
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "io/channel.h"
23 #include "qapi/error.h"
24 #include "qemu/main-loop.h"
25 #include "qemu/module.h"
26 #include "qemu/iov.h"
27 
28 bool qio_channel_has_feature(QIOChannel *ioc,
29                              QIOChannelFeature feature)
30 {
31     return ioc->features & (1 << feature);
32 }
33 
34 
35 void qio_channel_set_feature(QIOChannel *ioc,
36                              QIOChannelFeature feature)
37 {
38     ioc->features |= (1 << feature);
39 }
40 
41 
42 void qio_channel_set_name(QIOChannel *ioc,
43                           const char *name)
44 {
45     g_free(ioc->name);
46     ioc->name = g_strdup(name);
47 }
48 
49 
50 ssize_t qio_channel_readv_full(QIOChannel *ioc,
51                                const struct iovec *iov,
52                                size_t niov,
53                                int **fds,
54                                size_t *nfds,
55                                Error **errp)
56 {
57     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
58 
59     if ((fds || nfds) &&
60         !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
61         error_setg_errno(errp, EINVAL,
62                          "Channel does not support file descriptor passing");
63         return -1;
64     }
65 
66     return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
67 }
68 
69 
70 ssize_t qio_channel_writev_full(QIOChannel *ioc,
71                                 const struct iovec *iov,
72                                 size_t niov,
73                                 int *fds,
74                                 size_t nfds,
75                                 Error **errp)
76 {
77     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
78 
79     if ((fds || nfds) &&
80         !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
81         error_setg_errno(errp, EINVAL,
82                          "Channel does not support file descriptor passing");
83         return -1;
84     }
85 
86     return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
87 }
88 
89 
90 int qio_channel_readv_all_eof(QIOChannel *ioc,
91                               const struct iovec *iov,
92                               size_t niov,
93                               Error **errp)
94 {
95     int ret = -1;
96     struct iovec *local_iov = g_new(struct iovec, niov);
97     struct iovec *local_iov_head = local_iov;
98     unsigned int nlocal_iov = niov;
99     bool partial = false;
100 
101     nlocal_iov = iov_copy(local_iov, nlocal_iov,
102                           iov, niov,
103                           0, iov_size(iov, niov));
104 
105     while (nlocal_iov > 0) {
106         ssize_t len;
107         len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
108         if (len == QIO_CHANNEL_ERR_BLOCK) {
109             if (qemu_in_coroutine()) {
110                 qio_channel_yield(ioc, G_IO_IN);
111             } else {
112                 qio_channel_wait(ioc, G_IO_IN);
113             }
114             continue;
115         } else if (len < 0) {
116             goto cleanup;
117         } else if (len == 0) {
118             if (partial) {
119                 error_setg(errp,
120                            "Unexpected end-of-file before all bytes were read");
121             } else {
122                 ret = 0;
123             }
124             goto cleanup;
125         }
126 
127         partial = true;
128         iov_discard_front(&local_iov, &nlocal_iov, len);
129     }
130 
131     ret = 1;
132 
133  cleanup:
134     g_free(local_iov_head);
135     return ret;
136 }
137 
138 int qio_channel_readv_all(QIOChannel *ioc,
139                           const struct iovec *iov,
140                           size_t niov,
141                           Error **errp)
142 {
143     int ret = qio_channel_readv_all_eof(ioc, iov, niov, errp);
144 
145     if (ret == 0) {
146         ret = -1;
147         error_setg(errp,
148                    "Unexpected end-of-file before all bytes were read");
149     } else if (ret == 1) {
150         ret = 0;
151     }
152     return ret;
153 }
154 
155 int qio_channel_writev_all(QIOChannel *ioc,
156                            const struct iovec *iov,
157                            size_t niov,
158                            Error **errp)
159 {
160     int ret = -1;
161     struct iovec *local_iov = g_new(struct iovec, niov);
162     struct iovec *local_iov_head = local_iov;
163     unsigned int nlocal_iov = niov;
164 
165     nlocal_iov = iov_copy(local_iov, nlocal_iov,
166                           iov, niov,
167                           0, iov_size(iov, niov));
168 
169     while (nlocal_iov > 0) {
170         ssize_t len;
171         len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
172         if (len == QIO_CHANNEL_ERR_BLOCK) {
173             if (qemu_in_coroutine()) {
174                 qio_channel_yield(ioc, G_IO_OUT);
175             } else {
176                 qio_channel_wait(ioc, G_IO_OUT);
177             }
178             continue;
179         }
180         if (len < 0) {
181             goto cleanup;
182         }
183 
184         iov_discard_front(&local_iov, &nlocal_iov, len);
185     }
186 
187     ret = 0;
188  cleanup:
189     g_free(local_iov_head);
190     return ret;
191 }
192 
193 ssize_t qio_channel_readv(QIOChannel *ioc,
194                           const struct iovec *iov,
195                           size_t niov,
196                           Error **errp)
197 {
198     return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
199 }
200 
201 
202 ssize_t qio_channel_writev(QIOChannel *ioc,
203                            const struct iovec *iov,
204                            size_t niov,
205                            Error **errp)
206 {
207     return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
208 }
209 
210 
211 ssize_t qio_channel_read(QIOChannel *ioc,
212                          char *buf,
213                          size_t buflen,
214                          Error **errp)
215 {
216     struct iovec iov = { .iov_base = buf, .iov_len = buflen };
217     return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
218 }
219 
220 
221 ssize_t qio_channel_write(QIOChannel *ioc,
222                           const char *buf,
223                           size_t buflen,
224                           Error **errp)
225 {
226     struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
227     return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
228 }
229 
230 
231 int qio_channel_read_all_eof(QIOChannel *ioc,
232                              char *buf,
233                              size_t buflen,
234                              Error **errp)
235 {
236     struct iovec iov = { .iov_base = buf, .iov_len = buflen };
237     return qio_channel_readv_all_eof(ioc, &iov, 1, errp);
238 }
239 
240 
241 int qio_channel_read_all(QIOChannel *ioc,
242                          char *buf,
243                          size_t buflen,
244                          Error **errp)
245 {
246     struct iovec iov = { .iov_base = buf, .iov_len = buflen };
247     return qio_channel_readv_all(ioc, &iov, 1, errp);
248 }
249 
250 
251 int qio_channel_write_all(QIOChannel *ioc,
252                           const char *buf,
253                           size_t buflen,
254                           Error **errp)
255 {
256     struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
257     return qio_channel_writev_all(ioc, &iov, 1, errp);
258 }
259 
260 
261 int qio_channel_set_blocking(QIOChannel *ioc,
262                               bool enabled,
263                               Error **errp)
264 {
265     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
266     return klass->io_set_blocking(ioc, enabled, errp);
267 }
268 
269 
270 int qio_channel_close(QIOChannel *ioc,
271                       Error **errp)
272 {
273     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
274     return klass->io_close(ioc, errp);
275 }
276 
277 
278 GSource *qio_channel_create_watch(QIOChannel *ioc,
279                                   GIOCondition condition)
280 {
281     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
282     GSource *ret = klass->io_create_watch(ioc, condition);
283 
284     if (ioc->name) {
285         g_source_set_name(ret, ioc->name);
286     }
287 
288     return ret;
289 }
290 
291 
292 void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
293                                     AioContext *ctx,
294                                     IOHandler *io_read,
295                                     IOHandler *io_write,
296                                     void *opaque)
297 {
298     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
299 
300     klass->io_set_aio_fd_handler(ioc, ctx, io_read, io_write, opaque);
301 }
302 
303 guint qio_channel_add_watch_full(QIOChannel *ioc,
304                                  GIOCondition condition,
305                                  QIOChannelFunc func,
306                                  gpointer user_data,
307                                  GDestroyNotify notify,
308                                  GMainContext *context)
309 {
310     GSource *source;
311     guint id;
312 
313     source = qio_channel_create_watch(ioc, condition);
314 
315     g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
316 
317     id = g_source_attach(source, context);
318     g_source_unref(source);
319 
320     return id;
321 }
322 
323 guint qio_channel_add_watch(QIOChannel *ioc,
324                             GIOCondition condition,
325                             QIOChannelFunc func,
326                             gpointer user_data,
327                             GDestroyNotify notify)
328 {
329     return qio_channel_add_watch_full(ioc, condition, func,
330                                       user_data, notify, NULL);
331 }
332 
333 GSource *qio_channel_add_watch_source(QIOChannel *ioc,
334                                       GIOCondition condition,
335                                       QIOChannelFunc func,
336                                       gpointer user_data,
337                                       GDestroyNotify notify,
338                                       GMainContext *context)
339 {
340     GSource *source;
341     guint id;
342 
343     id = qio_channel_add_watch_full(ioc, condition, func,
344                                     user_data, notify, context);
345     source = g_main_context_find_source_by_id(context, id);
346     g_source_ref(source);
347     return source;
348 }
349 
350 
351 int qio_channel_shutdown(QIOChannel *ioc,
352                          QIOChannelShutdown how,
353                          Error **errp)
354 {
355     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
356 
357     if (!klass->io_shutdown) {
358         error_setg(errp, "Data path shutdown not supported");
359         return -1;
360     }
361 
362     return klass->io_shutdown(ioc, how, errp);
363 }
364 
365 
366 void qio_channel_set_delay(QIOChannel *ioc,
367                            bool enabled)
368 {
369     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
370 
371     if (klass->io_set_delay) {
372         klass->io_set_delay(ioc, enabled);
373     }
374 }
375 
376 
377 void qio_channel_set_cork(QIOChannel *ioc,
378                           bool enabled)
379 {
380     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
381 
382     if (klass->io_set_cork) {
383         klass->io_set_cork(ioc, enabled);
384     }
385 }
386 
387 
388 off_t qio_channel_io_seek(QIOChannel *ioc,
389                           off_t offset,
390                           int whence,
391                           Error **errp)
392 {
393     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
394 
395     if (!klass->io_seek) {
396         error_setg(errp, "Channel does not support random access");
397         return -1;
398     }
399 
400     return klass->io_seek(ioc, offset, whence, errp);
401 }
402 
403 
404 static void qio_channel_restart_read(void *opaque)
405 {
406     QIOChannel *ioc = opaque;
407     Coroutine *co = ioc->read_coroutine;
408 
409     /* Assert that aio_co_wake() reenters the coroutine directly */
410     assert(qemu_get_current_aio_context() ==
411            qemu_coroutine_get_aio_context(co));
412     aio_co_wake(co);
413 }
414 
415 static void qio_channel_restart_write(void *opaque)
416 {
417     QIOChannel *ioc = opaque;
418     Coroutine *co = ioc->write_coroutine;
419 
420     /* Assert that aio_co_wake() reenters the coroutine directly */
421     assert(qemu_get_current_aio_context() ==
422            qemu_coroutine_get_aio_context(co));
423     aio_co_wake(co);
424 }
425 
426 static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
427 {
428     IOHandler *rd_handler = NULL, *wr_handler = NULL;
429     AioContext *ctx;
430 
431     if (ioc->read_coroutine) {
432         rd_handler = qio_channel_restart_read;
433     }
434     if (ioc->write_coroutine) {
435         wr_handler = qio_channel_restart_write;
436     }
437 
438     ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
439     qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
440 }
441 
442 void qio_channel_attach_aio_context(QIOChannel *ioc,
443                                     AioContext *ctx)
444 {
445     assert(!ioc->read_coroutine);
446     assert(!ioc->write_coroutine);
447     ioc->ctx = ctx;
448 }
449 
450 void qio_channel_detach_aio_context(QIOChannel *ioc)
451 {
452     ioc->read_coroutine = NULL;
453     ioc->write_coroutine = NULL;
454     qio_channel_set_aio_fd_handlers(ioc);
455     ioc->ctx = NULL;
456 }
457 
458 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
459                                     GIOCondition condition)
460 {
461     assert(qemu_in_coroutine());
462     if (condition == G_IO_IN) {
463         assert(!ioc->read_coroutine);
464         ioc->read_coroutine = qemu_coroutine_self();
465     } else if (condition == G_IO_OUT) {
466         assert(!ioc->write_coroutine);
467         ioc->write_coroutine = qemu_coroutine_self();
468     } else {
469         abort();
470     }
471     qio_channel_set_aio_fd_handlers(ioc);
472     qemu_coroutine_yield();
473 
474     /* Allow interrupting the operation by reentering the coroutine other than
475      * through the aio_fd_handlers. */
476     if (condition == G_IO_IN && ioc->read_coroutine) {
477         ioc->read_coroutine = NULL;
478         qio_channel_set_aio_fd_handlers(ioc);
479     } else if (condition == G_IO_OUT && ioc->write_coroutine) {
480         ioc->write_coroutine = NULL;
481         qio_channel_set_aio_fd_handlers(ioc);
482     }
483 }
484 
485 
486 static gboolean qio_channel_wait_complete(QIOChannel *ioc,
487                                           GIOCondition condition,
488                                           gpointer opaque)
489 {
490     GMainLoop *loop = opaque;
491 
492     g_main_loop_quit(loop);
493     return FALSE;
494 }
495 
496 
497 void qio_channel_wait(QIOChannel *ioc,
498                       GIOCondition condition)
499 {
500     GMainContext *ctxt = g_main_context_new();
501     GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
502     GSource *source;
503 
504     source = qio_channel_create_watch(ioc, condition);
505 
506     g_source_set_callback(source,
507                           (GSourceFunc)qio_channel_wait_complete,
508                           loop,
509                           NULL);
510 
511     g_source_attach(source, ctxt);
512 
513     g_main_loop_run(loop);
514 
515     g_source_unref(source);
516     g_main_loop_unref(loop);
517     g_main_context_unref(ctxt);
518 }
519 
520 
521 static void qio_channel_finalize(Object *obj)
522 {
523     QIOChannel *ioc = QIO_CHANNEL(obj);
524 
525     g_free(ioc->name);
526 
527 #ifdef _WIN32
528     if (ioc->event) {
529         CloseHandle(ioc->event);
530     }
531 #endif
532 }
533 
534 static const TypeInfo qio_channel_info = {
535     .parent = TYPE_OBJECT,
536     .name = TYPE_QIO_CHANNEL,
537     .instance_size = sizeof(QIOChannel),
538     .instance_finalize = qio_channel_finalize,
539     .abstract = true,
540     .class_size = sizeof(QIOChannelClass),
541 };
542 
543 
544 static void qio_channel_register_types(void)
545 {
546     type_register_static(&qio_channel_info);
547 }
548 
549 
550 type_init(qio_channel_register_types);
551