async i/o on a volume handle

I am experiencing some very strange behavior trying to perform async i/o on a volume handle that I was wondering if someone could provide some insight into. I post this here because it seems to involve details about the interactions between IOCP and the file system, and seems more relevant here than anywhere else I could find.

Basically, I have a volume handle (i.e. opened with \?\Volume{Guid}) for direct (unbuffered) overlapped i/o. I scan the fs allocation bitmap looking for allocated blocks, and then read those blocks asynchronously using the volume handle and i/o completion ports. On my particular machine, the first few allocated blocks are 6 and 7, then a huge gap of unallocated blocks

When I attempt to read the first few blocks using IOCP everything is successful. I’m told that 8192 bytes were read successfully, and even making sure my buffer was allocated with MEM_WRITE_WATCH I can verify that indeed the page was written to. But the data is still uninitialized. Uninitialized in the sense that no matter what it contains before the i/o request was initiated, it contains the exact same data afterwords.

There are a couple of oddities about this: First, it only happens on the first few blocks. After that, it works fine and the data in the buffer I’ve supplied looks perfect for all subsequent blocks. Second, it doesn’t happen if I use synchronous I/O. In that case the data for the first few blocks looks fine after the read is completed.

I want to reiterate that at no point does any API ever return a status code indicating anything other than what it would indicate in full success conditions.

If there is a limitation that, say, overlapped i/o is invalid on certain blocks of the filesystem, then that is fine as long as I know exactly what blocks cannot be read in such fashion. Without knowing if that is the case though, this problem seems very mysterious and I would appreciate if someone more knowledgeable than me could provide some assistance.

Regards,
Zach Turner