crash when TransmitFile is used on my FSD

Hi all,

I am getting a crash when an application uses the TransmitFile API with my
file system. I am running on Windows XP SP2 checked build.

My file system gets a buffered, async, IRP_MJ_READ/IRP_MN_NORMAL, with a
non-null MDL (see stack trace 1 below). My dispatch routine gets the buffer
address from the MDL by calling MmGetSystemAddressForMdlSafe() and, for
debugging purposes at the moment, does nothing with it. I do not touch the
MDL otherwise. The dispatch routine then completes the IRP with
STATUS_SUCCESS and the length of the read.

I see the following assert (see stack trace 2):

*** Assertion failed: (MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) !=
0
*** Source File: d:\xpsprtm\base\ntos\mm\iosup.c, line 2346

followed eventually by the crash.

The MDL that my file system gets in the READ IRP looks like this:

kd> dt 85236fc4 pifsk!MDL
+0x000 Next : (null)
+0x004 Size : 32
+0x006 MdlFlags : 4 –> MDL_SOURCE_IS_NONPAGED_POOL
+0x008 Process : (null)
+0x00c MappedSystemVa : 0x85236000
+0x010 StartVa : 0x85236000
+0x014 ByteCount : 0xc04
+0x018 ByteOffset : 0

This MDL is not locked coming into my dispatch routine, and I do lock it
myself, so this explains the assert. My question though is: why is the MDL
not locked coming into my dispatch routine? The only other cases where I
have seen non-null MDLs in the READ IRP is for paging io, and those are all
locked coming in.

Thanks.

stack trace 1

ChildEBP RetAddr Args to Child
f3af0abc 80a21a49 851923d0 85236ee8 851923d0 Pifsk!PifsDispatchRead+0x973
[s:\pi\store\pifs.new\pifsk\read.cpp @ 440]
f3af0ad4 80cd4128 85236ee8 85236ea0 f3af0b18 nt!IopfCallDriver+0x51
f3af0af8 f5410567 00000103 86208b60 86208b60 nt!IovCallDriver+0xa0
f3af0b00 86208b60 86208b60 851923d0 f3af0b38 afd!AfdTPacketsBufferRead+0x217
WARNING: Frame IP not in any known module. Following frames may be wrong.
f3af0b38 f5411510 00000000 80102424 86716fdc 0x86208b60
f3af0bf4 f542b4bb 85a15e08 86716f00 00000000 afd!AfdTransmitFile+0x57c
f3af0c08 80a21a49 85a15e08 00716f00 85a15e08
afd!AfdDispatchDeviceControl+0x4b
f3af0c20 80cd4128 84e2efb8 801023e8 86716f00 nt!IopfCallDriver+0x51
f3af0c44 80b3157e 86716fdc 85aa5ee8 86716f00 nt!IovCallDriver+0xa0
f3af0c58 80b32663 85a15e08 86716f00 85aa5ee8
nt!IopSynchronousServiceTail+0x94
f3af0cf4 80b27bcc 00000424 000006f0 00000000 nt!IopXxxControlFile+0x64f
f3af0d28 80ad5a48 00000424 000006f0 00000000 nt!NtDeviceIoControlFile+0x2a
f3af0d28 7c834684 00000424 000006f0 00000000 nt!KiFastCallEntry+0x158
0336ead0 7c80e244 47398be0 00000424 000006f0 ntdll!KiFastSystemCallRet
0336ead4 47398be0 00000424 000006f0 00000000 ntdll!NtDeviceIoControlFile+0xc
0336eb74 4739ef8d 00000424 00000760 00010000 mswsock!MSAFD_TransmitFile+0xaa
*** WARNING: Unable to verify checksum for libapr-1.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
libapr-1.dll -
0336eba0 6eecba4d 00000424 00000760 00010000 mswsock!TransmitFile+0x64
00000000 00000000 00000000 00000000 00000000
libapr_1!apr_socket_sendfile+0x2ad

stack trace 2

