KMDF: always maps all MDLs?

Hi everybody,

when reviewing some old WDM disk filter code on the possibility of KMDF port, I found one nasty thing with KMDF which is maybe a stopper for this task of mine.

Namely: it looks like, for direct IO, KMDF always maps all MDLs by MmGetSystemAddressForMdlSafe, even if it is not required.

System PTEs are a valuable resource, so probably it is really a very bad idea to map all MDLs in the disk IO path. I’m not sure whether the loaded server will run out of system PTEs in this case and start to fail.

Details:

  • existing WDM logic (to be reproduced with KMDF) splits the request to several sub-requests by IoBuildPartialMdl.
  • to reproduce this in KMDF, I need to first get the memory buffer of the master request. There are only 2 ways of doing this:
    a) as WDFMEMORY
    b) as WdmMdl
  • and now, if you will see the KMDF source, you will see that, when you retrieve the incoming direct IO request memory as WDFMEMORY, MmGetSystemAddressForMdlSafe is ALWAYS called for the MDL (which is being wrapped around by FxRequestBuffer and then FxMemory).
  • more so. Somewhere in the source there is a comment like (not exactly) “if we will remake the WdfMemoryGetBuffer API and allow it to fail, then we can avoid to do the possibly redundant mapping of the MDL here”.
  • definitely, since WdfMemoryGetBuffer is not allowed to fail, MmGetSystemAddressForMdlSafe (which can fail) for the MDL-based WDFMEMORY cannot be delayed till WdfMemoryGetBuffer, so it MUST be executed during WDFMEMORY creation, even if the pointer is not needed at all, i.e. this memory object will only be used as a master for splitting.
  • OK, but, master-side, I have WdfRequestRetrieveInputWdmMdl. Kinda a solution.
  • the things are much worse slave-side. I can use the MDL to create a KMDF slave request in only 2 ways a) using WDF_MEMORY_DESCRIPTOR or b) using WDFMEMORY.
  • WDF_MEMORY_DESCRIPTOR is absolutely a great structure, but it cannot do the subdivision of MDL. Its union branch for the “raw MDL” case only has a length in it, not offset.
  • OK, so I’m back to WDFMEMORY, with its limitation of always map the MDL.

So the question once more: can I rewrite the WDM IoBuildPartialMdl request splitting logic in KMDF without mapping all MDLs to system PTEs?

If not so - then I would say this is a very serious deficiency of KMDF, which will require do raw WDM IRP handling in this project of mine (losing the sweet stuff like the KMDF IO target).

Is it possible in the future to a) improve WDF_MEMORY_DESCRIPTOR to allow for MasterMdl/Offset/Length parameter block b) allow usage of WDF_MEMORY_DESCRIPTOR not only in SendSynchronously API family, but also in Send and FormatRequest API families?

regards,
Max

Are you seeing it in x64? In my experience, all MDLs that have physically contiguous buffer are mapped to pre-mapped whole RAM.

Also, when you call BuildPartialMdl, it’s less expensive to map the master MDL first, because this allows the partial MDL to reuse the mapping.

Even if the paster MDL is not mapped, your partial MDLs (physically contiguous) can still enjow premapped memory.

> Are you seeing it in x64?

In both platforms, I’m seeing this source-wise and docs-wise.

In my experience, all MDLs that have physically contiguous buffer are mapped to pre-mapped whole
RAM.

…unless this is x86 with >1GB of RAM.

Also, when you call BuildPartialMdl, it’s less expensive to map the master MDL first, because this
allows the partial MDL to reuse the mapping.

Even if the paster MDL is not mapped, your partial MDLs (physically contiguous) can still enjow
premapped memory.

Yes and yes.

But my issue is not mapping. My issue is to avoid redundant mapping.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

I think KMDF source is available on Github. Check it out.

Careful reading of Mr. Shatskih’s initial post will tell you that he’s already referred to the WDF source code (on github or from elsewhere, it doesn’t matter). Mr. Shatskih wrote: "And now, if you will
see the KMDF source, you will see… "

Mr. Shatskih: First: Cool problem. Thanks for bringing it here.

Second, I’m having trouble following the “master side vs slave side” part of your description. If on your “slave” side you’re BUILDING the MDL, surely can be build in WDM-style (IoBuildPartial or whatever suits you) and then slap it into the memory descriptor using WDF_MEMORY_DESCRIPTOR_INIT_MDL… no?

Peter
OSR
@OSRDrivers