Prevent deadlocks of recently implemented synchronization.
authorshort <>
Tue, 5 Aug 2003 10:06:12 +0000 (10:06 +0000)
committershort <>
Tue, 5 Aug 2003 10:06:12 +0000 (10:06 +0000)
 - FIXME: Enable of file compression still hangs in CcFlushCache().

src/TraceFS/TraceFS-W32/TraceFS.c

index 1064f4b..6527a17 100644 (file)
@@ -62,12 +62,34 @@ static void lock(void)
        KeLeaveCriticalRegion();\r
        if (lock_resource_CurrentThread)\r
                KeBugCheck(0);\r
-       if (lock_resource_count!=0)\r
+       if (lock_resource_count)\r
                KeBugCheck(0);\r
        lock_resource_CurrentThread=PsGetCurrentThread();\r
        lock_resource_count++;\r
 }\r
 \r
+/* We need to _fully_ release the lock if we are passing the control to\r
+ * callback functions. Single unlock() would free us from our current 'enter:'\r
+ * lock but another lock() from Cc*() function which called us would be held.\r
+ */\r
+static void lock_full(int n)\r
+{\r
+       if (n<=0)\r
+               KeBugCheck(0);\r
+       if (lock_resource_CurrentThread==PsGetCurrentThread())\r
+               KeBugCheck(0);\r
+       KeEnterCriticalRegion();\r
+       if (!ExAcquireResourceExclusiveLite(&lock_resource,TRUE))\r
+               KeBugCheck(0);\r
+       KeLeaveCriticalRegion();\r
+       if (lock_resource_CurrentThread)\r
+               KeBugCheck(0);\r
+       if (lock_resource_count)\r
+               KeBugCheck(0);\r
+       lock_resource_CurrentThread=PsGetCurrentThread();\r
+       lock_resource_count+=n;\r
+}\r
+\r
 static void unlock(void)\r
 {\r
        if (lock_resource_CurrentThread!=PsGetCurrentThread())\r
@@ -82,6 +104,23 @@ static void unlock(void)
        KeLeaveCriticalRegion();\r
 }\r
 \r
+static int unlock_full(void)\r
+{\r
+int r;\r
+\r
+       if (lock_resource_CurrentThread!=PsGetCurrentThread())\r
+               KeBugCheck(0);\r
+       if (lock_resource_count<=0)\r
+               KeBugCheck(0);\r
+       r=lock_resource_count;\r
+       lock_resource_count=0;\r
+       lock_resource_CurrentThread=NULL;\r
+       KeEnterCriticalRegion();\r
+       ExReleaseResourceLite(&lock_resource);\r
+       KeLeaveCriticalRegion();\r
+       return r;\r
+}\r
+\r
 #define DBGPREFIX "TraceFS(0x%08lX/0x%08lX): "\r
 #define DBGARG PsGetCurrentProcess(),PsGetCurrentThread()\r
 \r
@@ -246,9 +285,10 @@ static void dump_FileObject(FILE_OBJECT *FileObject)
                DBGSINGLE0("FileObject=NULL");\r
                return;\r
                }\r
-       DBGSINGLE4("FileObject=0x%lX: FileName=%s,Flags=0x%lX,SectionObjectPointer->SharedCacheMap=0x%lX",\r
+       DBGSINGLE5("FileObject=0x%lX: FileName=%s,Flags=0x%lX,SectionObjectPointer=0x%lX,->SharedCacheMap=0x%lX",\r
                        (long)FileObject,\r
                        dbg_unicode_string(&FileObject->FileName),FileObject->Flags,\r
+                       (long)FileObject->SectionObjectPointer,\r
                        (!FileObject->SectionObjectPointer ? -1 : (long)FileObject->SectionObjectPointer->SharedCacheMap));\r
        SectionObjectPointer_set(FileObject);\r
 }\r
