Windows: Add Name Array Processing Trace Subsystem
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSGeneric.cpp
index 59a47e7..efc06e3 100644 (file)
@@ -424,10 +424,10 @@ AFSLockUserBuffer( IN void *UserBuffer,
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     void *pAddress = NULL;
-       MDL *pMdl = NULL;
+    MDL *pMdl = NULL;
 
-       __Enter
-       {
+    __Enter
+    {
 
         pMdl = IoAllocateMdl( UserBuffer,
                               BufferLength,
@@ -435,11 +435,11 @@ AFSLockUserBuffer( IN void *UserBuffer,
                               FALSE,
                               NULL);
 
-               if( pMdl == NULL)
-               {
+            if( pMdl == NULL)
+            {
 
-                       try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-               }
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
 
         //
         //  Lock the new Mdl in memory.
@@ -449,11 +449,11 @@ AFSLockUserBuffer( IN void *UserBuffer,
         {
 
             MmProbeAndLockPages( pMdl,
-                                                                KernelMode,
+                                 KernelMode,
                                  IoWriteAccess);
 
             pAddress = MmGetSystemAddressForMdlSafe( pMdl,
-                                                                                                        NormalPagePriority);
+                                                     NormalPagePriority);
         }
         __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
         {
@@ -463,11 +463,11 @@ AFSLockUserBuffer( IN void *UserBuffer,
             pAddress = NULL;
         }
 
-               if( pMdl != NULL)
-               {
+        if( pMdl != NULL)
+        {
 
-                       *Mdl = pMdl;
-               }
+            *Mdl = pMdl;
+        }
 
 try_exit:
 
@@ -1553,199 +1553,260 @@ try_exit:
 }
 
 NTSTATUS
-AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
+AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
+                     IN     ULONG Reason)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSFcb      *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
-    AFSVolumeCB *pVolumeCB = NULL;
-    AFSFcb      *pTargetDcb = NULL;
-    AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
-    AFSDirectoryCB *pCurrentDirEntry = NULL;
-    BOOLEAN     bIsChild = FALSE;
-    ULONGLONG   ullIndex = 0;
-    AFSObjectInfoCB *pObjectInfo = NULL;
     IO_STATUS_BLOCK stIoStatus;
     ULONG ulFilter = 0;
-    LONG lCount;
 
-    __Enter
+    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
+                  (*ppObjectInfo)->FileType,
+                  (*ppObjectInfo)->FileId.Cell,
+                  (*ppObjectInfo)->FileId.Volume,
+                  (*ppObjectInfo)->FileId.Vnode,
+                  (*ppObjectInfo)->FileId.Unique,
+                  Reason);
+
+    if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
+        (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
+        (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
     {
-
         //
-        // Need to locate the Fcb for the directory to purge
+        // We only act on the mount point itself, not the target. If the
+        // node has been deleted then mark it as such otherwise indicate
+        // it requires verification
         //
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
-                      &pDevExt->Specific.RDR.VolumeTreeLock,
-                      PsGetCurrentThread());
+        if( Reason == AFS_INVALIDATE_DELETED)
+        {
+            SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
+        }
+        else
+        {
 
-        //
-        // Starve any exclusive waiters on this paticular call
-        //
+            if( Reason == AFS_INVALIDATE_FLUSHED)
+            {
 
-        AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
+                (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
 
-        //
-        // Locate the volume node
-        //
+                SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
+            }
 
-        ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
+            (*ppObjectInfo)->Expiration.QuadPart = 0;
 
-        ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
-                                       ullIndex,
-                                       (AFSBTreeEntry **)&pVolumeCB);
-
-        if( pVolumeCB != NULL)
-        {
+            (*ppObjectInfo)->TargetFileId.Vnode = 0;
 
-            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            (*ppObjectInfo)->TargetFileId.Unique = 0;
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
-                          pVolumeCB,
-                          lCount);
+                          "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
+                          (*ppObjectInfo)->FileId.Cell,
+                          (*ppObjectInfo)->FileId.Volume,
+                          (*ppObjectInfo)->FileId.Vnode,
+                          (*ppObjectInfo)->FileId.Unique);
+
+            SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
         }
 
-        AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
+        ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
 
-        if( !NT_SUCCESS( ntStatus) ||
-            pVolumeCB == NULL)
+        if( Reason == AFS_INVALIDATE_CREDS)
         {
-            try_return( ntStatus = STATUS_SUCCESS);
+            ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
         }
 
-        //
-        // If this is a whole volume invalidation then go do it now
-        //
-
-        if( InvalidateCB->WholeVolume ||
-            AFSIsVolumeFID( &InvalidateCB->FileID))
+        if( Reason == AFS_INVALIDATE_DATA_VERSION ||
+            Reason == AFS_INVALIDATE_FLUSHED)
         {
-
-            ntStatus = AFSInvalidateVolume( pVolumeCB,
-                                            InvalidateCB->Reason);
-
-            AFSFsRtlNotifyFullReportChange( &pVolumeCB->ObjectInformation,
-                                            NULL,
-                                            FILE_NOTIFY_CHANGE_FILE_NAME |
-                                            FILE_NOTIFY_CHANGE_DIR_NAME |
-                                            FILE_NOTIFY_CHANGE_NAME |
-                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
-                                            FILE_NOTIFY_CHANGE_SIZE,
-                                            FILE_ACTION_MODIFIED);
-
-            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
-
-            try_return( ntStatus);
+            ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
+        }
+        else
+        {
+            ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
         }
 
-        AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
-                          TRUE);
-
-        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
+                                        NULL,
+                                        FILE_NOTIFY_CHANGE_FILE_NAME |
+                                        FILE_NOTIFY_CHANGE_ATTRIBUTES,
+                                        FILE_ACTION_MODIFIED);
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
-                      pVolumeCB,
-                      pVolumeCB->VolumeReferenceCount);
+        try_return( ntStatus);
+    }
 
-        ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
+    //
+    // Depending on the reason for invalidation then perform work on the node
+    //
 
-        ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
-                                       ullIndex,
-                                       (AFSBTreeEntry **)&pObjectInfo);
+    switch( Reason)
+    {
 
-        if( pObjectInfo != NULL)
+    case AFS_INVALIDATE_DELETED:
         {
 
             //
-            // Reference the node so it won't be torn down
+            // Mark this node as invalid
             //
 
-            lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+            SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
-                          pObjectInfo,
-                          lCount);
-        }
+                          "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
+                          (*ppObjectInfo)->FileId.Cell,
+                          (*ppObjectInfo)->FileId.Volume,
+                          (*ppObjectInfo)->FileId.Vnode,
+                          (*ppObjectInfo)->FileId.Unique);
 
