qemu

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

raw-format.c (20068B)


      1 /* BlockDriver implementation for "raw" format driver
      2  *
      3  * Copyright (C) 2010-2016 Red Hat, Inc.
      4  * Copyright (C) 2010, Blue Swirl <blauwirbel@gmail.com>
      5  * Copyright (C) 2009, Anthony Liguori <aliguori@us.ibm.com>
      6  *
      7  * Author:
      8  *   Laszlo Ersek <lersek@redhat.com>
      9  *
     10  * Permission is hereby granted, free of charge, to any person obtaining a copy
     11  * of this software and associated documentation files (the "Software"), to
     12  * deal in the Software without restriction, including without limitation the
     13  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     14  * sell copies of the Software, and to permit persons to whom the Software is
     15  * furnished to do so, subject to the following conditions:
     16  *
     17  * The above copyright notice and this permission notice shall be included in
     18  * all copies or substantial portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     26  * IN THE SOFTWARE.
     27  */
     28 
     29 #include "qemu/osdep.h"
     30 #include "block/block_int.h"
     31 #include "qapi/error.h"
     32 #include "qemu/module.h"
     33 #include "qemu/option.h"
     34 #include "qemu/memalign.h"
     35 
     36 typedef struct BDRVRawState {
     37     uint64_t offset;
     38     uint64_t size;
     39     bool has_size;
     40 } BDRVRawState;
     41 
     42 static const char *const mutable_opts[] = { "offset", "size", NULL };
     43 
     44 static QemuOptsList raw_runtime_opts = {
     45     .name = "raw",
     46     .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
     47     .desc = {
     48         {
     49             .name = "offset",
     50             .type = QEMU_OPT_SIZE,
     51             .help = "offset in the disk where the image starts",
     52         },
     53         {
     54             .name = "size",
     55             .type = QEMU_OPT_SIZE,
     56             .help = "virtual disk size",
     57         },
     58         { /* end of list */ }
     59     },
     60 };
     61 
     62 static QemuOptsList raw_create_opts = {
     63     .name = "raw-create-opts",
     64     .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
     65     .desc = {
     66         {
     67             .name = BLOCK_OPT_SIZE,
     68             .type = QEMU_OPT_SIZE,
     69             .help = "Virtual disk size"
     70         },
     71         { /* end of list */ }
     72     }
     73 };
     74 
     75 static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
     76                             uint64_t *size, Error **errp)
     77 {
     78     QemuOpts *opts = NULL;
     79     int ret;
     80 
     81     opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
     82     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
     83         ret = -EINVAL;
     84         goto end;
     85     }
     86 
     87     *offset = qemu_opt_get_size(opts, "offset", 0);
     88     *has_size = qemu_opt_find(opts, "size");
     89     *size = qemu_opt_get_size(opts, "size", 0);
     90 
     91     ret = 0;
     92 end:
     93     qemu_opts_del(opts);
     94     return ret;
     95 }
     96 
     97 static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
     98                              uint64_t offset, bool has_size, uint64_t size,
     99                              Error **errp)
    100 {
    101     int64_t real_size = 0;
    102 
    103     real_size = bdrv_getlength(bs->file->bs);
    104     if (real_size < 0) {
    105         error_setg_errno(errp, -real_size, "Could not get image size");
    106         return real_size;
    107     }
    108 
    109     /* Check size and offset */
    110     if (offset > real_size) {
    111         error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
    112                    "size of the containing file (%" PRId64 ")",
    113                    s->offset, real_size);
    114         return -EINVAL;
    115     }
    116 
    117     if (has_size && (real_size - offset) < size) {
    118         error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
    119                    "(%" PRIu64 ") has to be smaller or equal to the "
    120                    " actual size of the containing file (%" PRId64 ")",
    121                    s->offset, s->size, real_size);
    122         return -EINVAL;
    123     }
    124 
    125     /* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
    126      * up and leaking out of the specified area. */
    127     if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
    128         error_setg(errp, "Specified size is not multiple of %llu",
    129                    BDRV_SECTOR_SIZE);
    130         return -EINVAL;
    131     }
    132 
    133     s->offset = offset;
    134     s->has_size = has_size;
    135     s->size = has_size ? size : real_size - offset;
    136 
    137     return 0;
    138 }
    139 
    140 static int raw_reopen_prepare(BDRVReopenState *reopen_state,
    141                               BlockReopenQueue *queue, Error **errp)
    142 {
    143     bool has_size;
    144     uint64_t offset, size;
    145     int ret;
    146 
    147     assert(reopen_state != NULL);
    148     assert(reopen_state->bs != NULL);
    149 
    150     reopen_state->opaque = g_new0(BDRVRawState, 1);
    151 
    152     ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
    153                            errp);
    154     if (ret < 0) {
    155         return ret;
    156     }
    157 
    158     ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
    159                             offset, has_size, size, errp);
    160     if (ret < 0) {
    161         return ret;
    162     }
    163 
    164     return 0;
    165 }
    166 
    167 static void raw_reopen_commit(BDRVReopenState *state)
    168 {
    169     BDRVRawState *new_s = state->opaque;
    170     BDRVRawState *s = state->bs->opaque;
    171 
    172     memcpy(s, new_s, sizeof(BDRVRawState));
    173 
    174     g_free(state->opaque);
    175     state->opaque = NULL;
    176 }
    177 
    178 static void raw_reopen_abort(BDRVReopenState *state)
    179 {
    180     g_free(state->opaque);
    181     state->opaque = NULL;
    182 }
    183 
    184 /* Check and adjust the offset, against 'offset' and 'size' options. */
    185 static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
    186                                     int64_t bytes, bool is_write)
    187 {
    188     BDRVRawState *s = bs->opaque;
    189 
    190     if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
    191         /* There's not enough space for the write, or the read request is
    192          * out-of-range. Don't read/write anything to prevent leaking out of
    193          * the size specified in options. */
    194         return is_write ? -ENOSPC : -EINVAL;
    195     }
    196 
    197     if (*offset > INT64_MAX - s->offset) {
    198         return -EINVAL;
    199     }
    200     *offset += s->offset;
    201 
    202     return 0;
    203 }
    204 
    205 static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
    206                                       int64_t bytes, QEMUIOVector *qiov,
    207                                       BdrvRequestFlags flags)
    208 {
    209     int ret;
    210 
    211     ret = raw_adjust_offset(bs, &offset, bytes, false);
    212     if (ret) {
    213         return ret;
    214     }
    215 
    216     BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
    217     return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
    218 }
    219 
    220 static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
    221                                        int64_t bytes, QEMUIOVector *qiov,
    222                                        BdrvRequestFlags flags)
    223 {
    224     void *buf = NULL;
    225     BlockDriver *drv;
    226     QEMUIOVector local_qiov;
    227     int ret;
    228 
    229     if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
    230         /* Handling partial writes would be a pain - so we just
    231          * require that guests have 512-byte request alignment if
    232          * probing occurred */
    233         QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512);
    234         QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512);
    235         assert(offset == 0 && bytes >= BLOCK_PROBE_BUF_SIZE);
    236 
    237         buf = qemu_try_blockalign(bs->file->bs, 512);
    238         if (!buf) {
    239             ret = -ENOMEM;
    240             goto fail;
    241         }
    242 
    243         ret = qemu_iovec_to_buf(qiov, 0, buf, 512);
    244         if (ret != 512) {
    245             ret = -EINVAL;
    246             goto fail;
    247         }
    248 
    249         drv = bdrv_probe_all(buf, 512, NULL);
    250         if (drv != bs->drv) {
    251             ret = -EPERM;
    252             goto fail;
    253         }
    254 
    255         /* Use the checked buffer, a malicious guest might be overwriting its
    256          * original buffer in the background. */
    257         qemu_iovec_init(&local_qiov, qiov->niov + 1);
    258         qemu_iovec_add(&local_qiov, buf, 512);
    259         qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512);
    260         qiov = &local_qiov;
    261 
    262         flags &= ~BDRV_REQ_REGISTERED_BUF;
    263     }
    264 
    265     ret = raw_adjust_offset(bs, &offset, bytes, true);
    266     if (ret) {
    267         goto fail;
    268     }
    269 
    270     BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
    271     ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
    272 
    273 fail:
    274     if (qiov == &local_qiov) {
    275         qemu_iovec_destroy(&local_qiov);
    276     }
    277     qemu_vfree(buf);
    278     return ret;
    279 }
    280 
    281 static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
    282                                             bool want_zero, int64_t offset,
    283                                             int64_t bytes, int64_t *pnum,
    284                                             int64_t *map,
    285                                             BlockDriverState **file)
    286 {
    287     BDRVRawState *s = bs->opaque;
    288     *pnum = bytes;
    289     *file = bs->file->bs;
    290     *map = offset + s->offset;
    291     return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
    292 }
    293 
    294 static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
    295                                              int64_t offset, int64_t bytes,
    296                                              BdrvRequestFlags flags)
    297 {
    298     int ret;
    299 
    300     ret = raw_adjust_offset(bs, &offset, bytes, true);
    301     if (ret) {
    302         return ret;
    303     }
    304     return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
    305 }
    306 
    307 static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
    308                                         int64_t offset, int64_t bytes)
    309 {
    310     int ret;
    311 
    312     ret = raw_adjust_offset(bs, &offset, bytes, true);
    313     if (ret) {
    314         return ret;
    315     }
    316     return bdrv_co_pdiscard(bs->file, offset, bytes);
    317 }
    318 
    319 static int64_t raw_getlength(BlockDriverState *bs)
    320 {
    321     int64_t len;
    322     BDRVRawState *s = bs->opaque;
    323 
    324     /* Update size. It should not change unless the file was externally
    325      * modified. */
    326     len = bdrv_getlength(bs->file->bs);
    327     if (len < 0) {
    328         return len;
    329     }
    330 
    331     if (len < s->offset) {
    332         s->size = 0;
    333     } else {
    334         if (s->has_size) {
    335             /* Try to honour the size */
    336             s->size = MIN(s->size, len - s->offset);
    337         } else {
    338             s->size = len - s->offset;
    339         }
    340     }
    341 
    342     return s->size;
    343 }
    344 
    345 static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
    346                                      Error **errp)
    347 {
    348     BlockMeasureInfo *info;
    349     int64_t required;
    350 
    351     if (in_bs) {
    352         required = bdrv_getlength(in_bs);
    353         if (required < 0) {
    354             error_setg_errno(errp, -required, "Unable to get image size");
    355             return NULL;
    356         }
    357     } else {
    358         required = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
    359                             BDRV_SECTOR_SIZE);
    360     }
    361 
    362     info = g_new0(BlockMeasureInfo, 1);
    363     info->required = required;
    364 
    365     /* Unallocated sectors count towards the file size in raw images */
    366     info->fully_allocated = info->required;
    367     return info;
    368 }
    369 
    370 static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
    371 {
    372     return bdrv_get_info(bs->file->bs, bdi);
    373 }
    374 
    375 static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
    376 {
    377     if (bs->probed) {
    378         /* To make it easier to protect the first sector, any probed
    379          * image is restricted to read-modify-write on sub-sector
    380          * operations. */
    381         bs->bl.request_alignment = BDRV_SECTOR_SIZE;
    382     }
    383 }
    384 
    385 static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
    386                                         bool exact, PreallocMode prealloc,
    387                                         BdrvRequestFlags flags, Error **errp)
    388 {
    389     BDRVRawState *s = bs->opaque;
    390 
    391     if (s->has_size) {
    392         error_setg(errp, "Cannot resize fixed-size raw disks");
    393         return -ENOTSUP;
    394     }
    395 
    396     if (INT64_MAX - offset < s->offset) {
    397         error_setg(errp, "Disk size too large for the chosen offset");
    398         return -EINVAL;
    399     }
    400 
    401     s->size = offset;
    402     offset += s->offset;
    403     return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
    404 }
    405 
    406 static void raw_eject(BlockDriverState *bs, bool eject_flag)
    407 {
    408     bdrv_eject(bs->file->bs, eject_flag);
    409 }
    410 
    411 static void raw_lock_medium(BlockDriverState *bs, bool locked)
    412 {
    413     bdrv_lock_medium(bs->file->bs, locked);
    414 }
    415 
    416 static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
    417                                      unsigned long int req, void *buf)
    418 {
    419     BDRVRawState *s = bs->opaque;
    420     if (s->offset || s->has_size) {
    421         return -ENOTSUP;
    422     }
    423     return bdrv_co_ioctl(bs->file->bs, req, buf);
    424 }
    425 
    426 static int raw_has_zero_init(BlockDriverState *bs)
    427 {
    428     return bdrv_has_zero_init(bs->file->bs);
    429 }
    430 
    431 static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
    432                                            const char *filename,
    433                                            QemuOpts *opts,
    434                                            Error **errp)
    435 {
    436     return bdrv_create_file(filename, opts, errp);
    437 }
    438 
    439 static int raw_open(BlockDriverState *bs, QDict *options, int flags,
    440                     Error **errp)
    441 {
    442     BDRVRawState *s = bs->opaque;
    443     bool has_size;
    444     uint64_t offset, size;
    445     BdrvChildRole file_role;
    446     int ret;
    447 
    448     ret = raw_read_options(options, &offset, &has_size, &size, errp);
    449     if (ret < 0) {
    450         return ret;
    451     }
    452 
    453     /*
    454      * Without offset and a size limit, this driver behaves very much
    455      * like a filter.  With any such limit, it does not.
    456      */
    457     if (offset || has_size) {
    458         file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
    459     } else {
    460         file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
    461     }
    462 
    463     bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
    464                     file_role, false, errp);
    465     if (!bs->file) {
    466         return -EINVAL;
    467     }
    468 
    469     bs->sg = bdrv_is_sg(bs->file->bs);
    470     bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
    471         (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
    472     bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
    473         ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
    474             bs->file->bs->supported_zero_flags);
    475     bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
    476                                    BDRV_REQ_ZERO_WRITE;
    477 
    478     if (bs->probed && !bdrv_is_read_only(bs)) {
    479         bdrv_refresh_filename(bs->file->bs);
    480         fprintf(stderr,
    481                 "WARNING: Image format was not specified for '%s' and probing "
    482                 "guessed raw.\n"
    483                 "         Automatically detecting the format is dangerous for "
    484                 "raw images, write operations on block 0 will be restricted.\n"
    485                 "         Specify the 'raw' format explicitly to remove the "
    486                 "restrictions.\n",
    487                 bs->file->bs->filename);
    488     }
    489 
    490     ret = raw_apply_options(bs, s, offset, has_size, size, errp);
    491     if (ret < 0) {
    492         return ret;
    493     }
    494 
    495     if (bdrv_is_sg(bs) && (s->offset || s->has_size)) {
    496         error_setg(errp, "Cannot use offset/size with SCSI generic devices");
    497         return -EINVAL;
    498     }
    499 
    500     return 0;
    501 }
    502 
    503 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
    504 {
    505     /* smallest possible positive score so that raw is used if and only if no
    506      * other block driver works
    507      */
    508     return 1;
    509 }
    510 
    511 static int raw_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
    512 {
    513     BDRVRawState *s = bs->opaque;
    514     int ret;
    515 
    516     ret = bdrv_probe_blocksizes(bs->file->bs, bsz);
    517     if (ret < 0) {
    518         return ret;
    519     }
    520 
    521     if (!QEMU_IS_ALIGNED(s->offset, MAX(bsz->log, bsz->phys))) {
    522         return -ENOTSUP;
    523     }
    524 
    525     return 0;
    526 }
    527 
    528 static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
    529 {
    530     BDRVRawState *s = bs->opaque;
    531     if (s->offset || s->has_size) {
    532         return -ENOTSUP;
    533     }
    534     return bdrv_probe_geometry(bs->file->bs, geo);
    535 }
    536 
    537 static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
    538                                                BdrvChild *src,
    539                                                int64_t src_offset,
    540                                                BdrvChild *dst,
    541                                                int64_t dst_offset,
    542                                                int64_t bytes,
    543                                                BdrvRequestFlags read_flags,
    544                                                BdrvRequestFlags write_flags)
    545 {
    546     int ret;
    547 
    548     ret = raw_adjust_offset(bs, &src_offset, bytes, false);
    549     if (ret) {
    550         return ret;
    551     }
    552     return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
    553                                    bytes, read_flags, write_flags);
    554 }
    555 
    556 static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
    557                                              BdrvChild *src,
    558                                              int64_t src_offset,
    559                                              BdrvChild *dst,
    560                                              int64_t dst_offset,
    561                                              int64_t bytes,
    562                                              BdrvRequestFlags read_flags,
    563                                              BdrvRequestFlags write_flags)
    564 {
    565     int ret;
    566 
    567     ret = raw_adjust_offset(bs, &dst_offset, bytes, true);
    568     if (ret) {
    569         return ret;
    570     }
    571     return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
    572                                  read_flags, write_flags);
    573 }
    574 
    575 static const char *const raw_strong_runtime_opts[] = {
    576     "offset",
    577     "size",
    578 
    579     NULL
    580 };
    581 
    582 static void raw_cancel_in_flight(BlockDriverState *bs)
    583 {
    584     bdrv_cancel_in_flight(bs->file->bs);
    585 }
    586 
    587 static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
    588                            BdrvChildRole role,
    589                            BlockReopenQueue *reopen_queue,
    590                            uint64_t parent_perm, uint64_t parent_shared,
    591                            uint64_t *nperm, uint64_t *nshared)
    592 {
    593     bdrv_default_perms(bs, c, role, reopen_queue, parent_perm,
    594                        parent_shared, nperm, nshared);
    595 
    596     /*
    597      * bdrv_default_perms() may add WRITE and/or RESIZE (see comment in
    598      * bdrv_default_perms_for_storage() for an explanation) but we only need
    599      * them if they are in parent_perm. Drop WRITE and RESIZE whenever possible
    600      * to avoid permission conflicts.
    601      */
    602     *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
    603     *nperm |= parent_perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
    604 }
    605 
    606 BlockDriver bdrv_raw = {
    607     .format_name          = "raw",
    608     .instance_size        = sizeof(BDRVRawState),
    609     .bdrv_probe           = &raw_probe,
    610     .bdrv_reopen_prepare  = &raw_reopen_prepare,
    611     .bdrv_reopen_commit   = &raw_reopen_commit,
    612     .bdrv_reopen_abort    = &raw_reopen_abort,
    613     .bdrv_open            = &raw_open,
    614     .bdrv_child_perm      = raw_child_perm,
    615     .bdrv_co_create_opts  = &raw_co_create_opts,
    616     .bdrv_co_preadv       = &raw_co_preadv,
    617     .bdrv_co_pwritev      = &raw_co_pwritev,
    618     .bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
    619     .bdrv_co_pdiscard     = &raw_co_pdiscard,
    620     .bdrv_co_block_status = &raw_co_block_status,
    621     .bdrv_co_copy_range_from = &raw_co_copy_range_from,
    622     .bdrv_co_copy_range_to  = &raw_co_copy_range_to,
    623     .bdrv_co_truncate     = &raw_co_truncate,
    624     .bdrv_getlength       = &raw_getlength,
    625     .is_format            = true,
    626     .has_variable_length  = true,
    627     .bdrv_measure         = &raw_measure,
    628     .bdrv_get_info        = &raw_get_info,
    629     .bdrv_refresh_limits  = &raw_refresh_limits,
    630     .bdrv_probe_blocksizes = &raw_probe_blocksizes,
    631     .bdrv_probe_geometry  = &raw_probe_geometry,
    632     .bdrv_eject           = &raw_eject,
    633     .bdrv_lock_medium     = &raw_lock_medium,
    634     .bdrv_co_ioctl        = &raw_co_ioctl,
    635     .create_opts          = &raw_create_opts,
    636     .bdrv_has_zero_init   = &raw_has_zero_init,
    637     .strong_runtime_opts  = raw_strong_runtime_opts,
    638     .mutable_opts         = mutable_opts,
    639     .bdrv_cancel_in_flight = raw_cancel_in_flight,
    640 };
    641 
    642 static void bdrv_raw_init(void)
    643 {
    644     bdrv_register(&bdrv_raw);
    645 }
    646 
    647 block_init(bdrv_raw_init);