while ((Mdl = Irp->MdlAddress))
{
Irp->MdlAddress = Mdl->Next;
+
+ MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
}
#ifndef _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 ******************************************************/
* FUNCTION: Returns the byte offset of the address within its page
*/
#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
*/
#define BYTES_TO_PAGES(Size) \
((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
STDCALL
(MemoryDescriptorList)->Size = (CSHORT)(sizeof(MDL) + \
(ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(ULONG))); \
(MemoryDescriptorList)->MdlFlags = 0; \
- (MemoryDescriptorList)->StartVa = (PVOID)PAGE_ROUND_DOWN((BaseVa)); \
- (MemoryDescriptorList)->ByteOffset = (ULONG)((BaseVa) - PAGE_ROUND_DOWN((BaseVa))); \
+ (MemoryDescriptorList)->StartVa = (PVOID)PAGE_BASE(BaseVa); \
+ (MemoryDescriptorList)->ByteOffset = (ULONG)PAGE_OFFSET(BaseVa); \
(MemoryDescriptorList)->ByteCount = (Length); \
- (MemoryDescriptorList)->Process = PsGetCurrentProcess(); \
}
/*
FileObject = IoStack->FileObject;
if (DeviceObject->Flags & DO_BUFFERED_IO)
- {
- if (IoStack->MajorFunction == IRP_MJ_READ)
- {
- DPRINT("Copying buffered io back to user\n");
- memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
+ {
+ if (IoStack->MajorFunction == IRP_MJ_READ)
+ {
+ DPRINT("Copying buffered io back to user\n");
+ memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
IoStack->Parameters.Read.Length);
- }
- ExFreePool(Irp->AssociatedIrp.SystemBuffer);
- }
+ }
+ ExFreePool(Irp->AssociatedIrp.SystemBuffer);
+ }
+
if (DeviceObject->Flags & DO_DIRECT_IO)
- {
- /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */
- DPRINT("Tearing down MDL\n");
- if (Irp->MdlAddress->MappedSystemVa != NULL)
- {
- MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
- Irp->MdlAddress);
- }
- MmUnlockPages(Irp->MdlAddress);
- ExFreePool(Irp->MdlAddress);
- }
+ {
+ IoFreeMdl(Irp->MdlAddress);
+ }
}
VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
Irp = (PIRP)(*SystemArgument1);
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.
To synchronize with the code inserting the entry, this code must run
}
//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 (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event)
ObDereferenceObject(Irp->UserEvent);
}
- if (IoStack->MajorFunction != IRP_MJ_CLOSE)
- {
- ObDereferenceObject(OriginalFileObject);
- }
+ ObDereferenceObject(OriginalFileObject);
}
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
-/* $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
* PROJECT: ReactOS kernel
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT OriginalFileObject;
KIRQL oldIrql;
+ PMDL Mdl;
DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
}
}
+ /*
+ * 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)
- {
- /* FIXME:
- * The mdl must be freed by the caller!
- */
- if (Irp->MdlAddress->MappedSystemVa != NULL)
- {
- MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
- Irp->MdlAddress);
- }
- MmUnlockPages(Irp->MdlAddress);
- ExFreePool(Irp->MdlAddress);
- }
- if (Irp->UserIosb)
- {
- *Irp->UserIosb = Irp->IoStatus;
- }
- if (Irp->UserEvent)
+ {
+ if (Irp->Flags & IRP_PAGING_IO)
+ {
+ /* FIXME:
+ * The mdl should be freed by the caller!
+ */
+ if (Irp->MdlAddress->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
{
- KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE);
- }
- IoFreeIrp(Irp);
- }
- else
- {
- //Windows NT File System Internals, page 154
- OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
+ MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa, Irp->MdlAddress);
+ }
+
+ ExFreePool(Irp->MdlAddress);
+ }
- if (Irp->PendingReturned || KeGetCurrentIrql() == DISPATCH_LEVEL)
- {
- BOOLEAN bStatus;
+ if (Irp->UserIosb)
+ {
+ *Irp->UserIosb = Irp->IoStatus;
+ }
+
+ if (Irp->UserEvent)
+ {
+ KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE);
+ }
+
+ /* io manager frees the irp for close operations */
+ if (Irp->Flags & IRP_PAGING_IO)
+ {
+ IoFreeIrp(Irp);
+ }
- DPRINT("Dispatching APC\n");
- KeInitializeApc( &Irp->Tail.Apc,
+ 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
+ OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
+
+ if (Irp->PendingReturned || KeGetCurrentIrql() == DISPATCH_LEVEL)
+ {
+ BOOLEAN bStatus;
+
+ DPRINT("Dispatching APC\n");
+ KeInitializeApc( &Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread->Tcb,
OriginalApcEnvironment,
IoSecondStageCompletion,//kernel routine
KernelMode,
OriginalFileObject);
- bStatus = KeInsertQueueApc(&Irp->Tail.Apc,
+ bStatus = KeInsertQueueApc(&Irp->Tail.Apc,
(PVOID)Irp,
(PVOID)(ULONG)PriorityBoost,
PriorityBoost);
- if (bStatus == FALSE)
- {
- DPRINT1("Error queueing APC for thread. Thread has probably exited.\n");
- }
+ if (bStatus == FALSE)
+ {
+ DPRINT1("Error queueing APC for thread. Thread has probably exited.\n");
+ }
- DPRINT("Finished dispatching APC\n");
- }
- else
- {
- DPRINT("Calling IoSecondStageCompletion routine directly\n");
- KeRaiseIrql(APC_LEVEL, &oldIrql);
- IoSecondStageCompletion(NULL,NULL,(PVOID)&OriginalFileObject,(PVOID) &Irp,(PVOID) &PriorityBoost);
- KeLowerIrql(oldIrql);
- DPRINT("Finished completition routine\n");
- }
+ DPRINT("Finished dispatching APC\n");
}
+ else
+ {
+ DPRINT("Calling IoSecondStageCompletion routine directly\n");
+ KeRaiseIrql(APC_LEVEL, &oldIrql);
+ IoSecondStageCompletion(NULL,NULL,(PVOID)&OriginalFileObject,(PVOID) &Irp,(PVOID) &PriorityBoost);
+ KeLowerIrql(oldIrql);
+ DPRINT("Finished completition routine\n");
+ }
+
}
-/* $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
* PROJECT: ReactOS kernel
TAG_MDL);
}
MmInitializeMdl(Mdl, (char*)VirtualAddress, Length);
- if (Irp!=NULL && !SecondaryBuffer)
- {
- Irp->MdlAddress = Mdl;
- }
+
+ 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;
+ }
+ }
+
return(Mdl);
}
/*
* @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
STDCALL
PAGE_SIZE;
for (Va = 0; Va < (PAGE_ROUND_UP(Length)/PAGE_SIZE); Va++)
- {
- TargetPages[Va] = SourcePages[Va+Delta];
- }
+ {
+ TargetPages[Va] = SourcePages[Va+Delta];
+ }
+
+ TargetMdl->MdlFlags |= MDL_PARTIAL;
}
/*
VOID STDCALL
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);
}