-        AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
+            if( (*ppObjectInfo)->ParentObjectInformation != NULL)
+            {
 
-        if( !NT_SUCCESS( ntStatus) ||
-            pObjectInfo == NULL)
-        {
-            try_return( ntStatus = STATUS_SUCCESS);
-        }
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
+                              (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
+                              (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
+                              (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
+                              (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
 
-        if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
-            pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK ||
-            pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
-        {
+                SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSInvalidateCache Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
-                          pObjectInfo->FileType,
-                          pObjectInfo->FileId.Cell,
-                          pObjectInfo->FileId.Volume,
-                          pObjectInfo->FileId.Vnode,
-                          pObjectInfo->FileId.Unique,
-                          InvalidateCB->Reason);
+                (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
 
-            //
-            // We only act on the mount point itself, not the target. If the
-            // node has been deleted then mark it as such otherwise indicate
-            // it requires verification
-            //
+                (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
+            }
 
-            if( InvalidateCB->Reason == AFS_INVALIDATE_DELETED)
+            if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
             {
-                SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
+                ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
             }
             else
             {
+                ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
+            }
 
-                if( InvalidateCB->Reason == AFS_INVALIDATE_FLUSHED)
+            AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
+                                            NULL,
+                                            ulFilter,
+                                            FILE_ACTION_REMOVED);
+
+            if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
+                                                      Reason)))
+            {
+                (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
+            }
+
+            break;
+        }
+
+    case AFS_INVALIDATE_FLUSHED:
+        {
+
+            if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
+                (*ppObjectInfo)->Fcb != NULL)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
+                              (*ppObjectInfo)->FileId.Cell,
+                              (*ppObjectInfo)->FileId.Volume,
+                              (*ppObjectInfo)->FileId.Vnode,
+                              (*ppObjectInfo)->FileId.Unique);
+
+                AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
+                                TRUE);
+
+                __try
                 {
 
-                    pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                    CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
+                                  NULL,
+                                  0,
+                                  &stIoStatus);
+
+                    if( !NT_SUCCESS( stIoStatus.Status))
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
+                                      (*ppObjectInfo)->FileId.Cell,
+                                      (*ppObjectInfo)->FileId.Volume,
+                                      (*ppObjectInfo)->FileId.Vnode,
+                                      (*ppObjectInfo)->FileId.Unique,
+                                      stIoStatus.Status,
+                                      stIoStatus.Information);
+
+                        ntStatus = stIoStatus.Status;
+                    }
+
+                    CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
+                                         NULL,
+                                         0,
+                                         FALSE);
+                }
+                __except( EXCEPTION_EXECUTE_HANDLER)
+                {
 
-                    SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
+                    ntStatus = GetExceptionCode();
                 }
 
-                pObjectInfo->Expiration.QuadPart = 0;
+                AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
+
+                //
+                // Clear out the extents
+                // Get rid of them (note this involves waiting
+                // for any writes or reads to the cache to complete)
+                //
+
+                (VOID) AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
+                                              NULL);
+            }
 
-                pObjectInfo->TargetFileId.Vnode = 0;
+            (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
 
-                pObjectInfo->TargetFileId.Unique = 0;
+
+            if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
+            {
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                              pObjectInfo->FileId.Cell,
-                              pObjectInfo->FileId.Volume,
-                              pObjectInfo->FileId.Vnode,
-                              pObjectInfo->FileId.Unique);
+                              "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
+                              (*ppObjectInfo)->FileId.Cell,
+                              (*ppObjectInfo)->FileId.Volume,
+                              (*ppObjectInfo)->FileId.Vnode,
+                              (*ppObjectInfo)->FileId.Unique);
 
-                SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
             }
 
-            ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
+            // Fall through to the default processing
+        }
+
+    default:
+        {
+
+            if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
+            {
+                ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
+            }
+            else
+            {
+                ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
+            }
 
-            if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
+            if( Reason == AFS_INVALIDATE_CREDS)
             {
                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
             }
 
-            if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION ||
-                InvalidateCB->Reason == AFS_INVALIDATE_FLUSHED)
+            if( Reason == AFS_INVALIDATE_DATA_VERSION)
             {
                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
             }
@@ -1754,223 +1815,212 @@ AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
             }
 
-            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+            AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
                                             NULL,
-                                            FILE_NOTIFY_CHANGE_FILE_NAME |
-                                            FILE_NOTIFY_CHANGE_ATTRIBUTES,
+                                            ulFilter,
                                             FILE_ACTION_MODIFIED);
 
-            try_return( ntStatus);
-        }
+            //
+            // Indicate this node requires re-evaluation for the remaining reasons
+            //
 
-        //
-        // Depending on the reason for invalidation then perform work on the node
-        //
+            (*ppObjectInfo)->Expiration.QuadPart = 0;
 
-        switch( InvalidateCB->Reason)
-        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
+                          (*ppObjectInfo)->FileId.Cell,
+                          (*ppObjectInfo)->FileId.Volume,
+                          (*ppObjectInfo)->FileId.Vnode,
+                          (*ppObjectInfo)->FileId.Unique);
 
-            case AFS_INVALIDATE_DELETED:
-            {
+            SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                //
-                // Mark this node as invalid
-                //
+            if( Reason == AFS_INVALIDATE_DATA_VERSION ||
+                (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
+                ( Reason == AFS_INVALIDATE_CALLBACK ||
+                  Reason == AFS_INVALIDATE_EXPIRED))
+            {
+                if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
+                                                           AFS_INVALIDATE_DATA_VERSION)))
+                {
 
-                SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
+                    (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
+                }
+            }
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSInvalidateCache Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                              pObjectInfo->FileId.Cell,
-                              pObjectInfo->FileId.Volume,
-                              pObjectInfo->FileId.Vnode,
-                              pObjectInfo->FileId.Unique);
+            break;
+        }
+    }
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
-                {
+  try_exit:
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSInvalidateCache Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
-                                  pObjectInfo->ParentObjectInformation->FileId.Cell,
-                                  pObjectInfo->ParentObjectInformation->FileId.Volume,
-                                  pObjectInfo->ParentObjectInformation->FileId.Vnode,
-                                  pObjectInfo->ParentObjectInformation->FileId.Unique);
+    return ntStatus;
+}
 
-                    SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+NTSTATUS
+AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
+{
 
-                    pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFcb      *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
+    AFSVolumeCB *pVolumeCB = NULL;
+    AFSFcb      *pTargetDcb = NULL;
+    AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
+    AFSDirectoryCB *pCurrentDirEntry = NULL;
+    BOOLEAN     bIsChild = FALSE;
+    ULONGLONG   ullIndex = 0;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+    LONG lCount;
 
-                    pObjectInfo->ParentObjectInformation->Expiration.QuadPart = 0;
-                }
+    __Enter
+    {
 
-                if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
-                {
-                    ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
-                }
-                else
-                {
-                    ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
-                }
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
+                      InvalidateCB->FileID.Cell,
+                      InvalidateCB->FileID.Volume,
+                      InvalidateCB->FileID.Vnode,
+                      InvalidateCB->FileID.Unique,
+                      InvalidateCB->FileType,
+                      InvalidateCB->WholeVolume,
+                      InvalidateCB->Reason);
 
