KMDF and MDL chain

I am writing a kmdf driver. I have virtually dis-contiguous memory buffers which needs to be used for a single IO and want to create MDL chain for this.
I was looking for KMDF APIs which would create wdf memory object representing MDL chain. I want to format a wdf request with this memory object.
I read the documentation of WdfMemoryCreate, WdfMemoryCreatePreallocated but doesnt seem to solve the purpose.
It seems I can get it working by creating IRP (in WDM way) and not wdf request.
Any help would highly be appreciated

KMDF does not support this scenario. The driver you are sending the io to also has to understand MDL chains (not many do)

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Tuesday, November 01, 2011 11:26 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] KMDF and MDL chain

I am writing a kmdf driver. I have virtually dis-contiguous memory buffers which needs to be used for a single IO and want to create MDL chain for this.
I was looking for KMDF APIs which would create wdf memory object representing MDL chain. I want to format a wdf request with this memory object.
I read the documentation of WdfMemoryCreate, WdfMemoryCreatePreallocated but doesnt seem to solve the purpose.
It seems I can get it working by creating IRP (in WDM way) and not wdf request.
Any help would highly be appreciated


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

I believe it supports chained MDLs. I will validate and update here.
So, if it is supporting chained MDLs, can I create IRP in KMDF driver. There seems no restriction using DDIs in KMDF

You can format the underlying IRP if you want. The io target will want you that you have used at some kind of KMDF formatting call though, typically WdfRequestWdmFormatUsingStackLocation works quite well in this scenario.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Tuesday, November 01, 2011 11:43 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KMDF and MDL chain

I believe it supports chained MDLs. I will validate and update here.
So, if it is supporting chained MDLs, can I create IRP in KMDF driver. There seems no restriction using DDIs in KMDF


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Yes, you CAN create your own IRPs and manage your own buffers/MDLs within a KMDF driver. That’s one of the beauties of KMDF.

But, as Doron suggested… proceed with caution. It is difficult to know whether the ultimate target of your I/O Request will support chained MDLs. For example, whether chained MDLs are supported or not can depend on which SPECIFIC DMA APIs the ultimate driver handling the request uses.

Good luck,

Peter
OSR

>your I/O Request will support chained MDLs

Things like TDI, for instance, surely support them.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Thanks Maxim, Doron, Peter for your quick reply.

Let me explain my requirement in a bit detail. The driver (Storage driver - disk/volume class drivers) I am sending the io, supports MDL chains. I tried MDL chain support with a test driver. Please confirm if this holds always true.

>WdfRequestWdmFormatUsingStackLocation works quite well in this scenario.

So, using WdfRequestWdmFormatUsingStackLocation I can set wdf request parameters. This will not set buffer (MDL in this case) for the request. I need to get the IRP using WdfRequestWdmGetIrp and set MdlAddress to MDL chain. Please correct me if I am wrong.

Yes, you need to set the mdl yourself. I didn’t think the underlying storage stack supported chained mdls

d

debt from my phone


From: xxxxx@gmail.com
Sent: 11/1/2011 9:37 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KMDF and MDL chain

Thanks Maxim, Doron, Peter for your quick reply.

Let me explain my requirement in a bit detail. The driver (Storage driver - disk/volume class drivers) I am sending the io, supports MDL chains. I tried MDL chain support with a test driver. Please confirm if this holds always true.

>WdfRequestWdmFormatUsingStackLocation works quite well in this scenario.

So, using WdfRequestWdmFormatUsingStackLocation I can set wdf request parameters. This will not set buffer (MDL in this case) for the request. I need to get the IRP using WdfRequestWdmGetIrp and set MdlAddress to MDL chain. Please correct me if I am wrong.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks Doron

> I didn’t think the underlying storage stack supported chained mdls

I have not found any documentation discussing MDL chain support with these drivers. It seems. there are chances that MDL chain support may not be consistent on different windows versions for these drivers and subject to change.

The alternative design to MDL chain, was to divide the IO (not standard windows IO request) into multiples (windows IO requests) considering contiguous virtual addresses which I wanted to avoid.

> Let me explain my requirement in a bit detail. The driver (Storage driver - disk/volume class drivers) I

am sending the io, supports MDL chains. I tried MDL chain support with a test driver. Please confirm
if this holds always true.

Storage stack actually was never ever supported MDL chains, I’m surprised it is so.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

This is how I verified MDL chain on windows 2008 R2

#define NUMBER_OF_PAGES 10

PVOID Vaddress[NUMBER_OF_PAGES] = {0};
PVOID Vaddress_hole[NUMBER_OF_PAGES] = {0};

