summaryrefslogtreecommitdiff
path: root/block/vhdx.c
diff options
context:
space:
mode:
authorJeff Cody <jcody@redhat.com>2013-10-30 10:44:43 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2013-11-07 13:58:58 +0100
commitc3906c5e8281b37a526c706596af8575d6ac00d3 (patch)
tree609b75718f7b1bd5a63bf99e2e9330420144603f /block/vhdx.c
parent0f48e8f0978afe0bd44c63749e7df6411da6c437 (diff)
downloadqemu-c3906c5e8281b37a526c706596af8575d6ac00d3.tar.gz
block: vhdx - update log guid in header, and first write tracker
Allow tracking of first file write in the VHDX image, as well as the ability to update the GUID in the header. This is in preparation for log support. Signed-off-by: Jeff Cody <jcody@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/vhdx.c')
-rw-r--r--block/vhdx.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/block/vhdx.c b/block/vhdx.c
index 68663c6aa3..241703a1ad 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -230,7 +230,7 @@ static int vhdx_probe(const uint8_t *buf, int buf_size, const char *filename)
* - non-current header is updated with largest sequence number
*/
static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
- bool generate_data_write_guid)
+ bool generate_data_write_guid, MSGUID *log_guid)
{
int ret = 0;
int hdr_idx = 0;
@@ -262,6 +262,11 @@ static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
vhdx_guid_generate(&inactive_header->data_write_guid);
}
+ /* update the log guid if present */
+ if (log_guid) {
+ inactive_header->log_guid = *log_guid;
+ }
+
/* the header checksum is not over just the packed size of VHDXHeader,
* but rather over the entire 'reserved' range for the header, which is
* 4KB (VHDX_HEADER_SIZE). */
@@ -294,16 +299,16 @@ exit:
* The VHDX spec calls for header updates to be performed twice, so that both
* the current and non-current header have valid info
*/
-static int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s,
- bool generate_data_write_guid)
+int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s,
+ bool generate_data_write_guid, MSGUID *log_guid)
{
int ret;
- ret = vhdx_update_header(bs, s, generate_data_write_guid);
+ ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid);
if (ret < 0) {
return ret;
}
- ret = vhdx_update_header(bs, s, generate_data_write_guid);
+ ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid);
return ret;
}
@@ -784,6 +789,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
s->bat = NULL;
+ s->first_visible_write = true;
qemu_co_mutex_init(&s->lock);
@@ -864,7 +870,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
}
if (flags & BDRV_O_RDWR) {
- ret = vhdx_update_headers(bs, s, false);
+ ret = vhdx_update_headers(bs, s, false, NULL);
if (ret < 0) {
goto fail;
}
@@ -1010,6 +1016,18 @@ exit:
+/* Per the spec, on the first write of guest-visible data to the file the
+ * data write guid must be updated in the header */
+int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
+{
+ int ret = 0;
+ if (s->first_visible_write) {
+ s->first_visible_write = false;
+ ret = vhdx_update_headers(bs, s, true, NULL);
+ }
+ return ret;
+}
+
static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, QEMUIOVector *qiov)
{