ChildEBP RetAddr Args to Child
f3af074c 80abbf3e 85236fc4 00000000 f3af0b18 nt!DbgBreakPoint
f3af0a3c 80abbf80 80a4f40e 80a4f3ee 0000092a nt!RtlAssert2+0x104
f3af0a58 80a4ff3f 80a4f40e 80a4f3ee 0000092a nt!RtlAssert+0x18
f3af0a90 80b0dd38 85236fc4 85de1560 851923d0 nt!MmUnlockPages+0x2b
f3af0aa4 80a18a68 85de1560 85236fc4 f3af0ad0 nt!CcMdlReadComplete2+0x16
f3af0ab4 80a1944a 85de1560 85236fc4 851923d0 nt!FsRtlMdlReadCompleteDev+0x10
f3af0ad0 f540dbbe 85de1560 85236fc4 85236fc4 nt!FsRtlMdlReadComplete+0x5e
f3af0ae4 f545ab02 85de1560 85236fc4 85236ea8 afd!AfdMdlReadComplete+0x32
85236fc4 00040020 00000000 85236000 85236000 afd!AfdCleanupPacketChain+0x14c
WARNING: Frame IP not in any known module. Following frames may be wrong.
f3af0b38 f5411510 00000002 80102424 86716fdc 0x40020
f3af0bf4 f542b4bb 85a15e08 86716f00 00000000 afd!AfdTransmitFile+0x57c
f3af0c08 80a21a49 85a15e08 00716f00 85a15e08
afd!AfdDispatchDeviceControl+0x4b
f3af0c20 80cd4128 84e2efb8 801023e8 86716f00 nt!IopfCallDriver+0x51
f3af0c44 80b3157e 86716fdc 85aa5ee8 86716f00 nt!IovCallDriver+0xa0
f3af0c58 80b32663 85a15e08 86716f00 85aa5ee8
nt!IopSynchronousServiceTail+0x94
f3af0cf4 80b27bcc 00000424 000006f0 00000000 nt!IopXxxControlFile+0x64f
f3af0d28 80ad5a48 00000424 000006f0 00000000 nt!NtDeviceIoControlFile+0x2a
f3af0d28 7c834684 00000424 000006f0 00000000 nt!KiFastCallEntry+0x158
0336ead0 7c80e244 47398be0 00000424 000006f0 ntdll!KiFastSystemCallRet
0336ead4 47398be0 00000424 000006f0 00000000 ntdll!NtDeviceIoControlFile+0xc

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

Hi all,

Sorry, typo in my original post: I meant to say “I do NOT lock it myself”. So the MDL is not locked coming into my dispatch rountine, and it is not locked in there either.

Have you tried implementing the Fast I/O functions for Mdl read (and
read complete)? AFD, as I recall, will use those first if they are
implemented and falls back to this (buffered I/O) code path otherwise.
I suspect you might be running afoul of the “this path hasn’t been
exercised in a while” sort of issue.

The second stack is consistent with the fast I/O routine being called
(are you using the FsRtl routine to implement fast I/O read complete?)

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Roger Tawa
Sent: Tuesday, September 12, 2006 11:55 AM
To: ntfsd redirect
Subject: [ntfsd] crash when TransmitFile is used on my FSD

Hi all,

I am getting a crash when an application uses the TransmitFile API with
my
file system. I am running on Windows XP SP2 checked build.

My file system gets a buffered, async, IRP_MJ_READ/IRP_MN_NORMAL, with a
non-null MDL (see stack trace 1 below). My dispatch routine gets the
buffer
address from the MDL by calling MmGetSystemAddressForMdlSafe() and, for
debugging purposes at the moment, does nothing with it. I do not touch
the
MDL otherwise. The dispatch routine then completes the IRP with
STATUS_SUCCESS and the length of the read.

I see the following assert (see stack trace 2):

*** Assertion failed: (MemoryDescriptorList->MdlFlags &
MDL_PAGES_LOCKED) !=
0
*** Source File: d:\xpsprtm\base\ntos\mm\iosup.c, line 2346

followed eventually by the crash.

The MDL that my file system gets in the READ IRP looks like this:

kd> dt 85236fc4 pifsk!MDL
+0x000 Next : (null)
+0x004 Size : 32
+0x006 MdlFlags : 4 –> MDL_SOURCE_IS_NONPAGED_POOL
+0x008 Process : (null)
+0x00c MappedSystemVa : 0x85236000
+0x010 StartVa : 0x85236000
+0x014 ByteCount : 0xc04
+0x018 ByteOffset : 0