PMDL MdlArr[NUMBER_OF_PAGES] = {0};

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
ULONG i;
PDEVICE_OBJECT DeviceObject;
NTSTATUS ntStatus = STATUS_SUCCESS;
PMDL SingleMdl;
PVOID buffer;

DriverObject->DriverUnload = Unload;

for (i =0 ; i < NUMBER_OF_PAGES; i++)
{
Vaddress[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
ASSERT(Vaddress[i]);

DbgPrint(“Vaddress[%d] = %p\n”, i, Vaddress[i]);

MdlArr[i] = IoAllocateMdl(
Vaddress[i] ,
4096,
FALSE,
FALSE,
NULL
);

DbgPrint(“MdlArr[%d] = %p\n”, i, MdlArr[i]);
MmBuildMdlForNonPagedPool(MdlArr[i]);

if( i != 0)
{
MdlArr[i - 1]->Next = MdlArr[i];
}

Vaddress_hole[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
ASSERT(Vaddress_hole[i]);
}

ntStatus = GetDeviceObject(&DeviceObject);
ASSERT(NT_SUCCESS(ntStatus));
if(!NT_SUCCESS(ntStatus))
{
goto claenup;
}

ntStatus =VolRead(DeviceObject, MdlArr[0],4096 * NUMBER_OF_PAGES);
ASSERT(NT_SUCCESS(ntStatus));

buffer = ExAllocatePoolWithTag(NonPagedPool,4096 * NUMBER_OF_PAGES,TEST_TAG);
ASSERT(buffer);

SingleMdl = IoAllocateMdl(
buffer,
4096 * 10,
FALSE,
FALSE,
NULL
);

MmBuildMdlForNonPagedPool(SingleMdl);
ASSERT(SingleMdl);

ntStatus =VolRead(DeviceObject, SingleMdl,4096 * NUMBER_OF_PAGES);
ASSERT(NT_SUCCESS(ntStatus));

for (i =0 ; i < NUMBER_OF_PAGES; i++)
{
ULONG MatchedBytes =RtlCompareMemory(
(PCHAR)buffer + (i * 4096),
Vaddress[i],
4096
);

ASSERT( 4096 == MatchedBytes);
}

claenup:
for (i =0 ; i < NUMBER_OF_PAGES; i++)
{
IoFreeMdl(MdlArr[i]);
ExFreePool(Vaddress[i]);
ExFreePool(Vaddress_hole[i]);
}

IoFreeMdl(SingleMdl);
ExFreePool(buffer);

return STATUS_SUCCESS;
}

Can anybody from MS tell whether this is a supported scenario?

What about large (>64K requests), for a case Disk.sys to split the request to several smaller ones? will they work?

What about 3rd party filter drivers? will all of them crash due to this code? I think there is a very major probability with this.

Will this work on both SATA and USB-connected storage? what about iSCSI?

I personally would never ever write such code in the product, unless some authority source within MS will answer “yes, it is OK”. Not only the question is about older Windows, but also about the compat issues listed above.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> This is how I verified MDL chain on windows 2008 R2
>
> #define NUMBER_OF_PAGES 10
>
> PVOID Vaddress[NUMBER_OF_PAGES] = {0};
> PVOID Vaddress_hole[NUMBER_OF_PAGES] = {0};
>
> PMDL MdlArr[NUMBER_OF_PAGES] = {0};
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> ULONG i;
> PDEVICE_OBJECT DeviceObject;
> NTSTATUS ntStatus = STATUS_SUCCESS;
> PMDL SingleMdl;
> PVOID buffer;
>
> DriverObject->DriverUnload = Unload;
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> Vaddress[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress[i]);
>
> DbgPrint(“Vaddress[%d] = %p\n”, i, Vaddress[i]);
>
> MdlArr[i] = IoAllocateMdl(
> Vaddress[i] ,
> 4096,
> FALSE,
> FALSE,
> NULL
> );
>
> DbgPrint(“MdlArr[%d] = %p\n”, i, MdlArr[i]);
> MmBuildMdlForNonPagedPool(MdlArr[i]);
>
> if( i != 0)
> {
> MdlArr[i - 1]->Next = MdlArr[i];
> }
>
> Vaddress_hole[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress_hole[i]);
> }
>
>
> ntStatus = GetDeviceObject(&DeviceObject);
> ASSERT(NT_SUCCESS(ntStatus));
> if(!NT_SUCCESS(ntStatus))
> {
> goto claenup;
> }
>
> ntStatus =VolRead(DeviceObject, MdlArr[0],4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> buffer = ExAllocatePoolWithTag(NonPagedPool,4096 * NUMBER_OF_PAGES,TEST_TAG);
> ASSERT(buffer);
>
> SingleMdl = IoAllocateMdl(
> buffer,
> 4096 * 10,
> FALSE,
> FALSE,
> NULL
> );
>
> MmBuildMdlForNonPagedPool(SingleMdl);
> ASSERT(SingleMdl);
>
> ntStatus =VolRead(DeviceObject, SingleMdl,4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> ULONG MatchedBytes =RtlCompareMemory(
> (PCHAR)buffer + (i * 4096),
> Vaddress[i],
> 4096
> );
>
> ASSERT( 4096 == MatchedBytes);
> }
>
> claenup:
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> IoFreeMdl(MdlArr[i]);
> ExFreePool(Vaddress[i]);
> ExFreePool(Vaddress_hole[i]);
> }
>
> IoFreeMdl(SingleMdl);
> ExFreePool(buffer);
>
> return STATUS_SUCCESS;
> }
>
>
>

