2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSCleanup.cpp
39 #include "AFSCommon.h"
42 // Function: AFSCleanup
46 // This function is the IRP_MJ_CLEANUP dispatch handler
50 // A status is returned for the handling of this request
54 AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
58 NTSTATUS ntStatus = STATUS_SUCCESS;
59 AFSDeviceExt *pDeviceExt = NULL;
60 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
63 PFILE_OBJECT pFileObject = NULL;
64 AFSFcb *pRootFcb = NULL;
65 AFSDeviceExt *pControlDeviceExt = NULL;
66 IO_STATUS_BLOCK stIoSB;
67 AFSObjectInfoCB *pObjectInfo = NULL;
68 AFSObjectInfoCB *pParentObjectInfo = NULL;
69 AFSFileCleanupCB stFileCleanup;
70 AFSFileCleanupResultCB *pResultCB = NULL;
71 ULONG ulResultLen = 0;
72 ULONG ulNotificationFlags = 0;
78 if( AFSRDRDeviceObject == NULL)
82 // Let this through, it's a cleanup on the library control device
85 try_return( ntStatus);
88 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
90 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
93 // Set some initial variables to make processing easier
96 pFileObject = pIrpSp->FileObject;
98 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
100 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
104 try_return( ntStatus);
107 pObjectInfo = pFcb->ObjectInformation;
109 pRootFcb = pObjectInfo->VolumeCB->RootFcb;
111 RtlZeroMemory( &stFileCleanup,
112 sizeof( AFSFileCleanupCB));
114 stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
116 stFileCleanup.Identifier = (ULONGLONG)pFileObject;
119 // Allocate our return buffer
122 pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
124 AFS_GENERIC_MEMORY_32_TAG);
126 if( pResultCB == NULL)
129 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
132 RtlZeroMemory( pResultCB,
135 ulResultLen = PAGE_SIZE;
139 // Perform the cleanup functionality depending on the type of node it is
142 switch( pFcb->Header.NodeTypeCode)
148 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
149 AFS_TRACE_LEVEL_VERBOSE,
150 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
151 &pFcb->NPFcb->Resource,
152 PsGetCurrentThread());
154 AFSAcquireExcl( &pFcb->NPFcb->Resource,
157 ASSERT( pFcb->OpenHandleCount != 0);
159 AFSReleaseResource( &pFcb->NPFcb->Resource);
161 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
163 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
164 AFS_TRACE_LEVEL_VERBOSE,
165 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
169 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
170 &pControlDeviceExt->Specific.Control.DirNotifyList,
179 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
180 AFS_TRACE_LEVEL_VERBOSE,
181 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
182 &pFcb->NPFcb->Resource,
183 PsGetCurrentThread());
185 AFSAcquireExcl( &pFcb->NPFcb->Resource,
188 ASSERT( pFcb->OpenHandleCount != 0);
191 // Decrement the open child handle count
194 if( pObjectInfo->ParentObjectInformation != NULL &&
195 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
198 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
200 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
201 AFS_TRACE_LEVEL_VERBOSE,
202 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
203 pObjectInfo->ParentObjectInformation,
207 AFSReleaseResource( &pFcb->NPFcb->Resource);
209 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
211 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
212 AFS_TRACE_LEVEL_VERBOSE,
213 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
221 // This Fcb represents a file
228 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
231 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
232 AFS_TRACE_LEVEL_VERBOSE,
233 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
234 &pFcb->NPFcb->Resource,
235 PsGetCurrentThread());
237 AFSAcquireExcl( &pFcb->NPFcb->Resource,
241 // If the handle has write permission ...
244 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
245 CcIsFileCached( pIrpSp->FileObject))
251 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
256 if( !NT_SUCCESS( stIoSB.Status))
259 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
260 AFS_TRACE_LEVEL_ERROR,
261 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
263 pObjectInfo->FileId.Cell,
264 pObjectInfo->FileId.Volume,
265 pObjectInfo->FileId.Vnode,
266 pObjectInfo->FileId.Unique,
270 ntStatus = stIoSB.Status;
273 __except( EXCEPTION_EXECUTE_HANDLER)
276 ntStatus = GetExceptionCode();
281 // Uninitialize the cache map. This call is unconditional.
284 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
285 AFS_TRACE_LEVEL_VERBOSE,
286 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
290 CcUninitializeCacheMap( pFileObject,
295 // Unlock all outstanding locks on the file, again, unconditionally
298 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
300 IoGetRequestorProcess( Irp),
304 // Tell the service to unlock all on the file
307 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
310 // Perform some final common processing
313 ASSERT( pFcb->OpenHandleCount != 0);
315 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
318 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
321 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
323 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
326 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
328 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
330 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
333 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
335 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
338 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
341 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
343 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
346 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
349 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
351 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
354 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
357 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
359 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
363 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
366 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
370 // If the count has dropped to one and there is a pending delete
371 // then delete the node. The final count will be decremented just
372 // before the Fcb->NPFcb->Resource is released.
375 if( pFcb->OpenHandleCount == 1 &&
376 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
380 // Stop anything possibly in process
383 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
384 AFS_TRACE_LEVEL_VERBOSE,
385 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
386 &pFcb->NPFcb->Specific.File.ExtentsResource,
387 PsGetCurrentThread());
389 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
392 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
394 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
399 // Before telling the server about the deleted file, tear down all extents for
403 AFSTearDownFcbExtents( pFcb,
406 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
407 AFS_TRACE_LEVEL_VERBOSE,
408 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
409 &pFcb->NPFcb->Specific.File.ExtentsResource,
410 PsGetCurrentThread());
412 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
414 ntStatus = STATUS_SUCCESS;
416 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
419 // Indicate the file access mode that is being released
422 stFileCleanup.FileAccess = pCcb->FileAccess;
425 // Push the request to the service
428 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
429 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
431 &pCcb->DirectoryCB->NameInformation.FileName,
432 &pObjectInfo->FileId,
434 sizeof( AFSFileCleanupCB),
438 if( !NT_SUCCESS( ntStatus) &&
439 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
442 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
443 AFS_TRACE_LEVEL_ERROR,
444 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
448 ntStatus = STATUS_SUCCESS;
450 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
455 ntStatus = STATUS_SUCCESS;
457 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
458 AFS_TRACE_LEVEL_VERBOSE,
459 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
463 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
465 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
467 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
469 ASSERT( pParentObjectInfo != NULL);
471 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
474 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
477 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
479 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
484 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
488 // Now that the service has the entry has deleted we need to remove it from the parent
489 // tree so another lookup on the node will fail
492 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
495 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
496 AFS_TRACE_LEVEL_VERBOSE,
497 "AFSCleanup DE %p for %wZ removing entry\n",
499 &pCcb->DirectoryCB->NameInformation.FileName);
501 AFSRemoveNameEntry( pParentObjectInfo,
507 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
508 AFS_TRACE_LEVEL_VERBOSE,
509 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
511 &pCcb->DirectoryCB->NameInformation.FileName);
514 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
516 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
518 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
519 (ULONG)FILE_ACTION_REMOVED);
526 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
529 ULONG ulNotifyFilter = 0;
531 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
533 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
535 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
537 (ULONG)ulNotifyFilter,
538 (ULONG)FILE_ACTION_MODIFIED);
542 // Attempt to flush any dirty extents to the server. This may be a little
543 // aggressive, to flush whenever the handle is closed, but it ensures
547 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
548 pFcb->Specific.File.ExtentsDirtyCount != 0)
551 AFSFlushExtents( pFcb,
555 if( pFcb->OpenHandleCount == 1)
559 // Wait for any outstanding queued flushes to complete
562 AFSWaitOnQueuedFlushes( pFcb);
564 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
566 AFSTearDownFcbExtents( pFcb,
571 // Indicate the file access mode that is being released
574 stFileCleanup.FileAccess = pCcb->FileAccess;
577 // Push the request to the service
580 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
581 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
583 &pCcb->DirectoryCB->NameInformation.FileName,
584 &pObjectInfo->FileId,
586 sizeof( AFSFileCleanupCB),
590 if ( NT_SUCCESS( ntStatus))
593 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
595 if ( pParentObjectInfo != NULL)
598 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
601 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
604 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
606 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
609 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
613 ntStatus = STATUS_SUCCESS;
617 // Remove the share access at this time since we may not get the close for sometime on this FO.
620 IoRemoveShareAccess( pFileObject,
624 // We don't need the name array after the user closes the handle on the file
627 if( pCcb->NameArray != NULL)
630 AFSFreeNameArray( pCcb->NameArray);
632 pCcb->NameArray = NULL;
636 // Decrement the open child handle count
639 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
641 if( pParentObjectInfo != NULL)
644 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
646 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
648 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
649 AFS_TRACE_LEVEL_VERBOSE,
650 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
655 AFSReleaseResource( &pFcb->NPFcb->Resource);
657 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
660 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
663 AFSObjectInfoIncrement( pObjectInfo);
665 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
667 AFSPerformObjectInvalidate( pObjectInfo,
668 AFS_INVALIDATE_DATA_VERSION);
671 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
673 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
674 AFS_TRACE_LEVEL_VERBOSE,
675 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
683 // Root or directory node
690 // Set the root Fcb to this node
696 // Fall through to below
700 case AFS_DIRECTORY_FCB:
704 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
707 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
708 AFS_TRACE_LEVEL_VERBOSE,
709 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
710 &pFcb->NPFcb->Resource,
711 PsGetCurrentThread());
713 AFSAcquireExcl( &pFcb->NPFcb->Resource,
717 // Perform some final common processing
720 ASSERT( pFcb->OpenHandleCount != 0);
722 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
725 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
728 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
730 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
733 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
735 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
738 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
740 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
743 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
746 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
748 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
751 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
754 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
756 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
761 // If the count has dropped to one and there is a pending delete
762 // then delete the node. The final count will be decremented just
763 // before the Fcb->NPFcb->Resource is released.
766 if( pFcb->OpenHandleCount == 1 &&
767 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
771 // Try to notify the service about the delete
774 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
777 // Indicate the file access mode that is being released
780 stFileCleanup.FileAccess = pCcb->FileAccess;
783 // Push the request to the service
786 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
787 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
789 &pCcb->DirectoryCB->NameInformation.FileName,
790 &pObjectInfo->FileId,
792 sizeof( AFSFileCleanupCB),
796 if( !NT_SUCCESS( ntStatus) &&
797 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
800 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
801 AFS_TRACE_LEVEL_ERROR,
802 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
806 ntStatus = STATUS_SUCCESS;
808 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
813 ntStatus = STATUS_SUCCESS;
815 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
816 AFS_TRACE_LEVEL_VERBOSE,
817 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
821 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
823 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
825 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
827 ASSERT( pParentObjectInfo != NULL);
829 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
832 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
835 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
837 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
842 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
846 // Now that the service has the entry has deleted we need to remove it from the parent
847 // tree so another lookup on the node will fail
850 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
853 AFSRemoveNameEntry( pParentObjectInfo,
859 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
860 AFS_TRACE_LEVEL_VERBOSE,
861 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
863 &pCcb->DirectoryCB->NameInformation.FileName);
866 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
868 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
870 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
871 (ULONG)FILE_ACTION_REMOVED);
877 // If there have been any updates to the node then push it to
884 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
887 ULONG ulNotifyFilter = 0;
889 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
891 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
893 if( pParentObjectInfo != NULL)
896 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
898 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
900 (ULONG)ulNotifyFilter,
901 (ULONG)FILE_ACTION_MODIFIED);
906 // Indicate the file access mode that is being released
909 stFileCleanup.FileAccess = pCcb->FileAccess;
911 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
912 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
914 &pCcb->DirectoryCB->NameInformation.FileName,
915 &pObjectInfo->FileId,
917 sizeof( AFSFileCleanupCB),
921 if ( NT_SUCCESS( ntStatus))
924 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
926 if ( pParentObjectInfo != NULL)
929 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
932 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
935 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
937 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
940 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
944 ntStatus = STATUS_SUCCESS;
948 // Release the notification for this directory if there is one
951 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
952 &pControlDeviceExt->Specific.Control.DirNotifyList,
956 // Remove the share access at this time since we may not get the close for sometime on this FO.
959 IoRemoveShareAccess( pFileObject,
963 // We don't need the name array after the user closes the handle on the file
966 if( pCcb->NameArray != NULL)
969 AFSFreeNameArray( pCcb->NameArray);
971 pCcb->NameArray = NULL;
975 // Decrement the open child handle count
978 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
980 if( pParentObjectInfo != NULL)
983 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
985 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
987 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
988 AFS_TRACE_LEVEL_VERBOSE,
989 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
994 AFSReleaseResource( &pFcb->NPFcb->Resource);
996 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
998 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
999 AFS_TRACE_LEVEL_VERBOSE,
1000 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
1007 case AFS_SYMBOLIC_LINK_FCB:
1008 case AFS_MOUNT_POINT_FCB:
1009 case AFS_DFS_LINK_FCB:
1010 case AFS_INVALID_FCB:
1014 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1017 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1018 AFS_TRACE_LEVEL_VERBOSE,
1019 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1020 &pFcb->NPFcb->Resource,
1021 PsGetCurrentThread());
1023 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1027 // Perform some final common processing
1030 ASSERT( pFcb->OpenHandleCount != 0);
1032 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1035 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1038 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1040 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1043 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1045 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1048 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1050 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1053 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1056 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1058 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1061 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1064 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1066 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1071 // If the count has dropped to one and there is a pending delete
1072 // then delete the node. The final count will be decremented just
1073 // before the Fcb->NPFcb->Resource is released.
1076 if( pFcb->OpenHandleCount == 1 &&
1077 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1081 // Try to notify the service about the delete
1084 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1087 // Indicate the file access mode that is being released
1090 stFileCleanup.FileAccess = pCcb->FileAccess;
1093 // Push the request to the service
1096 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1097 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1099 &pCcb->DirectoryCB->NameInformation.FileName,
1100 &pObjectInfo->FileId,
1102 sizeof( AFSFileCleanupCB),
1106 if( !NT_SUCCESS( ntStatus) &&
1107 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1111 AFS_TRACE_LEVEL_ERROR,
1112 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1113 &pCcb->FullFileName,
1116 ntStatus = STATUS_SUCCESS;
1118 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1123 ntStatus = STATUS_SUCCESS;
1125 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1126 AFS_TRACE_LEVEL_VERBOSE,
1127 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1128 &pCcb->FullFileName,
1131 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1133 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1135 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1137 ASSERT( pParentObjectInfo != NULL);
1139 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1142 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1145 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1147 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1151 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1155 // Now that the service has the entry has deleted we need to remove it from the parent
1156 // tree so another lookup on the node will fail
1159 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1162 AFSRemoveNameEntry( pParentObjectInfo,
1168 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1169 AFS_TRACE_LEVEL_VERBOSE,
1170 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1172 &pCcb->DirectoryCB->NameInformation.FileName);
1175 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1177 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1179 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1180 (ULONG)FILE_ACTION_REMOVED);
1186 // If there have been any updates to the node then push it to
1193 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1196 ULONG ulNotifyFilter = 0;
1198 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1200 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1202 if( pParentObjectInfo != NULL)
1205 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1207 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1209 (ULONG)ulNotifyFilter,
1210 (ULONG)FILE_ACTION_MODIFIED);
1215 // Indicate the file access mode that is being released
1218 stFileCleanup.FileAccess = pCcb->FileAccess;
1220 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1221 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1223 &pCcb->DirectoryCB->NameInformation.FileName,
1224 &pObjectInfo->FileId,
1226 sizeof( AFSFileCleanupCB),
1230 if ( NT_SUCCESS( ntStatus))
1233 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1235 if ( pParentObjectInfo != NULL)
1238 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1241 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1244 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1246 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1249 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1253 ntStatus = STATUS_SUCCESS;
1257 // Remove the share access at this time since we may not get the close for sometime on this FO.
1260 IoRemoveShareAccess( pFileObject,
1261 &pFcb->ShareAccess);
1264 // We don't need the name array after the user closes the handle on the file
1267 if( pCcb->NameArray != NULL)
1270 AFSFreeNameArray( pCcb->NameArray);
1272 pCcb->NameArray = NULL;
1276 // Decrement the open child handle count
1279 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1281 if( pParentObjectInfo != NULL)
1284 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1286 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1288 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1289 AFS_TRACE_LEVEL_VERBOSE,
1290 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1295 AFSReleaseResource( &pFcb->NPFcb->Resource);
1297 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1299 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1300 AFS_TRACE_LEVEL_VERBOSE,
1301 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1308 case AFS_SPECIAL_SHARE_FCB:
1311 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1312 AFS_TRACE_LEVEL_VERBOSE,
1313 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1314 &pFcb->NPFcb->Resource,
1315 PsGetCurrentThread());
1317 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1320 ASSERT( pFcb->OpenHandleCount != 0);
1323 // Decrement the open child handle count
1326 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1328 if( pParentObjectInfo != NULL &&
1329 pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1332 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1334 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1335 AFS_TRACE_LEVEL_VERBOSE,
1336 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1341 AFSReleaseResource( &pFcb->NPFcb->Resource);
1343 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1345 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1346 AFS_TRACE_LEVEL_VERBOSE,
1347 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1356 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1357 AFS_TRACE_LEVEL_WARNING,
1358 "AFSCleanup Processing unknown node type %d\n",
1359 pFcb->Header.NodeTypeCode);
1367 if( pResultCB != NULL)
1370 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1373 if( pFileObject != NULL)
1377 // Setup the fileobject flags to indicate cleanup is complete.
1380 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1384 // Complete the request
1387 AFSCompleteRequest( Irp, ntStatus);
1389 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1394 "EXCEPTION - AFSCleanup\n");
1396 AFSDumpTraceFilesFnc();