-                AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                NULL,
-                                                ulFilter,
-                                                FILE_ACTION_REMOVED);
+        //
+        // Need to locate the Fcb for the directory to purge
+        //
 
-                if( NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
-                                                          InvalidateCB->Reason)))
-                {
-                    pObjectInfo = NULL; // We'll dec the count in the worker item
-                }
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
+                      &pDevExt->Specific.RDR.VolumeTreeLock,
+                      PsGetCurrentThread());
 
-                break;
-            }
+        //
+        // Starve any exclusive waiters on this paticular call
+        //
 
-            case AFS_INVALIDATE_FLUSHED:
-            {
+        AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
 
-                if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
-                    pObjectInfo->Fcb != NULL)
-                {
+        //
+        // Locate the volume node
+        //
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSInvalidateCache Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
-                                  pObjectInfo->FileId.Cell,
-                                  pObjectInfo->FileId.Volume,
-                                  pObjectInfo->FileId.Vnode,
-                                  pObjectInfo->FileId.Unique);
+        ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
 
-                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
-                                    TRUE);
+        ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
+                                       ullIndex,
+                                       (AFSBTreeEntry **)&pVolumeCB);
 
-                    __try
-                    {
+        if( pVolumeCB != NULL)
+        {
 
-                        CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                      NULL,
-                                      0,
-                                      &stIoStatus);
+            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
 
-                        if( !NT_SUCCESS( stIoStatus.Status))
-                        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
+                          pVolumeCB,
+                          lCount);
+        }
 
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
-                                          AFS_TRACE_LEVEL_ERROR,
-                                          "AFSInvalidateCache CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
-                                          pObjectInfo->FileId.Cell,
-                                          pObjectInfo->FileId.Volume,
-                                          pObjectInfo->FileId.Vnode,
-                                          pObjectInfo->FileId.Unique,
-                                          stIoStatus.Status,
-                                          stIoStatus.Information);
+        AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
 
-                            ntStatus = stIoStatus.Status;
-                        }
+        if( !NT_SUCCESS( ntStatus) ||
+            pVolumeCB == NULL)
+        {
 
-                        CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                             NULL,
-                                             0,
-                                             FALSE);
-                    }
-                    __except( EXCEPTION_EXECUTE_HANDLER)
-                    {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          InvalidateCB->FileID.Cell,
+                          InvalidateCB->FileID.Volume,
+                          InvalidateCB->FileID.Vnode,
+                          InvalidateCB->FileID.Unique,
+                          ntStatus);
 
-                        ntStatus = GetExceptionCode();
-                    }
+            try_return( ntStatus = STATUS_SUCCESS);
+        }
 
-                    AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
+        //
+        // If this is a whole volume invalidation then go do it now
+        //
 
-                    //
-                    // Clear out the extents
-                    // Get rid of them (note this involves waiting
-                    // for any writes or reads to the cache to complete)
-                    //
+        if( InvalidateCB->WholeVolume)
+        {
 
-                    (VOID) AFSTearDownFcbExtents( pObjectInfo->Fcb,
-                                                  NULL);
-                }
+            ntStatus = AFSInvalidateVolume( pVolumeCB,
+                                            InvalidateCB->Reason);
 
-                pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
+            try_return( ntStatus);
+        }
 
-                if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
-                {
+        AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
+                          TRUE);
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSInvalidateCache Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                                  pObjectInfo->FileId.Cell,
-                                  pObjectInfo->FileId.Volume,
-                                  pObjectInfo->FileId.Vnode,
-                                  pObjectInfo->FileId.Unique);
+        if ( AFSIsVolumeFID( &InvalidateCB->FileID))
+        {
 
-                    SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
-                }
+            pObjectInfo = &pVolumeCB->ObjectInformation;
+        }
+        else
+        {
 
-                // Fall through to the default processing
-            }
+            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
-            default:
-            {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
+                          pVolumeCB,
+                          pVolumeCB->VolumeReferenceCount);
 
-                if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
-                {
-                    ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
-                }
-                else
-                {
-                    ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
-                }
+            ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
 
-                if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
-                }
+            ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
+                                           ullIndex,
+                                           (AFSBTreeEntry **)&pObjectInfo);
+        }
 
-                if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
-                }
-                else
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
-                }
+        if( pObjectInfo != NULL)
+        {
 
-                AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                NULL,
-                                                ulFilter,
-                                                FILE_ACTION_MODIFIED);
+            //
+            // Reference the node so it won't be torn down
+            //
 
-                //
-                // Indicate this node requires re-evaluation for the remaining reasons
-                //
+            lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
 
-                pObjectInfo->Expiration.QuadPart = 0;
+            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
+                          pObjectInfo,
+                          lCount);
+        }
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                              pObjectInfo->FileId.Cell,
-                              pObjectInfo->FileId.Volume,
-                              pObjectInfo->FileId.Vnode,
-                              pObjectInfo->FileId.Unique);
+        AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
 
-                SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+        if( !NT_SUCCESS( ntStatus) ||
+            pObjectInfo == NULL)
+        {
 
-                if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION &&
-                    NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
-                                                          InvalidateCB->Reason)))
-                {
-                    pObjectInfo = NULL; // We'll dec the count in the worker item
-                }
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          InvalidateCB->FileID.Cell,
+                          InvalidateCB->FileID.Volume,
+                          InvalidateCB->FileID.Vnode,
+                          InvalidateCB->FileID.Unique,
+                          ntStatus);
 
-                break;
-            }
+            try_return( ntStatus = STATUS_SUCCESS);
         }
 
+        AFSInvalidateObject( &pObjectInfo,
+                             InvalidateCB->Reason);
+
 try_exit:
 
         if( pObjectInfo != NULL)
@@ -2371,8 +2421,10 @@ AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSFcb *pFcb = NULL;
     AFSObjectInfoCB *pCurrentObject = NULL;
+    AFSObjectInfoCB *pNextObject = NULL;
+    LONG lCount;
+    AFSFcb *pFcb = NULL;
     ULONG ulFilter = 0;
 
     __Enter
@@ -2401,206 +2453,181 @@ AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
                 // Mark this volume as invalid
                 //
 
-                VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
-
                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
 
                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
 
-                AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
-                                                NULL,
-                                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                                FILE_ACTION_REMOVED);
+                break;
+            }
+        }
 
-                AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
-                                  TRUE);
+        //
+        // Invalidate the volume root directory
+        //
 
-                pCurrentObject = VolumeCB->ObjectInfoListHead;
+        pCurrentObject = &VolumeCB->ObjectInformation;
 