Thanks Maxim.

> What about large (>64K requests), for a case Disk.sys to split the request
> to several smaller ones? will they work?

Just out of curiosity - Can you elaborate on request splitting ? Does it also happen at volume layer (I can think of scenario of striped volume) ?

I also found MmProbeAndLockSelectedPages (http://msdn.microsoft.com/en-us/library/windows/hardware/hh406526(v=vs.85).aspx) which create single MDL from dis-contiguous address space. But not available on all windows versions.

“Maxim S. Shatskih” wrote in message news:xxxxx@ntdev…

What about large (>64K requests), for a case Disk.sys to split the request
to several smaller ones? will they work?

There was a post here a few months back where someone had system crash due
to sending disk.sys chained MDLs. More evidence that this has never been
supported in the storage stack.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Maxim S. Shatskih” wrote in message news:xxxxx@ntdev…

Can anybody from MS tell whether this is a supported scenario?

What about large (>64K requests), for a case Disk.sys to split the
request to several smaller ones? will they work?

What about 3rd party filter drivers? will all of them crash due to
this code? I think there is a very major probability with this.

Will this work on both SATA and USB-connected storage? what about iSCSI?

I personally would never ever write such code in the product, unless
some authority source within MS will answer “yes, it is OK”. Not only the
question is about older Windows, but also about the compat issues listed
above.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> This is how I verified MDL chain on windows 2008 R2
>
> #define NUMBER_OF_PAGES 10
>
> PVOID Vaddress[NUMBER_OF_PAGES] = {0};
> PVOID Vaddress_hole[NUMBER_OF_PAGES] = {0};
>
> PMDL MdlArr[NUMBER_OF_PAGES] = {0};
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> ULONG i;
> PDEVICE_OBJECT DeviceObject;
> NTSTATUS ntStatus = STATUS_SUCCESS;
> PMDL SingleMdl;
> PVOID buffer;
>
> DriverObject->DriverUnload = Unload;
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> Vaddress[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress[i]);
>
> DbgPrint(“Vaddress[%d] = %p\n”, i, Vaddress[i]);
>
> MdlArr[i] = IoAllocateMdl(
> Vaddress[i] ,
> 4096,
> FALSE,
> FALSE,
> NULL
> );
>
> DbgPrint(“MdlArr[%d] = %p\n”, i, MdlArr[i]);
> MmBuildMdlForNonPagedPool(MdlArr[i]);
>
> if( i != 0)
> {
> MdlArr[i - 1]->Next = MdlArr[i];
> }
>
> Vaddress_hole[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress_hole[i]);
> }
>
>
> ntStatus = GetDeviceObject(&DeviceObject);
> ASSERT(NT_SUCCESS(ntStatus));
> if(!NT_SUCCESS(ntStatus))
> {
> goto claenup;
> }
>
> ntStatus =VolRead(DeviceObject, MdlArr[0],4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> buffer = ExAllocatePoolWithTag(NonPagedPool,4096 *
> NUMBER_OF_PAGES,TEST_TAG);
> ASSERT(buffer);
>
> SingleMdl = IoAllocateMdl(
> buffer,
> 4096 * 10,
> FALSE,
> FALSE,
> NULL
> );
>
> MmBuildMdlForNonPagedPool(SingleMdl);
> ASSERT(SingleMdl);
>
> ntStatus =VolRead(DeviceObject, SingleMdl,4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> ULONG MatchedBytes =RtlCompareMemory(
> (PCHAR)buffer + (i * 4096),
> Vaddress[i],
> 4096
> );
>
> ASSERT( 4096 == MatchedBytes);
> }
>
> claenup:
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> IoFreeMdl(MdlArr[i]);
> ExFreePool(Vaddress[i]);
> ExFreePool(Vaddress_hole[i]);
> }
>
> IoFreeMdl(SingleMdl);
> ExFreePool(buffer);
>
> return STATUS_SUCCESS;
> }
>
>
>