This MDL is not locked coming into my dispatch routine, and I do lock it
myself, so this explains the assert. My question though is: why is the
MDL
not locked coming into my dispatch routine? The only other cases where
I
have seen non-null MDLs in the READ IRP is for paging io, and those are
all
locked coming in.

Thanks.

stack trace 1

ChildEBP RetAddr Args to Child
f3af0abc 80a21a49 851923d0 85236ee8 851923d0
Pifsk!PifsDispatchRead+0x973
[s:\pi\store\pifs.new\pifsk\read.cpp @ 440]
f3af0ad4 80cd4128 85236ee8 85236ea0 f3af0b18 nt!IopfCallDriver+0x51
f3af0af8 f5410567 00000103 86208b60 86208b60 nt!IovCallDriver+0xa0
f3af0b00 86208b60 86208b60 851923d0 f3af0b38
afd!AfdTPacketsBufferRead+0x217
WARNING: Frame IP not in any known module. Following frames may be
wrong.
f3af0b38 f5411510 00000000 80102424 86716fdc 0x86208b60
f3af0bf4 f542b4bb 85a15e08 86716f00 00000000 afd!AfdTransmitFile+0x57c
f3af0c08 80a21a49 85a15e08 00716f00 85a15e08
afd!AfdDispatchDeviceControl+0x4b
f3af0c20 80cd4128 84e2efb8 801023e8 86716f00 nt!IopfCallDriver+0x51
f3af0c44 80b3157e 86716fdc 85aa5ee8 86716f00 nt!IovCallDriver+0xa0
f3af0c58 80b32663 85a15e08 86716f00 85aa5ee8
nt!IopSynchronousServiceTail+0x94
f3af0cf4 80b27bcc 00000424 000006f0 00000000 nt!IopXxxControlFile+0x64f
f3af0d28 80ad5a48 00000424 000006f0 00000000
nt!NtDeviceIoControlFile+0x2a
f3af0d28 7c834684 00000424 000006f0 00000000 nt!KiFastCallEntry+0x158
0336ead0 7c80e244 47398be0 00000424 000006f0 ntdll!KiFastSystemCallRet
0336ead4 47398be0 00000424 000006f0 00000000
ntdll!NtDeviceIoControlFile+0xc
0336eb74 4739ef8d 00000424 00000760 00010000
mswsock!MSAFD_TransmitFile+0xaa
*** WARNING: Unable to verify checksum for libapr-1.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols
for
libapr-1.dll -
0336eba0 6eecba4d 00000424 00000760 00010000 mswsock!TransmitFile+0x64
00000000 00000000 00000000 00000000 00000000
libapr_1!apr_socket_sendfile+0x2ad

stack trace 2

ChildEBP RetAddr Args to Child
f3af074c 80abbf3e 85236fc4 00000000 f3af0b18 nt!DbgBreakPoint
f3af0a3c 80abbf80 80a4f40e 80a4f3ee 0000092a nt!RtlAssert2+0x104
f3af0a58 80a4ff3f 80a4f40e 80a4f3ee 0000092a nt!RtlAssert+0x18
f3af0a90 80b0dd38 85236fc4 85de1560 851923d0 nt!MmUnlockPages+0x2b
f3af0aa4 80a18a68 85de1560 85236fc4 f3af0ad0 nt!CcMdlReadComplete2+0x16
f3af0ab4 80a1944a 85de1560 85236fc4 851923d0
nt!FsRtlMdlReadCompleteDev+0x10
f3af0ad0 f540dbbe 85de1560 85236fc4 85236fc4
nt!FsRtlMdlReadComplete+0x5e
f3af0ae4 f545ab02 85de1560 85236fc4 85236ea8 afd!AfdMdlReadComplete+0x32
85236fc4 00040020 00000000 85236000 85236000
afd!AfdCleanupPacketChain+0x14c
WARNING: Frame IP not in any known module. Following frames may be
wrong.
f3af0b38 f5411510 00000002 80102424 86716fdc 0x40020
f3af0bf4 f542b4bb 85a15e08 86716f00 00000000 afd!AfdTransmitFile+0x57c
f3af0c08 80a21a49 85a15e08 00716f00 85a15e08
afd!AfdDispatchDeviceControl+0x4b
f3af0c20 80cd4128 84e2efb8 801023e8 86716f00 nt!IopfCallDriver+0x51
f3af0c44 80b3157e 86716fdc 85aa5ee8 86716f00 nt!IovCallDriver+0xa0
f3af0c58 80b32663 85a15e08 86716f00 85aa5ee8
nt!IopSynchronousServiceTail+0x94
f3af0cf4 80b27bcc 00000424 000006f0 00000000 nt!IopXxxControlFile+0x64f
f3af0d28 80ad5a48 00000424 000006f0 00000000
nt!NtDeviceIoControlFile+0x2a
f3af0d28 7c834684 00000424 000006f0 00000000 nt!KiFastCallEntry+0x158
0336ead0 7c80e244 47398be0 00000424 000006f0 ntdll!KiFastSystemCallRet
0336ead4 47398be0 00000424 000006f0 00000000
ntdll!NtDeviceIoControlFile+0xc

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Thanks Tony.

