aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c19
-rw-r--r--block/qcow.c7
-rw-r--r--block/qcow2.c10
-rw-r--r--block/qed.c7
-rw-r--r--block/vmdk.c6
-rw-r--r--include/block/block_int.h4
6 files changed, 44 insertions, 9 deletions
diff --git a/block.c b/block.c
index 31e4664..21395b5 100644
--- a/block.c
+++ b/block.c
@@ -2361,6 +2361,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
char *bdref_key_dot;
const char *reference = NULL;
int ret = 0;
+ bool implicit_backing = false;
BlockDriverState *backing_hd;
QDict *options;
QDict *tmp_parent_options = NULL;
@@ -2396,6 +2397,16 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
qobject_unref(options);
goto free_exit;
} else {
+ if (qdict_size(options) == 0) {
+ /* If the user specifies options that do not modify the
+ * backing file's behavior, we might still consider it the
+ * implicit backing file. But it's easier this way, and
+ * just specifying some of the backing BDS's options is
+ * only possible with -drive anyway (otherwise the QAPI
+ * schema forces the user to specify everything). */
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
+ }
+
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
&local_err);
if (local_err) {
@@ -2429,6 +2440,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
}
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
+ if (implicit_backing) {
+ bdrv_refresh_filename(backing_hd);
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_hd->filename);
+ }
+
/* Hook up the backing file link; drop our reference, bs owns the
* backing_hd reference now */
bdrv_set_backing_hd(bs, backing_hd, &local_err);
@@ -3848,6 +3865,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
if (ret == 0) {
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
}
return ret;
}
diff --git a/block/qcow.c b/block/qcow.c
index 0a235bf..d47515d 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -31,6 +31,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/bswap.h"
+#include "qemu/cutils.h"
#include <zlib.h>
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
@@ -295,11 +296,13 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
goto fail;
}
- bs->backing_file[len] = '\0';
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
/* Disable migration when qcow images are used */
diff --git a/block/qcow2.c b/block/qcow2.c
index 65a54c9..3826ce7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1474,13 +1474,15 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail;
}
- bs->backing_file[len] = '\0';
- s->image_backing_file = g_strdup(bs->backing_file);
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
}
/* Internal snapshots */
@@ -2518,6 +2520,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
return -EINVAL;
}
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
diff --git a/block/qed.c b/block/qed.c
index 1280870..81a1bed 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -454,11 +454,14 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
}
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
- s->header.backing_filename_size, bs->backing_file,
- sizeof(bs->backing_file));
+ s->header.backing_filename_size,
+ bs->auto_backing_file,
+ sizeof(bs->auto_backing_file));
if (ret < 0) {
return ret;
}
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
diff --git a/block/vmdk.c b/block/vmdk.c
index 117dc6a..464b718 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -386,12 +386,14 @@ static int vmdk_parent_open(BlockDriverState *bs)
ret = -EINVAL;
goto out;
}
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
ret = -EINVAL;
goto out;
}
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
out:
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 8437df8..dd7276c 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -702,6 +702,10 @@ struct BlockDriverState {
char filename[PATH_MAX];
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
this file image */
+ /* The backing filename indicated by the image header; if we ever
+ * open this file, then this is replaced by the resulting BDS's
+ * filename (i.e. after a bdrv_refresh_filename() run). */
+ char auto_backing_file[PATH_MAX];
char backing_format[16]; /* if non-zero and backing_file exists */
QDict *full_open_options;