Windows: AFSLocateNameEntry tracking DirectoryCB IN/OUT
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSGeneric.cpp
index e653397..78600a6 100644 (file)
@@ -2002,7 +2002,8 @@ AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
         if( pVolumeCB != NULL)
         {
 
-            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeIncrement( pVolumeCB,
+                                         AFS_VOLUME_REFERENCE_INVALIDATE);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
@@ -2116,7 +2117,8 @@ try_exit:
         if ( pVolumeCB != NULL)
         {
 
-            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeDecrement( pVolumeCB,
+                                         AFS_VOLUME_REFERENCE_INVALIDATE);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
@@ -2714,7 +2716,8 @@ AFSInvalidateAllVolumes( VOID)
                       pVolumeCB->ObjectInfoTree.TreeLock,
                       PsGetCurrentThread());
 
-        lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = AFSVolumeIncrement( pVolumeCB,
+                                     AFS_VOLUME_REFERENCE_INVALIDATE);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -2731,7 +2734,8 @@ AFSInvalidateAllVolumes( VOID)
         if ( pNextVolumeCB)
         {
 
-            lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeIncrement( pNextVolumeCB,
+                                         AFS_VOLUME_REFERENCE_INVALIDATE);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
@@ -2749,7 +2753,8 @@ AFSInvalidateAllVolumes( VOID)
         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
                           TRUE);
 
-        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = AFSVolumeDecrement( pVolumeCB,
+                                     AFS_VOLUME_REFERENCE_INVALIDATE);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -3313,7 +3318,8 @@ AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
         if( pVolumeCB != NULL)
         {
 
-            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeIncrement( pVolumeCB,
+                                         AFS_VOLUME_REFERENCE_INVALIDATE);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
@@ -6043,7 +6049,11 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
     UNICODE_STRING uniFullPathName = {0};
     AFSNameArrayHdr    *pNameArray = NULL;
     AFSVolumeCB *pVolumeCB = NULL;
+    LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
+    AFSVolumeCB *pNewVolumeCB = NULL;
+    LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
+    AFSDirectoryCB *pNewParentDirEntry = NULL;
     WCHAR *pwchBuffer = NULL;
     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
     ULONG ulNameDifference = 0;
@@ -6295,12 +6305,16 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
         // Increment the ref count on the volume and dir entry for correct processing below
         //
 
-        lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+        VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
+
+        lCount = AFSVolumeIncrement( pVolumeCB,
+                                     VolumeReferenceReason);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSRetrieveFileAttributes Increment count on volume %p Cnt %d\n",
+                      "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
                       pVolumeCB,
+                      VolumeReferenceReason,
                       lCount);
 
         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
@@ -6319,68 +6333,62 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
                                        &uniParsedName,
                                        pNameArray,
                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
-                                       &pVolumeCB,
-                                       &pParentDirEntry,
+                                       pVolumeCB,
+                                       pParentDirEntry,
+                                       &pNewVolumeCB,
+                                       &NewVolumeReferenceReason,
+                                       &pNewParentDirEntry,
                                        &pDirectoryEntry,
                                        NULL);
 
-        if( !NT_SUCCESS( ntStatus) ||
-            ntStatus == STATUS_REPARSE)
-        {
-
-            //
-            // The volume lock was released on failure or reparse above
-            // Except for STATUS_OBJECT_NAME_NOT_FOUND
-            //
+        //
+        // AFSLocateNameEntry returns pNewVolumeCB with a reference held
+        // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
+        // the reference on pVolumeCB that was held prior to the call.
+        // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
+        // will be released second.
+        //
 
-            if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
-            {
+        lCount = AFSVolumeDecrement( pVolumeCB,
+                                     VolumeReferenceReason);
 
-                if( pVolumeCB != NULL)
-                {
+        AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
+                      pVolumeCB,
+                      VolumeReferenceReason,
+                      lCount);
 
-                    lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        pVolumeCB = pNewVolumeCB;
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSRetrieveFileAttributes Decrement count on volume %p Cnt %d\n",
-                                  pVolumeCB,
-                                  lCount);
-                }
+        pNewVolumeCB = NULL;
 
-                if( pDirectoryEntry != NULL)
-                {
+        VolumeReferenceReason = NewVolumeReferenceReason;
 
-                    lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+        NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                  &pDirectoryEntry->NameInformation.FileName,
-                                  pDirectoryEntry,
-                                  NULL,
-                                  lCount);
+        //
+        // AFSLocateNameEntry does not alter the reference count of
+        // pParentDirectoryCB and it returns pNewParentDirectoryCB with
+        // a reference held.
+        //
 