No, I have not implemented fastio mdl read calls. I have implemented
the regular fastio read call though. FASTFAT does not implemented
fastio mdl read, and it works OK on this same machine. However, I
will do as you suggest and see.

About my question: Is an MDL supposed to be already locked by the time
it gets to the driver’s dispatch routine? Is this an assumption that
I am allowed to make?

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

Well, the call sequence you were showing indicates an MDL that is being
torn down via FsRtl, which is why I was asking questions about your fast
I/O implementation. As I recall, TransmitFile uses the Fast I/O
function if it is available and a normal buffer-based read if it is not.

So, if the MDL is not locked when you get it (and let’s confirm: it
isn’t locked upon *completion* right?) then the question will be: who is
locking it. One possibility is that you’re doing something with that
MDL - passing it to another driver, for example, and that is locking it
down. That might not be “your fault” but it might be sufficiently
different than the way that FastFat (for example) satisfies the request
for you to see the different behavior.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Roger Tawa
Sent: Tuesday, September 12, 2006 1:00 PM
To: ntfsd redirect
Subject: Re: [ntfsd] crash when TransmitFile is used on my FSD

Thanks Tony.

No, I have not implemented fastio mdl read calls. I have implemented
the regular fastio read call though. FASTFAT does not implemented
fastio mdl read, and it works OK on this same machine. However, I
will do as you suggest and see.

About my question: Is an MDL supposed to be already locked by the time
it gets to the driver’s dispatch routine? Is this an assumption that
I am allowed to make?

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Hi Tony,

I understand why you asked about my fastio implementation, no problem.

Maybe I don’t fully understand the terminology, but I think I am
seeing something slightly different from what you describe when the
fastio mdl reads are not available. I see a normal, direct io-based
read, not a normal, buffer-based read. That is, I am seeing an
IRP_MJ_READ/IRP_MN_NORMAL IRP, with a non-null MDL. Maybe its the
same thing?

To answer you question, the MDL is not locked upon *entry* to my READ
dispatch routine. I am not passing the IRP down to a lower level
driver, so there are no completion routines installed in the IRP. In
fact, to narrow down the problem, I am using the debugger to step
right over all the “real” code. The dispatch routine is pretty much
just calling MmGetSystemAddressForMdlSafe() and then completing the
IRP with STATUS_SUCCESS/readLength as if all was read correctly.

Also, just to clarify again, the problem is not that the MDL is
locked, the problem is that the MDL is *unlocked*. The assert happens
when MmUnlockPages() is called, and the assert text is:

(MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) != 0

which I understand to mean that the code expects the MDL to be locked,
but it is not. Do I have it right?

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

> I see a normal, direct io-based read, not a normal, buffer-based read.

If this is a request from the AFD and an MDL is not NULL, then this is an
IRP with all possible buffering methods. The Irp->MdlAddress,
Irp->UserBuffer and Irp->AssociatedIrp.SystemBuffer are all initialized. The
AFD must free this MDL in a completion routine.

Also, just to clarify again, the problem is not that the MDL is locked, the
problem is that the MDL is *unlocked*.

The pages described by the MDL are locked, because this is an MDL
initialized by MmBuildMdlForNonPagedPool.
There is no need to *lock* and *unlock* this MDL( trying to lock may lead to
BSOD in future ).

