Windows: Adjust Last Write time handling for -1
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.cpp
index 70ceb02..3361a9b 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
- * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Your File System, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * - Redistributions of source code must retain the above copyright notice,
  *   this list of conditions and the following disclaimer.
  * - Redistributions in binary form must reproduce the above copyright
- *   notice,
- *   this list of conditions and the following disclaimer in the
- *   documentation
- *   and/or other materials provided with the distribution.
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
  *   nor the names of their contributors may be used to endorse or promote
  *   products derived from this software without specific prior written
@@ -54,7 +52,7 @@ NTSTATUS
 AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
             IN PIRP Irp)
 {
-
+    UNREFERENCED_PARAMETER(LibDeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDeviceExt = NULL;
     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
@@ -65,8 +63,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 +84,7 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
         }
 
         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+
         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
 
         //
@@ -101,6 +104,14 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
         pObjectInfo = pFcb->ObjectInformation;
 
+        if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
+        {
+
+            pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
+                                                   &pObjectInfo->ParentFileId,
+                                                   FALSE);
+        }
+
         pRootFcb = pObjectInfo->VolumeCB->RootFcb;
 
         RtlZeroMemory( &stFileCleanup,
@@ -111,6 +122,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
         //
 
@@ -120,42 +151,42 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
             case AFS_ROOT_ALL:
             {
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
+                              "AFSCleanup Acquiring GlobalRoot lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              PsGetCurrentThread()));
 
                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                   TRUE);
 
+                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
+                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
+                                    pCcb);
+
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (RootAll) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
+                              lCount));
 
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
-                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
-                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
-                                    pCcb);
-
                 break;
             }
 
             case AFS_IOCTL_FCB:
             {
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
+                              "AFSCleanup Acquiring PIOCtl lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              PsGetCurrentThread()));
 
                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                   TRUE);
@@ -166,32 +197,28 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL &&
-                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+                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,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_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);
+                                  "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %p Cnt %d\n",
+                                  pParentObjectInfo,
+                                  lCount));
                 }
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
-
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
-
-                AFSReleaseResource( &pFcb->NPFcb->Resource);
+                              lCount));
 
                 break;
             }
@@ -207,24 +234,34 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                 //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+
+               AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                             AFS_TRACE_LEVEL_VERBOSE,
+                             "AFSCleanup Acquiring Fcb lock %p EXCL %08lX\n",
+                             &pFcb->NPFcb->Resource,
+                             PsGetCurrentThread()));
+
+               AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                               TRUE);
+
+               AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
-                              &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              "AFSCleanup Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread()));
 
-                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
                                 TRUE);
 
-                //
-                // If the handle has write permission ...
-                //
-
-                if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
-                    CcIsFileCached( pIrpSp->FileObject))
+               __try
                 {
 
-                    __try
+                   //
+                   // If the handle has write permission ...
+                   //
+
+                   if( ((pCcb->GrantedAccess & FILE_WRITE_DATA) || pFcb->OpenHandleCount == 1) &&
+                       CcIsFileCached( pIrpSp->FileObject))
                     {
 
                         CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
@@ -235,7 +272,7 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                         if( !NT_SUCCESS( stIoSB.Status))
                         {
 
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                            AFSDbgTrace(( 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,
@@ -244,31 +281,77 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                           pObjectInfo->FileId.Vnode,
                                           pObjectInfo->FileId.Unique,
                                           stIoSB.Status,
-                                          stIoSB.Information);
+                                          stIoSB.Information));
 
                             ntStatus = stIoSB.Status;
                         }
-                    }
-                    __except( EXCEPTION_EXECUTE_HANDLER)
-                    {
 
-                        ntStatus = GetExceptionCode();
+                        if ( ( pFcb->OpenHandleCount == 1 ||
+                               BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE)) &&
+                             pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
+                        {
+
+                            if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
+                                                       NULL,
+                                                       0,
+                                                       FALSE))
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                              AFS_TRACE_LEVEL_WARNING,
+                                              "AFSCleanup CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                              pObjectInfo->FileId.Cell,
+                                              pObjectInfo->FileId.Volume,
+                                              pObjectInfo->FileId.Vnode,
+                                              pObjectInfo->FileId.Unique));
+
+                                SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                            }
+                            else
+                            {
+                                ClearFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                            }
+                        }
                     }
-                }
 