-                    ASSERT( lCount >= 0);
-                }
-                else
-                {
+        lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
 
-                    lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+        AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
+                      &pParentDirEntry->NameInformation.FileName,
+                      pParentDirEntry,
+                      lCount);
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                  &pParentDirEntry->NameInformation.FileName,
-                                  pParentDirEntry,
-                                  NULL,
-                                  lCount);
+        pParentDirEntry = pNewParentDirEntry;
 
-                    ASSERT( lCount >= 0);
-                }
-            }
+        pNewParentDirEntry = NULL;
 
-            pVolumeCB = NULL;
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_REPARSE)
+        {
 
             try_return( ntStatus);
         }
@@ -6428,39 +6436,57 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
 
         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
 
-        //
-        // Remove the reference made above
-        //
+try_exit:
 
-        lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+        if( pDirEntry != NULL)
+        {
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
-                      &pDirectoryEntry->NameInformation.FileName,
-                      pDirectoryEntry,
-                      NULL,
-                      lCount);
+            AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
+        }
 
-        ASSERT( lCount >= 0);
+        if( pDirectoryEntry != NULL)
+        {
 
-try_exit:
+            lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
 
-        if( pDirEntry != NULL)
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirectoryEntry->NameInformation.FileName,
+                          pDirectoryEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
+        if ( pParentDirEntry != NULL)
         {
 
-            AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
+            lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pParentDirEntry->NameInformation.FileName,
+                          pParentDirEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
         }
 
         if( pVolumeCB != NULL)
         {
 
-            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeDecrement( pVolumeCB,
+                                         VolumeReferenceReason);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSRetrieveFileAttributes Decrement2 count on volume %p Cnt %d\n",
+                          "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
                           pVolumeCB,
+                          VolumeReferenceReason,
                           lCount);
         }
 
@@ -6667,7 +6693,7 @@ AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
                         IN LONG Reason)
 {
 
-    LONG lCount;
+    LONG lCount, lCount2;
 
     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
                       TRUE);
@@ -6687,9 +6713,9 @@ AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
     }
 
-    lCount = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
+    lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
 
-    ASSERT( lCount >= 0);
+    ASSERT( lCount2 >= 0);
 
     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
 
@@ -6898,7 +6924,11 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
     UNICODE_STRING uniFullPathName = {0};
     AFSNameArrayHdr    *pNameArray = NULL;
     AFSVolumeCB *pVolumeCB = NULL;
+    LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
+    AFSVolumeCB *pNewVolumeCB = NULL;
+    LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
+    AFSDirectoryCB *pNewParentDirEntry = NULL;
     WCHAR *pwchBuffer = NULL;
     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
     ULONG ulNameDifference = 0;
@@ -7057,12 +7087,16 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
 
         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
 
-        lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+        VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
+
+        lCount = AFSVolumeIncrement( pVolumeCB,
+                                     VolumeReferenceReason);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSEvaluateRootEntry Increment count on volume %p Cnt %d\n",
+                      "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
                       pVolumeCB,
+                      VolumeReferenceReason,
                       lCount);
 
         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
@@ -7081,66 +7115,62 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
                                        &uniParsedName,
                                        pNameArray,
                                        0,
-                                       &pVolumeCB,
-                                       &pParentDirEntry,
+                                       pVolumeCB,
+                                       pParentDirEntry,
+                                       &pNewVolumeCB,
+                                       &VolumeReferenceReason,
+                                       &pNewParentDirEntry,
                                        &pDirectoryEntry,
                                        NULL);
 
-        if( !NT_SUCCESS( ntStatus) ||
-            ntStatus == STATUS_REPARSE)
-        {
+        //
+        // AFSLocateNameEntry returns pNewVolumeCB with a reference held
+        // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
+        // the reference on pVolumeCB that was held prior to the call.
+        // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
+        // will be released second.
+        //
 
-            //
-            // The volume lock was released on failure or reparse above
-            // Except for STATUS_OBJECT_NAME_NOT_FOUND
-            //
+        lCount = AFSVolumeDecrement( pVolumeCB,
+                                     VolumeReferenceReason);
 
-            if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
-            {
+        AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
+                      pVolumeCB,
+                      VolumeReferenceReason,
+                      lCount);
 
-                if( pVolumeCB != NULL)
-                {
+        pVolumeCB = pNewVolumeCB;
 
-                    lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        pNewVolumeCB = NULL;
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSEvaluateRootEntry Decrement count on volume %p Cnt %d\n",
-                                  pVolumeCB,
-                                  lCount);
-                }
+        VolumeReferenceReason = NewVolumeReferenceReason;
 