-                while( pCurrentObject != NULL)
-                {
+        if ( pCurrentObject )
+        {
 
-                    if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
-                    {
-                        ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
-                    }
-                    else
-                    {
-                        ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
-                    }
+            lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
+                          pCurrentObject,
+                          lCount);
 
-                    AFSFsRtlNotifyFullReportChange( pCurrentObject,
-                                                    NULL,
-                                                    ulFilter,
-                                                    FILE_ACTION_REMOVED);
+            AFSInvalidateObject( &pCurrentObject,
+                                 Reason);
 
-                    SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
+            if ( pCurrentObject)
+            {
 
-                    pFcb = pCurrentObject->Fcb;
+                lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
 
-                    if( pFcb != NULL &&
-                        pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
-                    {
+                AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
+                              pCurrentObject,
+                              lCount);
+            }
+        }
 
+        //
+        // Apply invalidation to all other volume objects
+        //
 
-                        //
-                        // Clear out the extents
-                        // And get rid of them (note this involves waiting
-                        // for any writes or reads to the cache to complete)
-                        //
+        AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
+                          TRUE);
 
-                        (VOID) AFSTearDownFcbExtents( pFcb,
-                                                      NULL);
-                    }
+        pCurrentObject = VolumeCB->ObjectInfoListHead;
 
-                    pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
-                }
+        if ( pCurrentObject)
+        {
 
-                AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
+            //
+            // Reference the node so it won't be torn down
+            //
 
-                break;
-            }
+            lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
 
-            default:
+            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
+                          pCurrentObject,
+                          lCount);
+        }
+
+        while( pCurrentObject != NULL)
+        {
+
+            pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
+
+            if ( pNextObject)
             {
 
                 //
-                // Indicate this node requires re-evaluation for the remaining reasons
+                // Reference the node so it won't be torn down
                 //
 
-                VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
+                lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                              VolumeCB->ObjectInformation.FileId.Cell,
-                              VolumeCB->ObjectInformation.FileId.Volume,
-                              VolumeCB->ObjectInformation.FileId.Vnode,
-                              VolumeCB->ObjectInformation.FileId.Unique);
-
-                SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY);
-
-                if( Reason == AFS_INVALIDATE_FLUSHED)
-                {
+                              "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
+                              pNextObject,
+                              lCount);
+            }
 
-                    VolumeCB->ObjectInformation.DataVersion.QuadPart = (ULONGLONG)-1;
-                }
+            AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
 
-                //
-                // Notify anyone that cares
-                //
+            AFSInvalidateObject( &pCurrentObject,
+                                 Reason);
 
-                ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
+            if ( pCurrentObject )
+            {
 
-                if( Reason == AFS_INVALIDATE_CREDS)
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
-                }
+                lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
 
-                if( Reason == AFS_INVALIDATE_DATA_VERSION ||
-                    Reason == AFS_INVALIDATE_FLUSHED)
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
-                }
-                else
-                {
-                    ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
-                }
+                AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
+                              pCurrentObject,
+                              lCount);
+            }
 
-                AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
-                                                NULL,
-                                                ulFilter,
-                                                FILE_ACTION_MODIFIED);
+            AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
+                              TRUE);
 
-                //
-                // Volume invalidations require all objects in the volume be re-verified
-                //
+            pCurrentObject = pNextObject;
+        }
 
-                AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
-                                  TRUE);
+        AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
+    }
 
-                pCurrentObject = VolumeCB->ObjectInfoListHead;
+    return ntStatus;
+}
 
-                while( pCurrentObject != NULL)
-                {
+VOID
+AFSInvalidateAllVolumes( VOID)
+{
+    AFSVolumeCB *pVolumeCB = NULL;
+    AFSVolumeCB *pNextVolumeCB = NULL;
+    AFSDeviceExt *pRDRDeviceExt = NULL;
+    LONG lCount;
 
-                    pCurrentObject->Expiration.QuadPart = 0;
+    pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
 
-                    pCurrentObject->TargetFileId.Vnode = 0;
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
+                  &pRDRDeviceExt->Specific.RDR.VolumeListLock,
+                  PsGetCurrentThread());
 
-                    pCurrentObject->TargetFileId.Unique = 0;
+    AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
+                      TRUE);
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                                  pCurrentObject->FileId.Cell,
-                                  pCurrentObject->FileId.Volume,
-                                  pCurrentObject->FileId.Vnode,
-                                  pCurrentObject->FileId.Unique);
+    pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
 
-                    SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
+    if ( pVolumeCB)
+    {
 
-                    if( Reason == AFS_INVALIDATE_FLUSHED)
-                    {
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
+                      pVolumeCB->ObjectInfoTree.TreeLock,
+                      PsGetCurrentThread());
 
-                        pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
-                    }
+        lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+    }
 
-                    if( Reason == AFS_INVALIDATE_FLUSHED &&
-                        pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
-                    {
+    while( pVolumeCB != NULL)
+    {
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSInvalidateVolume Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
-                                      pCurrentObject->FileId.Cell,
-                                      pCurrentObject->FileId.Volume,
-                                      pCurrentObject->FileId.Vnode,
-                                      pCurrentObject->FileId.Unique);
+        pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
 
-                        SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
-                    }
+        if ( pNextVolumeCB)
+        {
 
-                    if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
-                    {
-                        ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
-                    }
-                    else
-                    {
-                        ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
-                    }
+            lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
+        }
 
-                    if( Reason == AFS_INVALIDATE_CREDS)
-                    {
-                        ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
-                    }
+        AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
 
-                    if( Reason == AFS_INVALIDATE_DATA_VERSION ||
-                        Reason == AFS_INVALIDATE_FLUSHED)
-                    {
-                        ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
-                    }
-                    else
-                    {
-                        ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
-                    }
+        // do I need to hold the volume lock here?
 
-                    AFSFsRtlNotifyFullReportChange( pCurrentObject,
-                                                    NULL,
-                                                    ulFilter,
-                                                    FILE_ACTION_MODIFIED);
+        AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
 
-                    pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
-                }
+        AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
+                          TRUE);
 
-                AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
+        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
-                break;
-            }
-        }
+        pVolumeCB = pNextVolumeCB;
     }
 
-    return ntStatus;
+    AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
 }
 
 NTSTATUS
