- Fix pipe connection to non-waiting pipes.

- More corrections to the cancellation logic.
- Minor correction to read/write event setting (still I'm getting infinite loops there in some cases).

svn path=/trunk/; revision=13856
This commit is contained in:
Filip Navara 2005-03-06 16:42:36 +00:00
parent 91979c15bb
commit dc2b964751
4 changed files with 99 additions and 61 deletions

View file

@ -147,40 +147,14 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
KeUnlockMutex(&DeviceExt->PipeListLock); KeUnlockMutex(&DeviceExt->PipeListLock);
/*
* Step 2. Search for listening server FCB.
*/
/* /*
* Acquire the lock for FCB lists. From now on no modifications to the * Acquire the lock for FCB lists. From now on no modifications to the
* FCB lists are allowed, because it can cause various misconsistencies. * FCB lists are allowed, because it can cause various misconsistencies.
*/ */
KeLockMutex(&Pipe->FcbListLock); KeLockMutex(&Pipe->FcbListLock);
if (!SpecialAccess)
{
ServerFcb = NpfsFindListeningServerInstance(Pipe);
if (ServerFcb == NULL)
{
/* Not found, bail out with error for FILE_OPEN requests. */
DPRINT("No listening server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
}
else if (IsListEmpty(&Pipe->ServerFcbListHead))
{
DPRINT("No server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/* /*
* Step 3. Create the client FCB. * Step 2. Create the client FCB.
*/ */
ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB)); ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
if (ClientFcb == NULL) if (ClientFcb == NULL)
@ -226,6 +200,73 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE); KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE);
/*
* Step 3. Search for listening server FCB.
*/
if (!SpecialAccess)
{
/*
* WARNING: Point of no return! Once we get the server FCB it's
* possible that we completed a wait request and so we have to
* complete even this request.
*/
ServerFcb = NpfsFindListeningServerInstance(Pipe);
if (ServerFcb == NULL)
{
PLIST_ENTRY CurrentEntry;
PNPFS_FCB Fcb;
/*
* If no waiting server FCB was found then try to pick
* one of the listing server FCB on the pipe.
*/
CurrentEntry = Pipe->ServerFcbListHead.Flink;
while (CurrentEntry != &Pipe->ServerFcbListHead)
{
Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry);
if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
ServerFcb = Fcb;
break;
}
CurrentEntry = CurrentEntry->Flink;
}
/*
* No one is listening to me?! I'm so lonely... :(
*/
if (ServerFcb == NULL)
{
/* Not found, bail out with error for FILE_OPEN requests. */
DPRINT("No listening server fcb found!\n");
if (ClientFcb->Data)
ExFreePool(ClientFcb->Data);
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
}
else
{
/* Signal the server thread and remove it from the waiter list */
/* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
}
}
else if (IsListEmpty(&Pipe->ServerFcbListHead))
{
DPRINT("No server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/* /*
* Step 4. Add the client FCB to a list and connect it if possible. * Step 4. Add the client FCB to a list and connect it if possible.
*/ */
@ -240,9 +281,6 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ServerFcb->OtherSide = ClientFcb; ServerFcb->OtherSide = ClientFcb;
ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE; ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE; ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
/* Signal the server thread and remove it from the waiter list */
NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
} }
KeUnlockMutex(&Pipe->FcbListLock); KeUnlockMutex(&Pipe->FcbListLock);

View file

@ -26,19 +26,12 @@ NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
DPRINT1("NpfsListeningCancelRoutine() called\n"); DPRINT1("NpfsListeningCancelRoutine() called\n");
/* FIXME: Not tested. */
IoReleaseCancelSpinLock(Irp->CancelIrql); IoReleaseCancelSpinLock(Irp->CancelIrql);
Waiter = Irp->Tail.Overlay.DriverContext[0]; Waiter = Irp->Tail.Overlay.DriverContext[0];
KeLockMutex(&Waiter->Pipe->FcbListLock); KeLockMutex(&Waiter->Pipe->FcbListLock);
RemoveEntryList(&Waiter->Entry); RemoveEntryList(&Waiter->Entry);
if (IoSetCancelRoutine(Waiter->Irp, NULL) == NULL)
{
KeUnlockMutex(&Waiter->Pipe->FcbListLock);
return;
}
KeUnlockMutex(&Waiter->Pipe->FcbListLock); KeUnlockMutex(&Waiter->Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Status = STATUS_CANCELLED;
@ -53,7 +46,6 @@ NpfsAddListeningServerInstance(PIRP Irp,
PNPFS_FCB Fcb) PNPFS_FCB Fcb)
{ {
PNPFS_WAITER_ENTRY Entry; PNPFS_WAITER_ENTRY Entry;
KIRQL OldIrql;
Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY)); Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY));
if (Entry == NULL) if (Entry == NULL)
@ -63,21 +55,26 @@ NpfsAddListeningServerInstance(PIRP Irp,
Entry->Fcb = Fcb; Entry->Fcb = Fcb;
Entry->Pipe = Fcb->Pipe; Entry->Pipe = Fcb->Pipe;
IoAcquireCancelSpinLock(&OldIrql); KeLockMutex(&Fcb->Pipe->FcbListLock);
IoMarkIrpPending(Irp);
Irp->Tail.Overlay.DriverContext[0] = Entry;
InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
if (!Irp->Cancel) if (!Irp->Cancel)
{ {
Irp->Tail.Overlay.DriverContext[0] = Entry;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
KeLockMutex(&Fcb->Pipe->FcbListLock);
InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
KeUnlockMutex(&Fcb->Pipe->FcbListLock); KeUnlockMutex(&Fcb->Pipe->FcbListLock);
IoReleaseCancelSpinLock(OldIrql);
return STATUS_PENDING; return STATUS_PENDING;
} }
/* IRP has already been cancelled */
IoReleaseCancelSpinLock(OldIrql); RemoveEntryList(&Entry->Entry);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeUnlockMutex(&Fcb->Pipe->FcbListLock);
ExFreePool(Entry); ExFreePool(Entry);
return STATUS_CANCELLED; return STATUS_CANCELLED;

View file

@ -165,7 +165,10 @@ NpfsRead(PDEVICE_OBJECT DeviceObject,
if (Length == 0) if (Length == 0)
{ {
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
}
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->Event);
break; break;
} }
@ -197,6 +200,11 @@ NpfsRead(PDEVICE_OBJECT DeviceObject,
} }
else else
{ {
KeResetEvent(&Fcb->Event);
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
}
Fcb->ReadDataAvailable = 0; Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Fcb->MaxDataLength; Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
} }
@ -204,11 +212,6 @@ NpfsRead(PDEVICE_OBJECT DeviceObject,
if (Information > 0) if (Information > 0)
{ {
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
}
KeResetEvent(&Fcb->Event);
break; break;
} }
} }
@ -383,12 +386,12 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
ReaderFcb->WriteQuotaAvailable = 0; ReaderFcb->WriteQuotaAvailable = 0;
} }
if (Information > 0) if (Information > 0)
{ {
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->Event);
break; break;
} }
} }
} }

View file

@ -36,7 +36,7 @@ NpfsQueryFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
DPRINT("NpfsQueryFsDeviceInformation() finished.\n"); DPRINT("NpfsQueryFsDeviceInformation() finished.\n");
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }