diff options
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 44 |
1 files changed, 37 insertions, 7 deletions
@@ -1046,7 +1046,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, } if (!drv->bdrv_file_open) { - ret = bdrv_open(&bs, filename, options, flags, drv, &local_err); + ret = bdrv_open(&bs, filename, NULL, options, flags, drv, &local_err); options = NULL; } else { ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err); @@ -1125,7 +1125,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) assert(bs->backing_hd == NULL); ret = bdrv_open(&bs->backing_hd, - *backing_filename ? backing_filename : NULL, options, + *backing_filename ? backing_filename : NULL, NULL, options, back_flags, back_drv, &local_err); if (ret < 0) { bs->backing_hd = NULL; @@ -1206,7 +1206,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename, goto done; } - ret = bdrv_open(pbs, filename, image_options, flags, NULL, errp); + ret = bdrv_open(pbs, filename, NULL, image_options, flags, NULL, errp); } else { ret = bdrv_file_open(pbs, filename, reference, image_options, flags, errp); @@ -1227,9 +1227,14 @@ done: * * If *pbs is NULL, a new BDS will be created with a pointer to it stored there. * If it is not NULL, the referenced BDS will be reused. + * + * The reference parameter may be used to specify an existing block device which + * should be opened. If specified, neither options nor a filename may be given, + * nor can an existing BDS be reused (that is, *pbs has to be NULL). */ -int bdrv_open(BlockDriverState **pbs, const char *filename, QDict *options, - int flags, BlockDriver *drv, Error **errp) +int bdrv_open(BlockDriverState **pbs, const char *filename, + const char *reference, QDict *options, int flags, + BlockDriver *drv, Error **errp) { int ret; /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ @@ -1240,6 +1245,31 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, QDict *options, assert(pbs); + if (reference) { + bool options_non_empty = options ? qdict_size(options) : false; + QDECREF(options); + + if (*pbs) { + error_setg(errp, "Cannot reuse an existing BDS when referencing " + "another block device"); + return -EINVAL; + } + + if (filename || options_non_empty) { + error_setg(errp, "Cannot reference an existing block device with " + "additional options or a new filename"); + return -EINVAL; + } + + bs = bdrv_lookup_bs(reference, reference, errp); + if (!bs) { + return -ENODEV; + } + bdrv_ref(bs); + *pbs = bs; + return 0; + } + if (*pbs) { bs = *pbs; } else { @@ -1268,7 +1298,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, QDict *options, /* Get the required size from the image */ QINCREF(options); bs1 = NULL; - ret = bdrv_open(&bs1, filename, options, BDRV_O_NO_BACKING, + ret = bdrv_open(&bs1, filename, NULL, options, BDRV_O_NO_BACKING, drv, &local_err); if (ret < 0) { goto fail; @@ -5309,7 +5339,7 @@ void bdrv_img_create(const char *filename, const char *fmt, flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); bs = NULL; - ret = bdrv_open(&bs, backing_file->value.s, NULL, back_flags, + ret = bdrv_open(&bs, backing_file->value.s, NULL, NULL, back_flags, backing_drv, &local_err); if (ret < 0) { error_setg_errno(errp, -ret, "Could not open '%s': %s", |