make mdl usage/impl. more windows compliant

svn path=/trunk/; revision=9189
This commit is contained in:
Gunnar Dalsnes 2004-04-20 19:04:11 +00:00
parent d169532a77
commit 03cfbfef0a
5 changed files with 163 additions and 87 deletions

View file

@ -32,6 +32,8 @@ VfatReadWriteCompletion (IN PDEVICE_OBJECT DeviceObject,
while ((Mdl = Irp->MdlAddress)) while ((Mdl = Irp->MdlAddress))
{ {
Irp->MdlAddress = Mdl->Next; Irp->MdlAddress = Mdl->Next;
MmUnlockPages(Mdl);
IoFreeMdl(Mdl); IoFreeMdl(Mdl);
} }

View file

@ -1,6 +1,6 @@
#ifndef _INCLUDE_DDK_MMFUNCS_H #ifndef _INCLUDE_DDK_MMFUNCS_H
#define _INCLUDE_DDK_MMFUNCS_H #define _INCLUDE_DDK_MMFUNCS_H
/* $Id: mmfuncs.h,v 1.20 2004/02/10 16:22:56 navaraf Exp $ */ /* $Id: mmfuncs.h,v 1.21 2004/04/20 19:04:11 gdalsnes Exp $ */
/* MEMORY MANAGMENT ******************************************************/ /* MEMORY MANAGMENT ******************************************************/
@ -51,6 +51,8 @@ extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va,
* FUNCTION: Returns the byte offset of the address within its page * FUNCTION: Returns the byte offset of the address within its page
*/ */
#define BYTE_OFFSET(va) (((ULONG)va)%PAGE_SIZE) #define BYTE_OFFSET(va) (((ULONG)va)%PAGE_SIZE)
#define PAGE_OFFSET(va) BYTE_OFFSET(va)
/* /*
* FUNCTION: Takes a count in bytes and returns the number of pages * FUNCTION: Takes a count in bytes and returns the number of pages
@ -59,6 +61,11 @@ extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va,
#define BYTES_TO_PAGES(Size) \ #define BYTES_TO_PAGES(Size) \
((ULONG) ((ULONG_PTR) (Size) >> PAGE_SHIFT) + (((ULONG) (Size) & (PAGE_SIZE - 1)) != 0)) ((ULONG) ((ULONG_PTR) (Size) >> PAGE_SHIFT) + (((ULONG) (Size) & (PAGE_SIZE - 1)) != 0))
#define PAGE_ALIGN(va) ( (PVOID) (((ULONG)(va)) & (~(PAGE_SIZE-1))) )
#define PAGE_BASE(va) PAGE_ALIGN(va)
DWORD DWORD
STDCALL STDCALL
MmAdjustWorkingSetSize ( MmAdjustWorkingSetSize (
@ -271,10 +278,9 @@ MmGrowKernelStack (
(MemoryDescriptorList)->Size = (CSHORT)(sizeof(MDL) + \ (MemoryDescriptorList)->Size = (CSHORT)(sizeof(MDL) + \
(ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(ULONG))); \ (ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(ULONG))); \
(MemoryDescriptorList)->MdlFlags = 0; \ (MemoryDescriptorList)->MdlFlags = 0; \
(MemoryDescriptorList)->StartVa = (PVOID)PAGE_ROUND_DOWN((BaseVa)); \ (MemoryDescriptorList)->StartVa = (PVOID)PAGE_BASE(BaseVa); \
(MemoryDescriptorList)->ByteOffset = (ULONG)((BaseVa) - PAGE_ROUND_DOWN((BaseVa))); \ (MemoryDescriptorList)->ByteOffset = (ULONG)PAGE_OFFSET(BaseVa); \
(MemoryDescriptorList)->ByteCount = (Length); \ (MemoryDescriptorList)->ByteCount = (Length); \
(MemoryDescriptorList)->Process = PsGetCurrentProcess(); \
} }
/* /*

View file

@ -128,17 +128,10 @@ VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
} }
ExFreePool(Irp->AssociatedIrp.SystemBuffer); ExFreePool(Irp->AssociatedIrp.SystemBuffer);
} }
if (DeviceObject->Flags & DO_DIRECT_IO) if (DeviceObject->Flags & DO_DIRECT_IO)
{ {
/* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */ IoFreeMdl(Irp->MdlAddress);
DPRINT("Tearing down MDL\n");
if (Irp->MdlAddress->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
Irp->MdlAddress);
}
MmUnlockPages(Irp->MdlAddress);
ExFreePool(Irp->MdlAddress);
} }
} }
@ -201,6 +194,13 @@ IoSecondStageCompletion(
Irp = (PIRP)(*SystemArgument1); Irp = (PIRP)(*SystemArgument1);
PriorityBoost = (CCHAR)(LONG)(*SystemArgument2); PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
/*
* Note that we'll never see irp's flagged IRP_PAGING_IO (IRP_MOUNT_OPERATION)
* or IRP_CLOSE_OPERATION (IRP_MJ_CLOSE and IRP_MJ_CLEANUP) here since their
* cleanup/completion is fully taken care of in IoCompleteRequest.
* -Gunnar
*/
/* /*
Remove synchronous irp's from the threads cleanup list. Remove synchronous irp's from the threads cleanup list.
To synchronize with the code inserting the entry, this code must run To synchronize with the code inserting the entry, this code must run
@ -278,7 +278,7 @@ IoSecondStageCompletion(
} }
//Windows NT File System Internals, page 154 //Windows NT File System Internals, page 154
if (!(Irp->Flags & IRP_PAGING_IO) && OriginalFileObject) if (OriginalFileObject)
{ {
// if the event is not the one in the file object, it needs dereferenced // if the event is not the one in the file object, it needs dereferenced
if (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event) if (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event)
@ -286,11 +286,8 @@ IoSecondStageCompletion(
ObDereferenceObject(Irp->UserEvent); ObDereferenceObject(Irp->UserEvent);
} }
if (IoStack->MajorFunction != IRP_MJ_CLOSE)
{
ObDereferenceObject(OriginalFileObject); ObDereferenceObject(OriginalFileObject);
} }
}
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL) if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
{ {

View file

@ -1,4 +1,4 @@
/* $Id: irp.c,v 1.58 2004/03/04 00:07:00 navaraf Exp $ /* $Id: irp.c,v 1.59 2004/04/20 19:01:47 gdalsnes Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -231,6 +231,7 @@ IofCompleteRequest(PIRP Irp,
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT OriginalFileObject; PFILE_OBJECT OriginalFileObject;
KIRQL oldIrql; KIRQL oldIrql;
PMDL Mdl;
DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n", DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread()); Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
@ -285,33 +286,74 @@ IofCompleteRequest(PIRP Irp,
} }
} }
/*
* Were done calling completion routines. Now do any cleanup that can be
* done in an arbitrarily context.
*/
/* Windows NT File System Internals, page 165 */
if (Irp->Flags & (IRP_PAGING_IO|IRP_CLOSE_OPERATION)) if (Irp->Flags & (IRP_PAGING_IO|IRP_CLOSE_OPERATION))
{ {
if (Irp->Flags & IRP_PAGING_IO) if (Irp->Flags & IRP_PAGING_IO)
{ {
/* FIXME: /* FIXME:
* The mdl must be freed by the caller! * The mdl should be freed by the caller!
*/ */
if (Irp->MdlAddress->MappedSystemVa != NULL) if (Irp->MdlAddress->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
{ {
MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa, MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa, Irp->MdlAddress);
Irp->MdlAddress);
} }
MmUnlockPages(Irp->MdlAddress);
ExFreePool(Irp->MdlAddress); ExFreePool(Irp->MdlAddress);
} }
if (Irp->UserIosb) if (Irp->UserIosb)
{ {
*Irp->UserIosb = Irp->IoStatus; *Irp->UserIosb = Irp->IoStatus;
} }
if (Irp->UserEvent) if (Irp->UserEvent)
{ {
KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE); KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE);
} }
/* io manager frees the irp for close operations */
if (Irp->Flags & IRP_PAGING_IO)
{
IoFreeIrp(Irp); IoFreeIrp(Irp);
} }
else
return;
}
/*
Hi Dave,
I went through my old notes. You are correct and in most cases
IoCompleteRequest() will issue an MmUnlockPages() for each MDL in the IRP
chain. There are however few exceptions: one is MDLs for associated IRPs,
it's expected that those MDLs have been initialized with
IoBuildPartialMdl(). Another exception is PAGING_IO irps, the i/o completion
code doesn't do anything to MDLs of those IRPs.
sara
*/
//Windows NT File System Internals, page 166/167
if (!(Irp->Flags & IRP_ASSOCIATED_IRP))
{ {
for (Mdl = Irp->MdlAddress; Mdl; Mdl = Mdl->Next)
{
/*
* Undo the MmProbeAndLockPages. If MmGetSystemAddressForMdl was called
* on this mdl, this mapping (if any) is also undone by MmUnlockPages.
*/
MmUnlockPages(Irp->MdlAddress);
}
}
//Windows NT File System Internals, page 154 //Windows NT File System Internals, page 154
OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject; OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
@ -349,7 +391,7 @@ IofCompleteRequest(PIRP Irp,
KeLowerIrql(oldIrql); KeLowerIrql(oldIrql);
DPRINT("Finished completition routine\n"); DPRINT("Finished completition routine\n");
} }
}
} }