@@ -2763,7 +2790,7 @@ AFSVerifyEntry( IN GUID *AuthGroup,
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                   AFS_TRACE_LEVEL_ERROR,
-                                  "AFSInvalidateCache Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
+                                  "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
                                   &DirEntry->NameInformation.FileName,
                                   pObjectInfo->FileId.Cell,
                                   pObjectInfo->FileId.Volume,
@@ -4840,6 +4867,7 @@ AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
 {
 
     AFSNameArrayHdr *pNameArray = NULL;
+    AFSNameArrayCB *pCurrentElement = NULL;
     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
     LONG lCount;
 
@@ -4860,7 +4888,7 @@ AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
         if( pNameArray == NULL)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
                           "AFSInitNameArray Failed to allocate name array\n");
 
@@ -4876,9 +4904,13 @@ AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
         if( DirectoryCB != NULL)
         {
 
-            pNameArray->CurrentEntry = &pNameArray->ElementArray[ 0];
+            pCurrentElement = &pNameArray->ElementArray[ 0];
 
-            lCount = InterlockedIncrement( &pNameArray->Count);
+            pNameArray->CurrentEntry = pCurrentElement;
+
+            pNameArray->Count = 1;
+
+            pNameArray->LinkCount = 0;
 
             lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
 
@@ -4889,11 +4921,29 @@ AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
                           DirectoryCB,
                           lCount);
 
-            pNameArray->CurrentEntry->DirectoryCB = DirectoryCB;
+            pCurrentElement->DirectoryCB = DirectoryCB;
+
+            pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
+
+            pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
 
-            pNameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
+            if( pCurrentElement->FileId.Vnode == 1)
+            {
+
+                SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+            }
 
-            pNameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                          pNameArray,
+                          pCurrentElement->DirectoryCB,
+                          pCurrentElement->FileId.Cell,
+                          pCurrentElement->FileId.Volume,
+                          pCurrentElement->FileId.Vnode,
+                          pCurrentElement->FileId.Unique,
+                          &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                          pCurrentElement->DirectoryCB->ObjectInformation->FileType);
         }
 
 try_exit:
@@ -4922,6 +4972,19 @@ AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
     __Enter
     {
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      &Path,
+                      DirectoryCB,
+                      DirectoryCB->ObjectInformation->FileId.Cell,
+                      DirectoryCB->ObjectInformation->FileId.Volume,
+                      DirectoryCB->ObjectInformation->FileId.Vnode,
+                      DirectoryCB->ObjectInformation->FileId.Unique,
+                      &DirectoryCB->NameInformation.FileName,
+                      DirectoryCB->ObjectInformation->FileType);
+
         //
         // Init some info in the header
         //
@@ -4949,10 +5012,30 @@ AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
 
         pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
 
+        pCurrentElement->Flags = 0;
+
+        if( pCurrentElement->FileId.Vnode == 1)
+        {
+
+            SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+        }
+
         NameArray->Count = 1;
 
         NameArray->LinkCount = 0;
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      pCurrentElement->DirectoryCB,
+                      pCurrentElement->FileId.Cell,
+                      pCurrentElement->FileId.Volume,
+                      pCurrentElement->FileId.Vnode,
+                      pCurrentElement->FileId.Unique,
+                      &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                      pCurrentElement->DirectoryCB->ObjectInformation->FileType);
+
         //
         // If the root is the parent then we are done ...
         //
@@ -4988,6 +5071,19 @@ AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
     __Enter
     {
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      RelatedNameArray,
+                      DirectoryCB,
+                      DirectoryCB->ObjectInformation->FileId.Cell,
+                      DirectoryCB->ObjectInformation->FileId.Volume,
+                      DirectoryCB->ObjectInformation->FileId.Vnode,
+                      DirectoryCB->ObjectInformation->FileId.Unique,
+                      &DirectoryCB->NameInformation.FileName,
+                      DirectoryCB->ObjectInformation->FileType);
+
         //
         // Init some info in the header
         //
@@ -5013,6 +5109,14 @@ AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
 
             pCurrentElement->FileId    = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
 
+            pCurrentElement->Flags = 0;
+
+            if( pCurrentElement->FileId.Vnode == 1)
+            {
+
+                SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+            }
+
             lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
@@ -5024,6 +5128,19 @@ AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
 
             lCount = InterlockedIncrement( &NameArray->Count);
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                          NameArray,
+                          lCount - 1,
+                          pCurrentElement->DirectoryCB,
+                          pCurrentElement->FileId.Cell,
+                          pCurrentElement->FileId.Volume,
+                          pCurrentElement->FileId.Vnode,
+                          pCurrentElement->FileId.Unique,
+                          &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                          pCurrentElement->DirectoryCB->ObjectInformation->FileType);
+
             if( pCurrentElement->DirectoryCB == DirectoryCB ||
                 NameArray->Count == RelatedNameArray->Count)
             {
@@ -5040,10 +5157,7 @@ AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
             pCurrentRelatedElement++;
         }
 
-        if( NameArray->Count > 0)
-        {
-            NameArray->CurrentEntry = pCurrentElement;
-        }
+        NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
     }
 
     return ntStatus;
@@ -5055,21 +5169,20 @@ AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSNameArrayCB *pCurrentElement = NULL;
-    LONG lCount;
+    LONG lCount, lElement;
 
     __Enter
     {
 
-        pCurrentElement = &NameArray->ElementArray[ 0];
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSFreeNameArray [NA:%p]\n",
+                      NameArray);
 
-        while( TRUE)
+        for ( lElement = 0; lElement < NameArray->Count; lElement++)
         {
 
-            if( pCurrentElement->DirectoryCB == NULL)
-            {
-
-                break;
-            }
+            pCurrentElement = &NameArray->ElementArray[ lElement];
 
             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
 
@@ -5079,8 +5192,6 @@ AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
                           pCurrentElement->DirectoryCB,
                           lCount);
-
-            pCurrentElement++;
         }
 
         AFSExFreePool( NameArray);
@@ -5091,26 +5202,49 @@ AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
 
 NTSTATUS
 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
-                      IN AFSDirectoryCB *DirEntry)
+                      IN AFSDirectoryCB *DirectoryCB)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
+    AFSNameArrayCB *pCurrentElement = NULL;
     LONG lCount;
 
     __Enter
     {
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      DirectoryCB,
+                      DirectoryCB->ObjectInformation->FileId.Cell,
+                      DirectoryCB->ObjectInformation->FileId.Volume,
+                      DirectoryCB->ObjectInformation->FileId.Vnode,
+                      DirectoryCB->ObjectInformation->FileId.Unique,
+                      &DirectoryCB->NameInformation.FileName,
+                      DirectoryCB->ObjectInformation->FileType);
+
         if( NameArray->Count == NameArray->MaxElementCount)
         {
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
+                          NameArray);
+
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
 
         if( NameArray->CurrentEntry != NULL &&
-            NameArray->CurrentEntry->DirectoryCB == DirEntry)
+            NameArray->CurrentEntry->DirectoryCB == DirectoryCB)
         {
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInsertNextElement [NA:%p] DE %p already current element\n",
+                          NameArray,
+                          DirectoryCB);
+
             try_return( ntStatus);
         }
 
@@ -5124,22 +5258,45 @@ AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
             NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
         }
 
+        pCurrentElement = NameArray->CurrentEntry;
+
         lCount = InterlockedIncrement( &NameArray->Count);
 
