1 /* 2 * QEMU I/O channels null driver 3 * 4 * Copyright (c) 2022 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.1 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-null.h" 23 #include "io/channel-watch.h" 24 #include "qapi/error.h" 25 #include "trace.h" 26 #include "qemu/iov.h" 27 28 typedef struct QIOChannelNullSource QIOChannelNullSource; 29 struct QIOChannelNullSource { 30 GSource parent; 31 QIOChannel *ioc; 32 GIOCondition condition; 33 }; 34 35 36 QIOChannelNull * 37 qio_channel_null_new(void) 38 { 39 QIOChannelNull *ioc; 40 41 ioc = QIO_CHANNEL_NULL(object_new(TYPE_QIO_CHANNEL_NULL)); 42 43 trace_qio_channel_null_new(ioc); 44 45 return ioc; 46 } 47 48 49 static void 50 qio_channel_null_init(Object *obj) 51 { 52 QIOChannelNull *ioc = QIO_CHANNEL_NULL(obj); 53 ioc->closed = false; 54 } 55 56 57 static ssize_t 58 qio_channel_null_readv(QIOChannel *ioc, 59 const struct iovec *iov, 60 size_t niov, 61 int **fds G_GNUC_UNUSED, 62 size_t *nfds G_GNUC_UNUSED, 63 int flags, 64 Error **errp) 65 { 66 QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); 67 68 if (nioc->closed) { 69 error_setg_errno(errp, EINVAL, 70 "Channel is closed"); 71 return -1; 72 } 73 74 return 0; 75 } 76 77 78 static ssize_t 79 qio_channel_null_writev(QIOChannel *ioc, 80 const struct iovec *iov, 81 size_t niov, 82 int *fds G_GNUC_UNUSED, 83 size_t nfds G_GNUC_UNUSED, 84 int flags G_GNUC_UNUSED, 85 Error **errp) 86 { 87 QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); 88 89 if (nioc->closed) { 90 error_setg_errno(errp, EINVAL, 91 "Channel is closed"); 92 return -1; 93 } 94 95 return iov_size(iov, niov); 96 } 97 98 99 static int 100 qio_channel_null_set_blocking(QIOChannel *ioc G_GNUC_UNUSED, 101 bool enabled G_GNUC_UNUSED, 102 Error **errp G_GNUC_UNUSED) 103 { 104 return 0; 105 } 106 107 108 static off_t 109 qio_channel_null_seek(QIOChannel *ioc G_GNUC_UNUSED, 110 off_t offset G_GNUC_UNUSED, 111 int whence G_GNUC_UNUSED, 112 Error **errp G_GNUC_UNUSED) 113 { 114 return 0; 115 } 116 117 118 static int 119 qio_channel_null_close(QIOChannel *ioc, 120 Error **errp G_GNUC_UNUSED) 121 { 122 QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); 123 124 nioc->closed = true; 125 return 0; 126 } 127 128 129 static void 130 qio_channel_null_set_aio_fd_handler(QIOChannel *ioc G_GNUC_UNUSED, 131 AioContext *ctx G_GNUC_UNUSED, 132 IOHandler *io_read G_GNUC_UNUSED, 133 IOHandler *io_write G_GNUC_UNUSED, 134 void *opaque G_GNUC_UNUSED) 135 { 136 } 137 138 139 static gboolean 140 qio_channel_null_source_prepare(GSource *source G_GNUC_UNUSED, 141 gint *timeout) 142 { 143 *timeout = -1; 144 145 return TRUE; 146 } 147 148 149 static gboolean 150 qio_channel_null_source_check(GSource *source G_GNUC_UNUSED) 151 { 152 return TRUE; 153 } 154 155 156 static gboolean 157 qio_channel_null_source_dispatch(GSource *source, 158 GSourceFunc callback, 159 gpointer user_data) 160 { 161 QIOChannelFunc func = (QIOChannelFunc)callback; 162 QIOChannelNullSource *ssource = (QIOChannelNullSource *)source; 163 164 return (*func)(ssource->ioc, 165 ssource->condition, 166 user_data); 167 } 168 169 170 static void 171 qio_channel_null_source_finalize(GSource *source) 172 { 173 QIOChannelNullSource *ssource = (QIOChannelNullSource *)source; 174 175 object_unref(OBJECT(ssource->ioc)); 176 } 177 178 179 GSourceFuncs qio_channel_null_source_funcs = { 180 qio_channel_null_source_prepare, 181 qio_channel_null_source_check, 182 qio_channel_null_source_dispatch, 183 qio_channel_null_source_finalize 184 }; 185 186 187 static GSource * 188 qio_channel_null_create_watch(QIOChannel *ioc, 189 GIOCondition condition) 190 { 191 GSource *source; 192 QIOChannelNullSource *ssource; 193 194 source = g_source_new(&qio_channel_null_source_funcs, 195 sizeof(QIOChannelNullSource)); 196 ssource = (QIOChannelNullSource *)source; 197 198 ssource->ioc = ioc; 199 object_ref(OBJECT(ioc)); 200 201 ssource->condition = condition; 202 203 return source; 204 } 205 206 207 static void 208 qio_channel_null_class_init(ObjectClass *klass, 209 void *class_data G_GNUC_UNUSED) 210 { 211 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 212 213 ioc_klass->io_writev = qio_channel_null_writev; 214 ioc_klass->io_readv = qio_channel_null_readv; 215 ioc_klass->io_set_blocking = qio_channel_null_set_blocking; 216 ioc_klass->io_seek = qio_channel_null_seek; 217 ioc_klass->io_close = qio_channel_null_close; 218 ioc_klass->io_create_watch = qio_channel_null_create_watch; 219 ioc_klass->io_set_aio_fd_handler = qio_channel_null_set_aio_fd_handler; 220 } 221 222 223 static const TypeInfo qio_channel_null_info = { 224 .parent = TYPE_QIO_CHANNEL, 225 .name = TYPE_QIO_CHANNEL_NULL, 226 .instance_size = sizeof(QIOChannelNull), 227 .instance_init = qio_channel_null_init, 228 .class_init = qio_channel_null_class_init, 229 }; 230 231 232 static void 233 qio_channel_null_register_types(void) 234 { 235 type_register_static(&qio_channel_null_info); 236 } 237 238 type_init(qio_channel_null_register_types); 239