The following strange behaviour has been spotted on Windows XP SP3 for file-based virtual disks: If a virtual disk driver with a filesystem mounted on it receives an IRP_MJ_READ request and issues a read request for some FS file using
the same buffer, this buffer remains allocated (held by system cache?) until a big timeout elapses or until the FS is dismounted. That leads to strange behaviour for reading large amounts of data from virtual disks: the system cache occupies all available RAM and the PC freezes continiously trying to free some RAM by moving data in and out the pagefile.
It looks like Windows XP (and Vista?) maintains a global map for buffers used for read requests, and the sequence that causes the bug is the following:
-
Windows issues a read request A to our virtual device
-
The buffer BUF is put in cache map
-
Our device issues a read request B for physical file with the same buffer
-
The buffer BUF enters some buggy state in cache map (or marked as very-very-frequently-used and, thus, non-discardable)
-
The normal event for freeing buffer BUF does not work, as it is in some buggy state
-
The buffer remains allocated until some other timeout elapses, or the FS is dismounted
The workaround is very simple: we allocate an intermediate buffer and substitute it to our Read() handlers instead of the original one. That way, it can safely be passed to file reading functions. If the size of a read request is greater than our buffer size, the request is split into several Read() calls.
- Attention:
- To enable the workaround, simpy call the BasicStorageVolume::EnableWindowsCacheBugWorkaround() method from your child class constructor.