xref: /qemu/migration/channel-block.c (revision 06e0f098)
165cf200aSDaniel P. Berrangé /*
265cf200aSDaniel P. Berrangé  * QEMU I/O channels block driver
365cf200aSDaniel P. Berrangé  *
465cf200aSDaniel P. Berrangé  * Copyright (c) 2022 Red Hat, Inc.
565cf200aSDaniel P. Berrangé  *
665cf200aSDaniel P. Berrangé  * This library is free software; you can redistribute it and/or
765cf200aSDaniel P. Berrangé  * modify it under the terms of the GNU Lesser General Public
865cf200aSDaniel P. Berrangé  * License as published by the Free Software Foundation; either
965cf200aSDaniel P. Berrangé  * version 2.1 of the License, or (at your option) any later version.
1065cf200aSDaniel P. Berrangé  *
1165cf200aSDaniel P. Berrangé  * This library is distributed in the hope that it will be useful,
1265cf200aSDaniel P. Berrangé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1365cf200aSDaniel P. Berrangé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1465cf200aSDaniel P. Berrangé  * Lesser General Public License for more details.
1565cf200aSDaniel P. Berrangé  *
1665cf200aSDaniel P. Berrangé  * You should have received a copy of the GNU Lesser General Public
1765cf200aSDaniel P. Berrangé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1865cf200aSDaniel P. Berrangé  *
1965cf200aSDaniel P. Berrangé  */
2065cf200aSDaniel P. Berrangé 
2165cf200aSDaniel P. Berrangé #include "qemu/osdep.h"
2265cf200aSDaniel P. Berrangé #include "migration/channel-block.h"
2365cf200aSDaniel P. Berrangé #include "qapi/error.h"
2465cf200aSDaniel P. Berrangé #include "block/block.h"
2565cf200aSDaniel P. Berrangé #include "trace.h"
2665cf200aSDaniel P. Berrangé 
2765cf200aSDaniel P. Berrangé QIOChannelBlock *
qio_channel_block_new(BlockDriverState * bs)2865cf200aSDaniel P. Berrangé qio_channel_block_new(BlockDriverState *bs)
2965cf200aSDaniel P. Berrangé {
3065cf200aSDaniel P. Berrangé     QIOChannelBlock *ioc;
3165cf200aSDaniel P. Berrangé 
3265cf200aSDaniel P. Berrangé     ioc = QIO_CHANNEL_BLOCK(object_new(TYPE_QIO_CHANNEL_BLOCK));
3365cf200aSDaniel P. Berrangé 
3465cf200aSDaniel P. Berrangé     bdrv_ref(bs);
3565cf200aSDaniel P. Berrangé     ioc->bs = bs;
3665cf200aSDaniel P. Berrangé 
3765cf200aSDaniel P. Berrangé     return ioc;
3865cf200aSDaniel P. Berrangé }
3965cf200aSDaniel P. Berrangé 
4065cf200aSDaniel P. Berrangé 
4165cf200aSDaniel P. Berrangé static void
qio_channel_block_finalize(Object * obj)4265cf200aSDaniel P. Berrangé qio_channel_block_finalize(Object *obj)
4365cf200aSDaniel P. Berrangé {
4465cf200aSDaniel P. Berrangé     QIOChannelBlock *ioc = QIO_CHANNEL_BLOCK(obj);
4565cf200aSDaniel P. Berrangé 
4665cf200aSDaniel P. Berrangé     g_clear_pointer(&ioc->bs, bdrv_unref);
4765cf200aSDaniel P. Berrangé }
4865cf200aSDaniel P. Berrangé 
4965cf200aSDaniel P. Berrangé 
5065cf200aSDaniel P. Berrangé static ssize_t
qio_channel_block_readv(QIOChannel * ioc,const struct iovec * iov,size_t niov,int ** fds,size_t * nfds,int flags,Error ** errp)5165cf200aSDaniel P. Berrangé qio_channel_block_readv(QIOChannel *ioc,
5265cf200aSDaniel P. Berrangé                         const struct iovec *iov,
5365cf200aSDaniel P. Berrangé                         size_t niov,
5465cf200aSDaniel P. Berrangé                         int **fds,
5565cf200aSDaniel P. Berrangé                         size_t *nfds,
5684615a19Smanish.mishra                         int flags,
5765cf200aSDaniel P. Berrangé                         Error **errp)
5865cf200aSDaniel P. Berrangé {
5965cf200aSDaniel P. Berrangé     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
6065cf200aSDaniel P. Berrangé     QEMUIOVector qiov;
6165cf200aSDaniel P. Berrangé     int ret;
6265cf200aSDaniel P. Berrangé 
6365cf200aSDaniel P. Berrangé     qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
6465cf200aSDaniel P. Berrangé     ret = bdrv_readv_vmstate(bioc->bs, &qiov, bioc->offset);
6565cf200aSDaniel P. Berrangé     if (ret < 0) {
66a216ec85SFiona Ebner         error_setg_errno(errp, -ret, "bdrv_readv_vmstate failed");
67a216ec85SFiona Ebner         return -1;
6865cf200aSDaniel P. Berrangé     }
6965cf200aSDaniel P. Berrangé 
7065cf200aSDaniel P. Berrangé     bioc->offset += qiov.size;
7165cf200aSDaniel P. Berrangé     return qiov.size;
7265cf200aSDaniel P. Berrangé }
7365cf200aSDaniel P. Berrangé 
7465cf200aSDaniel P. Berrangé 
7565cf200aSDaniel P. Berrangé static ssize_t
qio_channel_block_writev(QIOChannel * ioc,const struct iovec * iov,size_t niov,int * fds,size_t nfds,int flags,Error ** errp)7665cf200aSDaniel P. Berrangé qio_channel_block_writev(QIOChannel *ioc,
7765cf200aSDaniel P. Berrangé                          const struct iovec *iov,
7865cf200aSDaniel P. Berrangé                          size_t niov,
7965cf200aSDaniel P. Berrangé                          int *fds,
8065cf200aSDaniel P. Berrangé                          size_t nfds,
8165cf200aSDaniel P. Berrangé                          int flags,
8265cf200aSDaniel P. Berrangé                          Error **errp)
8365cf200aSDaniel P. Berrangé {
8465cf200aSDaniel P. Berrangé     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
8565cf200aSDaniel P. Berrangé     QEMUIOVector qiov;
8665cf200aSDaniel P. Berrangé     int ret;
8765cf200aSDaniel P. Berrangé 
8865cf200aSDaniel P. Berrangé     qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
8965cf200aSDaniel P. Berrangé     ret = bdrv_writev_vmstate(bioc->bs, &qiov, bioc->offset);
9065cf200aSDaniel P. Berrangé     if (ret < 0) {
91a216ec85SFiona Ebner         error_setg_errno(errp, -ret, "bdrv_writev_vmstate failed");
92a216ec85SFiona Ebner         return -1;
9365cf200aSDaniel P. Berrangé     }
9465cf200aSDaniel P. Berrangé 
9565cf200aSDaniel P. Berrangé     bioc->offset += qiov.size;
9665cf200aSDaniel P. Berrangé     return qiov.size;
9765cf200aSDaniel P. Berrangé }
9865cf200aSDaniel P. Berrangé 
9965cf200aSDaniel P. Berrangé 
10065cf200aSDaniel P. Berrangé static int
qio_channel_block_set_blocking(QIOChannel * ioc,bool enabled,Error ** errp)10165cf200aSDaniel P. Berrangé qio_channel_block_set_blocking(QIOChannel *ioc,
10265cf200aSDaniel P. Berrangé                                bool enabled,
10365cf200aSDaniel P. Berrangé                                Error **errp)
10465cf200aSDaniel P. Berrangé {
10565cf200aSDaniel P. Berrangé     if (!enabled) {
10665cf200aSDaniel P. Berrangé         error_setg(errp, "Non-blocking mode not supported for block devices");
10765cf200aSDaniel P. Berrangé         return -1;
10865cf200aSDaniel P. Berrangé     }
10965cf200aSDaniel P. Berrangé     return 0;
11065cf200aSDaniel P. Berrangé }
11165cf200aSDaniel P. Berrangé 
11265cf200aSDaniel P. Berrangé 
11365cf200aSDaniel P. Berrangé static off_t
qio_channel_block_seek(QIOChannel * ioc,off_t offset,int whence,Error ** errp)11465cf200aSDaniel P. Berrangé qio_channel_block_seek(QIOChannel *ioc,
11565cf200aSDaniel P. Berrangé                        off_t offset,
11665cf200aSDaniel P. Berrangé                        int whence,
11765cf200aSDaniel P. Berrangé                        Error **errp)
11865cf200aSDaniel P. Berrangé {
11965cf200aSDaniel P. Berrangé     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
12065cf200aSDaniel P. Berrangé 
12165cf200aSDaniel P. Berrangé     switch (whence) {
12265cf200aSDaniel P. Berrangé     case SEEK_SET:
12365cf200aSDaniel P. Berrangé         bioc->offset = offset;
12465cf200aSDaniel P. Berrangé         break;
12565cf200aSDaniel P. Berrangé     case SEEK_CUR:
12665cf200aSDaniel P. Berrangé         bioc->offset += whence;
12765cf200aSDaniel P. Berrangé         break;
12865cf200aSDaniel P. Berrangé     case SEEK_END:
12965cf200aSDaniel P. Berrangé         error_setg(errp, "Size of VMstate region is unknown");
13065cf200aSDaniel P. Berrangé         return (off_t)-1;
13165cf200aSDaniel P. Berrangé     default:
13265cf200aSDaniel P. Berrangé         g_assert_not_reached();
13365cf200aSDaniel P. Berrangé     }
13465cf200aSDaniel P. Berrangé 
13565cf200aSDaniel P. Berrangé     return bioc->offset;
13665cf200aSDaniel P. Berrangé }
13765cf200aSDaniel P. Berrangé 
13865cf200aSDaniel P. Berrangé 
13965cf200aSDaniel P. Berrangé static int
qio_channel_block_close(QIOChannel * ioc,Error ** errp)14065cf200aSDaniel P. Berrangé qio_channel_block_close(QIOChannel *ioc,
14165cf200aSDaniel P. Berrangé                         Error **errp)
14265cf200aSDaniel P. Berrangé {
14365cf200aSDaniel P. Berrangé     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
14465cf200aSDaniel P. Berrangé     int rv = bdrv_flush(bioc->bs);
14565cf200aSDaniel P. Berrangé 
14665cf200aSDaniel P. Berrangé     if (rv < 0) {
14765cf200aSDaniel P. Berrangé         error_setg_errno(errp, -rv,
14865cf200aSDaniel P. Berrangé                          "Unable to flush VMState");
14965cf200aSDaniel P. Berrangé         return -1;
15065cf200aSDaniel P. Berrangé     }
15165cf200aSDaniel P. Berrangé 
15265cf200aSDaniel P. Berrangé     g_clear_pointer(&bioc->bs, bdrv_unref);
15365cf200aSDaniel P. Berrangé     bioc->offset = 0;
15465cf200aSDaniel P. Berrangé 
15565cf200aSDaniel P. Berrangé     return 0;
15665cf200aSDaniel P. Berrangé }
15765cf200aSDaniel P. Berrangé 
15865cf200aSDaniel P. Berrangé 
15965cf200aSDaniel P. Berrangé static void
qio_channel_block_set_aio_fd_handler(QIOChannel * ioc,AioContext * read_ctx,IOHandler * io_read,AioContext * write_ctx,IOHandler * io_write,void * opaque)16065cf200aSDaniel P. Berrangé qio_channel_block_set_aio_fd_handler(QIOChannel *ioc,
16106e0f098SStefan Hajnoczi                                      AioContext *read_ctx,
16265cf200aSDaniel P. Berrangé                                      IOHandler *io_read,
16306e0f098SStefan Hajnoczi                                      AioContext *write_ctx,
16465cf200aSDaniel P. Berrangé                                      IOHandler *io_write,
16565cf200aSDaniel P. Berrangé                                      void *opaque)
16665cf200aSDaniel P. Berrangé {
16765cf200aSDaniel P. Berrangé     /* XXX anything we can do here ? */
16865cf200aSDaniel P. Berrangé }
16965cf200aSDaniel P. Berrangé 
17065cf200aSDaniel P. Berrangé 
17165cf200aSDaniel P. Berrangé static void
qio_channel_block_class_init(ObjectClass * klass,void * class_data G_GNUC_UNUSED)17265cf200aSDaniel P. Berrangé qio_channel_block_class_init(ObjectClass *klass,
17365cf200aSDaniel P. Berrangé                              void *class_data G_GNUC_UNUSED)
17465cf200aSDaniel P. Berrangé {
17565cf200aSDaniel P. Berrangé     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
17665cf200aSDaniel P. Berrangé 
17765cf200aSDaniel P. Berrangé     ioc_klass->io_writev = qio_channel_block_writev;
17865cf200aSDaniel P. Berrangé     ioc_klass->io_readv = qio_channel_block_readv;
17965cf200aSDaniel P. Berrangé     ioc_klass->io_set_blocking = qio_channel_block_set_blocking;
18065cf200aSDaniel P. Berrangé     ioc_klass->io_seek = qio_channel_block_seek;
18165cf200aSDaniel P. Berrangé     ioc_klass->io_close = qio_channel_block_close;
18265cf200aSDaniel P. Berrangé     ioc_klass->io_set_aio_fd_handler = qio_channel_block_set_aio_fd_handler;
18365cf200aSDaniel P. Berrangé }
18465cf200aSDaniel P. Berrangé 
18565cf200aSDaniel P. Berrangé static const TypeInfo qio_channel_block_info = {
18665cf200aSDaniel P. Berrangé     .parent = TYPE_QIO_CHANNEL,
18765cf200aSDaniel P. Berrangé     .name = TYPE_QIO_CHANNEL_BLOCK,
18865cf200aSDaniel P. Berrangé     .instance_size = sizeof(QIOChannelBlock),
18965cf200aSDaniel P. Berrangé     .instance_finalize = qio_channel_block_finalize,
19065cf200aSDaniel P. Berrangé     .class_init = qio_channel_block_class_init,
19165cf200aSDaniel P. Berrangé };
19265cf200aSDaniel P. Berrangé 
19365cf200aSDaniel P. Berrangé static void
qio_channel_block_register_types(void)19465cf200aSDaniel P. Berrangé qio_channel_block_register_types(void)
19565cf200aSDaniel P. Berrangé {
19665cf200aSDaniel P. Berrangé     type_register_static(&qio_channel_block_info);
19765cf200aSDaniel P. Berrangé }
19865cf200aSDaniel P. Berrangé 
19965cf200aSDaniel P. Berrangé type_init(qio_channel_block_register_types);
200