1 /* BlockDriver implementation for "raw"
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>
8 * Laszlo Ersek <lersek@redhat.com>
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
29 #include "qemu/osdep.h"
30 #include "block/block_int.h"
31 #include "qapi/error.h"
32 #include "qemu/option.h"
34 typedef struct BDRVRawState
{
40 static QemuOptsList raw_runtime_opts
= {
42 .head
= QTAILQ_HEAD_INITIALIZER(raw_runtime_opts
.head
),
46 .type
= QEMU_OPT_SIZE
,
47 .help
= "offset in the disk where the image starts",
51 .type
= QEMU_OPT_SIZE
,
52 .help
= "virtual disk size",
58 static QemuOptsList raw_create_opts
= {
59 .name
= "raw-create-opts",
60 .head
= QTAILQ_HEAD_INITIALIZER(raw_create_opts
.head
),
63 .name
= BLOCK_OPT_SIZE
,
64 .type
= QEMU_OPT_SIZE
,
65 .help
= "Virtual disk size"
71 static int raw_read_options(QDict
*options
, BlockDriverState
*bs
,
72 BDRVRawState
*s
, Error
**errp
)
74 Error
*local_err
= NULL
;
75 QemuOpts
*opts
= NULL
;
76 int64_t real_size
= 0;
79 real_size
= bdrv_getlength(bs
->file
->bs
);
81 error_setg_errno(errp
, -real_size
, "Could not get image size");
85 opts
= qemu_opts_create(&raw_runtime_opts
, NULL
, 0, &error_abort
);
86 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
88 error_propagate(errp
, local_err
);
93 s
->offset
= qemu_opt_get_size(opts
, "offset", 0);
94 if (s
->offset
> real_size
) {
95 error_setg(errp
, "Offset (%" PRIu64
") cannot be greater than "
96 "size of the containing file (%" PRId64
")",
97 s
->offset
, real_size
);
102 if (qemu_opt_find(opts
, "size") != NULL
) {
103 s
->size
= qemu_opt_get_size(opts
, "size", 0);
107 s
->size
= real_size
- s
->offset
;
110 /* Check size and offset */
111 if ((real_size
- s
->offset
) < s
->size
) {
112 error_setg(errp
, "The sum of offset (%" PRIu64
") and size "
113 "(%" PRIu64
") has to be smaller or equal to the "
114 " actual size of the containing file (%" PRId64
")",
115 s
->offset
, s
->size
, real_size
);
120 /* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
121 * up and leaking out of the specified area. */
122 if (s
->has_size
&& !QEMU_IS_ALIGNED(s
->size
, BDRV_SECTOR_SIZE
)) {
123 error_setg(errp
, "Specified size is not multiple of %llu",
138 static int raw_reopen_prepare(BDRVReopenState
*reopen_state
,
139 BlockReopenQueue
*queue
, Error
**errp
)
141 assert(reopen_state
!= NULL
);
142 assert(reopen_state
->bs
!= NULL
);
144 reopen_state
->opaque
= g_new0(BDRVRawState
, 1);
146 return raw_read_options(
147 reopen_state
->options
,
149 reopen_state
->opaque
,
153 static void raw_reopen_commit(BDRVReopenState
*state
)
155 BDRVRawState
*new_s
= state
->opaque
;
156 BDRVRawState
*s
= state
->bs
->opaque
;
158 memcpy(s
, new_s
, sizeof(BDRVRawState
));
160 g_free(state
->opaque
);
161 state
->opaque
= NULL
;
164 static void raw_reopen_abort(BDRVReopenState
*state
)
166 g_free(state
->opaque
);
167 state
->opaque
= NULL
;
170 static int coroutine_fn
raw_co_preadv(BlockDriverState
*bs
, uint64_t offset
,
171 uint64_t bytes
, QEMUIOVector
*qiov
,
174 BDRVRawState
*s
= bs
->opaque
;
176 if (offset
> UINT64_MAX
- s
->offset
) {
181 BLKDBG_EVENT(bs
->file
, BLKDBG_READ_AIO
);
182 return bdrv_co_preadv(bs
->file
, offset
, bytes
, qiov
, flags
);
185 static int coroutine_fn
raw_co_pwritev(BlockDriverState
*bs
, uint64_t offset
,
186 uint64_t bytes
, QEMUIOVector
*qiov
,
189 BDRVRawState
*s
= bs
->opaque
;
192 QEMUIOVector local_qiov
;
195 if (s
->has_size
&& (offset
> s
->size
|| bytes
> (s
->size
- offset
))) {
196 /* There's not enough space for the data. Don't write anything and just
197 * fail to prevent leaking out of the size specified in options. */
201 if (offset
> UINT64_MAX
- s
->offset
) {
206 if (bs
->probed
&& offset
< BLOCK_PROBE_BUF_SIZE
&& bytes
) {
207 /* Handling partial writes would be a pain - so we just
208 * require that guests have 512-byte request alignment if
209 * probing occurred */
210 QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE
!= 512);
211 QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE
!= 512);
212 assert(offset
== 0 && bytes
>= BLOCK_PROBE_BUF_SIZE
);
214 buf
= qemu_try_blockalign(bs
->file
->bs
, 512);
220 ret
= qemu_iovec_to_buf(qiov
, 0, buf
, 512);
226 drv
= bdrv_probe_all(buf
, 512, NULL
);
227 if (drv
!= bs
->drv
) {
232 /* Use the checked buffer, a malicious guest might be overwriting its
233 * original buffer in the background. */
234 qemu_iovec_init(&local_qiov
, qiov
->niov
+ 1);
235 qemu_iovec_add(&local_qiov
, buf
, 512);
236 qemu_iovec_concat(&local_qiov
, qiov
, 512, qiov
->size
- 512);
242 BLKDBG_EVENT(bs
->file
, BLKDBG_WRITE_AIO
);
243 ret
= bdrv_co_pwritev(bs
->file
, offset
, bytes
, qiov
, flags
);
246 if (qiov
== &local_qiov
) {
247 qemu_iovec_destroy(&local_qiov
);
253 static int64_t coroutine_fn
raw_co_get_block_status(BlockDriverState
*bs
,
255 int nb_sectors
, int *pnum
,
256 BlockDriverState
**file
)
258 BDRVRawState
*s
= bs
->opaque
;
260 *file
= bs
->file
->bs
;
261 sector_num
+= s
->offset
/ BDRV_SECTOR_SIZE
;
262 return BDRV_BLOCK_RAW
| BDRV_BLOCK_OFFSET_VALID
| BDRV_BLOCK_DATA
|
263 (sector_num
<< BDRV_SECTOR_BITS
);
266 static int coroutine_fn
raw_co_pwrite_zeroes(BlockDriverState
*bs
,
267 int64_t offset
, int count
,
268 BdrvRequestFlags flags
)
270 BDRVRawState
*s
= bs
->opaque
;
271 if (offset
> UINT64_MAX
- s
->offset
) {
275 return bdrv_co_pwrite_zeroes(bs
->file
, offset
, count
, flags
);
278 static int coroutine_fn
raw_co_pdiscard(BlockDriverState
*bs
,
279 int64_t offset
, int count
)
281 BDRVRawState
*s
= bs
->opaque
;
282 if (offset
> UINT64_MAX
- s
->offset
) {
286 return bdrv_co_pdiscard(bs
->file
->bs
, offset
, count
);
289 static int64_t raw_getlength(BlockDriverState
*bs
)
292 BDRVRawState
*s
= bs
->opaque
;
294 /* Update size. It should not change unless the file was externally
296 len
= bdrv_getlength(bs
->file
->bs
);
301 if (len
< s
->offset
) {
305 /* Try to honour the size */
306 s
->size
= MIN(s
->size
, len
- s
->offset
);
308 s
->size
= len
- s
->offset
;
315 static int raw_get_info(BlockDriverState
*bs
, BlockDriverInfo
*bdi
)
317 return bdrv_get_info(bs
->file
->bs
, bdi
);
320 static void raw_refresh_limits(BlockDriverState
*bs
, Error
**errp
)
323 /* To make it easier to protect the first sector, any probed
324 * image is restricted to read-modify-write on sub-sector
326 bs
->bl
.request_alignment
= BDRV_SECTOR_SIZE
;
330 static int raw_truncate(BlockDriverState
*bs
, int64_t offset
)
332 BDRVRawState
*s
= bs
->opaque
;
338 if (INT64_MAX
- offset
< s
->offset
) {
344 return bdrv_truncate(bs
->file
->bs
, offset
);
347 static int raw_media_changed(BlockDriverState
*bs
)
349 return bdrv_media_changed(bs
->file
->bs
);
352 static void raw_eject(BlockDriverState
*bs
, bool eject_flag
)
354 bdrv_eject(bs
->file
->bs
, eject_flag
);
357 static void raw_lock_medium(BlockDriverState
*bs
, bool locked
)
359 bdrv_lock_medium(bs
->file
->bs
, locked
);
362 static int raw_co_ioctl(BlockDriverState
*bs
, unsigned long int req
, void *buf
)
364 BDRVRawState
*s
= bs
->opaque
;
365 if (s
->offset
|| s
->has_size
) {
368 return bdrv_co_ioctl(bs
->file
->bs
, req
, buf
);
371 static int raw_has_zero_init(BlockDriverState
*bs
)
373 return bdrv_has_zero_init(bs
->file
->bs
);
376 static int raw_create(const char *filename
, QemuOpts
*opts
, Error
**errp
)
378 return bdrv_create_file(filename
, opts
, errp
);
381 static int raw_open(BlockDriverState
*bs
, QDict
*options
, int flags
,
384 BDRVRawState
*s
= bs
->opaque
;
387 bs
->sg
= bs
->file
->bs
->sg
;
388 bs
->supported_write_flags
= BDRV_REQ_FUA
&
389 bs
->file
->bs
->supported_write_flags
;
390 bs
->supported_zero_flags
= (BDRV_REQ_FUA
| BDRV_REQ_MAY_UNMAP
) &
391 bs
->file
->bs
->supported_zero_flags
;
393 if (bs
->probed
&& !bdrv_is_read_only(bs
)) {
395 "WARNING: Image format was not specified for '%s' and probing "
397 " Automatically detecting the format is dangerous for "
398 "raw images, write operations on block 0 will be restricted.\n"
399 " Specify the 'raw' format explicitly to remove the "
401 bs
->file
->bs
->filename
);
404 ret
= raw_read_options(options
, bs
, s
, errp
);
409 if (bs
->sg
&& (s
->offset
|| s
->has_size
)) {
410 error_setg(errp
, "Cannot use offset/size with SCSI generic devices");
417 static void raw_close(BlockDriverState
*bs
)
421 static int raw_probe(const uint8_t *buf
, int buf_size
, const char *filename
)
423 /* smallest possible positive score so that raw is used if and only if no
424 * other block driver works
429 static int raw_probe_blocksizes(BlockDriverState
*bs
, BlockSizes
*bsz
)
431 BDRVRawState
*s
= bs
->opaque
;
434 ret
= bdrv_probe_blocksizes(bs
->file
->bs
, bsz
);
439 if (!QEMU_IS_ALIGNED(s
->offset
, MAX(bsz
->log
, bsz
->phys
))) {
446 static int raw_probe_geometry(BlockDriverState
*bs
, HDGeometry
*geo
)
448 BDRVRawState
*s
= bs
->opaque
;
449 if (s
->offset
|| s
->has_size
) {
452 return bdrv_probe_geometry(bs
->file
->bs
, geo
);
455 BlockDriver bdrv_raw
= {
456 .format_name
= "raw",
457 .instance_size
= sizeof(BDRVRawState
),
458 .bdrv_probe
= &raw_probe
,
459 .bdrv_reopen_prepare
= &raw_reopen_prepare
,
460 .bdrv_reopen_commit
= &raw_reopen_commit
,
461 .bdrv_reopen_abort
= &raw_reopen_abort
,
462 .bdrv_open
= &raw_open
,
463 .bdrv_close
= &raw_close
,
464 .bdrv_create
= &raw_create
,
465 .bdrv_co_preadv
= &raw_co_preadv
,
466 .bdrv_co_pwritev
= &raw_co_pwritev
,
467 .bdrv_co_pwrite_zeroes
= &raw_co_pwrite_zeroes
,
468 .bdrv_co_pdiscard
= &raw_co_pdiscard
,
469 .bdrv_co_get_block_status
= &raw_co_get_block_status
,
470 .bdrv_truncate
= &raw_truncate
,
471 .bdrv_getlength
= &raw_getlength
,
472 .has_variable_length
= true,
473 .bdrv_get_info
= &raw_get_info
,
474 .bdrv_refresh_limits
= &raw_refresh_limits
,
475 .bdrv_probe_blocksizes
= &raw_probe_blocksizes
,
476 .bdrv_probe_geometry
= &raw_probe_geometry
,
477 .bdrv_media_changed
= &raw_media_changed
,
478 .bdrv_eject
= &raw_eject
,
479 .bdrv_lock_medium
= &raw_lock_medium
,
480 .bdrv_co_ioctl
= &raw_co_ioctl
,
481 .create_opts
= &raw_create_opts
,
482 .bdrv_has_zero_init
= &raw_has_zero_init
485 static void bdrv_raw_init(void)
487 bdrv_register(&bdrv_raw
);
490 block_init(bdrv_raw_init
);