-        lCount = InterlockedIncrement( &DirEntry->OpenReferenceCount);
+        lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
-                      &DirEntry->NameInformation.FileName,
-                      DirEntry,
+                      &DirectoryCB->NameInformation.FileName,
+                      DirectoryCB,
                       lCount);
 
-        NameArray->CurrentEntry->DirectoryCB = DirEntry;
+        pCurrentElement->DirectoryCB = DirectoryCB;
+
+        pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
+
+        pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
+
+        pCurrentElement->Flags = 0;
 
-        NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
+        if( pCurrentElement->FileId.Vnode == 1)
+        {
+
+            SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+        }
 
-        NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      NameArray->Count - 1,
+                      pCurrentElement->DirectoryCB,
+                      pCurrentElement->FileId.Cell,
+                      pCurrentElement->FileId.Volume,
+                      pCurrentElement->FileId.Vnode,
+                      pCurrentElement->FileId.Unique,
+                      &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                      pCurrentElement->DirectoryCB->ObjectInformation->FileType);
 
 try_exit:
 
@@ -5153,17 +5310,45 @@ void
 AFSReplaceCurrentElement( IN AFSNameArrayHdr *NameArray,
                           IN AFSDirectoryCB *DirectoryCB)
 {
+    AFSNameArrayCB *pCurrentElement = NULL;
     LONG lCount;
 
+    AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSReplaceCurrentElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                  NameArray,
+                  DirectoryCB,
+                  DirectoryCB->ObjectInformation->FileId.Cell,
+                  DirectoryCB->ObjectInformation->FileId.Volume,
+                  DirectoryCB->ObjectInformation->FileId.Vnode,
+                  DirectoryCB->ObjectInformation->FileId.Unique,
+                  &DirectoryCB->NameInformation.FileName,
+                  DirectoryCB->ObjectInformation->FileType);
+
     ASSERT( NameArray->CurrentEntry != NULL);
 
+    pCurrentElement = NameArray->CurrentEntry;
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSReplaceCurrentElement [NA:%p] Replacing Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                  NameArray,
+                  NameArray->Count - 1,
+                  pCurrentElement->DirectoryCB,
+                  pCurrentElement->FileId.Cell,
+                  pCurrentElement->FileId.Volume,
+                  pCurrentElement->FileId.Vnode,
+                  pCurrentElement->FileId.Unique,
+                  &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                  pCurrentElement->DirectoryCB->ObjectInformation->FileType);
+
     lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                   AFS_TRACE_LEVEL_VERBOSE,
                   "AFSReplaceCurrentElement Decrement count on %wZ DE %p Cnt %d\n",
-                  &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
-                  NameArray->CurrentEntry->DirectoryCB,
+                  &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                  pCurrentElement->DirectoryCB,
                   lCount);
 
     lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
@@ -5175,16 +5360,18 @@ AFSReplaceCurrentElement( IN AFSNameArrayHdr *NameArray,
                   DirectoryCB,
                   lCount);
 
-    NameArray->CurrentEntry->DirectoryCB = DirectoryCB;
+    pCurrentElement->DirectoryCB = DirectoryCB;
 
-    NameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
+    pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
 
-    NameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
+    pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
 
-    if( DirectoryCB->ObjectInformation->ParentObjectInformation == NULL)
+    pCurrentElement->Flags = 0;
+
+    if( pCurrentElement->FileId.Vnode == 1)
     {
 
-        SetFlag( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+        SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
     }
 
     return;
@@ -5194,15 +5381,27 @@ AFSDirectoryCB *
 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
 {
 
-    AFSDirectoryCB *pCurrentDirEntry = NULL;
+    AFSDirectoryCB *pDirectoryCB = NULL;
+    AFSNameArrayCB *pCurrentElement = NULL;
     LONG lCount;
 
     __Enter
     {
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSBackupEntry [NA:%p]\n",
+                      NameArray);
+
         if( NameArray->Count == 0)
         {
-            try_return( pCurrentDirEntry);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSBackupEntry [NA:%p] No more entries\n",
+                          NameArray);
+
+            try_return( pCurrentElement);
         }
 
         lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
@@ -5221,11 +5420,32 @@ AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
         if( lCount == 0)
         {
             NameArray->CurrentEntry = NULL;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSBackupEntry [NA:%p] No more entries\n",
+                          NameArray);
         }
         else
         {
             NameArray->CurrentEntry--;
-            pCurrentDirEntry = NameArray->CurrentEntry->DirectoryCB;
+
+            pCurrentElement = NameArray->CurrentEntry;
+
+            pDirectoryCB = pCurrentElement->DirectoryCB;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                          NameArray,
+                          NameArray->Count - 1,
+                          pCurrentElement->DirectoryCB,
+                          pCurrentElement->FileId.Cell,
+                          pCurrentElement->FileId.Volume,
+                          pCurrentElement->FileId.Vnode,
+                          pCurrentElement->FileId.Unique,
+                          &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                          pCurrentElement->DirectoryCB->ObjectInformation->FileType);
         }
 
 try_exit:
@@ -5233,7 +5453,7 @@ try_exit:
         NOTHING;
     }
 
-    return pCurrentDirEntry;
+    return pDirectoryCB;
 }
 
 AFSDirectoryCB *
@@ -5246,10 +5466,20 @@ AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
     __Enter
     {
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSGetParentEntry [NA:%p]\n",
+                      NameArray);
+
         if( NameArray->Count == 0 ||
             NameArray->Count == 1)
         {
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSGetParentEntry [NA:%p] No more entries\n",
+                          NameArray);
+
             try_return( pDirEntry = NULL);
         }
 
@@ -5257,6 +5487,19 @@ AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
 
         pDirEntry = pElement->DirectoryCB;
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      NameArray->Count - 2,
+                      pElement->DirectoryCB,
+                      pElement->FileId.Cell,
+                      pElement->FileId.Volume,
+                      pElement->FileId.Vnode,
+                      pElement->FileId.Unique,
+                      &pElement->DirectoryCB->NameInformation.FileName,
+                      pElement->DirectoryCB->ObjectInformation->FileType);
+
 try_exit:
 
         NOTHING;
@@ -5267,26 +5510,35 @@ try_exit:
 
 void
 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
