Windows: AFSCleanup Flush Data decision
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.cpp
index 527c675..3e370ab 100644 (file)
@@ -65,8 +65,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
     AFSDeviceExt *pControlDeviceExt = NULL;
     IO_STATUS_BLOCK stIoSB;
     AFSObjectInfoCB *pObjectInfo = NULL;
+    AFSObjectInfoCB *pParentObjectInfo = NULL;
     AFSFileCleanupCB stFileCleanup;
+    AFSFileCleanupResultCB *pResultCB = NULL;
+    ULONG ulResultLen = 0;
     ULONG   ulNotificationFlags = 0;
+    LONG    lCount;
 
     __try
     {
@@ -82,6 +86,7 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
         }
 
         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+
         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
 
         //
@@ -111,6 +116,26 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
         stFileCleanup.Identifier = (ULONGLONG)pFileObject;
 
         //
+        // Allocate our return buffer
+        //
+
+        pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                        PAGE_SIZE,
+                                                                        AFS_GENERIC_MEMORY_32_TAG);
+
+        if( pResultCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pResultCB,
+                       PAGE_SIZE);
+
+        ulResultLen = PAGE_SIZE;
+
+
+        //
         // Perform the cleanup functionality depending on the type of node it is
         //
 
@@ -131,15 +156,15 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
-
-                AFSReleaseResource( &pFcb->NPFcb->Resource);
+                              lCount);
 
                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
@@ -162,14 +187,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
-                              pFcb,
-                              pFcb->OpenHandleCount);
-
                 //
                 // Decrement the open child handle count
                 //
@@ -178,21 +195,25 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                 {
 
-                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                    lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                   pObjectInfo->ParentObjectInformation,
-                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                                  lCount);
                 }
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -217,6 +238,46 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                 TRUE);
 
                 //
+                // If the handle has write permission ...
+                //
+
+                if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
+                    CcIsFileCached( pIrpSp->FileObject))
+                {
+
+                    __try
+                    {
+
+                        CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
+                                      NULL,
+                                      0,
+                                      &stIoSB);
+
+                        if( !NT_SUCCESS( stIoSB.Status))
+                        {
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                                          AFS_TRACE_LEVEL_ERROR,
+                                          "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
+                                          &pCcb->FullFileName,
+                                          pObjectInfo->FileId.Cell,
+                                          pObjectInfo->FileId.Volume,
+                                          pObjectInfo->FileId.Vnode,
+                                          pObjectInfo->FileId.Unique,
+                                          stIoSB.Status,
+                                          stIoSB.Information);
+
+                            ntStatus = stIoSB.Status;
+                        }
+                    }
+                    __except( EXCEPTION_EXECUTE_HANDLER)
+                    {
+
+                        ntStatus = GetExceptionCode();
+                    }
+                }
+
+                //
                 // Uninitialize the cache map. This call is unconditional.
                 //
 
@@ -251,14 +312,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
-                              pFcb,
-                              pFcb->OpenHandleCount);
-
                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                 {
 
@@ -314,11 +367,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 }
 
                 //
-                // If the count has dropped to zero and there is a pending delete
-                // then delete the node
+                // If the count has dropped to one and there is a pending delete
+                // then delete the node.  The final count will be decremented just
+                // before the Fcb->NPFcb->Resource is released.
                 //
 
-                if( pFcb->OpenHandleCount == 0 &&
+                if( pFcb->OpenHandleCount == 1 &&
                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                 {
 
@@ -332,29 +386,30 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
                                   PsGetCurrentThread());
 
-                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                    AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
                                     TRUE);
 
-                    pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
+                    pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
 
-                    KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
+                    KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
                                 0,
                                 FALSE);
 
+                    //
+                    // Before telling the server about the deleted file, tear down all extents for
+                    // the file
+                    //
+
+                    AFSTearDownFcbExtents( pFcb,
+                                           &pCcb->AuthGroup);
+
                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
                                   PsGetCurrentThread());
 
-                    AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
-
-                    //
-                    // Before telling the server about the deleted file, tear down all extents for
-                    // the file
-                    //
-
-                    AFSTearDownFcbExtents( pFcb);
+                    AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
 
                     ntStatus = STATUS_SUCCESS;
 
@@ -372,13 +427,13 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                                  &pFcb->AuthGroup,
+                                                  &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -407,12 +462,27 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
 
