Hi, it´s me replying to myself
I spent some time placing some DbgPrint here and there and found out what I
was doing wrong. It seems that as the underlying driver (or someone else) is
allocating, probing and locking an MDL in irp->MdlAddress as a result of the
IRP read being completed.
As the IRP belongs to me and I´m stopping the I/O manager from performing
any more processing after I catch the completion (I return
STATUS_MORE_PROCESSING), it seems that it´s up to me to unmap, unlock and
free the MDL.
This is the code I placed after the IoCallDriver/KeWaitForSingleObject:
if (irp->MdlAddress != NULL) {
MmUnmapLockedPages(
MmGetSystemAddressForMdl(irp->MdlAddress),
irp->MdlAddress
);
MmUnlockPages(irp->MdlAddress);
IoFreeMdl(irp->MdlAddress);
}
At this point, I checked the NTFSD archives and found some messages
regarding this topic (sorry, I should have checked harder before posting,
but there´s so much material there, that sometimes it´s just too hard to
find what you´re looking for, specially when you don´t know exactly what
you´re looking for). Nonetheless, I have some questions (in seek of
perfection…
I´ve seen the same thing being done this way:
PMDL mdl;
if (irp->MdlAddress != NULL) {
mdl = irp->MdlAddress;
do { MmUnlockPages(mdl); mdl = mdl->Next; } while (mdl != NULL);
IoFreeMdl(Irp->MdlAddress);
}
What is the best/smarter/system-friendly/efficient way ?
Another question: I guess it doesn´t mather whether I put this MDL-cleanup
code in the completion routine or just after the
IoCallDriver/KeWaitForSingleObject, but where is the most coherent place ?.
My guess is that, since MDL cleanup is a task usually performed by the I/O
manager AFTER IRP completion notification has been performed for all the
devices in the IRP stack, and when perparing and passing down ourselves an
IRP we are doing somehow the I/O manager job, and we do it in the code were
we call IoCallDriver, the MDL cleanup should go there instead of in the
completion routine.
Ant thoughts welcome, including those saying I just think too much about
things not worth it
-IGP-
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Ignacio
Garcia-Perez
Sent: lunes, 29 de enero de 2001 17:48
To: File Systems Developers
Subject: [ntfsd] Assertion failed: Pfn1->u3.e2.ReferenceCount <
MmReferenceCountCheckHi, devs, I need some help:
I´m writing a FSF which monitors each IRP_MJ_CREATE, and then
checks if the
file just opened is a special type of file.For this purpose, I pass the IRP_MJ_CREATE down to the attached device and
wait for its completion. Then I do the file check. For this purpose I need
to do some read operations, which I perform building my own read IRPs and
passing them down to the underlying driver.The scheme seemed to work very well, and is being tested in a NT 4.0 SP6
checked platform.But today, just to stress my FSF a little bit, I tried a simple
program that
did the following operation 1000 times: CreateFile, GetFileSize,
CloseHandle. That´s it.Well, after one hundred or so of iterations, I get the following assertion
error when passing down the read IRP (using IoCallDriver):*** assertion failed: Pfn1->u3.e2.ReferenceCount < MmReferenceCountCheck2
*** source file: w:\nt\private\ntos\mm\up..\iosup.c, line 456The meaning seems rather evident: there is a reference count going out of
bounds, but I gave no clue to which objects it refers to.Since this happens only after about 100 iterations
(open/get_file_size/close):
It seems not to be the IRP itself, since a different one is created and
freed for each read operation.
It seems not to be the FileObject, since it is a different one for each
OPEN/GETFILESIZE/CLOSE operation.Any clues / directions ?. I would appreciate them very much.
Note: I don´t use IoBuildSynchronousFsdRequest, and I think it
was because I
had initialy some problems with it and got this approach working rather
fast. However, since I cook the whole read IRP myself, perhaps I´m
forgetting some obscure but important field… I attach my code at the end
of the message just in case some brave dev wants to have a look to itThanks. Nacho.
static NTSTATUS irpCompletion(
PDEVICE_OBJECT deviceObject,
PIRP irp,
PVOID context
)
{
*irp->UserIosb = irp->IoStatus; // Copy status information to
// the user
KeSetEvent(irp->UserEvent, 0, FALSE); // Signal event
IoFreeIrp(irp); // Free IRP
return STATUS_MORE_PROCESSING_REQUIRED; // Tell the I/O
manager to stop
}BOOLEAN irpRead(
PDEVICE_OBJECT hookedDevice,
PFILE_OBJECT fileObject,
PLARGE_INTEGER offset,
PVOID buffer,
ULONG length
)
{
PIRP irp;
PIO_STACK_LOCATION irpSp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;irp = IoAllocateIrp(hookedDevice->StackSize, FALSE);
if (irp == NULL) {
return FALSE;
}KeInitializeEvent(&event, NotificationEvent, FALSE);
// Read uses neither I/O, so we must pass the buffer in UserBuffer
irp->UserBuffer = buffer;
irp->UserEvent = &event;
irp->UserIosb = &ioStatus;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject = fileObject;
irp->RequestorMode = KernelMode;
irp->Flags = IRP_READ_OPERATION | IRP_NOCACHE;irpSp = IoGetNextIrpStackLocation(irp);
irpSp->MajorFunction = IRP_MJ_READ;
irpSp->MinorFunction = 0;
irpSp->DeviceObject = hookedDevice;
irpSp->FileObject = fileObject;
irpSp->Parameters.Read.Length = length;
irpSp->Parameters.Read.Key = 0;
irpSp->Parameters.Read.ByteOffset = *offset;IoSetCompletionRoutine(irp, irpCompletion, 0, TRUE, TRUE, TRUE);
DbgPrint((“??? About to call IoCallDriver for direct IRP read\n”));
IoCallDriver(hookedDevice, irp);
DbgPrint((“??? Just called IoCallDriver for direct IRP read\n”));
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);return NT_SUCCESS(ioStatus.Status) && // Success only if we could
ioStatus.Information == length; // read all requested data
}
You are currently subscribed to ntfsd as: xxxxx@trymedia.com
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com