Windows: Allow the Library to pend a write request
authorRod Widdowson <rdw@steadingsoftware.com>
Fri, 15 Feb 2013 10:57:29 +0000 (05:57 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Fri, 22 Feb 2013 21:11:30 +0000 (13:11 -0800)
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 <rdw@steadingsoftware.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp
src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp

index db85d9d..a996262 100644 (file)
@@ -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,
index 3420587..1ada012 100644 (file)
 
 #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;
+}