Hello,

I am currently porting a pseudo disk driver to NT from Unix of which one
aspect of its operation is to perform a mirrored write. The manner in
which it performs the mirrored write is to clone the original IRP for
each mirror and then issue the cloned IRPs to the primary and secondary
devices. During the mirrored write the original IRP is stalled. After
the cloned requests complete, the original IRP is eventually completed.

If I only clone the IRP once and issue the clone to the primary device
the driver seems to work well (as evidenced by a data integrity tool
I'm using).

However, if I instruct the driver to perform mirroring, the data sent
to the primary device is always corrupted (I am currently unable to
verify the secondary as it is not written in the original format).

Here's is the gist of my IRP clone operation. After calling the
cloning macro a cloned IRP is further modiefied to point to the
correct device by directly setting the DeviceObject field in the IRP.
Also, the IRPs are hand made and set up by IoInitializeIrp() rather
than by IoAllocateIrp().

It's probably worth admitting that while I have programmed drivers for
Unix for many years I've only been working with NT for a month or so.

I would greatly appreciate any insight into how to solve this problem
correctly. I have scoured this list and the web for similar examples
but haven't found anything relevant thus far.

Thanks!
Greg


#define CLONE_IRP(src, dst, zoffset) \
do { \
IO_STACK_LOCATION *srcstk, *dststk; \
srcstk = IoGetCurrentIrpStackLocation(src); \
dststk = IoGetCurrentIrpStackLocation(dst); \
*dststk = *srcstk; \
dststk->Context = (void *)0; \
(dst)->MdlAddress = IoAllocateMdl( \
MmGetMdlVirtualAddress((src)->MdlAddress), \
MmGetMdlByteCount((src)->MdlAddress), \
FALSE, FALSE, (IRP *)0); \
IoBuildPartialMdl((src)->MdlAddress, (dst)->MdlAddress, \
(char *)MmGetMdlVirtualAddress((src)->MdlAddress) + \
(zoffset), (unsigned long)0); \
(dst)->Tail.Overlay.Thread = (src)->Tail.Overlay.Thread; \
} while (0)

Re: irp cloning... by Martin

Martin
Fri Jan 07 06:31:14 CST 2005


"Greg Becker" <greg@codeconcepts.com> wrote in message
news:ohs0b2-5pa2.ln1@gromit.codeconcepts.com...

> However, if I instruct the driver to perform mirroring, the data sent
> to the primary device is always corrupted (I am currently unable to
> verify the secondary as it is not written in the original format).

> It's probably worth admitting that while I have programmed drivers for
> Unix for many years I've only been working with NT for a month or so.

First impressions?

> I would greatly appreciate any insight into how to solve this problem
> correctly. I have scoured this list and the web for similar examples
> but haven't found anything relevant thus far.

I could be totally wrong here (I'm not a guru or anything) but my thoughts
are:

> #define CLONE_IRP(src, dst, zoffset) \
> do { \
> IO_STACK_LOCATION *srcstk, *dststk; \
> srcstk = IoGetCurrentIrpStackLocation(src); \
> dststk = IoGetCurrentIrpStackLocation(dst); \
> *dststk = *srcstk; \

This seems a trifle on the "ambitious" side to me. In particularly, there's
quite a lot of stuff in an IO_STACK_LOCATION that you might want to
consider....

For a start, just looking at copying stack locations which are on the same
stack, the DDK gives you:

#define IoCopyCurrentIrpStackLocationToNext( Irp ) { \
PIO_STACK_LOCATION irpSp; \
PIO_STACK_LOCATION nextIrpSp; \
irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \
nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \
RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION,
CompletionRoutine)); \
nextIrpSp->Control = 0; }

So copying the completion routine or anything after might possibly be a bad
idea, and you may need to look at the control field.

Secondly, if you're copying to/from different stacks, then you're likely to
need to be a great deal more cautious in what you overwrite - the device
object & file object pointers might not take kindly to being overwritten.
After that, how you handle the actual parameters depends on the type of IRP,
and some things may not be as re-usable as one might think...

MH.



Re: irp cloning... by Greg

Greg
Fri Jan 07 18:30:01 CST 2005

Thanks! I didn't realize IoCopyCurrentIrpStackLocationToNext() is a
macro and have adjusted my clone macro accordingly. Now I only copy up
until the DeviceObject.

So, it turns out that my port was working all along. My test tool,
which was ported to Windows in a half-native, half cygwin fashion seems
to have been the problem, but I don't yet understand why. I'll post
back one I port it so as to eradicate cygwin from the picture.

First impressions? Hmm.. Well, I'm a Mac programmer from way back
(circa 95), but I can't comment on the UI as I've only been exposed to
the internals. I would say that I am impressed with the volume of
internals documentation, but unimpressed that the docs for functions
like IoAllocateMdl say nothing about how it doesn't actually fill out
the mappings (i.e., it took me a while to figure that one out, and was
led astray by several leads books on the issue which make no mention of
it). OTOH, it has a reasonably well thought out driver model wrt the
fact that it actually supports layered drivers unlike most OS's that
predate it. Anyway, that's me being nice :-)