-                if( pDirectoryEntry != NULL)
-                {
+        NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
 
-                    lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+        //
+        // AFSLocateNameEntry does not alter the reference count of
+        // pParentDirectoryCB and it returns pNewParentDirectoryCB with
+        // a reference held.
+        //
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                  &pDirectoryEntry->NameInformation.FileName,
-                                  pDirectoryEntry,
-                                  NULL,
-                                  lCount);
+        lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
 
-                    ASSERT( lCount >= 0);
-                }
-                else
-                {
+        AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
+                      &pParentDirEntry->NameInformation.FileName,
+                      pParentDirEntry,
+                      lCount);
 
-                    lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+        pParentDirEntry = pNewParentDirEntry;
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                  &pParentDirEntry->NameInformation.FileName,
-                                  pParentDirEntry,
-                                  NULL,
-                                  lCount);
+        pNewParentDirEntry = NULL;
 
-                    ASSERT( lCount >= 0);
-                }
-            }
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_REPARSE)
+        {
 
             pVolumeCB = NULL;
 
@@ -7154,8 +7184,42 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
 
         *TargetDirEntry = pDirectoryEntry;
 
+        pDirectoryEntry = NULL;
+
 try_exit:
 
+        if( pDirectoryEntry != NULL)
+        {
+
+            lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirectoryEntry->NameInformation.FileName,
+                          pDirectoryEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
+        if ( pParentDirEntry != NULL)
+        {
+
+            lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pParentDirEntry->NameInformation.FileName,
+                          pParentDirEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
         if( pDirEntry != NULL)
         {
 
@@ -7165,12 +7229,14 @@ try_exit:
         if( pVolumeCB != NULL)
         {
 
-            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = AFSVolumeDecrement( pVolumeCB,
+                                         VolumeReferenceReason);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSEvaluateRootEntry Decrement2 count on volume %p Cnt %d\n",
+                          "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
                           pVolumeCB,
+                          VolumeReferenceReason,
                           lCount);
         }
 
@@ -8136,6 +8202,7 @@ AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
 
         ntStatus = AFSInitVolume( NULL,
                                   &LibraryInit->GlobalRootFid,
+                                  AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
                                   &AFSGlobalRoot);
 
         if( !NT_SUCCESS( ntStatus))
@@ -8160,11 +8227,12 @@ AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
                           ntStatus);
 
-            lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
+            lCount = AFSVolumeDecrement( AFSGlobalRoot,
+                                         AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSInitializeLibrary Increment count on volume %p Cnt %d\n",
+                          "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
                           AFSGlobalRoot,
                           lCount);
 
@@ -8194,7 +8262,8 @@ AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
 
         AFSInitVolumeWorker( AFSGlobalRoot);
 
-        lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
+        lCount = AFSVolumeDecrement( AFSGlobalRoot,
+                                     AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -8333,12 +8402,16 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSVolumeCB *pVolumeCB = NULL;
+    LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
+    AFSVolumeCB *pNewVolumeCB = NULL;
+    LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
     AFSObjectInfoCB *pObjectInfo = NULL;
     ULONGLONG   ullIndex = 0;
     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
     AFSNameArrayHdr *pNameArray = NULL;
     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
+    AFSDirectoryCB *pNewParentDirEntry = NULL;
     LONG lCount;
 
     __Enter
@@ -8370,12 +8443,16 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
             if( pVolumeCB != NULL)
             {
 
-                lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+                VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
+
+                lCount = AFSVolumeIncrement( pVolumeCB,
+                                             VolumeReferenceReason);
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSGetObjectStatus Increment count on volume %p Cnt %d\n",
+                              "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
                               pVolumeCB,
+                              VolumeReferenceReason,
                               lCount);
             }
 
@@ -8400,14 +8477,6 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
                               pObjectInfo,
                               lCount);
-
-                lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSGetObjectStatus Decrement count on volume %p Cnt %d\n",
-                              pVolumeCB,
-                              lCount);
             }
             else
             {
@@ -8415,14 +8484,6 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
                                   TRUE);
 
-                lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSGetObjectStatus Decrement2 count on volume %p Cnt %d\n",
-                              pVolumeCB,
-                              lCount);
-
                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
 
                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
@@ -8513,12 +8574,16 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
             // Increment the ref count on the volume and dir entry for correct processing below
             //
 