-                //
-                // Uninitialize the cache map. This call is unconditional.
-                //
+                   //
+                   // Uninitialize the cache map. This call is unconditional.
+                   //
+
+                   AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                 AFS_TRACE_LEVEL_VERBOSE,
+                                 "AFSCleanup Tearing down cache map for Fcb %p FileObject %p\n",
+                                 pFcb,
+                                 pFileObject));
+
+                   CcUninitializeCacheMap( pFileObject,
+                                           NULL,
+                                           NULL);
+               }
+               __except( EXCEPTION_EXECUTE_HANDLER)
+               {
+
+                   ntStatus = GetExceptionCode();
+
+                   AFSDbgTrace(( 0,
+                                 0,
+                                 "EXCEPTION - AFSCleanup Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
+                                 pObjectInfo->FileId.Cell,
+                                 pObjectInfo->FileId.Volume,
+                                 pObjectInfo->FileId.Vnode,
+                                 pObjectInfo->FileId.Unique,
+                                 ntStatus));
+
+                   SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                }
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+               AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
-                              pFcb,
-                              pFileObject);
+                              "AFSCleanup Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread()));
 
-                CcUninitializeCacheMap( pFileObject,
-                                        NULL,
-                                        NULL);
+                AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
 
                 //
                 // Unlock all outstanding locks on the file, again, unconditionally
@@ -291,14 +374,29 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                if( pParentObjectInfo != NULL)
                 {
 
-                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                    stFileCleanup.ParentId = pParentObjectInfo->FileId;
                 }
 
                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
 
+               //
+               // If the file has been modified set the last write time in ObjectInfo to 'now'
+               // unless the last write time was set via this File Object.  Then tell the
+               // following code to write the time.
+               //
+               if ( BooleanFlagOn( pFileObject->Flags, FO_FILE_MODIFIED) &&
+                    !BooleanFlagOn( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET)) {
+
+                   SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+
+                   SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
+
+                   KeQuerySystemTime(&pFcb->ObjectInformation->LastWriteTime);
+               }
+
                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                 {
 
@@ -335,16 +433,10 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
 
-                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
+                       ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
                     }
                 }
 
-                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
-                {
-
-                    stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
-                }
-
                 //
                 // If the count has dropped to one and there is a pending delete
                 // then delete the node.  The final count will be decremented just
@@ -355,41 +447,6 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                 {
 
-                    //
-                    // Stop anything possibly in process
-                    //
-
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
-                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
-                                  PsGetCurrentThread());
-
-                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
-                                    TRUE);
-
-                    pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
-
-                    KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
-                                0,
-                                FALSE);
-
-                    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,
-                                           &pCcb->AuthGroup);
-
                     ntStatus = STATUS_SUCCESS;
 
                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
@@ -409,20 +466,22 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                                   &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                     {
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_ERROR,
                                       "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
                                       &pCcb->FullFileName,
-                                      ntStatus);
+                                      ntStatus));
 
                         ntStatus = STATUS_SUCCESS;
 
@@ -433,58 +492,127 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ntStatus = STATUS_SUCCESS;
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        if ( --pObjectInfo->Links < 1)
+                        {
+
+                            //
+                            // Stop anything possibly in process
+                            //
+
+                            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSCleanup Acquiring Fcb extents lock %p EXCL %08lX\n",
+                                          &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                          PsGetCurrentThread()));
+
+                            AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                            TRUE);
+
+                            pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
+
+                            KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
+                                        0,
+                                        FALSE);
+
+                            //
+                            // The file has been deleted since the Link count is zero
+                            //
+
+                            AFSDeleteFcbExtents( pFcb);
+
+                            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSCleanup Releasing Fcb extents lock %p EXCL %08lX\n",
+                                          &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                          PsGetCurrentThread()));
+
+                            AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
+                        }
+
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_VERBOSE,
                                       "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
                                       &pCcb->FullFileName,
-                                      pCcb->DirectoryCB);
+                                      pCcb->DirectoryCB));
 
                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
 
-                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
-
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                        //
-                        // Now that the service has the entry has deleted we need to remove it from the parent
-                        // tree so another lookup on the node will fail
-                        //
+                        ASSERT( pParentObjectInfo != NULL);
 
