Read Pointer in Motion help

I have a miinifilter that is similar to a HSM driver, but has its own ‘twist’ to it. The driver is very stable as there is plenty of ‘gotcha’ code to catch potential issues and handle them.

Just an up front detail, I am intentionally staying away from paging/cache unless it explicitly comes in (like a mapped file / etc). Yes I know of the performance, but for the precision needed on offsets, it works best that way. I do have a paging call handler and it works perfectly, but for this bug, its is never invoked (or at least from the last 20 times I duplicated it over ~20 mil read IOs)

In a nutshell, I’m check the file and process/thread in my PreCreate, if its something I need to watch, I tag a StreamHandleContext onto it in the PostCreate with some basic info (like name / internal parms / etc).

At that point, when a Read IO comes in, I check for the StreamHandleContext first, make sure it isnt a FASTIO operation, and if it is, I return FLT_PREOP_DISALLOW_FASTIO. I make sure its an irp, and if not, return FLT_PREOP_SUCCESS_NO_CALLBACK. Once I know its a read operation, I simply perform the Read myself by calling FltreadFile with the original Instance/FO, but I use FLTFL_IO_OPERATION_NON_CACHED | FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET.

I am framing a new buffer so it is aligned on both requirements (offset/len). Doing the read call, then copying the data I need from my new buffer into the original buffer. I do all the locking/checking / etc so its safe at all times, or I’d see a debugger print with issue. Then I take the number of bytes read from the read call, do the math so I have the original offset plus the number of bytes, then FltSetInformationFile the position offset (since I told it not to update, and if i did let it update, it would overshoot since my aligned buffer is always larger than the unaligned one.) I then FLT_PREOP_COMPLETE.

It works like a champ almost all of the time, but everyone once in a great while, I’ll get a read call inbound where the offset is way out of wack. Now the app that reproduces it runs multiple threads and basically when it needs a stream (since usually 2-3 audio streams are going at the time) one thread issues a new create, then jumps to the offset, and hands it off to another thread to do the streaming. These two threads play back and forth with each other depending on availability. The offset it jumps to in many instances is either a calculated value (like it will read a .zip header, then try to jump to the offset which is waaay off) or it will continue another object’s read call offset, almost as if my last position set was used for another create/read combo.

There are no other calls (paging/section sync/whatever) recorded in ProcessMon for the app as I compare the two logs for accuracy. And there are no paging calls or fast IO calls made while its running. This will happen usually ~10-20 minutes or so along, and not when its under heavy load.

Originally I was issuing a new Fltcreate in the PreRead path to do the work, but then I have to go down the recurring logic lane in case say an Antivirus decides to do a read ahead of my create from the top of the stack… (I ran into this once). So I went back to the original TargetInstance/FileObject.

So my question is this. Is there a way I can determine if a read offset / etc has been moved somehow where it does not generate an IRP or some form that I can track, and if so, with no paging / cacheing going on, can the VM still have some play in the mix here or have influence on where it can jump for a give FileObject?



Oh, and I’ve tried serializing the copy routine witha Mutex just to see if it was a concurrent threading issue, but same result.