-                   IN AFSDirectoryCB *DirEntry)
+                   IN AFSDirectoryCB *DirectoryCB)
 {
 
     AFSNameArrayCB *pCurrentElement = NULL;
     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
-    LONG lCount;
+    LONG lCount, lElement;
 
     __Enter
     {
 
-        pCurrentElement = &NameArray->ElementArray[ 0];
+        AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                      NameArray,
+                      DirectoryCB,
+                      DirectoryCB->ObjectInformation->FileId.Cell,
+                      DirectoryCB->ObjectInformation->FileId.Volume,
+                      DirectoryCB->ObjectInformation->FileId.Vnode,
+                      DirectoryCB->ObjectInformation->FileId.Unique,
+                      &DirectoryCB->NameInformation.FileName,
+                      DirectoryCB->ObjectInformation->FileType);
+        //
+        // Dereference previous name array contents
+        //
 
-        while( TRUE)
+        for ( lElement = 0; lElement < NameArray->Count; lElement++)
         {
 
-            if( pCurrentElement->DirectoryCB == NULL)
-            {
-
-                break;
-            }
+            pCurrentElement = &NameArray->ElementArray[ lElement];
 
             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
 
@@ -5296,8 +5548,6 @@ AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
                           pCurrentElement->DirectoryCB,
                           lCount);
-
-            pCurrentElement++;
         }
 
         RtlZeroMemory( NameArray,
@@ -5306,27 +5556,51 @@ AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
 
         NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
 
-        if( DirEntry != NULL)
+        if( DirectoryCB != NULL)
         {
 
-            NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
+            pCurrentElement = &NameArray->ElementArray[ 0];
 
-            lCount = InterlockedIncrement( &NameArray->Count);
+            NameArray->CurrentEntry = pCurrentElement;
+
+            NameArray->Count = 1;
+
+            NameArray->LinkCount = 0;
 
-            lCount = InterlockedIncrement( &DirEntry->OpenReferenceCount);
+            lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
-                          &DirEntry->NameInformation.FileName,
-                          DirEntry,
+                          &DirectoryCB->NameInformation.FileName,
+                          DirectoryCB,
                           lCount);
 
-            NameArray->CurrentEntry->DirectoryCB = DirEntry;
+            pCurrentElement->DirectoryCB = DirectoryCB;
+
+            pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
+
+            pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
+
+            pCurrentElement->Flags  = 0;
 
-            NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
+            if( pCurrentElement->FileId.Vnode == 1)
+            {
+
+                SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
+            }
 
-            NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
+            AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
+                          NameArray,
+                          pCurrentElement->DirectoryCB,
+                          pCurrentElement->FileId.Cell,
+                          pCurrentElement->FileId.Volume,
+                          pCurrentElement->FileId.Vnode,
+                          pCurrentElement->FileId.Unique,
+                          &pCurrentElement->DirectoryCB->NameInformation.FileName,
+                          pCurrentElement->DirectoryCB->ObjectInformation->FileType);
         }
     }
 
@@ -5374,25 +5648,10 @@ AFSSetEnumerationEvent( IN AFSFcb *Fcb)
     {
 
         case AFS_DIRECTORY_FCB:
-        {
-
-            KeSetEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
-                        0,
-                        FALSE);
-
-            lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
-
-            break;
-        }
-
         case AFS_ROOT_FCB:
         case AFS_ROOT_ALL:
         {
 
-            KeSetEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
-                        0,
-                        FALSE);
-
             lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
 
             break;
@@ -5416,21 +5675,6 @@ AFSClearEnumerationEvent( IN AFSFcb *Fcb)
     {
 
         case AFS_DIRECTORY_FCB:
-        {
-
-            ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
-
-            lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
-
-            if( lCount == 0)
-            {
-
-                KeClearEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent);
-            }
-
-            break;
-        }
-
         case AFS_ROOT_FCB:
         case AFS_ROOT_ALL:
         {
@@ -5439,12 +5683,6 @@ AFSClearEnumerationEvent( IN AFSFcb *Fcb)
 
             lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
 
-            if( lCount == 0)
-            {
-
-                KeClearEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent);
-            }
-
             break;
         }
     }
@@ -5467,30 +5705,15 @@ AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
             try_return( bIsInProcess);
         }
 
-        //
-        // Depending on the type of node, set the event
-        //
-
         switch( ObjectInfo->Fcb->Header.NodeTypeCode)
         {
 
             case AFS_DIRECTORY_FCB:
-            {
-
-                if( KeReadStateEvent( &ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent))
-                {
-
-                    bIsInProcess = TRUE;
-                }
-
-                break;
-            }
-
             case AFS_ROOT_FCB:
             case AFS_ROOT_ALL:
             {
 
-                if( KeReadStateEvent( &ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent))
+                if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
                 {
 
                     bIsInProcess = TRUE;
@@ -5528,6 +5751,7 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
     AFSDirectoryCB *pDirNode = NULL;
     ULONG ulEntryLength = 0;
     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
+    LONG lCount;
 
     __Enter
     {
@@ -5609,11 +5833,33 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
                                                                        TRUE);
 
-        ObjectInfo->Specific.Directory.PIOCtlDirectoryCB = pDirNode;
+        if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %08lX pFcb %08lX\n",
+                          ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
+                          pDirNode);
+
+            //
+            // Increment the open reference and handle on the node
+            //
+
+            lCount = InterlockedIncrement( &pDirNode->ObjectInformation->ObjectReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitPIOCtlDirectoryCB Increment count on Object %08lX Cnt %d\n",
+                          pDirNode->ObjectInformation,
+                          lCount);
+
+            try_return( ntStatus = STATUS_REPARSE);
+        }
 
 try_exit:
 
-        if ( !NT_SUCCESS( ntStatus))
+        if ( ntStatus != STATUS_SUCCESS)
         {
 
             if ( pDirNode != NULL)
@@ -7479,6 +7725,13 @@ AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
 
         //
+        // Invalidate all known volumes since contact with the service and therefore
+        // the file server was lost.
+        //
+
+        AFSInvalidateAllVolumes();
+
+        //
         // Drop the locks acquired above
         //
 
@@ -8568,6 +8821,9 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
                 LARGE_INTEGER liCurrentOffset = {0,0};
                 LARGE_INTEGER liFlushLength = {0,0};
                 ULONG ulFlushLength = 0;
+                BOOLEAN bLocked = FALSE;
+                BOOLEAN bExtentsLocked = FALSE;
+                BOOLEAN bCleanExtents = FALSE;
 
                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
                     ObjectInfo->Fcb != NULL)
@@ -8576,101 +8832,290 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
                                     TRUE);
 
-                    AFSLockForExtentsTrim( ObjectInfo->Fcb);
+                    bLocked = TRUE;
 
-                    __try
-                    {
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSPerformObjectInvalidate Acquiring Fcb extents lock %08lX SHARED %08lX\n",
+                                  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                  PsGetCurrentThread());
 
-                        le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+                    AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                      TRUE);
 
-                        ulProcessCount = 0;
+                    bExtentsLocked = TRUE;
 