-                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        if ( pParentObjectInfo != NULL)
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            AFSAcquireExcl( pParentObjectInfo->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);
+                            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;
+                            }
 
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
-                                                pCcb->DirectoryCB);
+                            //
+                            // Now that the service has the entry has deleted we need to remove it from the parent
+                            // tree so another lookup on the node will fail
+                            //
 
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ removing entry\n",
+                                              pCcb->DirectoryCB,
+                                              &pCcb->DirectoryCB->NameInformation.FileName));
+
+                                AFSRemoveNameEntry( pParentObjectInfo,
+                                                    pCcb->DirectoryCB);
+                            }
+                            else
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
+                                              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
                         {
-
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
-                                          pCcb->DirectoryCB,
-                                          &pCcb->DirectoryCB->NameInformation.FileName);
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
+                                              pCcb->DirectoryCB,
+                                              &pCcb->DirectoryCB->NameInformation.FileName));
+                            }
                         }
                     }
                 }
                 else
                 {
 
-                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
+                        pParentObjectInfo != NULL)
                     {
 
                         ULONG ulNotifyFilter = 0;
@@ -493,24 +621,31 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
 
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
                                                         pCcb,
                                                         (ULONG)ulNotifyFilter,
                                                         (ULONG)FILE_ACTION_MODIFIED);
                     }
 
+
                     //
-                    // 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.
+                    // Whenever a handle with write access or the last handle is closed
+                    // notify the service to FSync the file.  If the redirector is holding
+                    // dirty extents, flush them to the service.  This is a bit aggressive
+                    // but it ensures cache coherency.
                     //
 
-                    if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
-                        pFcb->Specific.File.ExtentsDirtyCount != 0)
+                    if( (pCcb->GrantedAccess & FILE_WRITE_DATA) || (pFcb->OpenHandleCount == 1))
                     {
 
-                        AFSFlushExtents( pFcb,
-                                         &pCcb->AuthGroup);
+                        if ( pFcb->Specific.File.ExtentsDirtyCount != 0)
+                        {
+
+                            AFSFlushExtents( pFcb,
+                                             &pCcb->AuthGroup);
+                        }
+
+                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
                     }
 
                     if( pFcb->OpenHandleCount == 1)
@@ -522,7 +657,8 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         AFSWaitOnQueuedFlushes( pFcb);
 
-                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
+                        AFSTearDownFcbExtents( pFcb,
+                                               &pCcb->AuthGroup);
                     }
 
                     //
@@ -532,70 +668,134 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                     stFileCleanup.FileAccess = pCcb->FileAccess;
 
                     //
+                    // Remove the share access at this time since we may not get the close for sometime on this FO.
+                    //
+
+                    IoRemoveShareAccess( pFileObject,
+                                         &pFcb->ShareAccess);
+
+
+                    //
+                    // We don't need the name array after the user closes the handle on the file
+                    //
+
+                    if( pCcb->NameArray != NULL)
+                    {
+
+                        AFSFreeNameArray( pCcb->NameArray);
+
+                        pCcb->NameArray = NULL;
+                    }
+
+                    //
+                    // Release the Fcb Resource across the call to the service
+                    // which may block for quite a while if flushing of the
+                    // data is required.
+                    //
+
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                    //
                     // Push the request to the service
                     //
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pCcb->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,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
 
-                //
-                // Remove the share access at this time since we may not get the close for sometime on this FO.
-                //
+                    //
+                    // Regain exclusive access to the Fcb
+                    //
 
-                IoRemoveShareAccess( pFileObject,
-                                     &pFcb->ShareAccess);
+                    AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                    TRUE);
 
-                //
-                // We don't need the name array after the user closes the handle on the file
-                //
+                    if ( NT_SUCCESS( ntStatus))
+                    {
 
-                if( pCcb->NameArray != NULL)
-                {
+                        if ( pParentObjectInfo != NULL)
+                        {
 
-                    AFSFreeNameArray( pCcb->NameArray);
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
 
-                    pCcb->NameArray = NULL;
+                            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;
                 }
 
                 //
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                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,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_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);
+                                  "AFSCleanup (File) Decrement child open handle count on Parent object %p Cnt %d\n",
+                                  pParentObjectInfo,
+                                  lCount));
                 }
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (File) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
+                              lCount));
 
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
+                {
+                    //
+                    // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
+                    //
 
-                AFSReleaseResource( &pFcb->NPFcb->Resource);
+                    lCount = AFSObjectInfoIncrement( pObjectInfo,
+                                                     AFS_OBJECT_REFERENCE_INVALIDATION);
+
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup Setting Purge on Close Increment count on object %p Cnt %d\n",
+                                  pObjectInfo,
+                                  lCount));
+
+                    ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                    AFSPerformObjectInvalidate( pObjectInfo,
+                                                AFS_INVALIDATE_DATA_VERSION);
+                }
+                else
+                {
+
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
+                }
 
                 break;
             }
