windows: ObjectInformationCB.ObjectReferenceCount
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.cpp
index 527c675..77bf7e9 100644 (file)
@@ -66,7 +66,10 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
     IO_STATUS_BLOCK stIoSB;
     AFSObjectInfoCB *pObjectInfo = NULL;
     AFSFileCleanupCB stFileCleanup;
+    AFSFileCleanupResultCB *pResultCB = NULL;
+    ULONG ulResultLen = 0;
     ULONG   ulNotificationFlags = 0;
+    LONG    lCount;
 
     __try
     {
@@ -111,6 +114,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 +154,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 +185,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 +193,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 +236,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 +310,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 +365,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))
                 {
 
@@ -354,7 +406,8 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     // the file
                     //
 
-                    AFSTearDownFcbExtents( pFcb);
+                    AFSTearDownFcbExtents( pFcb,
+                                           &pCcb->AuthGroup);
 
                     ntStatus = STATUS_SUCCESS;
 
@@ -372,13 +425,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)
@@ -409,10 +462,21 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -422,9 +486,6 @@ 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",
@@ -433,8 +494,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                             AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -445,6 +504,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
                 else
@@ -466,57 +533,20 @@ 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);
                     }
 
-                    if( pFcb->OpenHandleCount == 0)
+                    if( pFcb->OpenHandleCount == 1)
                     {
 
                         //
@@ -538,15 +568,38 @@ 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))
+                    {
+
+                        if ( pObjectInfo->ParentObjectInformation != NULL)
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
+
+                            if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -577,21 +630,35 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ASSERT( 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 (File) 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);
 
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
+                {
+                    InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+
+                    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 +702,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 +741,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 +768,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)
@@ -745,10 +805,21 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -758,13 +829,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,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -775,6 +841,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
 
@@ -811,15 +885,38 @@ 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))
+                    {
+
+                        if ( pObjectInfo->ParentObjectInformation != NULL)
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                              TRUE);
+
+                            if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -858,27 +955,32 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ASSERT( 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 (Dir) 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 (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 +1002,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 +1041,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 +1068,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)
@@ -1010,10 +1105,20 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
+
+                        if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                        {
+
+                            SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                        }
+                        else
+                        {
+                            pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                        }
 
                         //
                         // Now that the service has the entry has deleted we need to remove it from the parent
@@ -1023,13 +1128,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,
                                                 pCcb->DirectoryCB);
-
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                         }
                         else
                         {
@@ -1040,6 +1140,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pCcb->DirectoryCB,
                                           &pCcb->DirectoryCB->NameInformation.FileName);
                         }
+
+                        AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
                     }
                 }
 
@@ -1076,15 +1184,38 @@ 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))
+                    {
+
+                        if ( pObjectInfo->ParentObjectInformation != NULL)
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                              TRUE);
+
+                            if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
+                            {
+
+                                SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+
+                    ntStatus = STATUS_SUCCESS;
                 }
 
                 //
@@ -1115,21 +1246,25 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     ASSERT( 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 (MP/SL) 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 (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -1147,14 +1282,6 @@ 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
                 //
@@ -1163,21 +1290,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 (Share) 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 (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              lCount);
+
                 break;
             }
 
@@ -1194,6 +1325,12 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
 try_exit:
 
+        if( pResultCB != NULL)
+        {
+
+            AFSExFreePool( pResultCB);
+        }
+
         if( pFileObject != NULL)
         {