The AFD decides that this request has been processed through the CcMdlRead
and tries to free the returned MDL, but in fact this MDL has been created by
the AFD himself and the AFD has sent this request as a normal not IRP_MN_MDL
request. I think that the AFD makes use the such type of request only if FO
has been opened as not buffred( i.e. FILE_NO_INTERMEDIATE_BUFFERING ),
because in other case the IRP_MN_MDL request may be sent instead the
FastIo.


Slava Imameyev, xxxxx@hotmail.com

“Roger Tawa” wrote in message news:xxxxx@ntfsd…
> Hi Tony,
>
> I understand why you asked about my fastio implementation, no problem.
>
> Maybe I don’t fully understand the terminology, but I think I am
> seeing something slightly different from what you describe when the
> fastio mdl reads are not available. I see a normal, direct io-based
> read, not a normal, buffer-based read. That is, I am seeing an
> IRP_MJ_READ/IRP_MN_NORMAL IRP, with a non-null MDL. Maybe its the
> same thing?
>
> To answer you question, the MDL is not locked upon entry to my READ
> dispatch routine. I am not passing the IRP down to a lower level
> driver, so there are no completion routines installed in the IRP. In
> fact, to narrow down the problem, I am using the debugger to step
> right over all the “real” code. The dispatch routine is pretty much
> just calling MmGetSystemAddressForMdlSafe() and then completing the
> IRP with STATUS_SUCCESS/readLength as if all was read correctly.
>
> Also, just to clarify again, the problem is not that the MDL is
> locked, the problem is that the MDL is unlocked. The assert happens
> when MmUnlockPages() is called, and the assert text is:
>
> (MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) != 0
>
> which I understand to mean that the code expects the MDL to be locked,
> but it is not. Do I have it right?
>
> =================================================
> Roger Tawa
> http://tawacentral.net/
> [One thing about paradigms: shift happens.]
> [When you stop, you’re done.]
>

In my experience AFD will try the fast I/O path and if that fails fall
back to doing buffered I/O. As I noted originally, it is quite possible
that Roger is running down a path that has not been tested lately.

Roger asserted that Fat does not support the fast I/O functions, but in
fact I’m looking at the DriverEntry function for FAT right now and it
indicates that FAT uses FsRtlMdlReadDev and FsRtlMdlReadCompleteDev
(which basically call CcMdlRead and CcMdlReadComplete.) This is the
WNET version - it does in fact look like they omitted this in the WXP
sample at least.

In addition, this is an infrequently used API. IIS uses it, but IIS
runs over NTFS as I recall. Thus, my original suggestion of trying to
implement those fast I/O calls (they just copy into the cache anyway…)

The FAT path through this code is certainly (ahem) interesting. Since
the Irp has an MdlAddress, FatMapUserBuffer actually returns the value
from MmGetSystemAddressForMdlSafe. If this MDL was built using
non-paged pool, it should just get back the existing system address.

BUT, in XPSP2 FAT doesn’t implement these Fast I/O entry points either,
so it seems like it should exhibit the same behavior - yet Roger clearly
indicates his test program doesn’t have any problems over FAT. Thus,
there’s something more subtle happening here, which unfortunately means
Roger may have to watch the completion handling in AFD for FAT and
compare it to the completion handling in AFD for his own FSD.

I suggested implementing those fast I/O functions in order to see if
that changed the behavior.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Slava Imameyev
Sent: Tuesday, September 12, 2006 4:09 PM
To: ntfsd redirect
Subject: Re:[ntfsd] crash when TransmitFile is used on my FSD

I see a normal, direct io-based read, not a normal, buffer-based read.

If this is a request from the AFD and an MDL is not NULL, then this is
an
IRP with all possible buffering methods. The Irp->MdlAddress,
Irp->UserBuffer and Irp->AssociatedIrp.SystemBuffer are all initialized.
The
AFD must free this MDL in a completion routine.

Also, just to clarify again, the problem is not that the MDL is locked,
the
problem is that the MDL is *unlocked*.

The pages described by the MDL are locked, because this is an MDL
initialized by MmBuildMdlForNonPagedPool.
There is no need to *lock* and *unlock* this MDL( trying to lock may
lead to
BSOD in future ).