Martin Harvey (work) wrote:
> "Greg Becker" <greg@codeconcepts.com> wrote in message
> news:ohs0b2-5pa2.ln1@gromit.codeconcepts.com...
>
>
>>However, if I instruct the driver to perform mirroring, the data sent
>>to the primary device is always corrupted (I am currently unable to
>>verify the secondary as it is not written in the original format).
>
>
>>It's probably worth admitting that while I have programmed drivers for
>>Unix for many years I've only been working with NT for a month or so.
>
>
> First impressions?
>
>
>>I would greatly appreciate any insight into how to solve this problem
>>correctly. I have scoured this list and the web for similar examples
>>but haven't found anything relevant thus far.
>
>
> I could be totally wrong here (I'm not a guru or anything) but my thoughts
> are:
>
>
>>#define CLONE_IRP(src, dst, zoffset) \
>>do { \
>> IO_STACK_LOCATION *srcstk, *dststk; \
>> srcstk = IoGetCurrentIrpStackLocation(src); \
>> dststk = IoGetCurrentIrpStackLocation(dst); \
>> *dststk = *srcstk; \
>
>
> This seems a trifle on the "ambitious" side to me. In particularly, there's
> quite a lot of stuff in an IO_STACK_LOCATION that you might want to
> consider....
>
> For a start, just looking at copying stack locations which are on the same
> stack, the DDK gives you:
>
> #define IoCopyCurrentIrpStackLocationToNext( Irp ) { \
> PIO_STACK_LOCATION irpSp; \
> PIO_STACK_LOCATION nextIrpSp; \
> irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \
> nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \
> RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION,
> CompletionRoutine)); \
> nextIrpSp->Control = 0; }
>
> So copying the completion routine or anything after might possibly be a bad
> idea, and you may need to look at the control field.
>
> Secondly, if you're copying to/from different stacks, then you're likely to
> need to be a great deal more cautious in what you overwrite - the device
> object & file object pointers might not take kindly to being overwritten.
> After that, how you handle the actual parameters depends on the type of IRP,
> and some things may not be as re-usable as one might think...
>
> MH.
>
>

Re: irp cloning... by Alexander

Alexander
Fri Jan 07 23:03:52 CST 2005

You also have to copy some parameters from the IRP itself, such as
AssociatedIrp, MdlAddress, RequestorMode, UserBuffer.

"Greg Becker" <greg@codeconcepts.com> wrote in message
news:dpk3b2-6e3.ln1@gromit.codeconcepts.com...
> Thanks! I didn't realize IoCopyCurrentIrpStackLocationToNext() is a macro
> and have adjusted my clone macro accordingly. Now I only copy up until
> the DeviceObject.
>
> So, it turns out that my port was working all along. My test tool, which
> was ported to Windows in a half-native, half cygwin fashion seems to have
> been the problem, but I don't yet understand why. I'll post back one I
> port it so as to eradicate cygwin from the picture.
>
> First impressions? Hmm.. Well, I'm a Mac programmer from way back (circa
> 95), but I can't comment on the UI as I've only been exposed to the
> internals. I would say that I am impressed with the volume of internals
> documentation, but unimpressed that the docs for functions like
> IoAllocateMdl say nothing about how it doesn't actually fill out the
> mappings (i.e., it took me a while to figure that one out, and was led
> astray by several leads books on the issue which make no mention of it).
> OTOH, it has a reasonably well thought out driver model wrt the fact that
> it actually supports layered drivers unlike most OS's that predate it.
> Anyway, that's me being nice :-)
>
> Martin Harvey (work) wrote:
>> "Greg Becker" <greg@codeconcepts.com> wrote in message
>> news:ohs0b2-5pa2.ln1@gromit.codeconcepts.com...
>>
>>
>>>However, if I instruct the driver to perform mirroring, the data sent
>>>to the primary device is always corrupted (I am currently unable to
>>>verify the secondary as it is not written in the original format).
>>
>>
>>>It's probably worth admitting that while I have programmed drivers for
>>>Unix for many years I've only been working with NT for a month or so.
>>
>>
>> First impressions?
>>
>>
>>>I would greatly appreciate any insight into how to solve this problem
>>>correctly. I have scoured this list and the web for similar examples
>>>but haven't found anything relevant thus far.
>>
>>
>> I could be totally wrong here (I'm not a guru or anything) but my
>> thoughts are:
>>
>>
>>>#define CLONE_IRP(src, dst, zoffset) \
>>>do { \
>>> IO_STACK_LOCATION *srcstk, *dststk; \
>>> srcstk = IoGetCurrentIrpStackLocation(src); \
>>> dststk = IoGetCurrentIrpStackLocation(dst); \
>>> *dststk = *srcstk; \
>>
>>
>> This seems a trifle on the "ambitious" side to me. In particularly,
>> there's quite a lot of stuff in an IO_STACK_LOCATION that you might want
>> to consider....
>>
>> For a start, just looking at copying stack locations which are on the
>> same stack, the DDK gives you:
>>
>> #define IoCopyCurrentIrpStackLocationToNext( Irp ) { \
>> PIO_STACK_LOCATION irpSp; \
>> PIO_STACK_LOCATION nextIrpSp; \
>> irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \
>> nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \
>> RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION,
>> CompletionRoutine)); \
>> nextIrpSp->Control = 0; }
>>
>> So copying the completion routine or anything after might possibly be a
>> bad idea, and you may need to look at the control field.
>>
>> Secondly, if you're copying to/from different stacks, then you're likely
>> to need to be a great deal more cautious in what you overwrite - the
>> device object & file object pointers might not take kindly to being
>> overwritten. After that, how you handle the actual parameters depends on
>> the type of IRP, and some things may not be as re-usable as one might
>> think...
>>
>> MH.