-            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
+
+            lCount = AFSVolumeIncrement( pVolumeCB,
+                                         VolumeReferenceReason);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSGetObjectStatus Increment2 count on volume %p Cnt %d\n",
+                          "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
                           pVolumeCB,
+                          VolumeReferenceReason,
                           lCount);
 
             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
@@ -8538,88 +8603,68 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
                                            pNameArray,
                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
-                                           &pVolumeCB,
-                                           &pParentDirEntry,
+                                           pVolumeCB,
+                                           pParentDirEntry,
+                                           &pNewVolumeCB,
+                                           &NewVolumeReferenceReason,
+                                           &pNewParentDirEntry,
                                            &pDirectoryEntry,
                                            NULL);
 
-            if( !NT_SUCCESS( ntStatus) ||
-                ntStatus == STATUS_REPARSE)
-            {
+            //
+            // AFSLocateNameEntry returns pNewVolumeCB with a reference held
+            // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
+            // the reference on pVolumeCB that was held prior to the call.
+            // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
+            // will be released second.
+            //
 
-                //
-                // The volume lock was released on failure or reparse above
-                // Except for STATUS_OBJECT_NAME_NOT_FOUND
-                //
+            lCount = AFSVolumeDecrement( pVolumeCB,
+                                         VolumeReferenceReason);
 
-                if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
-                {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
+                          pVolumeCB,
+                          VolumeReferenceReason,
+                          lCount);
 
-                    if( pVolumeCB != NULL)
-                    {
+            pVolumeCB = pNewVolumeCB;
 
-                        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+            pNewVolumeCB = NULL;
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSGetObjectStatus Decrement3 count on volume %p Cnt %d\n",
-                                      pVolumeCB,
-                                      lCount);
-                    }
+            VolumeReferenceReason = NewVolumeReferenceReason;
 
-                    if( pDirectoryEntry != NULL)
-                    {
+            NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
 
-                        lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+            //
+            // AFSLocateNameEntry does not alter the reference count of
+            // pParentDirectoryCB and it returns pNewParentDirectoryCB with
+            // a reference held.
+            //
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                      &pDirectoryEntry->NameInformation.FileName,
-                                      pDirectoryEntry,
-                                      NULL,
-                                      lCount);
+            lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
 
-                        ASSERT( lCount >= 0);
-                    }
-                    else
-                    {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
+                          &pParentDirEntry->NameInformation.FileName,
+                          pParentDirEntry,
+                          lCount);
 
-                        lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+            pParentDirEntry = pNewParentDirEntry;
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
-                                      &pParentDirEntry->NameInformation.FileName,
-                                      pParentDirEntry,
-                                      NULL,
-                                      lCount);
+            pNewParentDirEntry = NULL;
 
-                        ASSERT( lCount >= 0);
-                    }
-                }
+            if( !NT_SUCCESS( ntStatus) ||
+                ntStatus == STATUS_REPARSE)
+            {
 
                 pVolumeCB = NULL;
 
                 try_return( ntStatus);
             }
 
-            //
-            // Remove the reference obtained from AFSLocateNameEntry
-            //
-
-            lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
-
-            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                          AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSGetObjectStatus Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
-                          &pDirectoryEntry->NameInformation.FileName,
-                          pDirectoryEntry,
-                          NULL,
-                          lCount);
-
-            ASSERT( lCount >= 0);
-
             pObjectInfo = pDirectoryEntry->ObjectInformation;
 
             lCount = AFSObjectInfoIncrement( pObjectInfo,
@@ -8630,18 +8675,6 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
                           pObjectInfo,
                           lCount);
-
-            if( pVolumeCB != NULL)
-            {
-
-                lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSGetObjectStatus Decrement4 count on volume %p Cnt %d\n",
-                              pVolumeCB,
-                              lCount);
-            }
         }
 
         //
@@ -8686,6 +8719,38 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
 
 try_exit:
 
+        if( pDirectoryEntry != NULL)
+        {
+
+            lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirectoryEntry->NameInformation.FileName,
+                          pDirectoryEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
+        if ( pParentDirEntry != NULL)
+        {
+
+            lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pParentDirEntry->NameInformation.FileName,
+                          pParentDirEntry,
+                          NULL,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
         if( pObjectInfo != NULL)
         {
 
@@ -8699,6 +8764,20 @@ try_exit:
                           lCount);
         }
 
+        if( pVolumeCB != NULL)
+        {
+
+            lCount = AFSVolumeDecrement( pVolumeCB,
+                                         VolumeReferenceReason);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
+                          pVolumeCB,
+                          VolumeReferenceReason,
+                          lCount);
+        }
+
         if( pNameArray != NULL)
         {