-                        ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
+                    //
+                    // There are several possibilities here:
+                    //
+                    // 0. If there are no extents or all of the extents are dirty, do nothing.
+                    //
+                    // 1. There could be nothing dirty and an open reference count of zero
+                    //    in which case we can just tear down all of the extents without
+                    //    holding any resources.
+                    //
+                    // 2. There could be nothing dirty and a non-zero open reference count
+                    //    in which case we can issue a CcPurge against the entire file
+                    //    while holding just the Fcb Resource.
+                    //
+                    // 3. There can be dirty extents in which case we need to identify
+                    //    the non-dirty ranges and then perform a CcPurge on just the
+                    //    non-dirty ranges while holding just the Fcb Resource.
+                    //
+
+                    if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
+                    {
 
-                        if( ulCount > 0)
+                        if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
                         {
-                            pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
 
-                            while( ulProcessCount < ulCount)
+                            if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
                             {
-                                pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
 
-                                if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
+
+                                bExtentsLocked = FALSE;
+
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
+
+                                bLocked = FALSE;
+
+                                (VOID) AFSTearDownFcbExtents( ObjectInfo->Fcb,
+                                                              NULL);
+                            }
+                            else
+                            {
+
+                                __try
                                 {
+
+                                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
+
+                                    bExtentsLocked = FALSE;
+
                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                              &pEntry->FileOffset,
-                                                              pEntry->Size,
+                                                              NULL,
+                                                              0,
                                                               FALSE))
                                     {
                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
                                     }
+                                    else
+                                    {
+
+                                        bCleanExtents = TRUE;
+                                    }
+                                }
+                                __except( EXCEPTION_EXECUTE_HANDLER)
+                                {
+
+                                    ntStatus = GetExceptionCode();
+
+                                    AFSDbgLogMsg( 0,
+                                                  0,
+                                                  "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
+                                                  ntStatus);
                                 }
+                            }
+                        }
+                        else
+                        {
+
+                            //
+                            // Must build a list of non-dirty ranges from the beginning of the file
+                            // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
+                            // ranges.  In all but the most extreme random data write scenario there will
+                            // be significantly fewer.
+                            //
+                            // For each range we need offset and size.
+                            //
+
+                            AFSByteRange * ByteRangeList = NULL;
+                            ULONG          ulByteRangeCount = 0;
+                            ULONG          ulIndex;
+                            BOOLEAN        bPurgeOnClose = FALSE;
+
+                            __try
+                            {
+
+                                ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
+                                                                                   &ByteRangeList);
 
-                                if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
+                                if ( ByteRangeList != NULL ||
+                                     ulByteRangeCount == 0)
                                 {
 
-                                    liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
+                                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
 
-                                    while( liFlushLength.QuadPart > 0)
+                                    bExtentsLocked = FALSE;
+
+                                    for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
                                     {
 
-                                        if( liFlushLength.QuadPart > 512 * 1024000)
-                                        {
-                                            ulFlushLength = 512 * 1024000;
-                                        }
-                                        else
+                                        ULONG ulSize;
+
+                                        do {
+
+                                            ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
+
+                                            if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                      &ByteRangeList[ulIndex].FileOffset,
+                                                                      ulSize,
+                                                                      FALSE))
+                                            {
+
+                                                bPurgeOnClose = TRUE;
+                                            }
+                                            else
+                                            {
+
+                                                bCleanExtents = TRUE;
+                                            }
+
+                                            ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
+
+                                            ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
+
+                                        } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
+                                    }
+                                }
+                                else
+                                {
+
+                                    //
+                                    // We couldn't allocate the memory to build the purge list
+                                    // so just walk the extent list while holding the ExtentsList Resource.
+                                    // This could deadlock but we do not have much choice.
+                                    //
+
+                                    le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+
+                                    ulProcessCount = 0;
+
+                                    ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
+
+                                    if( ulCount > 0)
+                                    {
+                                        pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
+
+                                        while( ulProcessCount < ulCount)
                                         {
-                                            ulFlushLength = liFlushLength.LowPart;
+                                            pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
+
+                                            if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
+                                            {
+                                                if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                          &pEntry->FileOffset,
+                                                                          pEntry->Size,
+                                                                          FALSE))
+                                                {
+
+                                                    bPurgeOnClose = TRUE;
+                                                }
+                                                else
+                                                {
+
+                                                    bCleanExtents = TRUE;
+                                                }
+                                            }
+
+                                            if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
+                                            {
+
+                                                liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
+
+                                                while( liFlushLength.QuadPart > 0)
+                                                {
+
+                                                    if( liFlushLength.QuadPart > 512 * 1024000)
+                                                    {
+                                                        ulFlushLength = 512 * 1024000;
+                                                    }
+                                                    else
+                                                    {
+                                                        ulFlushLength = liFlushLength.LowPart;
+                                                    }
+
+                                                    if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                              &liCurrentOffset,
+                                                                              ulFlushLength,
+                                                                              FALSE))
+                                                    {
+
+                                                        bPurgeOnClose = TRUE;
+                                                    }
+                                                    else
+                                                    {
+
+                                                        bCleanExtents = TRUE;
+                                                    }
+
+                                                    liFlushLength.QuadPart -= ulFlushLength;
+                                                }
+                                            }
+
+                                            liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
+
+                                            ulProcessCount++;
+                                            le = le->Flink;
                                         }
-
+                                    }
+                                    else
+                                    {
                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                                  &liCurrentOffset,
-                                                                  ulFlushLength,
+                                                                  NULL,
+                                                                  0,
                                                                   FALSE))
                                         {
-                                            SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+
+                                            bPurgeOnClose = TRUE;
                                         }
+                                        else
+                                        {
 
-                                        liFlushLength.QuadPart -= ulFlushLength;
+                                            bCleanExtents = TRUE;
+                                        }
                                     }
-                                }
 
-                                liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
+                                    if ( bPurgeOnClose)
+                                    {
 
-                                ulProcessCount++;
-                                le = le->Flink;
+                                        SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                                    }
+                                }
                             }
-                        }
-                        else
-                        {
-                            if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                      NULL,
-                                                      0,
-                                                      FALSE))
+                            __except( EXCEPTION_EXECUTE_HANDLER)
                             {
-                                SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+
+                                ntStatus = GetExceptionCode();
+
+                                AFSDbgLogMsg( 0,
+                                              0,
+                                              "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
+                                              ntStatus);
                             }
                         }
                     }
-                    __except( EXCEPTION_EXECUTE_HANDLER)
+
+                    if ( bExtentsLocked)
                     {
 
-                        ntStatus = GetExceptionCode();
+                        AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
                     }
 
-                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
-
-                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
+                    if ( bLocked)
+                    {
 
-                    AFSReleaseCleanExtents( ObjectInfo->Fcb,
-                                            NULL);
-                }
+                        AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
+                    }
 
-                break;
-            }
+                    if ( bCleanExtents)
+                    {
 
-            default:
-            {
+                        AFSReleaseCleanExtents( ObjectInfo->Fcb,
+                                                NULL);
+                    }
+                }
 
                 break;
             }