-                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        ASSERT( pParentObjectInfo != NULL);
+
+                        AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+
+                            pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -422,19 +492,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                            TRUE);
-
                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                           AFS_TRACE_LEVEL_VERBOSE,
                                           "AFSCleanup DE %p for %wZ removing entry\n",
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
 
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                            AFSRemoveNameEntry( pParentObjectInfo,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -445,6 +510,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
                 else
@@ -466,57 +539,22 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     }
 
                     //
-                    // Flush out any dirty pages on every handle close to reduce strain on the afs cache
-                    //
-
-                    if( CcIsFileCached( pIrpSp->FileObject))
-                    {
-
-                        __try
-                        {
-
-                            CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
-                                          NULL,
-                                          0,
-                                          &stIoSB);
-
-                            if( !NT_SUCCESS( stIoSB.Status))
-                            {
-
-                                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
-                                              AFS_TRACE_LEVEL_ERROR,
-                                              "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
-                                              &pCcb->FullFileName,
-                                              pObjectInfo->FileId.Cell,
-                                              pObjectInfo->FileId.Volume,
-                                              pObjectInfo->FileId.Vnode,
-                                              pObjectInfo->FileId.Unique,
-                                              stIoSB.Status,
-                                              stIoSB.Information);
-
-                                ntStatus = stIoSB.Status;
-                            }
-                        }
-                        __except( EXCEPTION_EXECUTE_HANDLER)
-                        {
-
-                            ntStatus = GetExceptionCode();
-                        }
-                    }
-
-                    //
                     // Attempt to flush any dirty extents to the server. This may be a little
                     // aggressive, to flush whenever the handle is closed, but it ensures
                     // coherency.
                     //
 
-                    if( pFcb->Specific.File.ExtentsDirtyCount)
+                    if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
+                        pFcb->Specific.File.ExtentsDirtyCount != 0)
                     {
 
-                        AFSFlushExtents( pFcb);
+                        AFSFlushExtents( pFcb,
+                                         &pCcb->AuthGroup);
+
+                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
                     }
 
-                    if( pFcb->OpenHandleCount == 0)
+                    if( pFcb->OpenHandleCount == 1)
                     {
 
                         //
@@ -525,7 +563,8 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         AFSWaitOnQueuedFlushes( pFcb);
 
-                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
+                        AFSTearDownFcbExtents( pFcb,
+                                               &pCcb->AuthGroup);
                     }
 
                     //
@@ -538,15 +577,40 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     // Push the request to the service
                     //
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pFcb->AuthGroup,
-                                       &pCcb->DirectoryCB->NameInformation.FileName,
-                                       &pObjectInfo->FileId,
-                                       &stFileCleanup,
-                                       sizeof( AFSFileCleanupCB),
-                                       NULL,
-                                       NULL);
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pCcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
+
+                    if ( NT_SUCCESS( ntStatus))
+                    {
+
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        if ( pParentObjectInfo != NULL)
+                        {
+
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
+
+                            if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -572,26 +636,46 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                if( pParentObjectInfo != NULL)
                 {
 
-                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+                    ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
 
-                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                    lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
-                                  pObjectInfo->ParentObjectInformation,
-                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                                  pParentObjectInfo,
+                                  lCount);
                 }
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
+                {
+                    //
+                    // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
+                    //
+
+                    AFSObjectInfoIncrement( pObjectInfo);
+
+                    ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+
+                    AFSPerformObjectInvalidate( pObjectInfo,
+                                                AFS_INVALIDATE_DATA_VERSION);
+                }
+
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -635,14 +719,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
-                              pFcb,
-                              pFcb->OpenHandleCount);
-
                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                 {
 
@@ -682,11 +758,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 }
 
                 //
-                // If the count has dropped to zero and there is a pending delete
-                // then delete the node
+                // If the count has dropped to one and there is a pending delete
+                // then delete the node.  The final count will be decremented just
+                // before the Fcb->NPFcb->Resource is released.
                 //
 