@@ -625,11 +825,11 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                 //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
+                              "AFSCleanup Acquiring Dcb lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              PsGetCurrentThread()));
 
                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                   TRUE);
@@ -640,10 +840,10 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                if( pParentObjectInfo != NULL)
                 {
 
-                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                    stFileCleanup.ParentId = pParentObjectInfo->FileId;
                 }
 
                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
@@ -709,20 +909,22 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                                   &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                     {
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_ERROR,
                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
                                       &pCcb->FullFileName,
-                                      ntStatus);
+                                      ntStatus));
 
                         ntStatus = STATUS_SUCCESS;
 
@@ -733,45 +935,76 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ntStatus = STATUS_SUCCESS;
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_VERBOSE,
                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
                                       &pCcb->FullFileName,
-                                      pCcb->DirectoryCB);
+                                      pCcb->DirectoryCB));
 
                         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);
+                        ASSERT( pParentObjectInfo != NULL);
 
-                        //
-                        // Now that the service has the entry has deleted we need to remove it from the parent
-                        // tree so another lookup on the node will fail
-                        //
-
-                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        if ( pParentObjectInfo != NULL)
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                             TRUE);
 
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
-                                                pCcb->DirectoryCB);
+                            if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                            {
+
+                                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+                                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                            }
+                            else
+                            {
 
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                                pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
+                            }
+
+                            //
+                            // Now that the service has the entry has deleted we need to remove it from the parent
+                            // tree so another lookup on the node will fail
+                            //
+
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSRemoveNameEntry( pParentObjectInfo,
+                                                    pCcb->DirectoryCB);
+                            }
+                            else
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
+                                              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
                         {
-
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
-                                          pCcb->DirectoryCB,
-                                          &pCcb->DirectoryCB->NameInformation.FileName);
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
+                                              pCcb->DirectoryCB,
+                                              &pCcb->DirectoryCB->NameInformation.FileName));
+                            }
                         }
                     }
                 }
@@ -784,23 +1017,20 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 else
                 {
 
-                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
+                        pParentObjectInfo != NULL)
                     {
 
                         ULONG ulNotifyFilter = 0;
 
                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
 
-                        if(  pObjectInfo->ParentObjectInformation != NULL)
-                        {
-
-                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
+                        ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
 
-                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                            pCcb,
-                                                            (ULONG)ulNotifyFilter,
-                                                            (ULONG)FILE_ACTION_MODIFIED);
-                        }
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                                        pCcb,
+                                                        (ULONG)ulNotifyFilter,
+                                                        (ULONG)FILE_ACTION_MODIFIED);
                     }
 
                     //
@@ -809,15 +1039,40 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     stFileCleanup.FileAccess = pCcb->FileAccess;
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pCcb->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,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
+
+                    if ( NT_SUCCESS( ntStatus))
+                    {
+
+                        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;
                 }
 
                 //
@@ -851,31 +1106,27 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                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,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_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);
+                                  "AFSCleanup (Dir) Decrement child open handle count on Parent object %p Cnt %d\n",
+                                  pParentObjectInfo,
+                                  lCount));
                 }
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (Dir) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
-
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
+                              lCount));
 
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
@@ -892,11 +1143,11 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                 //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
+                              "AFSCleanup (MP/SL) Acquiring Dcb lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              PsGetCurrentThread()));
 
                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                   TRUE);
@@ -907,10 +1158,10 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ASSERT( pFcb->OpenHandleCount != 0);
 
-                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                if( pParentObjectInfo != NULL)
                 {
 
-                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                    stFileCleanup.ParentId = pParentObjectInfo->FileId;
                 }
 
                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
@@ -976,20 +1227,22 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                                                   &pCcb->AuthGroup,
                                                   &pCcb->DirectoryCB->NameInformation.FileName,
                                                   &pObjectInfo->FileId,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
                                                   &stFileCleanup,
                                                   sizeof( AFSFileCleanupCB),
-                                                  NULL,
-                                                  NULL);
+                                                  pResultCB,
+                                                  &ulResultLen);
 
                     if( !NT_SUCCESS( ntStatus) &&
                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                     {
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_ERROR,
                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
                                       &pCcb->FullFileName,
-                                      ntStatus);
+                                      ntStatus));
 
                         ntStatus = STATUS_SUCCESS;
 
@@ -1000,45 +1253,76 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                         ntStatus = STATUS_SUCCESS;
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                       AFS_TRACE_LEVEL_VERBOSE,
                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
                                       &pCcb->FullFileName,
-                                      pCcb->DirectoryCB);
+                                      pCcb->DirectoryCB));
 
                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
 
