question

baluT-1942 avatar image
0 Votes"
baluT-1942 asked cwoljcq-4745 published

RCT implementation query

Hi, we are trying to use the RCT . Few questions related to it:

the query WMI GetVirtualDiskChanges or VHD QueryChangesVirtualDisk returns access_denied error while getting the disk changes for full. Any idea on what is best to perform full backup ?

We tried the below procedure and found to get the corrupted disk.

  1. Create production snapshot using WMI

  2. then we manually copied the base read-only vhdx file to some other directory (say c:\temp\vm1)

  3. Created reference point (say, RCT_id1).

  4. Created snapshot again

  5. Run in GetVirtualDiskChanges query to get changed blocks since RCT_id1

  6. Read the blocks (offset/length) - (seek and read) to get the data to buffer.

  7. Write the buffer to c:\temp\vm1\ (saved in step 2) - overwrite

  8. Open/attach the c:\temp\vm1\vm1.vhdx =====> This is corrupted.


Any help here is appreciated


windows-api
· 7
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Have you tried opening VHD handle with VIRTUAL_DISK_ACCESS_ALL or running your application as Administrator?


0 Votes 0 ·

we tried with this option but still it fails with ACCESS_DENIED. Per MS document, the openVirtualDisk() should use VIRTUAL_DISK_ACCESS_GET_INFO (https://docs.microsoft.com/en-us/windows/win32/api/virtdisk/nf-virtdisk-querychangesvirtualdisk).

0 Votes 0 ·

Could you show a mini and reproducible sample?

0 Votes 0 ·
Show more comments
baluT-1942 avatar image
0 Votes"
baluT-1942 answered cwoljcq-4745 published

 HANDLE vhdHandle;
 _VIRTUAL_STORAGE_TYPE storageType;
 storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
 storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
 wchar_t path[] = L"C:\\Hyper-V\\Virtual Hard Disks\\L\\Windows2016.vhdx";
 VIRTUAL_DISK_ACCESS_MASK mask = VIRTUAL_DISK_ACCESS_GET_INFO;

 PGET_VIRTUAL_DISK_INFO diskInfo;
 ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO) + sizeof(changeTrackingInfo);
 std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
 diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);

...

 OPEN_VIRTUAL_DISK_PARAMETERS *openParameters = NULL;

   DWORD res = OpenVirtualDisk(&storageType, path,
     VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_DETACH | VIRTUAL_DISK_ACCESS_ATTACH_RO,
     OPEN_VIRTUAL_DISK_FLAG_NONE,
     openParameters,
     &vhdHandle);

 diskInfo->Version = GET_VIRTUAL_DISK_INFO_SIZE;

 res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, &szUsed);
 
 ULONGLONG physicalSize = diskInfo->Size.PhysicalSize;
 ULONGLONG virtualSize = diskInfo->Size.VirtualSize;
 ULONG sectorSize = diskInfo->Size.SectorSize;
 ULONG blockSize = diskInfo->Size.BlockSize;
  

 diskInfo->Version = (GET_VIRTUAL_DISK_INFO_VERSION)GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
 szUsed = NULL;
 res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, &szUsed);
 if (res != ERROR_SUCCESS)
 {
     std::cout << "Failed to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE, ret=" << res << std::endl;
 }
 std::wcout << "\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
 std::wcout << "\change tracking enabled: " << diskInfo->ChangeTrackingState.Enabled << std::endl;
 WCHAR* rctId = diskInfo->ChangeTrackingState.MostRecentId;

    
 //to get incr changes we used rct id like this L"rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001";
 //to get allocated blocks for full backup we used rct is as "*", "0", etc.
 std::wcout << "\nQuerying for changed disk areas..." << rctId << std::endl;

 ULONG64   byteOffset = 0;
 ULONG64   byteLength = 19327352832; //set disk max internal size.
 QUERY_CHANGES_VIRTUAL_DISK_RANGE* changedAreas = NULL;
 ULONG     rangeCount = 0;
 ULONG64   processedLength = 0;
 res = QueryChangesVirtualDisk(vhdHandle, rctId, byteOffset, byteLength,
     QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
     changedAreas, &rangeCount, &processedLength);

 if (res != ERROR_SUCCESS)
 {
     std::cout << "Failed to get changed areas, ret=" << res << std::endl;

;
}
....

· 13
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

the above is not the solution.....with teh above code, we still get the access denied err.

0 Votes 0 ·

