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 "qemu/coroutine.h" 24 25 bool qio_channel_has_feature(QIOChannel *ioc, 26 QIOChannelFeature feature) 27 { 28 return ioc->features & (1 << feature); 29 } 30 31 32 ssize_t qio_channel_readv_full(QIOChannel *ioc, 33 const struct iovec *iov, 34 size_t niov, 35 int **fds, 36 size_t *nfds, 37 Error **errp) 38 { 39 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 40 41 if ((fds || nfds) && 42 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) { 43 error_setg_errno(errp, EINVAL, 44 "Channel does not support file descriptor passing"); 45 return -1; 46 } 47 48 return klass->io_readv(ioc, iov, niov, fds, nfds, errp); 49 } 50 51 52 ssize_t qio_channel_writev_full(QIOChannel *ioc, 53 const struct iovec *iov, 54 size_t niov, 55 int *fds, 56 size_t nfds, 57 Error **errp) 58 { 59 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 60 61 if ((fds || nfds) && 62 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) { 63 error_setg_errno(errp, EINVAL, 64 "Channel does not support file descriptor passing"); 65 return -1; 66 } 67 68 return klass->io_writev(ioc, iov, niov, fds, nfds, errp); 69 } 70 71 72 ssize_t qio_channel_readv(QIOChannel *ioc, 73 const struct iovec *iov, 74 size_t niov, 75 Error **errp) 76 { 77 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp); 78 } 79 80 81 ssize_t qio_channel_writev(QIOChannel *ioc, 82 const struct iovec *iov, 83 size_t niov, 84 Error **errp) 85 { 86 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp); 87 } 88 89 90 ssize_t qio_channel_read(QIOChannel *ioc, 91 char *buf, 92 size_t buflen, 93 Error **errp) 94 { 95 struct iovec iov = { .iov_base = buf, .iov_len = buflen }; 96 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp); 97 } 98 99 100 ssize_t qio_channel_write(QIOChannel *ioc, 101 const char *buf, 102 size_t buflen, 103 Error **errp) 104 { 105 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen }; 106 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp); 107 } 108 109 110 int qio_channel_set_blocking(QIOChannel *ioc, 111 bool enabled, 112 Error **errp) 113 { 114 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 115 return klass->io_set_blocking(ioc, enabled, errp); 116 } 117 118 119 int qio_channel_close(QIOChannel *ioc, 120 Error **errp) 121 { 122 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 123 return klass->io_close(ioc, errp); 124 } 125 126 127 GSource *qio_channel_create_watch(QIOChannel *ioc, 128 GIOCondition condition) 129 { 130 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 131 return klass->io_create_watch(ioc, condition); 132 } 133 134 135 guint qio_channel_add_watch(QIOChannel *ioc, 136 GIOCondition condition, 137 QIOChannelFunc func, 138 gpointer user_data, 139 GDestroyNotify notify) 140 { 141 GSource *source; 142 guint id; 143 144 source = qio_channel_create_watch(ioc, condition); 145 146 g_source_set_callback(source, (GSourceFunc)func, user_data, notify); 147 148 id = g_source_attach(source, NULL); 149 g_source_unref(source); 150 151 return id; 152 } 153 154 155 int qio_channel_shutdown(QIOChannel *ioc, 156 QIOChannelShutdown how, 157 Error **errp) 158 { 159 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 160 161 if (!klass->io_shutdown) { 162 error_setg(errp, "Data path shutdown not supported"); 163 return -1; 164 } 165 166 return klass->io_shutdown(ioc, how, errp); 167 } 168 169 170 void qio_channel_set_delay(QIOChannel *ioc, 171 bool enabled) 172 { 173 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 174 175 if (klass->io_set_delay) { 176 klass->io_set_delay(ioc, enabled); 177 } 178 } 179 180 181 void qio_channel_set_cork(QIOChannel *ioc, 182 bool enabled) 183 { 184 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 185 186 if (klass->io_set_cork) { 187 klass->io_set_cork(ioc, enabled); 188 } 189 } 190 191 192 off_t qio_channel_io_seek(QIOChannel *ioc, 193 off_t offset, 194 int whence, 195 Error **errp) 196 { 197 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); 198 199 if (!klass->io_seek) { 200 error_setg(errp, "Channel does not support random access"); 201 return -1; 202 } 203 204 return klass->io_seek(ioc, offset, whence, errp); 205 } 206 207 208 typedef struct QIOChannelYieldData QIOChannelYieldData; 209 struct QIOChannelYieldData { 210 QIOChannel *ioc; 211 Coroutine *co; 212 }; 213 214 215 static gboolean qio_channel_yield_enter(QIOChannel *ioc, 216 GIOCondition condition, 217 gpointer opaque) 218 { 219 QIOChannelYieldData *data = opaque; 220 qemu_coroutine_enter(data->co, NULL); 221 return FALSE; 222 } 223 224 225 void coroutine_fn qio_channel_yield(QIOChannel *ioc, 226 GIOCondition condition) 227 { 228 QIOChannelYieldData data; 229 230 assert(qemu_in_coroutine()); 231 data.ioc = ioc; 232 data.co = qemu_coroutine_self(); 233 qio_channel_add_watch(ioc, 234 condition, 235 qio_channel_yield_enter, 236 &data, 237 NULL); 238 qemu_coroutine_yield(); 239 } 240 241 242 static gboolean qio_channel_wait_complete(QIOChannel *ioc, 243 GIOCondition condition, 244 gpointer opaque) 245 { 246 GMainLoop *loop = opaque; 247 248 g_main_loop_quit(loop); 249 return FALSE; 250 } 251 252 253 void qio_channel_wait(QIOChannel *ioc, 254 GIOCondition condition) 255 { 256 GMainContext *ctxt = g_main_context_new(); 257 GMainLoop *loop = g_main_loop_new(ctxt, TRUE); 258 GSource *source; 259 260 source = qio_channel_create_watch(ioc, condition); 261 262 g_source_set_callback(source, 263 (GSourceFunc)qio_channel_wait_complete, 264 loop, 265 NULL); 266 267 g_source_attach(source, ctxt); 268 269 g_main_loop_run(loop); 270 271 g_source_unref(source); 272 g_main_loop_unref(loop); 273 g_main_context_unref(ctxt); 274 } 275 276 277 #ifdef _WIN32 278 static void qio_channel_finalize(Object *obj) 279 { 280 QIOChannel *ioc = QIO_CHANNEL(obj); 281 282 if (ioc->event) { 283 CloseHandle(ioc->event); 284 } 285 } 286 #endif 287 288 static const TypeInfo qio_channel_info = { 289 .parent = TYPE_OBJECT, 290 .name = TYPE_QIO_CHANNEL, 291 .instance_size = sizeof(QIOChannel), 292 #ifdef _WIN32 293 .instance_finalize = qio_channel_finalize, 294 #endif 295 .abstract = true, 296 .class_size = sizeof(QIOChannelClass), 297 }; 298 299 300 static void qio_channel_register_types(void) 301 { 302 type_register_static(&qio_channel_info); 303 } 304 305 306 type_init(qio_channel_register_types); 307