[ReFS] Is there a supported way to obtain volume allocation bitmap information similar to FSCTL_GET_VOLUME_BITMAP on NTFS?

zihming 40 Reputation points
2026-06-23T06:36:57.8266667+00:00

I am trying to determine which regions of a volume are allocated on ReFS.

For NTFS, I can use FSCTL_GET_VOLUME_BITMAP to obtain the volume bitmap and identify which clusters are in use. However, the documentation does not clearly state whether ReFS supports this control code. To investigate it, I wrote a program that repeatedly calls DeviceIoControl with parameter FSCTL_GET_VOLUME_BITMAP until the operation completes without ERROR_MORE_DATA. The program also calls GetDiskFreeSpace to obtain the total number of clusters on the volume.


HANDLE hVolume = INVALID_HANDLE_VALUE;
STARTING_LCN_INPUT_BUFFER startingLcn;
VOLUME_BITMAP_BUFFER *volBitmap = NULL;
UINT32 bitmapSize;
DWORD bytesReturned;
std::vector<uint8_t> bitmap;

utf_converter converter;

hVolume = CreateFileW(converter.from_bytes(drive).c_str(), GENERIC_READ,
                     FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

if (hVolume == INVALID_HANDLE_VALUE) {
	goto end;
}

startingLcn.StartingLcn.QuadPart = 0;
bitmapSize = 1024 * 1024 + sizeof(LARGE_INTEGER) * 2;
volBitmap = (VOLUME_BITMAP_BUFFER *)malloc(bitmapSize);

while (1) {
	bool rc
	    = DeviceIoControl(hVolume, FSCTL_GET_VOLUME_BITMAP, &startingLcn, sizeof(STARTING_LCN_INPUT_BUFFER),
	                      volBitmap, bitmapSize, &bytesReturned, NULL);

	if (startingLcn.StartingLcn.QuadPart != volBitmap->StartingLcn.QuadPart) {
		goto end;
	}

	if (rc == FALSE && GetLastError() != ERROR_MORE_DATA) {
		goto end;
	}

	/* find out the exact bytes read from $bitmap */
	bytesReturned -= sizeof(LARGE_INTEGER) * 2;

	bitmap.insert(bitmap.end(), volBitmap->Buffer, volBitmap->Buffer + bytesReturned);

	/* If eof occured for reading $bitmap break the loop */
	if (rc == TRUE) {
		break;
	}

	/* Update the read offset for next request */
	startingLcn.StartingLcn.QuadPart += bytesReturned * 8;
}

DWORD sectors_per_cluster;
DWORD bytes_per_sector;
DWORD number_of_free_clusters;
DWORD total_number_of_clusters;

if (GetDiskFreeSpaceW(converter.from_bytes(drive + "\\").c_str(), &sectors_per_cluster,
                     &bytes_per_sector, &number_of_free_clusters, &total_number_of_clusters)
    == FALSE) {
	goto end;
}

std::cout << "Sectors per cluster: " << sectors_per_cluster << ", Bytes per sector: " << bytes_per_sector << std::endl;
std::cout << "Number of free clusters: " << number_of_free_clusters << ", Total number of clusters: " << total_number_of_clusters << std::endl;

std::cout << "Volume bitmap size: " << bitmap.size() << " (" << bitmap.size() * 8 << " bits)" << std::endl;

end:
if (volBitmap != NULL) {
	free(volBitmap);
}

if (hVolume != INVALID_HANDLE_VALUE) {
	CloseHandle(hVolume);
}

On an NTFS volume, the reported bitmap size is consistent with the cluster count and the results appear reasonable.

User's image

On a ReFS volume, however, the reported bitmap size is much larger than the total number of clusters reported by GetDiskFreeSpace, making it unclear whether the returned bitmap is meaningful or whether ReFS actually supports FSCTL_GET_VOLUME_BITMAP.

User's image

My questions are:

  1. Is FSCTL_GET_VOLUME_BITMAP officially supported on ReFS?
  2. If it is supported, how should the returned bitmap be interpreted on ReFS, and are there any ReFS-specific requirements when calling FSCTL_GET_VOLUME_BITMAP?
  3. If it is not supported, is there any documented API or other supported method to obtain allocation information (for example, determining which clusters or regions of a ReFS volume are currently in use)?
Windows development | Windows API - Win32
0 comments No comments

1 answer

Sort by: Most helpful
  1. Taki Ly (WICLOUD CORPORATION) 4,275 Reputation points Microsoft External Staff Moderator
    2026-06-23T09:39:19.9+00:00

    Hello @zihming ,

    Thank you for sharing your C++ testing approach. I'd like to share a few thoughts that might help address your questions.

    Regarding whether FSCTL_GET_VOLUME_BITMAP is officially supported, while the API doesn't throw an explicit error, its use for determining physical cluster allocation doesn't appear to be practically functional or officially intended for ReFS.

    If you are wondering how to interpret the returned bitmap, it helps to look at how ReFS organizes its underlying storage. As mentioned in the ReFS Block Cloning documentation, ReFS manages data using an allocate-on-write mechanism and tracks files through logical metadata mapping. To support this gracefully, ReFS utilizes a much larger, sparse virtual address space. It seems that when querying the volume bitmap on ReFS, the API actually returns the map of this massive virtual space rather than the physical disk clusters themselves. This abstract mapping would explain why the returned bitmap size drastically exceeds the physical limits reported by GetDiskFreeSpace. Because of this, trying to interpret this specific volume bitmap to locate absolute physical data likely won't yield meaningful results.

    As for finding a documented API or alternative method to obtain actual volume allocation information, there currently doesn't appear to be a supported method that returns a simple 1:1 physical volume allocation bitmap for ReFS like NTFS does. However, if your overarching goal involves building a backup, replication, or block-tracking solution, you might want to explore the Volume Shadow Copy Service (VSS). Current Windows Server environments typically track volume-level block changes safely through VSS integrations rather than using bare-metal IOCTL volume bitmaps.

    I hope this provides some helpful context on the allocation mechanics and points you toward a workable approach! If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

    Thank you.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.