When using VIXDISKLIB_FLAG_OPEN_SINGLE_LINK, parent images are not taken into
account. However, the data we get from VixDiskLib_QueryAllocatedBlocks() has
such granularity that it might return incorrect information. For example when
the top image has only one block allocated, we get information about the whole
chunk being allocated. This results in the consequent read to return invalid
data - the rest of the chunk is just zeros. To eliminate losing data integrity
this patch makes the plugin hold two separate handles, one opened with the
VIXDISKLIB_FLAG_OPEN_SINGLE_LINK flag and one without it. The top image without
the parent chain is then used only for returning information about extents and
the original handle is used for the rest of the operations. Even though this
way we report more data in the top image, the resulting data is correct.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
plugins/vddk/vddk.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index ca6ae6d6ff63..8cf54f6e2b96 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -428,6 +428,7 @@ struct vddk_handle {
VixDiskLibConnectParams *params; /* connection parameters */
VixDiskLibConnection connection; /* connection */
VixDiskLibHandle handle; /* disk handle */
+ VixDiskLibHandle handle_single_link; /* disk handle for single_link=true */
};
static inline VixDiskLibConnectParams *
@@ -522,8 +523,6 @@ vddk_open (int readonly)
flags = 0;
if (readonly)
flags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
- if (single_link)
- flags |= VIXDISKLIB_FLAG_OPEN_SINGLE_LINK;
if (unbuffered)
flags |= VIXDISKLIB_FLAG_OPEN_UNBUFFERED;
@@ -538,6 +537,21 @@ vddk_open (int readonly)
nbdkit_debug ("transport mode: %s",
VixDiskLib_GetTransportMode (h->handle));
+ if (single_link) {
+ flags |= VIXDISKLIB_FLAG_OPEN_SINGLE_LINK;
+
+ DEBUG_CALL ("VixDiskLib_Open",
+ "connection, %s, %d, &handle_single_link", filename,
flags);
+ err = VixDiskLib_Open (h->connection, filename, flags,
&h->handle_single_link);
+ if (err != VIX_OK) {
+ VDDK_ERROR (err, "VixDiskLib_Open: %s", filename);
+ goto err2;
+ }
+
+ nbdkit_debug ("transport mode for single_link: %s",
+ VixDiskLib_GetTransportMode (h->handle_single_link));
+ }
+
return h;
err2:
@@ -559,6 +573,10 @@ vddk_close (void *handle)
free_connect_params (h->params);
DEBUG_CALL ("VixDiskLib_Close", "handle");
VixDiskLib_Close (h->handle);
+ if (single_link) {
+ DEBUG_CALL ("VixDiskLib_Close", "handle_single_link");
+ VixDiskLib_Close (h->handle_single_link);
+ }
DEBUG_CALL ("VixDiskLib_Disconnect", "connection");
VixDiskLib_Disconnect (h->connection);
free (h);
@@ -698,7 +716,7 @@ vddk_flush (void *handle, uint32_t flags)
return 0;
DEBUG_CALL ("VixDiskLib_Flush", "handle");
- err = VixDiskLib_Flush (h->handle);
+ err = VixDiskLib_Flush (single_link ? h->handle_single_link : h->handle);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Flush");
return -1;
@@ -730,7 +748,7 @@ vddk_can_extents (void *handle)
DEBUG_CALL ("VixDiskLib_QueryAllocatedBlocks",
"handle, 0, %d sectors, %d sectors",
VIXDISKLIB_MIN_CHUNK_SIZE, VIXDISKLIB_MIN_CHUNK_SIZE);
- err = VixDiskLib_QueryAllocatedBlocks (h->handle,
+ err = VixDiskLib_QueryAllocatedBlocks (single_link ? h->handle_single_link :
h->handle,
0, VIXDISKLIB_MIN_CHUNK_SIZE,
VIXDISKLIB_MIN_CHUNK_SIZE,
&block_list);
@@ -809,7 +827,7 @@ vddk_extents (void *handle, uint32_t count, uint64_t offset, uint32_t
flags,
"handle, %" PRIu64 " sectors, %" PRIu64 "
sectors, "
"%d sectors",
start_sector, nr_sectors, VIXDISKLIB_MIN_CHUNK_SIZE);
- err = VixDiskLib_QueryAllocatedBlocks (h->handle,
+ err = VixDiskLib_QueryAllocatedBlocks (single_link ? h->handle_single_link :
h->handle,
start_sector, nr_sectors,
VIXDISKLIB_MIN_CHUNK_SIZE,
&block_list);
--
2.21.0