MmUnlockPages and Irp->UserBuffer

In my DispatchWrite routine I need more processing for the IRP so I pend it and queue it to a worker thread.
If I have a neither I/O write then first I allocate a MDL, lock it and get a system space mapped virtual address with MmGetSystemAddressForMdlSafe, the i use MmProtectMdlSystemAddress to set the PAGE_EXECUTE_READWRITE flag.

Now for my IRP to be succesfully completed in the worker thread I change the IRP->UserBuffer with what MmGetSystemAddressForMdlSafe returns.
In most of the cases this works really fine.
The whole cleanup (unlocking the pages and free ing the mdl are done in the worker thread)

The worker thread mostly calls IoCallDriver with the lower device object I am attached to, than calls MmUnlockPages.

But sometimes on the virtual machine IoCallDriver throws an exception and I see written in WinDbg: “a driver has leaked xxxx bytes of virtual memory”
sometimes IoCallDriver works fine but when I call MmUnlockPages i get another exception that it ultimately is handled by the OS (because the debugger is connected), but on the real machine I get blue screen with the messahe: a thread tried to free a resource that I did not own.

I tested it on a real machine and it works fine, except when I receive a Write request from my usb connected hdd, which is “\Device\HarddiskVolume2”

I thought of another way. I should copy the contents of the user buffer in a different system buffer and the build an irp and send it, and complete the initial irp without sending it and put the status code from my built irp.
But I am still puzzled what is wrong with what am I doing and why it works only in certain
cases.

Why not simly stall the calling thread( the call is on PASSIVE_LEVEL and
from a user thread ), then perform all necessary operations in your worker
threads and then allow an Irp to proceed in the context of an original
thread without any changes. This will only reduce throughput of
apllications using overlapped IO, but in case of synchronous IO the stalling
of a thread and pending of a request have the same result - apllication
waits for IO completion.


Slava Imameyev, xxxxx@hotmail.com

wrote in message news:xxxxx@ntfsd…
> In my DispatchWrite routine I need more processing for the IRP so I pend
> it and queue it to a worker thread.
> If I have a neither I/O write then first I allocate a MDL, lock it and get
> a system space mapped virtual address with MmGetSystemAddressForMdlSafe,
> the i use MmProtectMdlSystemAddress to set the PAGE_EXECUTE_READWRITE
> flag.
>
> Now for my IRP to be succesfully completed in the worker thread I change
> the IRP->UserBuffer with what MmGetSystemAddressForMdlSafe returns.
> In most of the cases this works really fine.
> The whole cleanup (unlocking the pages and free ing the mdl are done in
> the worker thread)
>
> The worker thread mostly calls IoCallDriver with the lower device object I
> am attached to, than calls MmUnlockPages.
>
> But sometimes on the virtual machine IoCallDriver throws an exception and
> I see written in WinDbg: “a driver has leaked xxxx bytes of virtual
> memory”
> sometimes IoCallDriver works fine but when I call MmUnlockPages i get
> another exception that it ultimately is handled by the OS (because the
> debugger is connected), but on the real machine I get blue screen with the
> messahe: a thread tried to free a resource that I did not own.
>
> I tested it on a real machine and it works fine, except when I receive a
> Write request from my usb connected hdd, which is
> “\Device\HarddiskVolume2”
>
> I thought of another way. I should copy the contents of the user buffer in
> a different system buffer and the build an irp and send it, and complete
> the initial irp without sending it and put the status code from my built
> irp.
> But I am still puzzled what is wrong with what am I doing and why it works
> only in certain
> cases.
>

If you did not replace the original buffer with your own buffer you should
not change Irp->UserBuffer. Just make sure that you set Irp->MdlAddress to
point to your MDL. If the IRP in question was not created by your driver then
you should not unlock buffer either, IoManager takes care of it (given that
Irp->MdlAddress points to the MDL which you allocated).

Alexei.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of xxxxx@gmail.com
Sent: Thursday, October 04, 2007 2:08 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] MmUnlockPages and Irp->UserBuffer

In my DispatchWrite routine I need more processing for the IRP so I pend it
and queue it to a worker thread.
If I have a neither I/O write then first I allocate a MDL, lock it and get a
system space mapped virtual address with MmGetSystemAddressForMdlSafe, the i
use MmProtectMdlSystemAddress to set the PAGE_EXECUTE_READWRITE flag.

Now for my IRP to be succesfully completed in the worker thread I change the
IRP->UserBuffer with what MmGetSystemAddressForMdlSafe returns.
In most of the cases this works really fine.
The whole cleanup (unlocking the pages and free ing the mdl are done in the
worker thread)

The worker thread mostly calls IoCallDriver with the lower device object I am
attached to, than calls MmUnlockPages.

But sometimes on the virtual machine IoCallDriver throws an exception and I
see written in WinDbg: “a driver has leaked xxxx bytes of virtual memory”
sometimes IoCallDriver works fine but when I call MmUnlockPages i get
another exception that it ultimately is handled by the OS (because the
debugger is connected), but on the real machine I get blue screen with the
messahe: a thread tried to free a resource that I did not own.

I tested it on a real machine and it works fine, except when I receive a
Write request from my usb connected hdd, which is “\Device\HarddiskVolume2”

I thought of another way. I should copy the contents of the user buffer in a
different system buffer and the build an irp and send it, and complete the
initial irp without sending it and put the status code from my built irp.
But I am still puzzled what is wrong with what am I doing and why it works
only in certain
cases.


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@vmware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

What about setting DO_DIRECT_IO in the Flags member of your device object and let IO manager do job for you? You are FSD, not FSF, right? Even though you will have to check IRPs if they have allocated MDL, because there might be File System Filters which don’t delegate device flags of device which they are attaching to, but note it is the bug in the FSF. In such case as was said allocated mdl assign to Irp->MdlAddress. You can even free it right before completion. I don’t understand why you do change Irp->UserBuffer, because MDL describes buffer in it. The lower device should prefer access through mdl than UserBuffer. It shouldn’t suppose that it is executed in arbitrary thread. I am not sure about MmProtectMdlSystemAddress(), did you try to omit it?

Yes I thought about changing DeviceObject flags to DIRECT_IO and set the Irp->MdlAddres to my MDL but changing Irp->UserBuffer to a non paged system rezident memory is ok to because the I/O manager will not attempt to alter this buffer because it is initially supposed to run in the context of the calling process.
I observed that by setting the Irp->MdlAddress to the mdl describing the userBuffer I don’t have unlock pages, bause the I/O manager will do it for me
thank you very much fior your anwers