-                if( pFcb->OpenHandleCount == 0 &&
+                if( pFcb->OpenHandleCount == 1 &&
                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                 {
 
@@ -708,13 +785,13 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                                  &pFcb->AuthGroup,
+                                                  &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -743,12 +820,27 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
 
-                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        ASSERT( pParentObjectInfo != NULL);
+
+                        AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+
+                            pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -758,13 +850,8 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                            TRUE);
-
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                            AFSRemoveNameEntry( pParentObjectInfo,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -775,6 +862,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
 
@@ -793,12 +888,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
 
-                        if(  pObjectInfo->ParentObjectInformation != NULL)
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        if(  pParentObjectInfo != NULL)
                         {
 
                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
 
-                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                            AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
                                                             pCcb,
                                                             (ULONG)ulNotifyFilter,
                                                             (ULONG)FILE_ACTION_MODIFIED);
@@ -811,15 +908,40 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     stFileCleanup.FileAccess = pCcb->FileAccess;
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pFcb->AuthGroup,
-                                       &pCcb->DirectoryCB->NameInformation.FileName,
-                                       &pObjectInfo->FileId,
-                                       &stFileCleanup,
-                                       sizeof( AFSFileCleanupCB),
-                                       NULL,
-                                       NULL);
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pCcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
+
+                    if ( NT_SUCCESS( ntStatus))
+                    {
+
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        if ( pParentObjectInfo != NULL)
+                        {
+
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                              TRUE);
+
+                            if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -853,32 +975,39 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                if( pParentObjectInfo != NULL)
                 {
 
-                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+                    ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
 
-                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                    lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
-                                  pObjectInfo->ParentObjectInformation,
-                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                                  pParentObjectInfo,
+                                  lCount);
                 }
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
             case AFS_SYMBOLIC_LINK_FCB:
             case AFS_MOUNT_POINT_FCB:
             case AFS_DFS_LINK_FCB:
+            case AFS_INVALID_FCB:
             {
 
                 //
@@ -900,14 +1029,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
-                              pFcb,
-                              pFcb->OpenHandleCount);
-
                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                 {
 
@@ -947,11 +1068,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 }
 
                 //
-                // If the count has dropped to zero and there is a pending delete
-                // then delete the node
+                // If the count has dropped to one and there is a pending delete
+                // then delete the node.  The final count will be decremented just
+                // before the Fcb->NPFcb->Resource is released.
                 //
 
-                if( pFcb->OpenHandleCount == 0 &&
+                if( pFcb->OpenHandleCount == 1 &&
                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                 {
 
@@ -973,13 +1095,13 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                                  &pFcb->AuthGroup,
+                                                  &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -1008,12 +1130,26 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
 
-                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        ASSERT( pParentObjectInfo != NULL);
+
+                        AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+                            pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -1023,13 +1159,8 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                            TRUE);
-
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                            AFSRemoveNameEntry( pParentObjectInfo,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -1040,6 +1171,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
 
@@ -1058,12 +1197,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
 
-                        if(  pObjectInfo->ParentObjectInformation != NULL)
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        if(  pParentObjectInfo != NULL)
                         {
 
                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
 
-                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                            AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
                                                             pCcb,
                                                             (ULONG)ulNotifyFilter,
                                                             (ULONG)FILE_ACTION_MODIFIED);
@@ -1076,15 +1217,40 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     stFileCleanup.FileAccess = pCcb->FileAccess;
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pFcb->AuthGroup,
-                                       &pCcb->DirectoryCB->NameInformation.FileName,
-                                       &pObjectInfo->FileId,
-                                       &stFileCleanup,
-                                       sizeof( AFSFileCleanupCB),
-                                       NULL,
-                                       NULL);
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pCcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
+
+                    if ( NT_SUCCESS( ntStatus))
+                    {
+
+                        pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                        if ( pParentObjectInfo != NULL)
+                        {
+
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                              TRUE);
+
+                            if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -1110,26 +1276,32 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                if( pParentObjectInfo != NULL)
                 {
 
-                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+                    ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
 
-                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                    lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
-                                  pObjectInfo->ParentObjectInformation,
-                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                                  pParentObjectInfo,
+                                  lCount);
                 }
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -1147,37 +1319,35 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
-                              pFcb,
-                              pFcb->OpenHandleCount);
-
                 //
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL &&
-                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+                pParentObjectInfo = pObjectInfo->ParentObjectInformation;
+
+                if( pParentObjectInfo != NULL &&
+                    pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
                 {
 
-                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                    lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
-                                  pObjectInfo->ParentObjectInformation,
-                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                                  pParentObjectInfo,
+                                  lCount);
                 }
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -1194,6 +1364,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
 try_exit:
 
+        if( pResultCB != NULL)
+        {
+
+            AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
+        }
+
         if( pFileObject != NULL)
         {
 
@@ -1210,12 +1386,14 @@ try_exit:
 
         AFSCompleteRequest( Irp, ntStatus);
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSCleanup\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;