Sending I/O from minifilter to a RAW volume

I’m in the middle of a project about caching data and I am hitting many walls right now. I’m not a Windows professional, so pardon me for any dumb questions or statements… However, I’ll try to describe them as clearly as possible, in case any more data is needed please tell me.

My setup consists of an ordinary NTFS volume C: on an HDD and a RAW (without any filesystem) volume D: on an SSD. I want to cache requests going to C: using a faster D:. The only requirement is that the D: is a RAW volume (please, don’t ask why).

For this purpose, at first, I opened the D: exclusively with ZwCreateFile when I load the module and later in the PreRead/WriteCallback I read/wrote using ZwWrite/ReadFile. Everything worked fine until I wanted to use them in the PostRead/WriteCallback, the issue happened to be IRQL equal to DISPATCH_LEVEL. I found that I either need to create my own IRPs or use the worker threads, but I haven’t tried any of those yet.

Q1 - Should I pick one option or am I free to choose depending on my needs? What is the best possible solution?

I also went another way - I read that in case of minifilter it is best to use the FltRead/Write family, so I created a second version using those. This version attaches both to the NTFS volume (to intercept requests) and to one RAW volume (to get the minifilter instance from FltObjects->Instance required for FltRead/Write). Here I’m having much more problems:

a) In case of C:, the InstanceSetupCallback is called once only, but for D: (RAW) it is called multiple times when I create it and even when I delete it. Is this expected behaviour?

Q2 - Which instance should I save in my module for the FltRead/Write to use?

b) For now, I decided to change the minifilter instance everytime the setup callback is called. The instance is saved to Globals.CacheVolumeInstance after the call to FltSetInstanceContext is successful. However, the first call to FltCreateFile fails with the beautiful part below:

Access violation - code c0000005 (!!! second chance !!!)
nt!KxWaitForLockOwnerShipWithIrql+0x14:

The call to FltCreateFile is as follows:

status = FltCreateFile(Globals.Filter,
Globals.CacheVolumeInstance,
&hdl,
GENERIC_READ | GENERIC_WRITE,
&objattr,
&iostat,
NULL,
0,
0,
FILE_OPEN,
FILE_NO_INTERMEDIATE_BUFFERING,
NULL,
0,
0);

All parameters are the same as in my attempts with ZwCreateFile apart from the Globals.Filter and Globals.CacheVolumeInstance, so I suppose the latter is the issue, which brings me back to point a)…

Q3 - What is the problem with FltCreateFile?

Or maybe my plan is bad from the beginning and I should use another approach? Is there any advice you can give me? I can post some code, but I don’t want to trash the thread unnecessarily…

This is really a set of questions for NTFSD, you should start future posts
there.

To be completely accurate, RAW *is* a file system, it just only supports
volume opens. This comes into play later in your post…

Sending IRPs doesn’t help you, the I/O requests must be sent to the target
file system at PASSIVE_LEVEL. So, you need worker threads/work items to get
back down to PASSIVE_LEVEL.

This isn’t what you want to do. Note that the Instance parameter is
optional, you only specify it when you want to send an I/O request “down” to
the filters/file system you are attached to. In your case, you want to send
the request to the top of the remote RAW stack, so you would open D: with
FltCreateFile and use FltReadFile/WriteFile with a NULL instance.

Yes. When you open D: RAW mounts, when you close D: RAW dismounts. After you
close it someone else might be opening it, check the call stack from your
InstanceSetup callback to figure out who is opening it.

There’s unfortunately a LOT to lean to play in the file system space. Start
by sleeping with a copy of Windows NT File System Internals:

https://www.osronline.com/store/moreinfo.cfm?Product_ID=65

Reinforce your understanding by playing with the Minispy sample and the FAT
source code in the WDK.

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntdev…

I’m in the middle of a project about caching data and I am hitting many
walls right now. I’m not a Windows professional, so pardon me for any dumb
questions or statements… However, I’ll try to describe them as clearly as
possible, in case any more data is needed please tell me.

My setup consists of an ordinary NTFS volume C: on an HDD and a RAW (without
any filesystem) volume D: on an SSD. I want to cache requests going to C:
using a faster D:. The only requirement is that the D: is a RAW volume
(please, don’t ask why).

For this purpose, at first, I opened the D: exclusively with ZwCreateFile
when I load the module and later in the PreRead/WriteCallback I read/wrote
using ZwWrite/ReadFile. Everything worked fine until I wanted to use them in
the PostRead/WriteCallback, the issue happened to be IRQL equal to
DISPATCH_LEVEL. I found that I either need to create my own IRPs or use the
worker threads, but I haven’t tried any of those yet.

Q1 - Should I pick one option or am I free to choose depending on my needs?
What is the best possible solution?

I also went another way - I read that in case of minifilter it is best to
use the FltRead/Write family, so I created a second version using those.
This version attaches both to the NTFS volume (to intercept requests) and to
one RAW volume (to get the minifilter instance from FltObjects->Instance
required for FltRead/Write). Here I’m having much more problems:

a) In case of C:, the InstanceSetupCallback is called once only, but for D:
(RAW) it is called multiple times when I create it and even when I delete
it. Is this expected behaviour?

Q2 - Which instance should I save in my module for the FltRead/Write to use?

b) For now, I decided to change the minifilter instance everytime the setup
callback is called. The instance is saved to Globals.CacheVolumeInstance
after the call to FltSetInstanceContext is successful. However, the first
call to FltCreateFile fails with the beautiful part below:

Access violation - code c0000005 (!!! second chance !!!)
nt!KxWaitForLockOwnerShipWithIrql+0x14:

The call to FltCreateFile is as follows:

status = FltCreateFile(Globals.Filter,
Globals.CacheVolumeInstance,
&hdl,
GENERIC_READ | GENERIC_WRITE,
&objattr,
&iostat,
NULL,
0,
0,
FILE_OPEN,
FILE_NO_INTERMEDIATE_BUFFERING,
NULL,
0,
0);

All parameters are the same as in my attempts with ZwCreateFile apart from
the Globals.Filter and Globals.CacheVolumeInstance, so I suppose the latter
is the issue, which brings me back to point a)…

Q3 - What is the problem with FltCreateFile?

Or maybe my plan is bad from the beginning and I should use another
approach? Is there any advice you can give me? I can post some code, but I
don’t want to trash the thread unnecessarily…