>Just out of curiosity - Can you elaborate on request splitting ? Does it

also happen at volume layer (I can think of scenario of striped volume) ?

Absolutely. It can happen at file system layer (fragmentation), the volume
layer (RAID), and the disk layer (maximum adapter transfer length). Normally
it’s done by associated IRPs (either the O/S support or custom) and partial
MDLs. See ServiceTransferRequest in the classpnp source for how disk.sys
does the splitting.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

wrote in message news:xxxxx@ntdev…

Thanks Maxim.

> What about large (>64K requests), for a case Disk.sys to split the
> request
> to several smaller ones? will they work?

Just out of curiosity - Can you elaborate on request splitting ? Does it
also happen at volume layer (I can think of scenario of striped volume) ?

I also found MmProbeAndLockSelectedPages
(http://msdn.microsoft.com/en-us/library/windows/hardware/hh406526(v=vs.85).aspx)
which create single MDL from dis-contiguous address space. But not available
on all windows versions.

Talking to the storage team developers, it doesn’t sound like anyone has added mdl chain support recently.

I’d say it’s unsupported and this experiment was a fluke if it really worked.

Don’t try to use chained mdls in the storage stack.
-p

Sent from my Windows Phone


From: Maxim S. Shatskih
Sent: 11/2/2011 9:00 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] KMDF and MDL chain

Can anybody from MS tell whether this is a supported scenario?

What about large (>64K requests), for a case Disk.sys to split the request to several smaller ones? will they work?

What about 3rd party filter drivers? will all of them crash due to this code? I think there is a very major probability with this.

Will this work on both SATA and USB-connected storage? what about iSCSI?

I personally would never ever write such code in the product, unless some authority source within MS will answer “yes, it is OK”. Not only the question is about older Windows, but also about the compat issues listed above.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> This is how I verified MDL chain on windows 2008 R2
>
> #define NUMBER_OF_PAGES 10
>
> PVOID Vaddress[NUMBER_OF_PAGES] = {0};
> PVOID Vaddress_hole[NUMBER_OF_PAGES] = {0};
>
> PMDL MdlArr[NUMBER_OF_PAGES] = {0};
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> ULONG i;
> PDEVICE_OBJECT DeviceObject;
> NTSTATUS ntStatus = STATUS_SUCCESS;
> PMDL SingleMdl;
> PVOID buffer;
>
> DriverObject->DriverUnload = Unload;
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> Vaddress[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress[i]);
>
> DbgPrint(“Vaddress[%d] = %p\n”, i, Vaddress[i]);
>
> MdlArr[i] = IoAllocateMdl(
> Vaddress[i] ,
> 4096,
> FALSE,
> FALSE,
> NULL
> );
>
> DbgPrint(“MdlArr[%d] = %p\n”, i, MdlArr[i]);
> MmBuildMdlForNonPagedPool(MdlArr[i]);
>
> if( i != 0)
> {
> MdlArr[i - 1]->Next = MdlArr[i];
> }
>
> Vaddress_hole[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress_hole[i]);
> }
>
>
> ntStatus = GetDeviceObject(&DeviceObject);
> ASSERT(NT_SUCCESS(ntStatus));
> if(!NT_SUCCESS(ntStatus))
> {
> goto claenup;
> }
>
> ntStatus =VolRead(DeviceObject, MdlArr[0],4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> buffer = ExAllocatePoolWithTag(NonPagedPool,4096 * NUMBER_OF_PAGES,TEST_TAG);
> ASSERT(buffer);
>
> SingleMdl = IoAllocateMdl(
> buffer,
> 4096 * 10,
> FALSE,
> FALSE,
> NULL
> );
>
> MmBuildMdlForNonPagedPool(SingleMdl);
> ASSERT(SingleMdl);
>
> ntStatus =VolRead(DeviceObject, SingleMdl,4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> ULONG MatchedBytes =RtlCompareMemory(
> (PCHAR)buffer + (i * 4096),
> Vaddress[i],
> 4096
> );
>
> ASSERT( 4096 == MatchedBytes);
> }
>
> claenup:
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> IoFreeMdl(MdlArr[i]);
> ExFreePool(Vaddress[i]);
> ExFreePool(Vaddress_hole[i]);
> }
>
> IoFreeMdl(SingleMdl);
> ExFreePool(buffer);
>
> return STATUS_SUCCESS;
> }
>
>
>


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

