From dc2b9647516ef0787f9356a583b66049f8b9fa99 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 6 Mar 2005 16:42:36 +0000 Subject: [PATCH] - 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 --- reactos/drivers/fs/np/create.c | 98 +++++++++++++++++++++++----------- reactos/drivers/fs/np/fsctrl.c | 33 ++++++------ reactos/drivers/fs/np/rw.c | 27 +++++----- reactos/drivers/fs/np/volume.c | 2 +- 4 files changed, 99 insertions(+), 61 deletions(-) diff --git a/reactos/drivers/fs/np/create.c b/reactos/drivers/fs/np/create.c index c2a5aaa0512..c3d0005586b 100644 --- a/reactos/drivers/fs/np/create.c +++ b/reactos/drivers/fs/np/create.c @@ -147,40 +147,14 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, KeUnlockMutex(&DeviceExt->PipeListLock); - /* - * Step 2. Search for listening server FCB. - */ - /* * Acquire the lock for FCB lists. From now on no modifications to the * FCB lists are allowed, because it can cause various misconsistencies. */ 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)); if (ClientFcb == NULL) @@ -226,6 +200,73 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, KeInitializeEvent(&ClientFcb->ConnectEvent, 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. */ @@ -240,9 +281,6 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, ServerFcb->OtherSide = ClientFcb; ClientFcb->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); diff --git a/reactos/drivers/fs/np/fsctrl.c b/reactos/drivers/fs/np/fsctrl.c index 4bb68190c5f..89539d865d3 100644 --- a/reactos/drivers/fs/np/fsctrl.c +++ b/reactos/drivers/fs/np/fsctrl.c @@ -26,19 +26,12 @@ NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject, DPRINT1("NpfsListeningCancelRoutine() called\n"); - /* FIXME: Not tested. */ - IoReleaseCancelSpinLock(Irp->CancelIrql); Waiter = Irp->Tail.Overlay.DriverContext[0]; KeLockMutex(&Waiter->Pipe->FcbListLock); RemoveEntryList(&Waiter->Entry); - if (IoSetCancelRoutine(Waiter->Irp, NULL) == NULL) - { - KeUnlockMutex(&Waiter->Pipe->FcbListLock); - return; - } KeUnlockMutex(&Waiter->Pipe->FcbListLock); Irp->IoStatus.Status = STATUS_CANCELLED; @@ -53,7 +46,6 @@ NpfsAddListeningServerInstance(PIRP Irp, PNPFS_FCB Fcb) { PNPFS_WAITER_ENTRY Entry; - KIRQL OldIrql; Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY)); if (Entry == NULL) @@ -63,21 +55,26 @@ NpfsAddListeningServerInstance(PIRP Irp, Entry->Fcb = Fcb; 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) { - 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); - IoReleaseCancelSpinLock(OldIrql); 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); return STATUS_CANCELLED; diff --git a/reactos/drivers/fs/np/rw.c b/reactos/drivers/fs/np/rw.c index 5338323c555..254f4b1ba47 100644 --- a/reactos/drivers/fs/np/rw.c +++ b/reactos/drivers/fs/np/rw.c @@ -165,7 +165,10 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, 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); break; } @@ -197,6 +200,11 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, } else { + KeResetEvent(&Fcb->Event); + if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); + } Fcb->ReadDataAvailable = 0; Fcb->WriteQuotaAvailable = Fcb->MaxDataLength; } @@ -204,11 +212,6 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, if (Information > 0) { - if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) - { - KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); - } - KeResetEvent(&Fcb->Event); break; } } @@ -383,12 +386,12 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, ReaderFcb->WriteQuotaAvailable = 0; } - if (Information > 0) - { - KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); - KeResetEvent(&Fcb->Event); - break; - } + if (Information > 0) + { + KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Fcb->Event); + break; + } } } diff --git a/reactos/drivers/fs/np/volume.c b/reactos/drivers/fs/np/volume.c index 98314fc8472..1ea4168cf87 100644 --- a/reactos/drivers/fs/np/volume.c +++ b/reactos/drivers/fs/np/volume.c @@ -36,7 +36,7 @@ NpfsQueryFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, DPRINT("NpfsQueryFsDeviceInformation() finished.\n"); - return STATUS_SUCCESS; + return STATUS_SUCCESS; }