Changed Block Tracking on Virtual Disks

On ESXi hosts release 4.0 and later, virtual machines can keep track of disk sectors that have changed. This is called changed block tracking. Its method in the VMware vSphere API is QueryChangedDiskAreas, which takes the following parameters:

  • _this – Managed object reference to the virtual machine.
  • snapshot – Managed object reference to a Snapshot of the virtual machine.
  • deviceKey – Virtual disk for which to compute the changes.
  • startOffset – Byte offset where to start computing changes to virtual disk. The length of virtual disk sector(s) examined is returned in DiskChangeInfo.
  • changeId – An identifier for the state of a virtual disk at a specific point in time. A new ChangeId results every time someone creates a snapshot. You should retain this value with the version of change data that you extract (using QueryChangedDiskAreas) from the snapshot’s virtual disk.

When you back up a snapshot for the first time, ChangeId should be unset, or unsaved, indicating that a baseline (full) backup is required. If you have a saved ChangeId, it identifies the last time a backup was taken, and tells the changed block tracking logic to identify changes that have occurred since the time indicated by the saved ChangeId.

There are two ways to get this baseline backup:

  • Directly save the entire contents of the virtual disk.
  • Call the VixDiskLib_QueryAllocatedBlocks function, which returns the allocated portions of a virtual disk. Usually this substantially reduces the amount of data to save, especially for thin provisioned and sparse virtual disks.

To summarize, changeID is an identifier for a time in the past. It should be a changeId string saved at the time when a pre-backup snapshot was taken. If a previous ChangeId does exist, then QueryChangedDiskAreas returns the disk sectors that changed since the new ChangeId was collected. Use of Change ID for Changed Block Tracking shows the algorithm.

Table 1. Use of Change ID for Changed Block Tracking
New Change ID Old Change ID Used for Query Result
change 0 none null All sectors, use Query Allocated Sectors instead.
change 1 change 0 change 0 All sectors altered since change 0.