-                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
-
-                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                        pCcb,
-                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                        (ULONG)FILE_ACTION_REMOVED);
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                        //
-                        // Now that the service has the entry has deleted we need to remove it from the parent
-                        // tree so another lookup on the node will fail
-                        //
+                        ASSERT( pParentObjectInfo != NULL);
 
-                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        if ( pParentObjectInfo != NULL)
                         {
 
-                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                             TRUE);
 
-                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
-                                                pCcb->DirectoryCB);
+                            if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
+                            {
 
-                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                                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
+                            // tree so another lookup on the node will fail
+                            //
+
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSRemoveNameEntry( pParentObjectInfo,
+                                                    pCcb->DirectoryCB);
+                            }
+                            else
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
+                                              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
                         {
 
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
-                                          pCcb->DirectoryCB,
-                                          &pCcb->DirectoryCB->NameInformation.FileName);
+                            if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                            {
+
+                                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
+                                              pCcb->DirectoryCB,
+                                              &pCcb->DirectoryCB->NameInformation.FileName));
+                            }
                         }
                     }
                 }
@@ -1051,23 +1335,20 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 else
                 {
 
-                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
+                        pParentObjectInfo != NULL)
                     {
 
                         ULONG ulNotifyFilter = 0;
 
                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
 
-                        if(  pObjectInfo->ParentObjectInformation != NULL)
-                        {
-
-                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
+                        ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
 
-                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
-                                                            pCcb,
-                                                            (ULONG)ulNotifyFilter,
-                                                            (ULONG)FILE_ACTION_MODIFIED);
-                        }
+                        AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                                        pCcb,
+                                                        (ULONG)ulNotifyFilter,
+                                                        (ULONG)FILE_ACTION_MODIFIED);
                     }
 
                     //
@@ -1076,15 +1357,40 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
                     stFileCleanup.FileAccess = pCcb->FileAccess;
 
-                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
-                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
-                                       &pCcb->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,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                                  pObjectInfo->VolumeCB->VolumeInformation.CellLength,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  pResultCB,
+                                                  &ulResultLen);
+
+                    if ( NT_SUCCESS( ntStatus))
+                    {
+
+                        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,31 +1416,27 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL)
+                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,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_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);
+                                  "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %p Cnt %d\n",
+                                  pParentObjectInfo,
+                                  lCount));
                 }
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
-
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
+                              lCount));
 
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
@@ -1144,11 +1446,11 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
             case AFS_SPECIAL_SHARE_FCB:
             {
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
+                              "AFSCleanup Acquiring SPECIAL SHARE lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->Resource,
-                              PsGetCurrentThread());
+                              PsGetCurrentThread()));
 
                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                 TRUE);
@@ -1159,30 +1461,26 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
                 // Decrement the open child handle count
                 //
 
-                if( pObjectInfo->ParentObjectInformation != NULL &&
-                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+                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,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_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);
+                                  "AFSCleanup (Share) Decrement child open handle count on Parent object %p Cnt %d\n",
+                                  pParentObjectInfo,
+                                  lCount));
                 }
 
-                InterlockedDecrement( &pFcb->OpenHandleCount);
+                lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              "AFSCleanup (Share) Decrement handle count on Fcb %p Cnt %d\n",
                               pFcb,
-                              pFcb->OpenHandleCount);
-
-                //
-                // And finally, release the Fcb if we acquired it.
-                //
+                              lCount));
 
                 AFSReleaseResource( &pFcb->NPFcb->Resource);
 
@@ -1191,10 +1489,10 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
             default:
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_WARNING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
                               "AFSCleanup Processing unknown node type %d\n",
-                              pFcb->Header.NodeTypeCode);
+                              pFcb->Header.NodeTypeCode));
 
                 break;
         }
@@ -1202,6 +1500,18 @@ AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
 
 try_exit:
 
+        if ( pParentObjectInfo != NULL)
+        {
+
+            AFSReleaseObjectInfo( &pParentObjectInfo);
+        }
+
+        if( pResultCB != NULL)
+        {
+
+            AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
+        }
+
         if( pFileObject != NULL)
         {
 
@@ -1218,12 +1528,14 @@ try_exit:
 
         AFSCompleteRequest( Irp, ntStatus);
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
-        AFSDbgLogMsg( 0,
+        AFSDbgTrace(( 0,
                       0,
-                      "EXCEPTION - AFSCleanup\n");
+                      "EXCEPTION - AFSCleanup\n"));
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;