/**
* Truncate file to 'offset' bytes (needed only for file protocols)
*/
-int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
+ Error **errp)
{
BlockDriverState *bs = child->bs;
BlockDriver *drv = bs->drv;
assert(!(bs->open_flags & BDRV_O_INACTIVE));
- ret = drv->bdrv_truncate(bs, offset, PREALLOC_MODE_OFF, errp);
+ ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
if (ret == 0) {
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
bdrv_dirty_bitmap_truncate(bs);
return retval;
}
-int bdrv_get_backing_file_depth(BlockDriverState *bs)
-{
- if (!bs->drv) {
- return 0;
- }
-
- if (!bs->backing) {
- return 0;
- }
-
- return 1 + bdrv_get_backing_file_depth(bs->backing->bs);
-}
-
void bdrv_init(void)
{
module_call_init(MODULE_INIT_BLOCK);
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
blocker = QLIST_FIRST(&bs->op_blockers[op]);
- if (errp) {
- *errp = error_copy(blocker->reason);
- error_prepend(errp, "Node '%s' is busy: ",
- bdrv_get_device_or_node_name(bs));
- }
+ error_propagate(errp, error_copy(blocker->reason));
+ error_prepend(errp, "Node '%s' is busy: ",
+ bdrv_get_device_or_node_name(bs));
return true;
}
return false;
backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
- // The size for the image must always be specified, with one exception:
- // If we are using a backing file, we can obtain the size from there
+ /* The size for the image must always be specified, unless we have a backing
+ * file and we have not been forbidden from opening it. */
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
- if (size == -1) {
- if (backing_file) {
- BlockDriverState *bs;
- char *full_backing = g_new0(char, PATH_MAX);
- int64_t size;
- int back_flags;
- QDict *backing_options = NULL;
-
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
- full_backing, PATH_MAX,
- &local_err);
- if (local_err) {
- g_free(full_backing);
- goto out;
- }
+ if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
+ BlockDriverState *bs;
+ char *full_backing = g_new0(char, PATH_MAX);
+ int back_flags;
+ QDict *backing_options = NULL;
+
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
+ full_backing, PATH_MAX,
+ &local_err);
+ if (local_err) {
+ g_free(full_backing);
+ goto out;
+ }
- /* backing files always opened read-only */
- back_flags = flags;
- back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+ /* backing files always opened read-only */
+ back_flags = flags;
+ back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
- if (backing_fmt) {
- backing_options = qdict_new();
- qdict_put_str(backing_options, "driver", backing_fmt);
- }
+ if (backing_fmt) {
+ backing_options = qdict_new();
+ qdict_put_str(backing_options, "driver", backing_fmt);
+ }
- bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
- &local_err);
- g_free(full_backing);
- if (!bs) {
- goto out;
- }
- size = bdrv_getlength(bs);
- if (size < 0) {
- error_setg_errno(errp, -size, "Could not get size of '%s'",
- backing_file);
- bdrv_unref(bs);
- goto out;
+ bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
+ &local_err);
+ g_free(full_backing);
+ if (!bs && size != -1) {
+ /* Couldn't open BS, but we have a size, so it's nonfatal */
+ warn_reportf_err(local_err,
+ "Could not verify backing image. "
+ "This may become an error in future versions.\n");
+ local_err = NULL;
+ } else if (!bs) {
+ /* Couldn't open bs, do not have size */
+ error_append_hint(&local_err,
+ "Could not open backing image to determine size.\n");
+ goto out;
+ } else {
+ if (size == -1) {
+ /* Opened BS, have no size */
+ size = bdrv_getlength(bs);
+ if (size < 0) {
+ error_setg_errno(errp, -size, "Could not get size of '%s'",
+ backing_file);
+ bdrv_unref(bs);
+ goto out;
+ }
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
}
-
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
-
bdrv_unref(bs);
- } else {
- error_setg(errp, "Image creation needs a size parameter");
- goto out;
}
+ } /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
+
+ if (size == -1) {
+ error_setg(errp, "Image creation needs a size parameter");
+ goto out;
}
if (!quiet) {