The AFD decides that this request has been processed through the
CcMdlRead
and tries to free the returned MDL, but in fact this MDL has been
created by
the AFD himself and the AFD has sent this request as a normal not
IRP_MN_MDL
request. I think that the AFD makes use the such type of request only if
FO
has been opened as not buffred( i.e. FILE_NO_INTERMEDIATE_BUFFERING ),
because in other case the IRP_MN_MDL request may be sent instead the
FastIo.


Slava Imameyev, xxxxx@hotmail.com

“Roger Tawa” wrote in message news:xxxxx@ntfsd…
> Hi Tony,
>
> I understand why you asked about my fastio implementation, no problem.
>
> Maybe I don’t fully understand the terminology, but I think I am
> seeing something slightly different from what you describe when the
> fastio mdl reads are not available. I see a normal, direct io-based
> read, not a normal, buffer-based read. That is, I am seeing an
> IRP_MJ_READ/IRP_MN_NORMAL IRP, with a non-null MDL. Maybe its the
> same thing?
>
> To answer you question, the MDL is not locked upon entry to my READ
> dispatch routine. I am not passing the IRP down to a lower level
> driver, so there are no completion routines installed in the IRP. In
> fact, to narrow down the problem, I am using the debugger to step
> right over all the “real” code. The dispatch routine is pretty much
> just calling MmGetSystemAddressForMdlSafe() and then completing the
> IRP with STATUS_SUCCESS/readLength as if all was read correctly.
>
> Also, just to clarify again, the problem is not that the MDL is
> locked, the problem is that the MDL is unlocked. The assert happens
> when MmUnlockPages() is called, and the assert text is:
>
> (MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) != 0
>
> which I understand to mean that the code expects the MDL to be locked,
> but it is not. Do I have it right?
>
> =================================================
> Roger Tawa
> http://tawacentral.net/
> [One thing about paradigms: shift happens.]
> [When you stop, you’re done.]
>


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Thanks Slava, Tony. Lots of information to digest here!

Wrt FASTFAT and the fastio mdl read calls, you are correct that I only
looked at WXP and not WNET (IFS kit 3790). I guess this is one of the
differentiators between the two OS versions?

I implemented Tony’s suggestion (using FsRtlMdlReadDev and
FsRtlMdlReadCompleteDev) but I got the same result. I am going to
check to make sure that fastio is really turned on for this file, but
I did verify that FCB->IsFastIoPossible is set to 1. Maybe there is a
problem with my Is-Fast-Io-Possible logic.

I see what you mean Slava: since this is an NPP MDL, there is no need
to lock or unlock. That’s the part I don’t understand: why is AFD
trying to unlock it, assuming it was the one that allocated the MDL in
the first place. I know that I did not get an IRP_MJ_READ/IRP_MN_MDL,
so I know that my file system did not allocate it.

I have already stepped through the AFD completion of the IRP (AFD
installs a completion routine in the IRP). What I noticed is that it
copies the MDL out of the IRP into its own memory, then nulls
Irp->MdlAddress. It ends by returning STATUS_MORE_PROCESSING_REQUIRED
from the completion routine. At that point I loose track of the MDL.
I think I’ll use a data breakpoint.

As Tony suggested, I may need to more closely compare this completion
with the completion over FASTFAT…

Can you explain a bit more about the relationship between buffered or
non-buffered FO, AFD, fastio, and IRP_MN_MDL? I don’t know if the FO
is buffered or not in this case, I’ll go take a look.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

> I don’t know if the FO is buffered or not in this case

Your FSD must set FO_CACHE_SUPPORTED. If ( FO->Flags & FO_CACHE_SUPPORTED )
then the file is opened as buffered( cached ) and FSD can initialize cache
map for this file if needed.

Can you explain a bit more about the relationship between buffered or
non-buffered FO, AFD, fastio, and IRP_MN_MDL

I think the AFD logic is

