qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

channel-block.c (5105B)


      1 /*
      2  * QEMU I/O channels block 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 "migration/channel-block.h"
     23 #include "qapi/error.h"
     24 #include "block/block.h"
     25 #include "trace.h"
     26 
     27 QIOChannelBlock *
     28 qio_channel_block_new(BlockDriverState *bs)
     29 {
     30     QIOChannelBlock *ioc;
     31 
     32     ioc = QIO_CHANNEL_BLOCK(object_new(TYPE_QIO_CHANNEL_BLOCK));
     33 
     34     bdrv_ref(bs);
     35     ioc->bs = bs;
     36 
     37     return ioc;
     38 }
     39 
     40 
     41 static void
     42 qio_channel_block_finalize(Object *obj)
     43 {
     44     QIOChannelBlock *ioc = QIO_CHANNEL_BLOCK(obj);
     45 
     46     g_clear_pointer(&ioc->bs, bdrv_unref);
     47 }
     48 
     49 
     50 static ssize_t
     51 qio_channel_block_readv(QIOChannel *ioc,
     52                         const struct iovec *iov,
     53                         size_t niov,
     54                         int **fds,
     55                         size_t *nfds,
     56                         Error **errp)
     57 {
     58     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
     59     QEMUIOVector qiov;
     60     int ret;
     61 
     62     qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
     63     ret = bdrv_readv_vmstate(bioc->bs, &qiov, bioc->offset);
     64     if (ret < 0) {
     65         error_setg_errno(errp, -ret, "bdrv_readv_vmstate failed");
     66         return -1;
     67     }
     68 
     69     bioc->offset += qiov.size;
     70     return qiov.size;
     71 }
     72 
     73 
     74 static ssize_t
     75 qio_channel_block_writev(QIOChannel *ioc,
     76                          const struct iovec *iov,
     77                          size_t niov,
     78                          int *fds,
     79                          size_t nfds,
     80                          int flags,
     81                          Error **errp)
     82 {
     83     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
     84     QEMUIOVector qiov;
     85     int ret;
     86 
     87     qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
     88     ret = bdrv_writev_vmstate(bioc->bs, &qiov, bioc->offset);
     89     if (ret < 0) {
     90         error_setg_errno(errp, -ret, "bdrv_writev_vmstate failed");
     91         return -1;
     92     }
     93 
     94     bioc->offset += qiov.size;
     95     return qiov.size;
     96 }
     97 
     98 
     99 static int
    100 qio_channel_block_set_blocking(QIOChannel *ioc,
    101                                bool enabled,
    102                                Error **errp)
    103 {
    104     if (!enabled) {
    105         error_setg(errp, "Non-blocking mode not supported for block devices");
    106         return -1;
    107     }
    108     return 0;
    109 }
    110 
    111 
    112 static off_t
    113 qio_channel_block_seek(QIOChannel *ioc,
    114                        off_t offset,
    115                        int whence,
    116                        Error **errp)
    117 {
    118     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
    119 
    120     switch (whence) {
    121     case SEEK_SET:
    122         bioc->offset = offset;
    123         break;
    124     case SEEK_CUR:
    125         bioc->offset += whence;
    126         break;
    127     case SEEK_END:
    128         error_setg(errp, "Size of VMstate region is unknown");
    129         return (off_t)-1;
    130     default:
    131         g_assert_not_reached();
    132     }
    133 
    134     return bioc->offset;
    135 }
    136 
    137 
    138 static int
    139 qio_channel_block_close(QIOChannel *ioc,
    140                         Error **errp)
    141 {
    142     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
    143     int rv = bdrv_flush(bioc->bs);
    144 
    145     if (rv < 0) {
    146         error_setg_errno(errp, -rv,
    147                          "Unable to flush VMState");
    148         return -1;
    149     }
    150 
    151     g_clear_pointer(&bioc->bs, bdrv_unref);
    152     bioc->offset = 0;
    153 
    154     return 0;
    155 }
    156 
    157 
    158 static void
    159 qio_channel_block_set_aio_fd_handler(QIOChannel *ioc,
    160                                      AioContext *ctx,
    161                                      IOHandler *io_read,
    162                                      IOHandler *io_write,
    163                                      void *opaque)
    164 {
    165     /* XXX anything we can do here ? */
    166 }
    167 
    168 
    169 static void
    170 qio_channel_block_class_init(ObjectClass *klass,
    171                              void *class_data G_GNUC_UNUSED)
    172 {
    173     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
    174 
    175     ioc_klass->io_writev = qio_channel_block_writev;
    176     ioc_klass->io_readv = qio_channel_block_readv;
    177     ioc_klass->io_set_blocking = qio_channel_block_set_blocking;
    178     ioc_klass->io_seek = qio_channel_block_seek;
    179     ioc_klass->io_close = qio_channel_block_close;
    180     ioc_klass->io_set_aio_fd_handler = qio_channel_block_set_aio_fd_handler;
    181 }
    182 
    183 static const TypeInfo qio_channel_block_info = {
    184     .parent = TYPE_QIO_CHANNEL,
    185     .name = TYPE_QIO_CHANNEL_BLOCK,
    186     .instance_size = sizeof(QIOChannelBlock),
    187     .instance_finalize = qio_channel_block_finalize,
    188     .class_init = qio_channel_block_class_init,
    189 };
    190 
    191 static void
    192 qio_channel_block_register_types(void)
    193 {
    194     type_register_static(&qio_channel_block_info);
    195 }
    196 
    197 type_init(qio_channel_block_register_types);