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