{

if( FastIo is possible ){

FastIoSucceed = DoFastIoMdlRead();
if( FastIoSucceed ){
DoFastIoCompleteMdlRead();
return;
}
}

//
// FastIo failed or NA. If the file is cached( or cache can be
initialized for this file ) retrieve an MDL for a mapped file, else allocate
a buffer
//
if ( FO->Flags & FO_CACHE_SUPPORTED ){

//
// retrieve the MDL that describes pages of the mapped file
//
Irp->MdlAddress = NULL;
Irp->MinorFunction = IRP_MN_MDL;
CompletionContext->MdlRead = TRUE;

}else {

//
// allocate the buffer for read
//
Allocate Non Paged Buffer;
Mdl = MmBuildMdlForNonPagedPool();
Irp->MdlAddress = Mdl;
CompletionContext->MdlRead = FALSE;
}

IoSetCompletionRoutine( Irp, AfdReadCompletion, CompletionContext,
… );

IoCallDriver( …, Irp );
return;
}

And something confuse the AFD and while its completion routine is executing
it finds( or decides ) that TRUE == CompletionContext->MdlRead.
I think if you set FO_CACHE_SUPPORTED and initialize the cache map for a FO
you will receive an IRP_MN_MDL read request.


Slava Imameyev, xxxxx@hotmail.com

“Roger Tawa” wrote in message news:xxxxx@ntfsd…
> Thanks Slava, Tony. Lots of information to digest here!
>
> Wrt FASTFAT and the fastio mdl read calls, you are correct that I only
> looked at WXP and not WNET (IFS kit 3790). I guess this is one of the
> differentiators between the two OS versions?
>
> I implemented Tony’s suggestion (using FsRtlMdlReadDev and
> FsRtlMdlReadCompleteDev) but I got the same result. I am going to
> check to make sure that fastio is really turned on for this file, but
> I did verify that FCB->IsFastIoPossible is set to 1. Maybe there is a
> problem with my Is-Fast-Io-Possible logic.
>
> I see what you mean Slava: since this is an NPP MDL, there is no need
> to lock or unlock. That’s the part I don’t understand: why is AFD
> trying to unlock it, assuming it was the one that allocated the MDL in
> the first place. I know that I did not get an IRP_MJ_READ/IRP_MN_MDL,
> so I know that my file system did not allocate it.
>
> I have already stepped through the AFD completion of the IRP (AFD
> installs a completion routine in the IRP). What I noticed is that it
> copies the MDL out of the IRP into its own memory, then nulls
> Irp->MdlAddress. It ends by returning STATUS_MORE_PROCESSING_REQUIRED
> from the completion routine. At that point I loose track of the MDL.
> I think I’ll use a data breakpoint.
>
> As Tony suggested, I may need to more closely compare this completion
> with the completion over FASTFAT…
>
> Can you explain a bit more about the relationship between buffered or
> non-buffered FO, AFD, fastio, and IRP_MN_MDL? I don’t know if the FO
> is buffered or not in this case, I’ll go take a look.
>
> =================================================
> Roger Tawa
> http://tawacentral.net/
> [One thing about paradigms: shift happens.]
> [When you stop, you’re done.]
>

>I implemented Tony’s suggestion (using FsRtlMdlReadDev and

FsRtlMdlReadCompleteDev) but I got the same result.

I think this is because you did not set FO_CACHE_SUPPORTED flag.
If this flag is set the FastIo is used if
FastIoIsPossible==FCB->IsFastIoPossible or FastIoCheckIfPossible returns
TRUE.
If FastIo failed the IRP_MN_MDL Irp is sent if FO_CACHE_SUPPORTED is set,
else buffer is allocated and the Irp which you see is used.

So the AFD code must be like this

{

if( ( FO->Flags & FO_CACHE_SUPPORTED ) && ( FastIoIsPossible ==
FCB->IsFastIoPossible ) ){

if( NULL != DriverObject->FastIoDispatch->MdlRead ){
FastIoSucceed = DriverObject->FastIoDispatch->MdlRead( FO,… );
} else {
FastIoSucceed = FsRtlMdlReadDev( FO, … );
}

if( FastIoSucceed ){
DoFastIoCompleteMdlRead();
return;
}
}

//
// FastIo failed or NA. If the file is cached( or cache can be
// initialized for this file ) retrieve an MDL for a mapped file, else
allocate
// a buffer
//
if ( FO->Flags & FO_CACHE_SUPPORTED ){

//
// retrieve the MDL that describes pages of the mapped file
//
Irp->MdlAddress = NULL;
Irp->MinorFunction = IRP_MN_MDL;
CompletionContext->MdlRead = TRUE;

}else {

//
// allocate the buffer for read
//
Allocate Non Paged Buffer;
Mdl = MmBuildMdlForNonPagedPool();
Irp->MdlAddress = Mdl;
CompletionContext->MdlRead = FALSE;
}

IoSetCompletionRoutine( Irp, AfdReadCompletion, CompletionContext,
… );

IoCallDriver( …, Irp );
return;
}


