xref: /qemu/block/raw-format.c (revision b49f4755)
12e6fc7ebSEric Blake /* BlockDriver implementation for "raw" format driver
22e6fc7ebSEric Blake  *
32e6fc7ebSEric Blake  * Copyright (C) 2010-2016 Red Hat, Inc.
42e6fc7ebSEric Blake  * Copyright (C) 2010, Blue Swirl <blauwirbel@gmail.com>
52e6fc7ebSEric Blake  * Copyright (C) 2009, Anthony Liguori <aliguori@us.ibm.com>
62e6fc7ebSEric Blake  *
72e6fc7ebSEric Blake  * Author:
82e6fc7ebSEric Blake  *   Laszlo Ersek <lersek@redhat.com>
92e6fc7ebSEric Blake  *
102e6fc7ebSEric Blake  * Permission is hereby granted, free of charge, to any person obtaining a copy
112e6fc7ebSEric Blake  * of this software and associated documentation files (the "Software"), to
122e6fc7ebSEric Blake  * deal in the Software without restriction, including without limitation the
132e6fc7ebSEric Blake  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
142e6fc7ebSEric Blake  * sell copies of the Software, and to permit persons to whom the Software is
152e6fc7ebSEric Blake  * furnished to do so, subject to the following conditions:
162e6fc7ebSEric Blake  *
172e6fc7ebSEric Blake  * The above copyright notice and this permission notice shall be included in
182e6fc7ebSEric Blake  * all copies or substantial portions of the Software.
192e6fc7ebSEric Blake  *
202e6fc7ebSEric Blake  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
212e6fc7ebSEric Blake  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
222e6fc7ebSEric Blake  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
232e6fc7ebSEric Blake  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
242e6fc7ebSEric Blake  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
252e6fc7ebSEric Blake  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
262e6fc7ebSEric Blake  * IN THE SOFTWARE.
272e6fc7ebSEric Blake  */
282e6fc7ebSEric Blake 
292e6fc7ebSEric Blake #include "qemu/osdep.h"
30e2c1c34fSMarkus Armbruster #include "block/block-io.h"
312e6fc7ebSEric Blake #include "block/block_int.h"
322e6fc7ebSEric Blake #include "qapi/error.h"
330b8fa32fSMarkus Armbruster #include "qemu/module.h"
342e6fc7ebSEric Blake #include "qemu/option.h"
355df022cfSPeter Maydell #include "qemu/memalign.h"
362e6fc7ebSEric Blake 
372e6fc7ebSEric Blake typedef struct BDRVRawState {
382e6fc7ebSEric Blake     uint64_t offset;
392e6fc7ebSEric Blake     uint64_t size;
402e6fc7ebSEric Blake     bool has_size;
412e6fc7ebSEric Blake } BDRVRawState;
422e6fc7ebSEric Blake 
438a2ce0bcSAlberto Garcia static const char *const mutable_opts[] = { "offset", "size", NULL };
448a2ce0bcSAlberto Garcia 
452e6fc7ebSEric Blake static QemuOptsList raw_runtime_opts = {
462e6fc7ebSEric Blake     .name = "raw",
472e6fc7ebSEric Blake     .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
482e6fc7ebSEric Blake     .desc = {
492e6fc7ebSEric Blake         {
502e6fc7ebSEric Blake             .name = "offset",
512e6fc7ebSEric Blake             .type = QEMU_OPT_SIZE,
522e6fc7ebSEric Blake             .help = "offset in the disk where the image starts",
532e6fc7ebSEric Blake         },
542e6fc7ebSEric Blake         {
552e6fc7ebSEric Blake             .name = "size",
562e6fc7ebSEric Blake             .type = QEMU_OPT_SIZE,
572e6fc7ebSEric Blake             .help = "virtual disk size",
582e6fc7ebSEric Blake         },
592e6fc7ebSEric Blake         { /* end of list */ }
602e6fc7ebSEric Blake     },
612e6fc7ebSEric Blake };
622e6fc7ebSEric Blake 
632e6fc7ebSEric Blake static QemuOptsList raw_create_opts = {
642e6fc7ebSEric Blake     .name = "raw-create-opts",
652e6fc7ebSEric Blake     .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
662e6fc7ebSEric Blake     .desc = {
672e6fc7ebSEric Blake         {
682e6fc7ebSEric Blake             .name = BLOCK_OPT_SIZE,
692e6fc7ebSEric Blake             .type = QEMU_OPT_SIZE,
702e6fc7ebSEric Blake             .help = "Virtual disk size"
712e6fc7ebSEric Blake         },
722e6fc7ebSEric Blake         { /* end of list */ }
732e6fc7ebSEric Blake     }
742e6fc7ebSEric Blake };
752e6fc7ebSEric Blake 
raw_read_options(QDict * options,uint64_t * offset,bool * has_size,uint64_t * size,Error ** errp)76500e2434SMax Reitz static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
77500e2434SMax Reitz                             uint64_t *size, Error **errp)
782e6fc7ebSEric Blake {
792e6fc7ebSEric Blake     QemuOpts *opts = NULL;
802e6fc7ebSEric Blake     int ret;
812e6fc7ebSEric Blake 
822e6fc7ebSEric Blake     opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
83af175e85SMarkus Armbruster     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
842e6fc7ebSEric Blake         ret = -EINVAL;
852e6fc7ebSEric Blake         goto end;
862e6fc7ebSEric Blake     }
872e6fc7ebSEric Blake 
88500e2434SMax Reitz     *offset = qemu_opt_get_size(opts, "offset", 0);
89500e2434SMax Reitz     *has_size = qemu_opt_find(opts, "size");
90500e2434SMax Reitz     *size = qemu_opt_get_size(opts, "size", 0);
91500e2434SMax Reitz 
92500e2434SMax Reitz     ret = 0;
93500e2434SMax Reitz end:
94500e2434SMax Reitz     qemu_opts_del(opts);
95500e2434SMax Reitz     return ret;
962e6fc7ebSEric Blake }
972e6fc7ebSEric Blake 
981f051dcbSKevin Wolf static int GRAPH_RDLOCK
raw_apply_options(BlockDriverState * bs,BDRVRawState * s,uint64_t offset,bool has_size,uint64_t size,Error ** errp)991f051dcbSKevin Wolf raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
1001f051dcbSKevin Wolf                   bool has_size, uint64_t size, Error **errp)
101500e2434SMax Reitz {
102500e2434SMax Reitz     int64_t real_size = 0;
103500e2434SMax Reitz 
104500e2434SMax Reitz     real_size = bdrv_getlength(bs->file->bs);
105500e2434SMax Reitz     if (real_size < 0) {
106500e2434SMax Reitz         error_setg_errno(errp, -real_size, "Could not get image size");
107500e2434SMax Reitz         return real_size;
1082e6fc7ebSEric Blake     }
1092e6fc7ebSEric Blake 
1102e6fc7ebSEric Blake     /* Check size and offset */
111500e2434SMax Reitz     if (offset > real_size) {
112500e2434SMax Reitz         error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
113500e2434SMax Reitz                    "size of the containing file (%" PRId64 ")",
114500e2434SMax Reitz                    s->offset, real_size);
115500e2434SMax Reitz         return -EINVAL;
116500e2434SMax Reitz     }
117500e2434SMax Reitz 
118500e2434SMax Reitz     if (has_size && (real_size - offset) < size) {
1192e6fc7ebSEric Blake         error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
1202e6fc7ebSEric Blake                    "(%" PRIu64 ") has to be smaller or equal to the "
1212e6fc7ebSEric Blake                    " actual size of the containing file (%" PRId64 ")",
1222e6fc7ebSEric Blake                    s->offset, s->size, real_size);
123500e2434SMax Reitz         return -EINVAL;
1242e6fc7ebSEric Blake     }
1252e6fc7ebSEric Blake 
1262e6fc7ebSEric Blake     /* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
1272e6fc7ebSEric Blake      * up and leaking out of the specified area. */
128500e2434SMax Reitz     if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
1292e6fc7ebSEric Blake         error_setg(errp, "Specified size is not multiple of %llu",
1302e6fc7ebSEric Blake                    BDRV_SECTOR_SIZE);
131500e2434SMax Reitz         return -EINVAL;
1322e6fc7ebSEric Blake     }
1332e6fc7ebSEric Blake 
134500e2434SMax Reitz     s->offset = offset;
135500e2434SMax Reitz     s->has_size = has_size;
136500e2434SMax Reitz     s->size = has_size ? size : real_size - offset;
1372e6fc7ebSEric Blake 
138500e2434SMax Reitz     return 0;
1392e6fc7ebSEric Blake }
1402e6fc7ebSEric Blake 
raw_reopen_prepare(BDRVReopenState * reopen_state,BlockReopenQueue * queue,Error ** errp)1412e6fc7ebSEric Blake static int raw_reopen_prepare(BDRVReopenState *reopen_state,
1422e6fc7ebSEric Blake                               BlockReopenQueue *queue, Error **errp)
1432e6fc7ebSEric Blake {
144500e2434SMax Reitz     bool has_size;
145500e2434SMax Reitz     uint64_t offset, size;
146500e2434SMax Reitz     int ret;
147500e2434SMax Reitz 
1481f051dcbSKevin Wolf     GLOBAL_STATE_CODE();
1491f051dcbSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
1501f051dcbSKevin Wolf 
1512e6fc7ebSEric Blake     assert(reopen_state != NULL);
1522e6fc7ebSEric Blake     assert(reopen_state->bs != NULL);
1532e6fc7ebSEric Blake 
1542e6fc7ebSEric Blake     reopen_state->opaque = g_new0(BDRVRawState, 1);
1552e6fc7ebSEric Blake 
156500e2434SMax Reitz     ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
1572e6fc7ebSEric Blake                            errp);
158500e2434SMax Reitz     if (ret < 0) {
159500e2434SMax Reitz         return ret;
160500e2434SMax Reitz     }
161500e2434SMax Reitz 
162500e2434SMax Reitz     ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
163500e2434SMax Reitz                             offset, has_size, size, errp);
164500e2434SMax Reitz     if (ret < 0) {
165500e2434SMax Reitz         return ret;
166500e2434SMax Reitz     }
167500e2434SMax Reitz 
168500e2434SMax Reitz     return 0;
1692e6fc7ebSEric Blake }
1702e6fc7ebSEric Blake 
raw_reopen_commit(BDRVReopenState * state)1712e6fc7ebSEric Blake static void raw_reopen_commit(BDRVReopenState *state)
1722e6fc7ebSEric Blake {
1732e6fc7ebSEric Blake     BDRVRawState *new_s = state->opaque;
1742e6fc7ebSEric Blake     BDRVRawState *s = state->bs->opaque;
1752e6fc7ebSEric Blake 
1762e6fc7ebSEric Blake     memcpy(s, new_s, sizeof(BDRVRawState));
1772e6fc7ebSEric Blake 
1782e6fc7ebSEric Blake     g_free(state->opaque);
1792e6fc7ebSEric Blake     state->opaque = NULL;
1802e6fc7ebSEric Blake }
1812e6fc7ebSEric Blake 
raw_reopen_abort(BDRVReopenState * state)1822e6fc7ebSEric Blake static void raw_reopen_abort(BDRVReopenState *state)
1832e6fc7ebSEric Blake {
1842e6fc7ebSEric Blake     g_free(state->opaque);
1852e6fc7ebSEric Blake     state->opaque = NULL;
1862e6fc7ebSEric Blake }
1872e6fc7ebSEric Blake 
18838445538SFam Zheng /* Check and adjust the offset, against 'offset' and 'size' options. */
raw_adjust_offset(BlockDriverState * bs,int64_t * offset,int64_t bytes,bool is_write)189f7ef38ddSVladimir Sementsov-Ogievskiy static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
190f7ef38ddSVladimir Sementsov-Ogievskiy                                     int64_t bytes, bool is_write)
19138445538SFam Zheng {
19238445538SFam Zheng     BDRVRawState *s = bs->opaque;
19338445538SFam Zheng 
19438445538SFam Zheng     if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
19538445538SFam Zheng         /* There's not enough space for the write, or the read request is
19638445538SFam Zheng          * out-of-range. Don't read/write anything to prevent leaking out of
19738445538SFam Zheng          * the size specified in options. */
1986d6bcc46SFam Zheng         return is_write ? -ENOSPC : -EINVAL;
19938445538SFam Zheng     }
20038445538SFam Zheng 
20138445538SFam Zheng     if (*offset > INT64_MAX - s->offset) {
20238445538SFam Zheng         return -EINVAL;
20338445538SFam Zheng     }
20438445538SFam Zheng     *offset += s->offset;
20538445538SFam Zheng 
20638445538SFam Zheng     return 0;
20738445538SFam Zheng }
20838445538SFam Zheng 
209b9b10c35SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_preadv(BlockDriverState * bs,int64_t offset,int64_t bytes,QEMUIOVector * qiov,BdrvRequestFlags flags)210b9b10c35SKevin Wolf raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
211b9b10c35SKevin Wolf               QEMUIOVector *qiov, BdrvRequestFlags flags)
2122e6fc7ebSEric Blake {
21338445538SFam Zheng     int ret;
2142e6fc7ebSEric Blake 
21538445538SFam Zheng     ret = raw_adjust_offset(bs, &offset, bytes, false);
21638445538SFam Zheng     if (ret) {
21738445538SFam Zheng         return ret;
2182e6fc7ebSEric Blake     }
2192e6fc7ebSEric Blake 
22017362398SPaolo Bonzini     BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO);
2212e6fc7ebSEric Blake     return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
2222e6fc7ebSEric Blake }
2232e6fc7ebSEric Blake 
224b9b10c35SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_pwritev(BlockDriverState * bs,int64_t offset,int64_t bytes,QEMUIOVector * qiov,BdrvRequestFlags flags)225b9b10c35SKevin Wolf raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
226b9b10c35SKevin Wolf                QEMUIOVector *qiov, BdrvRequestFlags flags)
2272e6fc7ebSEric Blake {
2282e6fc7ebSEric Blake     void *buf = NULL;
2292e6fc7ebSEric Blake     BlockDriver *drv;
2302e6fc7ebSEric Blake     QEMUIOVector local_qiov;
2312e6fc7ebSEric Blake     int ret;
2322e6fc7ebSEric Blake 
2332e6fc7ebSEric Blake     if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
2342e6fc7ebSEric Blake         /* Handling partial writes would be a pain - so we just
2352e6fc7ebSEric Blake          * require that guests have 512-byte request alignment if
2362e6fc7ebSEric Blake          * probing occurred */
2372e6fc7ebSEric Blake         QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512);
2382e6fc7ebSEric Blake         QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512);
2392e6fc7ebSEric Blake         assert(offset == 0 && bytes >= BLOCK_PROBE_BUF_SIZE);
2402e6fc7ebSEric Blake 
2412e6fc7ebSEric Blake         buf = qemu_try_blockalign(bs->file->bs, 512);
2422e6fc7ebSEric Blake         if (!buf) {
2432e6fc7ebSEric Blake             ret = -ENOMEM;
2442e6fc7ebSEric Blake             goto fail;
2452e6fc7ebSEric Blake         }
2462e6fc7ebSEric Blake 
2472e6fc7ebSEric Blake         ret = qemu_iovec_to_buf(qiov, 0, buf, 512);
2482e6fc7ebSEric Blake         if (ret != 512) {
2492e6fc7ebSEric Blake             ret = -EINVAL;
2502e6fc7ebSEric Blake             goto fail;
2512e6fc7ebSEric Blake         }
2522e6fc7ebSEric Blake 
2532e6fc7ebSEric Blake         drv = bdrv_probe_all(buf, 512, NULL);
2542e6fc7ebSEric Blake         if (drv != bs->drv) {
2552e6fc7ebSEric Blake             ret = -EPERM;
2562e6fc7ebSEric Blake             goto fail;
2572e6fc7ebSEric Blake         }
2582e6fc7ebSEric Blake 
2592e6fc7ebSEric Blake         /* Use the checked buffer, a malicious guest might be overwriting its
2602e6fc7ebSEric Blake          * original buffer in the background. */
2612e6fc7ebSEric Blake         qemu_iovec_init(&local_qiov, qiov->niov + 1);
2622e6fc7ebSEric Blake         qemu_iovec_add(&local_qiov, buf, 512);
2632e6fc7ebSEric Blake         qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512);
2642e6fc7ebSEric Blake         qiov = &local_qiov;
265e8b65355SStefan Hajnoczi 
266e8b65355SStefan Hajnoczi         flags &= ~BDRV_REQ_REGISTERED_BUF;
2672e6fc7ebSEric Blake     }
2682e6fc7ebSEric Blake 
269e75abedaSVladimir Sementsov-Ogievskiy     ret = raw_adjust_offset(bs, &offset, bytes, true);
27038445538SFam Zheng     if (ret) {
27138445538SFam Zheng         goto fail;
27238445538SFam Zheng     }
2732e6fc7ebSEric Blake 
27417362398SPaolo Bonzini     BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO);
2752e6fc7ebSEric Blake     ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
2762e6fc7ebSEric Blake 
2772e6fc7ebSEric Blake fail:
2782e6fc7ebSEric Blake     if (qiov == &local_qiov) {
2792e6fc7ebSEric Blake         qemu_iovec_destroy(&local_qiov);
2802e6fc7ebSEric Blake     }
2812e6fc7ebSEric Blake     qemu_vfree(buf);
2822e6fc7ebSEric Blake     return ret;
2832e6fc7ebSEric Blake }
2842e6fc7ebSEric Blake 
28579a55866SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_block_status(BlockDriverState * bs,bool want_zero,int64_t offset,int64_t bytes,int64_t * pnum,int64_t * map,BlockDriverState ** file)28679a55866SKevin Wolf raw_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
28779a55866SKevin Wolf                     int64_t bytes, int64_t *pnum, int64_t *map,
2882e6fc7ebSEric Blake                     BlockDriverState **file)
2892e6fc7ebSEric Blake {
2902e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
291d41aa7e3SEric Blake     *pnum = bytes;
2922e6fc7ebSEric Blake     *file = bs->file->bs;
293d41aa7e3SEric Blake     *map = offset + s->offset;
294d41aa7e3SEric Blake     return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
2952e6fc7ebSEric Blake }
2962e6fc7ebSEric Blake 
297abaf8b75SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_pwrite_zeroes(BlockDriverState * bs,int64_t offset,int64_t bytes,BdrvRequestFlags flags)298abaf8b75SKevin Wolf raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
2992e6fc7ebSEric Blake                      BdrvRequestFlags flags)
3002e6fc7ebSEric Blake {
30138445538SFam Zheng     int ret;
30238445538SFam Zheng 
303f7ef38ddSVladimir Sementsov-Ogievskiy     ret = raw_adjust_offset(bs, &offset, bytes, true);
30438445538SFam Zheng     if (ret) {
30538445538SFam Zheng         return ret;
3062e6fc7ebSEric Blake     }
307f5a5ca79SManos Pitsidianakis     return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
3082e6fc7ebSEric Blake }
3092e6fc7ebSEric Blake 
3109a5a1c62SEmanuele Giuseppe Esposito static int coroutine_fn GRAPH_RDLOCK
raw_co_pdiscard(BlockDriverState * bs,int64_t offset,int64_t bytes)3119a5a1c62SEmanuele Giuseppe Esposito raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
3122e6fc7ebSEric Blake {
31338445538SFam Zheng     int ret;
31438445538SFam Zheng 
315f7ef38ddSVladimir Sementsov-Ogievskiy     ret = raw_adjust_offset(bs, &offset, bytes, true);
31638445538SFam Zheng     if (ret) {
31738445538SFam Zheng         return ret;
3182e6fc7ebSEric Blake     }
3190b9fd3f4SFam Zheng     return bdrv_co_pdiscard(bs->file, offset, bytes);
3202e6fc7ebSEric Blake }
3212e6fc7ebSEric Blake 
32250c4bcd4SSam Li static int coroutine_fn GRAPH_RDLOCK
raw_co_zone_report(BlockDriverState * bs,int64_t offset,unsigned int * nr_zones,BlockZoneDescriptor * zones)32350c4bcd4SSam Li raw_co_zone_report(BlockDriverState *bs, int64_t offset,
32450c4bcd4SSam Li                    unsigned int *nr_zones,
32550c4bcd4SSam Li                    BlockZoneDescriptor *zones)
32650c4bcd4SSam Li {
32750c4bcd4SSam Li     return bdrv_co_zone_report(bs->file->bs, offset, nr_zones, zones);
32850c4bcd4SSam Li }
32950c4bcd4SSam Li 
33050c4bcd4SSam Li static int coroutine_fn GRAPH_RDLOCK
raw_co_zone_mgmt(BlockDriverState * bs,BlockZoneOp op,int64_t offset,int64_t len)33150c4bcd4SSam Li raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
33250c4bcd4SSam Li                  int64_t offset, int64_t len)
33350c4bcd4SSam Li {
33450c4bcd4SSam Li     return bdrv_co_zone_mgmt(bs->file->bs, op, offset, len);
33550c4bcd4SSam Li }
33650c4bcd4SSam Li 
3374751d09aSSam Li static int coroutine_fn GRAPH_RDLOCK
raw_co_zone_append(BlockDriverState * bs,int64_t * offset,QEMUIOVector * qiov,BdrvRequestFlags flags)3384751d09aSSam Li raw_co_zone_append(BlockDriverState *bs,int64_t *offset, QEMUIOVector *qiov,
3394751d09aSSam Li                    BdrvRequestFlags flags)
3404751d09aSSam Li {
3414751d09aSSam Li     return bdrv_co_zone_append(bs->file->bs, offset, qiov, flags);
3424751d09aSSam Li }
3434751d09aSSam Li 
3448ab8140aSKevin Wolf static int64_t coroutine_fn GRAPH_RDLOCK
raw_co_getlength(BlockDriverState * bs)3458ab8140aSKevin Wolf raw_co_getlength(BlockDriverState *bs)
3462e6fc7ebSEric Blake {
3472e6fc7ebSEric Blake     int64_t len;
3482e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
3492e6fc7ebSEric Blake 
3502e6fc7ebSEric Blake     /* Update size. It should not change unless the file was externally
3512e6fc7ebSEric Blake      * modified. */
352c86422c5SEmanuele Giuseppe Esposito     len = bdrv_co_getlength(bs->file->bs);
3532e6fc7ebSEric Blake     if (len < 0) {
3542e6fc7ebSEric Blake         return len;
3552e6fc7ebSEric Blake     }
3562e6fc7ebSEric Blake 
3572e6fc7ebSEric Blake     if (len < s->offset) {
3582e6fc7ebSEric Blake         s->size = 0;
3592e6fc7ebSEric Blake     } else {
3602e6fc7ebSEric Blake         if (s->has_size) {
3612e6fc7ebSEric Blake             /* Try to honour the size */
3622e6fc7ebSEric Blake             s->size = MIN(s->size, len - s->offset);
3632e6fc7ebSEric Blake         } else {
3642e6fc7ebSEric Blake             s->size = len - s->offset;
3652e6fc7ebSEric Blake         }
3662e6fc7ebSEric Blake     }
3672e6fc7ebSEric Blake 
3682e6fc7ebSEric Blake     return s->size;
3692e6fc7ebSEric Blake }
3702e6fc7ebSEric Blake 
raw_measure(QemuOpts * opts,BlockDriverState * in_bs,Error ** errp)371a843a22aSStefan Hajnoczi static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
372a843a22aSStefan Hajnoczi                                      Error **errp)
373a843a22aSStefan Hajnoczi {
374a843a22aSStefan Hajnoczi     BlockMeasureInfo *info;
375a843a22aSStefan Hajnoczi     int64_t required;
376a843a22aSStefan Hajnoczi 
377a843a22aSStefan Hajnoczi     if (in_bs) {
378a843a22aSStefan Hajnoczi         required = bdrv_getlength(in_bs);
379a843a22aSStefan Hajnoczi         if (required < 0) {
380a843a22aSStefan Hajnoczi             error_setg_errno(errp, -required, "Unable to get image size");
381a843a22aSStefan Hajnoczi             return NULL;
382a843a22aSStefan Hajnoczi         }
383a843a22aSStefan Hajnoczi     } else {
384a843a22aSStefan Hajnoczi         required = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
385a843a22aSStefan Hajnoczi                             BDRV_SECTOR_SIZE);
386a843a22aSStefan Hajnoczi     }
387a843a22aSStefan Hajnoczi 
3885d72c68bSEric Blake     info = g_new0(BlockMeasureInfo, 1);
389a843a22aSStefan Hajnoczi     info->required = required;
390a843a22aSStefan Hajnoczi 
391a843a22aSStefan Hajnoczi     /* Unallocated sectors count towards the file size in raw images */
392a843a22aSStefan Hajnoczi     info->fully_allocated = info->required;
393a843a22aSStefan Hajnoczi     return info;
394a843a22aSStefan Hajnoczi }
395a843a22aSStefan Hajnoczi 
396a00e70c0SEmanuele Giuseppe Esposito static int coroutine_fn GRAPH_RDLOCK
raw_co_get_info(BlockDriverState * bs,BlockDriverInfo * bdi)3973d47eb0aSEmanuele Giuseppe Esposito raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
3982e6fc7ebSEric Blake {
3993d47eb0aSEmanuele Giuseppe Esposito     return bdrv_co_get_info(bs->file->bs, bdi);
4002e6fc7ebSEric Blake }
4012e6fc7ebSEric Blake 
raw_refresh_limits(BlockDriverState * bs,Error ** errp)40279a55866SKevin Wolf static void GRAPH_RDLOCK raw_refresh_limits(BlockDriverState *bs, Error **errp)
4032e6fc7ebSEric Blake {
4048c6f27e7SPaolo Bonzini     bs->bl.has_variable_length = bs->file->bs->bl.has_variable_length;
4058c6f27e7SPaolo Bonzini 
4062e6fc7ebSEric Blake     if (bs->probed) {
4072e6fc7ebSEric Blake         /* To make it easier to protect the first sector, any probed
4082e6fc7ebSEric Blake          * image is restricted to read-modify-write on sub-sector
4092e6fc7ebSEric Blake          * operations. */
4102e6fc7ebSEric Blake         bs->bl.request_alignment = BDRV_SECTOR_SIZE;
4112e6fc7ebSEric Blake     }
4122e6fc7ebSEric Blake }
4132e6fc7ebSEric Blake 
414c2b8e315SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_truncate(BlockDriverState * bs,int64_t offset,bool exact,PreallocMode prealloc,BdrvRequestFlags flags,Error ** errp)415c2b8e315SKevin Wolf raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
416c2b8e315SKevin Wolf                 PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
4172e6fc7ebSEric Blake {
4182e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
4192e6fc7ebSEric Blake 
4202e6fc7ebSEric Blake     if (s->has_size) {
421f59adb32SMax Reitz         error_setg(errp, "Cannot resize fixed-size raw disks");
4222e6fc7ebSEric Blake         return -ENOTSUP;
4232e6fc7ebSEric Blake     }
4242e6fc7ebSEric Blake 
4252e6fc7ebSEric Blake     if (INT64_MAX - offset < s->offset) {
426f59adb32SMax Reitz         error_setg(errp, "Disk size too large for the chosen offset");
4272e6fc7ebSEric Blake         return -EINVAL;
4282e6fc7ebSEric Blake     }
4292e6fc7ebSEric Blake 
4302e6fc7ebSEric Blake     s->size = offset;
4312e6fc7ebSEric Blake     offset += s->offset;
4321ddaabaeSKevin Wolf     return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
4332e6fc7ebSEric Blake }
4342e6fc7ebSEric Blake 
43579a292e5SKevin Wolf static void coroutine_fn GRAPH_RDLOCK
raw_co_eject(BlockDriverState * bs,bool eject_flag)43679a292e5SKevin Wolf raw_co_eject(BlockDriverState *bs, bool eject_flag)
4372e6fc7ebSEric Blake {
4382531b390SEmanuele Giuseppe Esposito     bdrv_co_eject(bs->file->bs, eject_flag);
4392e6fc7ebSEric Blake }
4402e6fc7ebSEric Blake 
44179a292e5SKevin Wolf static void coroutine_fn GRAPH_RDLOCK
raw_co_lock_medium(BlockDriverState * bs,bool locked)44279a292e5SKevin Wolf raw_co_lock_medium(BlockDriverState *bs, bool locked)
4432e6fc7ebSEric Blake {
4442c75261cSEmanuele Giuseppe Esposito     bdrv_co_lock_medium(bs->file->bs, locked);
4452e6fc7ebSEric Blake }
4462e6fc7ebSEric Blake 
44726c518abSKevin Wolf static int coroutine_fn GRAPH_RDLOCK
raw_co_ioctl(BlockDriverState * bs,unsigned long int req,void * buf)44826c518abSKevin Wolf raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
4492e6fc7ebSEric Blake {
4502e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
4512e6fc7ebSEric Blake     if (s->offset || s->has_size) {
4522e6fc7ebSEric Blake         return -ENOTSUP;
4532e6fc7ebSEric Blake     }
4542e6fc7ebSEric Blake     return bdrv_co_ioctl(bs->file->bs, req, buf);
4552e6fc7ebSEric Blake }
4562e6fc7ebSEric Blake 
raw_has_zero_init(BlockDriverState * bs)45706717986SKevin Wolf static int GRAPH_RDLOCK raw_has_zero_init(BlockDriverState *bs)
4582e6fc7ebSEric Blake {
4592e6fc7ebSEric Blake     return bdrv_has_zero_init(bs->file->bs);
4602e6fc7ebSEric Blake }
4612e6fc7ebSEric Blake 
4624db7ba3bSKevin Wolf static int coroutine_fn GRAPH_UNLOCKED
raw_co_create_opts(BlockDriver * drv,const char * filename,QemuOpts * opts,Error ** errp)4634ec8df01SKevin Wolf raw_co_create_opts(BlockDriver *drv, const char *filename,
4644ec8df01SKevin Wolf                    QemuOpts *opts, Error **errp)
4652e6fc7ebSEric Blake {
4662475a0d0SEmanuele Giuseppe Esposito     return bdrv_co_create_file(filename, opts, errp);
4672e6fc7ebSEric Blake }
4682e6fc7ebSEric Blake 
raw_open(BlockDriverState * bs,QDict * options,int flags,Error ** errp)4692e6fc7ebSEric Blake static int raw_open(BlockDriverState *bs, QDict *options, int flags,
4702e6fc7ebSEric Blake                     Error **errp)
4712e6fc7ebSEric Blake {
4722e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
473500e2434SMax Reitz     bool has_size;
474500e2434SMax Reitz     uint64_t offset, size;
47558944401SMax Reitz     BdrvChildRole file_role;
4762e6fc7ebSEric Blake     int ret;
4772e6fc7ebSEric Blake 
478a4b740dbSKevin Wolf     GLOBAL_STATE_CODE();
479a4b740dbSKevin Wolf 
480500e2434SMax Reitz     ret = raw_read_options(options, &offset, &has_size, &size, errp);
481500e2434SMax Reitz     if (ret < 0) {
482500e2434SMax Reitz         return ret;
483500e2434SMax Reitz     }
484500e2434SMax Reitz 
48558944401SMax Reitz     /*
48658944401SMax Reitz      * Without offset and a size limit, this driver behaves very much
48758944401SMax Reitz      * like a filter.  With any such limit, it does not.
48858944401SMax Reitz      */
48958944401SMax Reitz     if (offset || has_size) {
49058944401SMax Reitz         file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
49158944401SMax Reitz     } else {
49258944401SMax Reitz         file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
49358944401SMax Reitz     }
49458944401SMax Reitz 
4955bb04747SVladimir Sementsov-Ogievskiy     bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
49658944401SMax Reitz                     file_role, false, errp);
497a4b740dbSKevin Wolf 
498a4b740dbSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
4994e4bf5c4SKevin Wolf     if (!bs->file) {
5004e4bf5c4SKevin Wolf         return -EINVAL;
5014e4bf5c4SKevin Wolf     }
5024e4bf5c4SKevin Wolf 
503006e1962SDenis V. Lunev     bs->sg = bdrv_is_sg(bs->file->bs);
504228345bfSMax Reitz     bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
505228345bfSMax Reitz         (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
506228345bfSMax Reitz     bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
50780f5c33fSKevin Wolf         ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
508228345bfSMax Reitz             bs->file->bs->supported_zero_flags);
5091ddaabaeSKevin Wolf     bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
5101ddaabaeSKevin Wolf                                    BDRV_REQ_ZERO_WRITE;
5112e6fc7ebSEric Blake 
5122e6fc7ebSEric Blake     if (bs->probed && !bdrv_is_read_only(bs)) {
513f30c66baSMax Reitz         bdrv_refresh_filename(bs->file->bs);
5142e6fc7ebSEric Blake         fprintf(stderr,
5152e6fc7ebSEric Blake                 "WARNING: Image format was not specified for '%s' and probing "
5162e6fc7ebSEric Blake                 "guessed raw.\n"
5172e6fc7ebSEric Blake                 "         Automatically detecting the format is dangerous for "
5182e6fc7ebSEric Blake                 "raw images, write operations on block 0 will be restricted.\n"
5192e6fc7ebSEric Blake                 "         Specify the 'raw' format explicitly to remove the "
5202e6fc7ebSEric Blake                 "restrictions.\n",
5212e6fc7ebSEric Blake                 bs->file->bs->filename);
5222e6fc7ebSEric Blake     }
5232e6fc7ebSEric Blake 
524500e2434SMax Reitz     ret = raw_apply_options(bs, s, offset, has_size, size, errp);
5252e6fc7ebSEric Blake     if (ret < 0) {
5262e6fc7ebSEric Blake         return ret;
5272e6fc7ebSEric Blake     }
5282e6fc7ebSEric Blake 
529006e1962SDenis V. Lunev     if (bdrv_is_sg(bs) && (s->offset || s->has_size)) {
5302e6fc7ebSEric Blake         error_setg(errp, "Cannot use offset/size with SCSI generic devices");
5312e6fc7ebSEric Blake         return -EINVAL;
5322e6fc7ebSEric Blake     }
5332e6fc7ebSEric Blake 
5342e6fc7ebSEric Blake     return 0;
5352e6fc7ebSEric Blake }
5362e6fc7ebSEric Blake 
raw_probe(const uint8_t * buf,int buf_size,const char * filename)5372e6fc7ebSEric Blake static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
5382e6fc7ebSEric Blake {
5392e6fc7ebSEric Blake     /* smallest possible positive score so that raw is used if and only if no
5402e6fc7ebSEric Blake      * other block driver works
5412e6fc7ebSEric Blake      */
5422e6fc7ebSEric Blake     return 1;
5432e6fc7ebSEric Blake }
5442e6fc7ebSEric Blake 
545221caadcSKevin Wolf static int GRAPH_RDLOCK
raw_probe_blocksizes(BlockDriverState * bs,BlockSizes * bsz)546221caadcSKevin Wolf raw_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
5472e6fc7ebSEric Blake {
5482e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
5492e6fc7ebSEric Blake     int ret;
5502e6fc7ebSEric Blake 
5512e6fc7ebSEric Blake     ret = bdrv_probe_blocksizes(bs->file->bs, bsz);
5522e6fc7ebSEric Blake     if (ret < 0) {
5532e6fc7ebSEric Blake         return ret;
5542e6fc7ebSEric Blake     }
5552e6fc7ebSEric Blake 
5562e6fc7ebSEric Blake     if (!QEMU_IS_ALIGNED(s->offset, MAX(bsz->log, bsz->phys))) {
5572e6fc7ebSEric Blake         return -ENOTSUP;
5582e6fc7ebSEric Blake     }
5592e6fc7ebSEric Blake 
5602e6fc7ebSEric Blake     return 0;
5612e6fc7ebSEric Blake }
5622e6fc7ebSEric Blake 
56379a55866SKevin Wolf static int GRAPH_RDLOCK
raw_probe_geometry(BlockDriverState * bs,HDGeometry * geo)56479a55866SKevin Wolf raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
5652e6fc7ebSEric Blake {
5662e6fc7ebSEric Blake     BDRVRawState *s = bs->opaque;
5672e6fc7ebSEric Blake     if (s->offset || s->has_size) {
5682e6fc7ebSEric Blake         return -ENOTSUP;
5692e6fc7ebSEric Blake     }
5702e6fc7ebSEric Blake     return bdrv_probe_geometry(bs->file->bs, geo);
5712e6fc7ebSEric Blake }
5722e6fc7ebSEric Blake 
573742bf09bSEmanuele Giuseppe Esposito static int coroutine_fn GRAPH_RDLOCK
raw_co_copy_range_from(BlockDriverState * bs,BdrvChild * src,int64_t src_offset,BdrvChild * dst,int64_t dst_offset,int64_t bytes,BdrvRequestFlags read_flags,BdrvRequestFlags write_flags)574742bf09bSEmanuele Giuseppe Esposito raw_co_copy_range_from(BlockDriverState *bs,
575742bf09bSEmanuele Giuseppe Esposito                        BdrvChild *src, int64_t src_offset,
576742bf09bSEmanuele Giuseppe Esposito                        BdrvChild *dst, int64_t dst_offset,
577742bf09bSEmanuele Giuseppe Esposito                        int64_t bytes, BdrvRequestFlags read_flags,
57867b51fb9SVladimir Sementsov-Ogievskiy                        BdrvRequestFlags write_flags)
57972d219e2SFam Zheng {
58072d219e2SFam Zheng     int ret;
58172d219e2SFam Zheng 
58248535049SVladimir Sementsov-Ogievskiy     ret = raw_adjust_offset(bs, &src_offset, bytes, false);
58372d219e2SFam Zheng     if (ret) {
58472d219e2SFam Zheng         return ret;
58572d219e2SFam Zheng     }
58672d219e2SFam Zheng     return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
58767b51fb9SVladimir Sementsov-Ogievskiy                                    bytes, read_flags, write_flags);
58872d219e2SFam Zheng }
58972d219e2SFam Zheng 
590742bf09bSEmanuele Giuseppe Esposito static int coroutine_fn GRAPH_RDLOCK
raw_co_copy_range_to(BlockDriverState * bs,BdrvChild * src,int64_t src_offset,BdrvChild * dst,int64_t dst_offset,int64_t bytes,BdrvRequestFlags read_flags,BdrvRequestFlags write_flags)591742bf09bSEmanuele Giuseppe Esposito raw_co_copy_range_to(BlockDriverState *bs,
592742bf09bSEmanuele Giuseppe Esposito                      BdrvChild *src, int64_t src_offset,
593742bf09bSEmanuele Giuseppe Esposito                      BdrvChild *dst, int64_t dst_offset,
594742bf09bSEmanuele Giuseppe Esposito                      int64_t bytes, BdrvRequestFlags read_flags,
59567b51fb9SVladimir Sementsov-Ogievskiy                      BdrvRequestFlags write_flags)
59672d219e2SFam Zheng {
59772d219e2SFam Zheng     int ret;
59872d219e2SFam Zheng 
59948535049SVladimir Sementsov-Ogievskiy     ret = raw_adjust_offset(bs, &dst_offset, bytes, true);
60072d219e2SFam Zheng     if (ret) {
60172d219e2SFam Zheng         return ret;
60272d219e2SFam Zheng     }
60372d219e2SFam Zheng     return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
60467b51fb9SVladimir Sementsov-Ogievskiy                                  read_flags, write_flags);
60572d219e2SFam Zheng }
60672d219e2SFam Zheng 
6072654267cSMax Reitz static const char *const raw_strong_runtime_opts[] = {
6082654267cSMax Reitz     "offset",
6092654267cSMax Reitz     "size",
6102654267cSMax Reitz 
6112654267cSMax Reitz     NULL
6122654267cSMax Reitz };
6132654267cSMax Reitz 
raw_cancel_in_flight(BlockDriverState * bs)61479a55866SKevin Wolf static void GRAPH_RDLOCK raw_cancel_in_flight(BlockDriverState *bs)
6153fc1ec37SVladimir Sementsov-Ogievskiy {
6163fc1ec37SVladimir Sementsov-Ogievskiy     bdrv_cancel_in_flight(bs->file->bs);
6173fc1ec37SVladimir Sementsov-Ogievskiy }
6183fc1ec37SVladimir Sementsov-Ogievskiy 
raw_child_perm(BlockDriverState * bs,BdrvChild * c,BdrvChildRole role,BlockReopenQueue * reopen_queue,uint64_t parent_perm,uint64_t parent_shared,uint64_t * nperm,uint64_t * nshared)619b68ce824SStefan Hajnoczi static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
620b68ce824SStefan Hajnoczi                            BdrvChildRole role,
621b68ce824SStefan Hajnoczi                            BlockReopenQueue *reopen_queue,
622b68ce824SStefan Hajnoczi                            uint64_t parent_perm, uint64_t parent_shared,
623b68ce824SStefan Hajnoczi                            uint64_t *nperm, uint64_t *nshared)
624b68ce824SStefan Hajnoczi {
625b68ce824SStefan Hajnoczi     bdrv_default_perms(bs, c, role, reopen_queue, parent_perm,
626b68ce824SStefan Hajnoczi                        parent_shared, nperm, nshared);
627b68ce824SStefan Hajnoczi 
628b68ce824SStefan Hajnoczi     /*
629b68ce824SStefan Hajnoczi      * bdrv_default_perms() may add WRITE and/or RESIZE (see comment in
630b68ce824SStefan Hajnoczi      * bdrv_default_perms_for_storage() for an explanation) but we only need
631b68ce824SStefan Hajnoczi      * them if they are in parent_perm. Drop WRITE and RESIZE whenever possible
632b68ce824SStefan Hajnoczi      * to avoid permission conflicts.
633b68ce824SStefan Hajnoczi      */
634b68ce824SStefan Hajnoczi     *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
635b68ce824SStefan Hajnoczi     *nperm |= parent_perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
636b68ce824SStefan Hajnoczi }
637b68ce824SStefan Hajnoczi 
6382e6fc7ebSEric Blake BlockDriver bdrv_raw = {
6392e6fc7ebSEric Blake     .format_name          = "raw",
6402e6fc7ebSEric Blake     .instance_size        = sizeof(BDRVRawState),
641774c726cSSam Li     .supports_zoned_children = true,
6422e6fc7ebSEric Blake     .bdrv_probe           = &raw_probe,
6432e6fc7ebSEric Blake     .bdrv_reopen_prepare  = &raw_reopen_prepare,
6442e6fc7ebSEric Blake     .bdrv_reopen_commit   = &raw_reopen_commit,
6452e6fc7ebSEric Blake     .bdrv_reopen_abort    = &raw_reopen_abort,
6462e6fc7ebSEric Blake     .bdrv_open            = &raw_open,
647b68ce824SStefan Hajnoczi     .bdrv_child_perm      = raw_child_perm,
648efc75e2aSStefan Hajnoczi     .bdrv_co_create_opts  = &raw_co_create_opts,
6492e6fc7ebSEric Blake     .bdrv_co_preadv       = &raw_co_preadv,
6502e6fc7ebSEric Blake     .bdrv_co_pwritev      = &raw_co_pwritev,
6512e6fc7ebSEric Blake     .bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
6522e6fc7ebSEric Blake     .bdrv_co_pdiscard     = &raw_co_pdiscard,
65350c4bcd4SSam Li     .bdrv_co_zone_report  = &raw_co_zone_report,
65450c4bcd4SSam Li     .bdrv_co_zone_mgmt  = &raw_co_zone_mgmt,
6554751d09aSSam Li     .bdrv_co_zone_append = &raw_co_zone_append,
656d41aa7e3SEric Blake     .bdrv_co_block_status = &raw_co_block_status,
65772d219e2SFam Zheng     .bdrv_co_copy_range_from = &raw_co_copy_range_from,
65872d219e2SFam Zheng     .bdrv_co_copy_range_to  = &raw_co_copy_range_to,
659061ca8a3SKevin Wolf     .bdrv_co_truncate     = &raw_co_truncate,
660c86422c5SEmanuele Giuseppe Esposito     .bdrv_co_getlength    = &raw_co_getlength,
661d67066d8SMax Reitz     .is_format            = true,
662a843a22aSStefan Hajnoczi     .bdrv_measure         = &raw_measure,
6633d47eb0aSEmanuele Giuseppe Esposito     .bdrv_co_get_info     = &raw_co_get_info,
6642e6fc7ebSEric Blake     .bdrv_refresh_limits  = &raw_refresh_limits,
6652e6fc7ebSEric Blake     .bdrv_probe_blocksizes = &raw_probe_blocksizes,
6662e6fc7ebSEric Blake     .bdrv_probe_geometry  = &raw_probe_geometry,
6672531b390SEmanuele Giuseppe Esposito     .bdrv_co_eject        = &raw_co_eject,
6682c75261cSEmanuele Giuseppe Esposito     .bdrv_co_lock_medium  = &raw_co_lock_medium,
6692e6fc7ebSEric Blake     .bdrv_co_ioctl        = &raw_co_ioctl,
6702e6fc7ebSEric Blake     .create_opts          = &raw_create_opts,
6712654267cSMax Reitz     .bdrv_has_zero_init   = &raw_has_zero_init,
6722654267cSMax Reitz     .strong_runtime_opts  = raw_strong_runtime_opts,
6738a2ce0bcSAlberto Garcia     .mutable_opts         = mutable_opts,
6743fc1ec37SVladimir Sementsov-Ogievskiy     .bdrv_cancel_in_flight = raw_cancel_in_flight,
6752e6fc7ebSEric Blake };
6762e6fc7ebSEric Blake 
bdrv_raw_init(void)6772e6fc7ebSEric Blake static void bdrv_raw_init(void)
6782e6fc7ebSEric Blake {
6792e6fc7ebSEric Blake     bdrv_register(&bdrv_raw);
6802e6fc7ebSEric Blake }
6812e6fc7ebSEric Blake 
6822e6fc7ebSEric Blake block_init(bdrv_raw_init);
683