Yes I also get access denied error using your code. But change
VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_DETACH | VIRTUAL_DISK_ACCESS_ATTACH_RO to VIRTUAL_DISK_ACCESS_ALL, error code turns to 0xc03a0029 (The specified change tracking identifier is not valid.) It seems there are some differences between my .`vhdx` file and yours. So I can't reproduce this issue. Can you show detailed information of steps 1-4 mentioned in your question? So I can try to create a similar target file as yours to reproduce this issue.


0 Votes 0 ·

thanks RitaHan for your response.

By changing to VIRTUAL_DISK_ACCESS_ALL, we are not getting the ACCESS_DENIED but the query output returns with ZERO range.

what is the value to provide for the rctId ? As for the first time query to vhdx, there is no recent ID. So what value we need to provide to get the disk blocks.

WCHAR* rctId = diskInfo->ChangeTrackingState.MostRecentId;


  1. Create new VM with dynamic disks (a.vhdx)

  2. Create a snapshot (this will create a.vhdx and a.avhdx)

  3. now run the program with a.vhdx as input to OpenVirtualDisk()

  4. Query will return with zero range which is strange and does not give in the allocated blocks.


0 Votes 0 ·
Show more comments

Same problems as you @baluT-1942 , has you solved the problem?

0 Votes 0 ·
RitaHan-MSFT avatar image
0 Votes"
RitaHan-MSFT answered RitaHan-MSFT edited

Hello @baluT-1942,

Sharing the instructions for getting the detailed tracing here:

In short these are the steps that need to be performed (More detailed information please refer to here.) :

  • Open Event Viewer. On the View menu, click Show Analytic and Debug Logs. Locate the Trace channel log for WMI under Applications and Service Logs | Microsoft | Windows | WMI Activity.

  • Right-click the Trace log and select Log Properties. Click the Enable Logging check box to start the WMI event tracing. For more information about channels, see Event Logs and Channels in Windows Event Log.

  • Save the log – Action -> Save all events as VMMS and vhdmp.sys.

Captures via batch file:

 @echo off
 ECHO These commands will enable tracing:
 @echo on
 logman create trace "vm_manifests" -ow -o c:\vm_manifests.etl -p "Microsoft-Windows-Hyper-V-VMMS" 0xffffffffffffffff 0xff -nb 16 16 -bs 1024 -mode Circular -f bincirc -max 4096 -ets
 logman update trace "vm_manifests" -p {4DDF50D0-75DE-4FBE-8F08-F8936638E7A1} 0xffffffffffffffff 0xff -ets
 logman update trace "vm_manifests" -p "Microsoft-Windows-VHDMP" 0xffffffffffffffff 0xff -ets
 logman update trace "vm_manifests" -p "Microsoft-Windows-Hyper-V-VHDMP" 0xffffffffffffffff 0xff -ets
 @echo off
 echo
 ECHO Reproduce your issue and enter any key to stop tracing
 @echo on
 pause
 logman stop "vm_manifests" -ets
 @echo off
 echo Tracing has been captured and saved successfully at c:\vm_manifests.etl
 pause

Enable additional VMMS event logs via the Event Viewer:

A. Open EventVwr and in the main menu select View and ensure "Show Analytic and Debug logs" is checked

B. Under Applications and Services Logs -> Microsoft -> Windows -> Hyper-V-VMMS, select each item (Admin, etc.) and ensure that you "Enable Log" in the Actions pane on the right. Analytic is disabled by default.

So when you upload the vm_manifests.etl file, include the EventVwr log via Main Menu -> Action -> Save All Events as, and include everything.


This will help us in determining the reason for this behavior.


Thank you!









5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

nmam avatar image
0 Votes"
nmam answered

Do we have a resolution here ? I am facing the exact same access denied and then (with VIRTUAL_DISK_ACCESS_ALL) the zero range count issue...

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

nmam avatar image
0 Votes"
nmam answered nmam edited

Figured out the zero range count issue.. working sample here:

https://stackoverflow.com/questions/63358492/querychangesvirtualdisk-is-returning-error-invalid-handle6-even-though-openvir/65273895#65273895

The only blocker now is how to get this working with a live checkpointed VM...

also how do we query CBT data from WMI as the OP has done in the above post (image reproduced below)

47588-image.png



image.png (65.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

nmam avatar image
0 Votes"
nmam answered nmam edited

Both issues fixed. Please see the below git repo. Thanks to alexpilotti the dev for this repo

https://github.com/cloudbase/rct-service/issues/1

Maybe the docs should highlight the correct OpenVirtualDisk API usage.

47681-image.png



image.png (25.7 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

richealnull-9842 avatar image
0 Votes"
richealnull-9842 answered

Hello, I encountered the same problem here, according to the changed area to write a copy of the disk, after writing open the disk found that the disk is damaged, how do you solve this problem

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.