@@ -343,10 +383,16 @@ static NTSTATUS (*tracefs_major_##irp_mj_name##_orig)(IN struct _DEVICE_OBJECT *
 static NTSTATUS tracefs_major_##irp_mj_name(IN struct _DEVICE_OBJECT *DeviceObject,IN struct _IRP *Irp) \\r
 { \\r
 NTSTATUS r; \\r
+int locked; \\r
  \\r
        DBGSINGLEENTER0( #irp_mj_name ); \\r
        dump_irp_mj(DeviceObject,Irp); \\r
+       /* Prevent deadlock during display of File Explorer directory listing. \\r
+        * Needed at least for IRP_MJ_DIRECTORY_CONTROL and IRP_MJ_CLOSE. \\r
+        */ \\r
+       locked=unlock_full(); \\r
        r=(*tracefs_major_##irp_mj_name##_orig)(DeviceObject,Irp); \\r
+       lock_full(locked); \\r
        DBGSINGLELEAVE1( #irp_mj_name ": r=0x%lX",(long)r); \\r
        return r; \\r
 }\r
@@ -745,11 +791,15 @@ static BOOLEAN TcInitializeCacheMap_AcquireForLazyWrite(IN PVOID Context,IN BOOL
 {\r
 struct Callbacks *callbacksp=Context;\r
 BOOLEAN r;\r
+int locked;\r
 \r
        DBGSINGLEENTER3("AcquireForLazyWrite: FileObject=0x%lX,Context=0x%lX,Wait=%d",\r
                        (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait);\r
        dump_FileObject(callbacksp->FileObject);\r
+       /* Prevent deadlock during File Explorer copy to our destination. */\r
+       locked=unlock_full();\r
        r=(*callbacksp->Callbacks.AcquireForLazyWrite)(callbacksp->LazyWriteContext,Wait);\r
+       lock_full(locked);\r
        DBGSINGLELEAVE1("AcquireForLazyWrite: r=%d",r);\r
        return r;\r
 }\r
@@ -757,11 +807,15 @@ BOOLEAN r;
 static VOID TcInitializeCacheMap_ReleaseFromLazyWrite(IN PVOID Context)\r
 {\r
 struct Callbacks *callbacksp=Context;\r
+int locked;\r
 \r
        DBGSINGLEENTER2("ReleaseFromLazyWrite: FileObject=0x%lX,Context=0x%lX",\r
                        (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext);\r
        dump_FileObject(callbacksp->FileObject);\r
+       /* Prevent deadlock during File Explorer copy to our destination. */\r
+       locked=unlock_full();\r
        (*callbacksp->Callbacks.ReleaseFromLazyWrite)(callbacksp->LazyWriteContext);\r
+       lock_full(locked);\r
        DBGSINGLELEAVE0("ReleaseFromLazyWrite");\r
 }\r
 \r
@@ -769,11 +823,15 @@ static BOOLEAN TcInitializeCacheMap_AcquireForReadAhead(IN PVOID Context,IN BOOL
 {\r
 struct Callbacks *callbacksp=Context;\r
 BOOLEAN r;\r
+int locked;\r
 \r
        DBGSINGLEENTER3("AcquireForReadAhead: FileObject=0x%lX,Context=0x%lX,Wait=%d",\r
                        (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext,Wait);\r
        dump_FileObject(callbacksp->FileObject);\r
+       /* Prevent deadlock during File Explorer copy to our destination. */\r
+       locked=unlock_full();\r
        r=(*callbacksp->Callbacks.AcquireForReadAhead)(callbacksp->LazyWriteContext,Wait);\r
+       lock_full(locked);\r
        DBGSINGLELEAVE1("AcquireForReadAhead: r=%d",r);\r
        return r;\r
 }\r
@@ -781,11 +839,15 @@ BOOLEAN r;
 static VOID TcInitializeCacheMap_ReleaseFromReadAhead(IN PVOID Context)\r
 {\r
 struct Callbacks *callbacksp=Context;\r
+int locked;\r
 \r
        DBGSINGLEENTER2("ReleaseFromReadAhead: FileObject=0x%lX,Context=0x%lX",\r
                        (long)callbacksp->FileObject,(long)callbacksp->LazyWriteContext);\r
        dump_FileObject(callbacksp->FileObject);\r
+       /* Prevent deadlock during File Explorer copy to our destination. */\r
+       locked=unlock_full();\r
        (*callbacksp->Callbacks.ReleaseFromReadAhead)(callbacksp->LazyWriteContext);\r
+       lock_full(locked);\r
        DBGSINGLELEAVE0("ReleaseFromReadAhead");\r
 }\r
 \r
@@ -1313,11 +1375,15 @@ struct LogHandle *loghandlep;
 static VOID TcSetLogHandleForFile_FlushToLsnRoutine(IN PVOID LogHandle,IN LARGE_INTEGER Lsn)\r
 {\r
 PFLUSH_TO_LSN FlushToLsnRoutine;\r
+int locked;\r
 \r
        DBGSINGLEENTER2("FlushToLsnRoutine: LogHandle=0x%lX,Lsn=0x%lX",\r
                        (long)LogHandle,(long)Lsn.QuadPart);\r
+       /* Prevent deadlock during display of File Explorer directory listing. */\r
+       locked=unlock_full();\r
        if ((FlushToLsnRoutine=LogHandle_find(LogHandle)))\r
                (*FlushToLsnRoutine)(LogHandle,Lsn);\r
+       lock_full(locked);\r
        DBGSINGLELEAVE0("FlushToLsnRoutine");\r
 }\r
 \r