Slava Imameyev, xxxxx@hotmail.com

“Roger Tawa” wrote in message news:xxxxx@ntfsd…
> Thanks Slava, Tony. Lots of information to digest here!
>
> Wrt FASTFAT and the fastio mdl read calls, you are correct that I only
> looked at WXP and not WNET (IFS kit 3790). I guess this is one of the
> differentiators between the two OS versions?
>
> I implemented Tony’s suggestion (using FsRtlMdlReadDev and
> FsRtlMdlReadCompleteDev) but I got the same result. I am going to
> check to make sure that fastio is really turned on for this file, but
> I did verify that FCB->IsFastIoPossible is set to 1. Maybe there is a
> problem with my Is-Fast-Io-Possible logic.
>
> I see what you mean Slava: since this is an NPP MDL, there is no need
> to lock or unlock. That’s the part I don’t understand: why is AFD
> trying to unlock it, assuming it was the one that allocated the MDL in
> the first place. I know that I did not get an IRP_MJ_READ/IRP_MN_MDL,
> so I know that my file system did not allocate it.
>
> I have already stepped through the AFD completion of the IRP (AFD
> installs a completion routine in the IRP). What I noticed is that it
> copies the MDL out of the IRP into its own memory, then nulls
> Irp->MdlAddress. It ends by returning STATUS_MORE_PROCESSING_REQUIRED
> from the completion routine. At that point I loose track of the MDL.
> I think I’ll use a data breakpoint.
>
> As Tony suggested, I may need to more closely compare this completion
> with the completion over FASTFAT…
>
> Can you explain a bit more about the relationship between buffered or
> non-buffered FO, AFD, fastio, and IRP_MN_MDL? I don’t know if the FO
> is buffered or not in this case, I’ll go take a look.
>
> =================================================
> Roger Tawa
> http://tawacentral.net/
> [One thing about paradigms: shift happens.]
> [When you stop, you’re done.]
>

Thanks again for your responses Slava.

You are correct about my handling of FO_CACHE_SUPPORTED. I delay
CcInitializeCacheMap() until I really need to do it, and only then do
I set the FO_CACHE_SUPPORTED flag, as a way to remember that the cache
has been initialized. I now see that this is incorrect.

I will set this flag in the same way that FASTFAT does and use another
mechanism to determine if the cache has been initialized or not. I’ll
see how it goes.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

You nailed it Slava! Thanks! No more crash.

Looking back at what I was doing, I suspect I was confusing AFD by
changing the state of the FO_CACHE_SUPPORTED flag. Before AFD sent
the READ IRP to my file system, FO_CACHE_SUPPORTED was not set.
During the execution of the read, I was initializing the cache map and
setting the FO_CACHE_SUPPORTED flag.

When the AFD’s completion routine executes, it probably takes a code
path based on the state of FO_CACHE_SUPPORTED, which is incompatible
with the code path it executed when creating the READ IRP (and MDL).

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

> About my question: Is an MDL supposed to be already locked by the time

it gets to the driver’s dispatch routine? Is this an assumption that
I am allowed to make?

Yes.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

>In addition, this is an infrequently used API. IIS uses it, but IIS

runs over NTFS as I recall.

IIS can run over FAT just fine.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Let me then clarify: MS strongly discourages the use of IIS over FAT
(c.f. http://msdn2.microsoft.com/en-us/library/ms172965.aspx) and would
work to optimize performance over NTFS, not FAT.

I wonder if it works over CDFS…

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Wednesday, September 13, 2006 1:58 PM
To: ntfsd redirect
Subject: Re: [ntfsd] crash when TransmitFile is used on my FSD

In addition, this is an infrequently used API. IIS uses it, but IIS
runs over NTFS as I recall.

IIS can run over FAT just fine.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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