From 82161c478a871d959daf7f3ffb4d38d1bfabe6d6 Mon Sep 17 00:00:00 2001 From: Rod Widdowson Date: Fri, 15 Feb 2013 05:57:29 -0500 Subject: [PATCH] Windows: Allow the Library to pend a write request If the library pends a request pending memory becoming available then the FS must ensure that the library stays loaded until the IRP is completed. Change-Id: Idbfdd84ecd364c99d3ad9cd8dd7e000f47be4b58 Reviewed-on: http://gerrit.openafs.org/9126 Reviewed-by: Rod Widdowson Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp | 5 ++ src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp | 87 ++++++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp b/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp index db85d9dd1..a9962625b 100644 --- a/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp +++ b/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp @@ -1327,6 +1327,11 @@ AFSSendDeviceIoControl( IN DEVICE_OBJECT *TargetDeviceObject, // Set the completion routine. // + AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "Setting AFSIrpComplete as IoCompletion Routine Irp %p\n", + pIrp); + IoSetCompletionRoutine( pIrp, AFSIrpComplete, &kEvent, diff --git a/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp b/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp index 342058765..1ada0128f 100644 --- a/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp +++ b/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp @@ -38,12 +38,22 @@ #include "AFSCommon.h" + +static +NTSTATUS +AFSWriteComplete( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt); + // // Function: AFSWrite // // Description: // -// This is the dispatch handler for the IRP_MJ_WRITE request +// This is the dispatch handler for the IRP_MJ_WRITE request. Since we want to +// allow the library to pend the write we need to lock the library for the +// duration of the thread calling the library but also for the life of the IRP. +// So this code path establishes an IO completion function. // // Return: // @@ -84,19 +94,54 @@ AFSWrite( IN PDEVICE_OBJECT DeviceObject, if( ntStatus != STATUS_PENDING) { + + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + // + // Increment the outstanding IO count again - this time for the + // completion routine. + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + AFSClearLibraryRequest(); + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } - IoSkipCurrentIrpStackLocation( Irp); + // + // And send it down, but arrange to capture the comletion + // so we can free our lock against unloading. + // + + IoCopyCurrentIrpStackLocationToNext( Irp); + + AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "Setting AFSWriteComplete as IoCompletion Routine Irp %p\n", + Irp); + + IoSetCompletionRoutine( Irp, AFSWriteComplete, NULL, TRUE, TRUE, TRUE); ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, Irp); // - // Indicate the library is done with the request + // Indicate the library/thread pair is done with the request // AFSClearLibraryRequest(); @@ -115,3 +160,39 @@ try_exit: return ntStatus; } + +// +// AFSWriteComplete +// +static +NTSTATUS +AFSWriteComplete( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Irp); + UNREFERENCED_PARAMETER(Context); + BOOLEAN bPending = FALSE; + + // + // Indicate the library/IRP pair is done with the request + // + + AFSClearLibraryRequest(); + + if (Irp->PendingReturned) { + + bPending = TRUE; + + IoMarkIrpPending(Irp); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSWriteComplete Irp %p%s\n", + Irp, + bPending ? " PENDING" : ""); + + return STATUS_CONTINUE_COMPLETION; +} -- 2.39.5