187e42764SDaniel P. Berrangé /*
287e42764SDaniel P. Berrangé * QEMU I/O channels null driver
387e42764SDaniel P. Berrangé *
487e42764SDaniel P. Berrangé * Copyright (c) 2022 Red Hat, Inc.
587e42764SDaniel P. Berrangé *
687e42764SDaniel P. Berrangé * This library is free software; you can redistribute it and/or
787e42764SDaniel P. Berrangé * modify it under the terms of the GNU Lesser General Public
887e42764SDaniel P. Berrangé * License as published by the Free Software Foundation; either
987e42764SDaniel P. Berrangé * version 2.1 of the License, or (at your option) any later version.
1087e42764SDaniel P. Berrangé *
1187e42764SDaniel P. Berrangé * This library is distributed in the hope that it will be useful,
1287e42764SDaniel P. Berrangé * but WITHOUT ANY WARRANTY; without even the implied warranty of
1387e42764SDaniel P. Berrangé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1487e42764SDaniel P. Berrangé * Lesser General Public License for more details.
1587e42764SDaniel P. Berrangé *
1687e42764SDaniel P. Berrangé * You should have received a copy of the GNU Lesser General Public
1787e42764SDaniel P. Berrangé * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1887e42764SDaniel P. Berrangé *
1987e42764SDaniel P. Berrangé */
2087e42764SDaniel P. Berrangé
2187e42764SDaniel P. Berrangé #include "qemu/osdep.h"
2287e42764SDaniel P. Berrangé #include "io/channel-null.h"
2387e42764SDaniel P. Berrangé #include "io/channel-watch.h"
2487e42764SDaniel P. Berrangé #include "qapi/error.h"
2587e42764SDaniel P. Berrangé #include "trace.h"
2687e42764SDaniel P. Berrangé #include "qemu/iov.h"
2787e42764SDaniel P. Berrangé
2887e42764SDaniel P. Berrangé typedef struct QIOChannelNullSource QIOChannelNullSource;
2987e42764SDaniel P. Berrangé struct QIOChannelNullSource {
3087e42764SDaniel P. Berrangé GSource parent;
3187e42764SDaniel P. Berrangé QIOChannel *ioc;
3287e42764SDaniel P. Berrangé GIOCondition condition;
3387e42764SDaniel P. Berrangé };
3487e42764SDaniel P. Berrangé
3587e42764SDaniel P. Berrangé
3687e42764SDaniel P. Berrangé QIOChannelNull *
qio_channel_null_new(void)3787e42764SDaniel P. Berrangé qio_channel_null_new(void)
3887e42764SDaniel P. Berrangé {
3987e42764SDaniel P. Berrangé QIOChannelNull *ioc;
4087e42764SDaniel P. Berrangé
4187e42764SDaniel P. Berrangé ioc = QIO_CHANNEL_NULL(object_new(TYPE_QIO_CHANNEL_NULL));
4287e42764SDaniel P. Berrangé
4387e42764SDaniel P. Berrangé trace_qio_channel_null_new(ioc);
4487e42764SDaniel P. Berrangé
4587e42764SDaniel P. Berrangé return ioc;
4687e42764SDaniel P. Berrangé }
4787e42764SDaniel P. Berrangé
4887e42764SDaniel P. Berrangé
4987e42764SDaniel P. Berrangé static void
qio_channel_null_init(Object * obj)5087e42764SDaniel P. Berrangé qio_channel_null_init(Object *obj)
5187e42764SDaniel P. Berrangé {
5287e42764SDaniel P. Berrangé QIOChannelNull *ioc = QIO_CHANNEL_NULL(obj);
5387e42764SDaniel P. Berrangé ioc->closed = false;
5487e42764SDaniel P. Berrangé }
5587e42764SDaniel P. Berrangé
5687e42764SDaniel P. Berrangé
5787e42764SDaniel P. Berrangé static ssize_t
qio_channel_null_readv(QIOChannel * ioc,const struct iovec * iov,size_t niov,int ** fds G_GNUC_UNUSED,size_t * nfds G_GNUC_UNUSED,int flags,Error ** errp)5887e42764SDaniel P. Berrangé qio_channel_null_readv(QIOChannel *ioc,
5987e42764SDaniel P. Berrangé const struct iovec *iov,
6087e42764SDaniel P. Berrangé size_t niov,
6187e42764SDaniel P. Berrangé int **fds G_GNUC_UNUSED,
6287e42764SDaniel P. Berrangé size_t *nfds G_GNUC_UNUSED,
6384615a19Smanish.mishra int flags,
6487e42764SDaniel P. Berrangé Error **errp)
6587e42764SDaniel P. Berrangé {
6687e42764SDaniel P. Berrangé QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc);
6787e42764SDaniel P. Berrangé
6887e42764SDaniel P. Berrangé if (nioc->closed) {
6987e42764SDaniel P. Berrangé error_setg_errno(errp, EINVAL,
7087e42764SDaniel P. Berrangé "Channel is closed");
7187e42764SDaniel P. Berrangé return -1;
7287e42764SDaniel P. Berrangé }
7387e42764SDaniel P. Berrangé
7487e42764SDaniel P. Berrangé return 0;
7587e42764SDaniel P. Berrangé }
7687e42764SDaniel P. Berrangé
7787e42764SDaniel P. Berrangé
7887e42764SDaniel P. Berrangé static ssize_t
qio_channel_null_writev(QIOChannel * ioc,const struct iovec * iov,size_t niov,int * fds G_GNUC_UNUSED,size_t nfds G_GNUC_UNUSED,int flags G_GNUC_UNUSED,Error ** errp)7987e42764SDaniel P. Berrangé qio_channel_null_writev(QIOChannel *ioc,
8087e42764SDaniel P. Berrangé const struct iovec *iov,
8187e42764SDaniel P. Berrangé size_t niov,
8287e42764SDaniel P. Berrangé int *fds G_GNUC_UNUSED,
8387e42764SDaniel P. Berrangé size_t nfds G_GNUC_UNUSED,
8487e42764SDaniel P. Berrangé int flags G_GNUC_UNUSED,
8587e42764SDaniel P. Berrangé Error **errp)
8687e42764SDaniel P. Berrangé {
8787e42764SDaniel P. Berrangé QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc);
8887e42764SDaniel P. Berrangé
8987e42764SDaniel P. Berrangé if (nioc->closed) {
9087e42764SDaniel P. Berrangé error_setg_errno(errp, EINVAL,
9187e42764SDaniel P. Berrangé "Channel is closed");
9287e42764SDaniel P. Berrangé return -1;
9387e42764SDaniel P. Berrangé }
9487e42764SDaniel P. Berrangé
9587e42764SDaniel P. Berrangé return iov_size(iov, niov);
9687e42764SDaniel P. Berrangé }
9787e42764SDaniel P. Berrangé
9887e42764SDaniel P. Berrangé
9987e42764SDaniel P. Berrangé static int
qio_channel_null_set_blocking(QIOChannel * ioc G_GNUC_UNUSED,bool enabled G_GNUC_UNUSED,Error ** errp G_GNUC_UNUSED)10087e42764SDaniel P. Berrangé qio_channel_null_set_blocking(QIOChannel *ioc G_GNUC_UNUSED,
10187e42764SDaniel P. Berrangé bool enabled G_GNUC_UNUSED,
10287e42764SDaniel P. Berrangé Error **errp G_GNUC_UNUSED)
10387e42764SDaniel P. Berrangé {
10487e42764SDaniel P. Berrangé return 0;
10587e42764SDaniel P. Berrangé }
10687e42764SDaniel P. Berrangé
10787e42764SDaniel P. Berrangé
10887e42764SDaniel P. Berrangé static off_t
qio_channel_null_seek(QIOChannel * ioc G_GNUC_UNUSED,off_t offset G_GNUC_UNUSED,int whence G_GNUC_UNUSED,Error ** errp G_GNUC_UNUSED)10987e42764SDaniel P. Berrangé qio_channel_null_seek(QIOChannel *ioc G_GNUC_UNUSED,
11087e42764SDaniel P. Berrangé off_t offset G_GNUC_UNUSED,
11187e42764SDaniel P. Berrangé int whence G_GNUC_UNUSED,
11287e42764SDaniel P. Berrangé Error **errp G_GNUC_UNUSED)
11387e42764SDaniel P. Berrangé {
11487e42764SDaniel P. Berrangé return 0;
11587e42764SDaniel P. Berrangé }
11687e42764SDaniel P. Berrangé
11787e42764SDaniel P. Berrangé
11887e42764SDaniel P. Berrangé static int
qio_channel_null_close(QIOChannel * ioc,Error ** errp G_GNUC_UNUSED)11987e42764SDaniel P. Berrangé qio_channel_null_close(QIOChannel *ioc,
12087e42764SDaniel P. Berrangé Error **errp G_GNUC_UNUSED)
12187e42764SDaniel P. Berrangé {
12287e42764SDaniel P. Berrangé QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc);
12387e42764SDaniel P. Berrangé
12487e42764SDaniel P. Berrangé nioc->closed = true;
12587e42764SDaniel P. Berrangé return 0;
12687e42764SDaniel P. Berrangé }
12787e42764SDaniel P. Berrangé
12887e42764SDaniel P. Berrangé
12987e42764SDaniel P. Berrangé static void
qio_channel_null_set_aio_fd_handler(QIOChannel * ioc G_GNUC_UNUSED,AioContext * read_ctx G_GNUC_UNUSED,IOHandler * io_read G_GNUC_UNUSED,AioContext * write_ctx G_GNUC_UNUSED,IOHandler * io_write G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)13087e42764SDaniel P. Berrangé qio_channel_null_set_aio_fd_handler(QIOChannel *ioc G_GNUC_UNUSED,
131*06e0f098SStefan Hajnoczi AioContext *read_ctx G_GNUC_UNUSED,
13287e42764SDaniel P. Berrangé IOHandler *io_read G_GNUC_UNUSED,
133*06e0f098SStefan Hajnoczi AioContext *write_ctx G_GNUC_UNUSED,
13487e42764SDaniel P. Berrangé IOHandler *io_write G_GNUC_UNUSED,
13587e42764SDaniel P. Berrangé void *opaque G_GNUC_UNUSED)
13687e42764SDaniel P. Berrangé {
13787e42764SDaniel P. Berrangé }
13887e42764SDaniel P. Berrangé
13987e42764SDaniel P. Berrangé
14087e42764SDaniel P. Berrangé static gboolean
qio_channel_null_source_prepare(GSource * source G_GNUC_UNUSED,gint * timeout)14187e42764SDaniel P. Berrangé qio_channel_null_source_prepare(GSource *source G_GNUC_UNUSED,
14287e42764SDaniel P. Berrangé gint *timeout)
14387e42764SDaniel P. Berrangé {
14487e42764SDaniel P. Berrangé *timeout = -1;
14587e42764SDaniel P. Berrangé
14687e42764SDaniel P. Berrangé return TRUE;
14787e42764SDaniel P. Berrangé }
14887e42764SDaniel P. Berrangé
14987e42764SDaniel P. Berrangé
15087e42764SDaniel P. Berrangé static gboolean
qio_channel_null_source_check(GSource * source G_GNUC_UNUSED)15187e42764SDaniel P. Berrangé qio_channel_null_source_check(GSource *source G_GNUC_UNUSED)
15287e42764SDaniel P. Berrangé {
15387e42764SDaniel P. Berrangé return TRUE;
15487e42764SDaniel P. Berrangé }
15587e42764SDaniel P. Berrangé
15687e42764SDaniel P. Berrangé
15787e42764SDaniel P. Berrangé static gboolean
qio_channel_null_source_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)15887e42764SDaniel P. Berrangé qio_channel_null_source_dispatch(GSource *source,
15987e42764SDaniel P. Berrangé GSourceFunc callback,
16087e42764SDaniel P. Berrangé gpointer user_data)
16187e42764SDaniel P. Berrangé {
16287e42764SDaniel P. Berrangé QIOChannelFunc func = (QIOChannelFunc)callback;
16387e42764SDaniel P. Berrangé QIOChannelNullSource *ssource = (QIOChannelNullSource *)source;
16487e42764SDaniel P. Berrangé
16587e42764SDaniel P. Berrangé return (*func)(ssource->ioc,
16687e42764SDaniel P. Berrangé ssource->condition,
16787e42764SDaniel P. Berrangé user_data);
16887e42764SDaniel P. Berrangé }
16987e42764SDaniel P. Berrangé
17087e42764SDaniel P. Berrangé
17187e42764SDaniel P. Berrangé static void
qio_channel_null_source_finalize(GSource * source)17287e42764SDaniel P. Berrangé qio_channel_null_source_finalize(GSource *source)
17387e42764SDaniel P. Berrangé {
17487e42764SDaniel P. Berrangé QIOChannelNullSource *ssource = (QIOChannelNullSource *)source;
17587e42764SDaniel P. Berrangé
17687e42764SDaniel P. Berrangé object_unref(OBJECT(ssource->ioc));
17787e42764SDaniel P. Berrangé }
17887e42764SDaniel P. Berrangé
17987e42764SDaniel P. Berrangé
18087e42764SDaniel P. Berrangé GSourceFuncs qio_channel_null_source_funcs = {
18187e42764SDaniel P. Berrangé qio_channel_null_source_prepare,
18287e42764SDaniel P. Berrangé qio_channel_null_source_check,
18387e42764SDaniel P. Berrangé qio_channel_null_source_dispatch,
18487e42764SDaniel P. Berrangé qio_channel_null_source_finalize
18587e42764SDaniel P. Berrangé };
18687e42764SDaniel P. Berrangé
18787e42764SDaniel P. Berrangé
18887e42764SDaniel P. Berrangé static GSource *
qio_channel_null_create_watch(QIOChannel * ioc,GIOCondition condition)18987e42764SDaniel P. Berrangé qio_channel_null_create_watch(QIOChannel *ioc,
19087e42764SDaniel P. Berrangé GIOCondition condition)
19187e42764SDaniel P. Berrangé {
19287e42764SDaniel P. Berrangé GSource *source;
19387e42764SDaniel P. Berrangé QIOChannelNullSource *ssource;
19487e42764SDaniel P. Berrangé
19587e42764SDaniel P. Berrangé source = g_source_new(&qio_channel_null_source_funcs,
19687e42764SDaniel P. Berrangé sizeof(QIOChannelNullSource));
19787e42764SDaniel P. Berrangé ssource = (QIOChannelNullSource *)source;
19887e42764SDaniel P. Berrangé
19987e42764SDaniel P. Berrangé ssource->ioc = ioc;
20087e42764SDaniel P. Berrangé object_ref(OBJECT(ioc));
20187e42764SDaniel P. Berrangé
20287e42764SDaniel P. Berrangé ssource->condition = condition;
20387e42764SDaniel P. Berrangé
20487e42764SDaniel P. Berrangé return source;
20587e42764SDaniel P. Berrangé }
20687e42764SDaniel P. Berrangé
20787e42764SDaniel P. Berrangé
20887e42764SDaniel P. Berrangé static void
qio_channel_null_class_init(ObjectClass * klass,void * class_data G_GNUC_UNUSED)20987e42764SDaniel P. Berrangé qio_channel_null_class_init(ObjectClass *klass,
21087e42764SDaniel P. Berrangé void *class_data G_GNUC_UNUSED)
21187e42764SDaniel P. Berrangé {
21287e42764SDaniel P. Berrangé QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
21387e42764SDaniel P. Berrangé
21487e42764SDaniel P. Berrangé ioc_klass->io_writev = qio_channel_null_writev;
21587e42764SDaniel P. Berrangé ioc_klass->io_readv = qio_channel_null_readv;
21687e42764SDaniel P. Berrangé ioc_klass->io_set_blocking = qio_channel_null_set_blocking;
21787e42764SDaniel P. Berrangé ioc_klass->io_seek = qio_channel_null_seek;
21887e42764SDaniel P. Berrangé ioc_klass->io_close = qio_channel_null_close;
21987e42764SDaniel P. Berrangé ioc_klass->io_create_watch = qio_channel_null_create_watch;
22087e42764SDaniel P. Berrangé ioc_klass->io_set_aio_fd_handler = qio_channel_null_set_aio_fd_handler;
22187e42764SDaniel P. Berrangé }
22287e42764SDaniel P. Berrangé
22387e42764SDaniel P. Berrangé
22487e42764SDaniel P. Berrangé static const TypeInfo qio_channel_null_info = {
22587e42764SDaniel P. Berrangé .parent = TYPE_QIO_CHANNEL,
22687e42764SDaniel P. Berrangé .name = TYPE_QIO_CHANNEL_NULL,
22787e42764SDaniel P. Berrangé .instance_size = sizeof(QIOChannelNull),
22887e42764SDaniel P. Berrangé .instance_init = qio_channel_null_init,
22987e42764SDaniel P. Berrangé .class_init = qio_channel_null_class_init,
23087e42764SDaniel P. Berrangé };
23187e42764SDaniel P. Berrangé
23287e42764SDaniel P. Berrangé
23387e42764SDaniel P. Berrangé static void
qio_channel_null_register_types(void)23487e42764SDaniel P. Berrangé qio_channel_null_register_types(void)
23587e42764SDaniel P. Berrangé {
23687e42764SDaniel P. Berrangé type_register_static(&qio_channel_null_info);
23787e42764SDaniel P. Berrangé }
23887e42764SDaniel P. Berrangé
23987e42764SDaniel P. Berrangé type_init(qio_channel_null_register_types);
240