View file

@ -1,4 +1,4 @@
/* $Id: mdl.c,v 1.13 2003/12/30 18:52:04 fireball Exp $ /* $Id: mdl.c,v 1.14 2004/04/20 19:01:47 gdalsnes Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -50,15 +50,38 @@ IoAllocateMdl(PVOID VirtualAddress,
TAG_MDL); TAG_MDL);
} }
MmInitializeMdl(Mdl, (char*)VirtualAddress, Length); MmInitializeMdl(Mdl, (char*)VirtualAddress, Length);
if (Irp!=NULL && !SecondaryBuffer)
if (Irp)
{ {
if (SecondaryBuffer)
{
assert(Irp->MdlAddress);
/* FIXME: add to end of list maybe?? */
Mdl->Next = Irp->MdlAddress->Next;
Irp->MdlAddress->Next = Mdl;
}
else
{
/*
* What if there's allready an mdl at Irp->MdlAddress?
* Is that bad and should we do something about it?
*/
Irp->MdlAddress = Mdl; Irp->MdlAddress = Mdl;
} }
}
return(Mdl); return(Mdl);
} }
/* /*
* @implemented * @implemented
*
* You must IoFreeMdl the slave before freeing the master.
*
* IoBuildPartialMdl is more similar to MmBuildMdlForNonPagedPool, the difference
* is that the former takes the physical addresses from the master MDL, while the
* latter - from the known location of the NPP.
*/ */
VOID VOID
STDCALL STDCALL
@ -77,6 +100,8 @@ IoBuildPartialMdl(PMDL SourceMdl,
{ {
TargetPages[Va] = SourcePages[Va+Delta]; TargetPages[Va] = SourcePages[Va+Delta];
} }
TargetMdl->MdlFlags |= MDL_PARTIAL;
} }
/* /*
@ -85,8 +110,12 @@ IoBuildPartialMdl(PMDL SourceMdl,
VOID STDCALL VOID STDCALL
IoFreeMdl(PMDL Mdl) IoFreeMdl(PMDL Mdl)
{ {
MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl); /*
MmUnlockPages(Mdl); * This unmaps partial mdl's from kernel space but also asserts that non-partial
* mdl's isn't still mapped into kernel space.
*/
MmPrepareMdlForReuse(Mdl);
ExFreePool(Mdl); ExFreePool(Mdl);
} }