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 ")",
114*a22bd366SKevin Wolf 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 ")",
122*a22bd366SKevin Wolf offset, 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