I spend a lot of time reading code, and I’ve never seen chained MDLs used or
supported anywhere outside of networking.

Jake Oshins
Hyper-V I/O Architect
Windows Kernel Group

This post implies no warranties and confers no rights.


“Peter Wieland” wrote in message
news:xxxxx@ntdev…
Talking to the storage team developers, it doesn’t sound like anyone has
added mdl chain support recently.

I’d say it’s unsupported and this experiment was a fluke if it really
worked.

Don’t try to use chained mdls in the storage stack.
-p

Sent from my Windows Phone
From: Maxim S. Shatskih
Sent: 11/2/2011 9:00 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] KMDF and MDL chain

Can anybody from MS tell whether this is a supported scenario?

What about large (>64K requests), for a case Disk.sys to split the
request to several smaller ones? will they work?

What about 3rd party filter drivers? will all of them crash due to
this code? I think there is a very major probability with this.

Will this work on both SATA and USB-connected storage? what about iSCSI?

I personally would never ever write such code in the product, unless
some authority source within MS will answer “yes, it is OK”. Not only the
question is about older Windows, but also about the compat issues listed
above.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> This is how I verified MDL chain on windows 2008 R2
>
> #define NUMBER_OF_PAGES 10
>
> PVOID Vaddress[NUMBER_OF_PAGES] = {0};
> PVOID Vaddress_hole[NUMBER_OF_PAGES] = {0};
>
> PMDL MdlArr[NUMBER_OF_PAGES] = {0};
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> ULONG i;
> PDEVICE_OBJECT DeviceObject;
> NTSTATUS ntStatus = STATUS_SUCCESS;
> PMDL SingleMdl;
> PVOID buffer;
>
> DriverObject->DriverUnload = Unload;
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> Vaddress[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress[i]);
>
> DbgPrint(“Vaddress[%d] = %p\n”, i, Vaddress[i]);
>
> MdlArr[i] = IoAllocateMdl(
> Vaddress[i] ,
> 4096,
> FALSE,
> FALSE,
> NULL
> );
>
> DbgPrint(“MdlArr[%d] = %p\n”, i, MdlArr[i]);
> MmBuildMdlForNonPagedPool(MdlArr[i]);
>
> if( i != 0)
> {
> MdlArr[i - 1]->Next = MdlArr[i];
> }
>
> Vaddress_hole[i] = ExAllocatePoolWithTag(NonPagedPool,4096, TEST_TAG);
> ASSERT(Vaddress_hole[i]);
> }
>
>
> ntStatus = GetDeviceObject(&DeviceObject);
> ASSERT(NT_SUCCESS(ntStatus));
> if(!NT_SUCCESS(ntStatus))
> {
> goto claenup;
> }
>
> ntStatus =VolRead(DeviceObject, MdlArr[0],4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> buffer = ExAllocatePoolWithTag(NonPagedPool,4096 *
> NUMBER_OF_PAGES,TEST_TAG);
> ASSERT(buffer);
>
> SingleMdl = IoAllocateMdl(
> buffer,
> 4096 * 10,
> FALSE,
> FALSE,
> NULL
> );
>
> MmBuildMdlForNonPagedPool(SingleMdl);
> ASSERT(SingleMdl);
>
> ntStatus =VolRead(DeviceObject, SingleMdl,4096 * NUMBER_OF_PAGES);
> ASSERT(NT_SUCCESS(ntStatus));
>
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> ULONG MatchedBytes =RtlCompareMemory(
> (PCHAR)buffer + (i * 4096),
> Vaddress[i],
> 4096
> );
>
> ASSERT( 4096 == MatchedBytes);
> }
>
> claenup:
> for (i =0 ; i < NUMBER_OF_PAGES; i++)
> {
> IoFreeMdl(MdlArr[i]);
> ExFreePool(Vaddress[i]);
> ExFreePool(Vaddress_hole[i]);
> }
>
> IoFreeMdl(SingleMdl);
> ExFreePool(buffer);
>
> return STATUS_SUCCESS;
> }
>
>
>


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thanks Scott for detailed explanation about request splitting.

Thanks Peter and Jake from conforming. I am trying to find different solutions than using chained MDL.

> Just out of curiosity - Can you elaborate on request splitting ?

When Disk/ClassPnP translate from MJ_READ to SCSIOP_READ, they split the single request to many smaller requests according to the storage controller’s maximum request size.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com