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 AFSFileCleanupCB stFileCleanup;
69 AFSFileCleanupResultCB *pResultCB = NULL;
70 ULONG ulResultLen = 0;
71 ULONG ulNotificationFlags = 0;
77 if( AFSRDRDeviceObject == NULL)
81 // Let this through, it's a cleanup on the library control device
84 try_return( ntStatus);
87 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
89 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
92 // Set some initial variables to make processing easier
95 pFileObject = pIrpSp->FileObject;
97 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
99 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
103 try_return( ntStatus);
106 pObjectInfo = pFcb->ObjectInformation;
108 pRootFcb = pObjectInfo->VolumeCB->RootFcb;
110 RtlZeroMemory( &stFileCleanup,
111 sizeof( AFSFileCleanupCB));
113 stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
115 stFileCleanup.Identifier = (ULONGLONG)pFileObject;
118 // Allocate our return buffer
121 pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
123 AFS_GENERIC_MEMORY_32_TAG);
125 if( pResultCB == NULL)
128 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
131 RtlZeroMemory( pResultCB,
134 ulResultLen = PAGE_SIZE;
138 // Perform the cleanup functionality depending on the type of node it is
141 switch( pFcb->Header.NodeTypeCode)
147 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
148 AFS_TRACE_LEVEL_VERBOSE,
149 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
150 &pFcb->NPFcb->Resource,
151 PsGetCurrentThread());
153 AFSAcquireExcl( &pFcb->NPFcb->Resource,
156 ASSERT( pFcb->OpenHandleCount != 0);
158 AFSReleaseResource( &pFcb->NPFcb->Resource);
160 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
162 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
163 AFS_TRACE_LEVEL_VERBOSE,
164 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
168 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
169 &pControlDeviceExt->Specific.Control.DirNotifyList,
178 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
179 AFS_TRACE_LEVEL_VERBOSE,
180 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
181 &pFcb->NPFcb->Resource,
182 PsGetCurrentThread());
184 AFSAcquireExcl( &pFcb->NPFcb->Resource,
187 ASSERT( pFcb->OpenHandleCount != 0);
190 // Decrement the open child handle count
193 if( pObjectInfo->ParentObjectInformation != NULL &&
194 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
197 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
199 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
200 AFS_TRACE_LEVEL_VERBOSE,
201 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
202 pObjectInfo->ParentObjectInformation,
206 AFSReleaseResource( &pFcb->NPFcb->Resource);
208 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
210 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
211 AFS_TRACE_LEVEL_VERBOSE,
212 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
220 // This Fcb represents a file
227 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
230 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
231 AFS_TRACE_LEVEL_VERBOSE,
232 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
233 &pFcb->NPFcb->Resource,
234 PsGetCurrentThread());
236 AFSAcquireExcl( &pFcb->NPFcb->Resource,
240 // If the handle has write permission ...
243 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
244 CcIsFileCached( pIrpSp->FileObject))
250 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
255 if( !NT_SUCCESS( stIoSB.Status))
258 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
259 AFS_TRACE_LEVEL_ERROR,
260 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
262 pObjectInfo->FileId.Cell,
263 pObjectInfo->FileId.Volume,
264 pObjectInfo->FileId.Vnode,
265 pObjectInfo->FileId.Unique,
269 ntStatus = stIoSB.Status;
272 __except( EXCEPTION_EXECUTE_HANDLER)
275 ntStatus = GetExceptionCode();
280 // Uninitialize the cache map. This call is unconditional.
283 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
284 AFS_TRACE_LEVEL_VERBOSE,
285 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
289 CcUninitializeCacheMap( pFileObject,
294 // Unlock all outstanding locks on the file, again, unconditionally
297 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
299 IoGetRequestorProcess( Irp),
303 // Tell the service to unlock all on the file
306 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
309 // Perform some final common processing
312 ASSERT( pFcb->OpenHandleCount != 0);
314 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
317 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
320 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
322 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
325 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
327 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
329 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
332 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
334 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
337 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
340 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
342 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
345 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
348 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
350 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
353 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
356 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
358 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
362 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
365 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
369 // If the count has dropped to one and there is a pending delete
370 // then delete the node. The final count will be decremented just
371 // before the Fcb->NPFcb->Resource is released.
374 if( pFcb->OpenHandleCount == 1 &&
375 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
379 // Stop anything possibly in process
382 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
383 AFS_TRACE_LEVEL_VERBOSE,
384 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
385 &pFcb->NPFcb->Specific.File.ExtentsResource,
386 PsGetCurrentThread());
388 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
391 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
393 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
398 // Before telling the server about the deleted file, tear down all extents for
402 AFSTearDownFcbExtents( pFcb,
405 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
406 AFS_TRACE_LEVEL_VERBOSE,
407 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
408 &pFcb->NPFcb->Specific.File.ExtentsResource,
409 PsGetCurrentThread());
411 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
413 ntStatus = STATUS_SUCCESS;
415 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
418 // Indicate the file access mode that is being released
421 stFileCleanup.FileAccess = pCcb->FileAccess;
424 // Push the request to the service
427 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
428 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
430 &pCcb->DirectoryCB->NameInformation.FileName,
431 &pObjectInfo->FileId,
433 sizeof( AFSFileCleanupCB),
437 if( !NT_SUCCESS( ntStatus) &&
438 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
441 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
442 AFS_TRACE_LEVEL_ERROR,
443 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
447 ntStatus = STATUS_SUCCESS;
449 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
454 ntStatus = STATUS_SUCCESS;
456 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
457 AFS_TRACE_LEVEL_VERBOSE,
458 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
462 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
464 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
466 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
469 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
472 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
474 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
479 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
483 // Now that the service has the entry has deleted we need to remove it from the parent
484 // tree so another lookup on the node will fail
487 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
490 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
491 AFS_TRACE_LEVEL_VERBOSE,
492 "AFSCleanup DE %p for %wZ removing entry\n",
494 &pCcb->DirectoryCB->NameInformation.FileName);
496 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
502 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
503 AFS_TRACE_LEVEL_VERBOSE,
504 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
506 &pCcb->DirectoryCB->NameInformation.FileName);
509 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
511 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
513 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
514 (ULONG)FILE_ACTION_REMOVED);
521 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
524 ULONG ulNotifyFilter = 0;
526 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
528 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
530 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
532 (ULONG)ulNotifyFilter,
533 (ULONG)FILE_ACTION_MODIFIED);
537 // Attempt to flush any dirty extents to the server. This may be a little
538 // aggressive, to flush whenever the handle is closed, but it ensures
542 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
543 pFcb->Specific.File.ExtentsDirtyCount != 0)
546 AFSFlushExtents( pFcb,
550 if( pFcb->OpenHandleCount == 1)
554 // Wait for any outstanding queued flushes to complete
557 AFSWaitOnQueuedFlushes( pFcb);
559 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
561 AFSTearDownFcbExtents( pFcb,
566 // Indicate the file access mode that is being released
569 stFileCleanup.FileAccess = pCcb->FileAccess;
572 // Push the request to the service
575 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
576 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
578 &pCcb->DirectoryCB->NameInformation.FileName,
579 &pObjectInfo->FileId,
581 sizeof( AFSFileCleanupCB),
585 if ( NT_SUCCESS( ntStatus))
588 if ( pObjectInfo->ParentObjectInformation != NULL)
591 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
594 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
597 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
599 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
602 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
606 ntStatus = STATUS_SUCCESS;
610 // Remove the share access at this time since we may not get the close for sometime on this FO.
613 IoRemoveShareAccess( pFileObject,
617 // We don't need the name array after the user closes the handle on the file
620 if( pCcb->NameArray != NULL)
623 AFSFreeNameArray( pCcb->NameArray);
625 pCcb->NameArray = NULL;
629 // Decrement the open child handle count
632 if( pObjectInfo->ParentObjectInformation != NULL)
635 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
637 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
639 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
640 AFS_TRACE_LEVEL_VERBOSE,
641 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
642 pObjectInfo->ParentObjectInformation,
646 AFSReleaseResource( &pFcb->NPFcb->Resource);
648 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
651 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
654 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
656 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
658 AFSPerformObjectInvalidate( pObjectInfo,
659 AFS_INVALIDATE_DATA_VERSION);
662 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
664 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
665 AFS_TRACE_LEVEL_VERBOSE,
666 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
674 // Root or directory node
681 // Set the root Fcb to this node
687 // Fall through to below
691 case AFS_DIRECTORY_FCB:
695 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
698 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
699 AFS_TRACE_LEVEL_VERBOSE,
700 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
701 &pFcb->NPFcb->Resource,
702 PsGetCurrentThread());
704 AFSAcquireExcl( &pFcb->NPFcb->Resource,
708 // Perform some final common processing
711 ASSERT( pFcb->OpenHandleCount != 0);
713 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
716 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
719 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
721 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
724 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
726 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
729 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
731 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
734 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
737 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
739 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
742 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
745 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
747 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
752 // If the count has dropped to one and there is a pending delete
753 // then delete the node. The final count will be decremented just
754 // before the Fcb->NPFcb->Resource is released.
757 if( pFcb->OpenHandleCount == 1 &&
758 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
762 // Try to notify the service about the delete
765 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
768 // Indicate the file access mode that is being released
771 stFileCleanup.FileAccess = pCcb->FileAccess;
774 // Push the request to the service
777 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
778 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
780 &pCcb->DirectoryCB->NameInformation.FileName,
781 &pObjectInfo->FileId,
783 sizeof( AFSFileCleanupCB),
787 if( !NT_SUCCESS( ntStatus) &&
788 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
791 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
792 AFS_TRACE_LEVEL_ERROR,
793 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
797 ntStatus = STATUS_SUCCESS;
799 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
804 ntStatus = STATUS_SUCCESS;
806 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
807 AFS_TRACE_LEVEL_VERBOSE,
808 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
812 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
814 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
816 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
819 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
822 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
824 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
829 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
833 // Now that the service has the entry has deleted we need to remove it from the parent
834 // tree so another lookup on the node will fail
837 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
840 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
846 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
847 AFS_TRACE_LEVEL_VERBOSE,
848 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
850 &pCcb->DirectoryCB->NameInformation.FileName);
853 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
855 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
857 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
858 (ULONG)FILE_ACTION_REMOVED);
864 // If there have been any updates to the node then push it to
871 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
874 ULONG ulNotifyFilter = 0;
876 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
878 if( pObjectInfo->ParentObjectInformation != NULL)
881 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
883 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
885 (ULONG)ulNotifyFilter,
886 (ULONG)FILE_ACTION_MODIFIED);
891 // Indicate the file access mode that is being released
894 stFileCleanup.FileAccess = pCcb->FileAccess;
896 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
897 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
899 &pCcb->DirectoryCB->NameInformation.FileName,
900 &pObjectInfo->FileId,
902 sizeof( AFSFileCleanupCB),
906 if ( NT_SUCCESS( ntStatus))
909 if ( pObjectInfo->ParentObjectInformation != NULL)
912 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
915 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
918 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
920 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
923 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
927 ntStatus = STATUS_SUCCESS;
931 // Release the notification for this directory if there is one
934 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
935 &pControlDeviceExt->Specific.Control.DirNotifyList,
939 // Remove the share access at this time since we may not get the close for sometime on this FO.
942 IoRemoveShareAccess( pFileObject,
946 // We don't need the name array after the user closes the handle on the file
949 if( pCcb->NameArray != NULL)
952 AFSFreeNameArray( pCcb->NameArray);
954 pCcb->NameArray = NULL;
958 // Decrement the open child handle count
961 if( pObjectInfo->ParentObjectInformation != NULL)
964 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
966 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
968 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
969 AFS_TRACE_LEVEL_VERBOSE,
970 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
971 pObjectInfo->ParentObjectInformation,
975 AFSReleaseResource( &pFcb->NPFcb->Resource);
977 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
979 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
980 AFS_TRACE_LEVEL_VERBOSE,
981 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
988 case AFS_SYMBOLIC_LINK_FCB:
989 case AFS_MOUNT_POINT_FCB:
990 case AFS_DFS_LINK_FCB:
991 case AFS_INVALID_FCB:
995 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
998 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
999 AFS_TRACE_LEVEL_VERBOSE,
1000 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1001 &pFcb->NPFcb->Resource,
1002 PsGetCurrentThread());
1004 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1008 // Perform some final common processing
1011 ASSERT( pFcb->OpenHandleCount != 0);
1013 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1016 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1019 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1021 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1024 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1026 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1029 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1031 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1034 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1037 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1039 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1042 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1045 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1047 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1052 // If the count has dropped to one and there is a pending delete
1053 // then delete the node. The final count will be decremented just
1054 // before the Fcb->NPFcb->Resource is released.
1057 if( pFcb->OpenHandleCount == 1 &&
1058 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1062 // Try to notify the service about the delete
1065 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1068 // Indicate the file access mode that is being released
1071 stFileCleanup.FileAccess = pCcb->FileAccess;
1074 // Push the request to the service
1077 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1078 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1080 &pCcb->DirectoryCB->NameInformation.FileName,
1081 &pObjectInfo->FileId,
1083 sizeof( AFSFileCleanupCB),
1087 if( !NT_SUCCESS( ntStatus) &&
1088 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1091 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1092 AFS_TRACE_LEVEL_ERROR,
1093 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1094 &pCcb->FullFileName,
1097 ntStatus = STATUS_SUCCESS;
1099 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1104 ntStatus = STATUS_SUCCESS;
1106 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1107 AFS_TRACE_LEVEL_VERBOSE,
1108 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1109 &pCcb->FullFileName,
1112 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1114 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
1116 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1119 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1122 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1124 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1128 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1132 // Now that the service has the entry has deleted we need to remove it from the parent
1133 // tree so another lookup on the node will fail
1136 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1139 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1145 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1146 AFS_TRACE_LEVEL_VERBOSE,
1147 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1149 &pCcb->DirectoryCB->NameInformation.FileName);
1152 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1154 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1156 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1157 (ULONG)FILE_ACTION_REMOVED);
1163 // If there have been any updates to the node then push it to
1170 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1173 ULONG ulNotifyFilter = 0;
1175 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1177 if( pObjectInfo->ParentObjectInformation != NULL)
1180 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1182 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1184 (ULONG)ulNotifyFilter,
1185 (ULONG)FILE_ACTION_MODIFIED);
1190 // Indicate the file access mode that is being released
1193 stFileCleanup.FileAccess = pCcb->FileAccess;
1195 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1196 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1198 &pCcb->DirectoryCB->NameInformation.FileName,
1199 &pObjectInfo->FileId,
1201 sizeof( AFSFileCleanupCB),
1205 if ( NT_SUCCESS( ntStatus))
1208 if ( pObjectInfo->ParentObjectInformation != NULL)
1211 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1214 if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1217 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1219 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1222 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1226 ntStatus = STATUS_SUCCESS;
1230 // Remove the share access at this time since we may not get the close for sometime on this FO.
1233 IoRemoveShareAccess( pFileObject,
1234 &pFcb->ShareAccess);
1237 // We don't need the name array after the user closes the handle on the file
1240 if( pCcb->NameArray != NULL)
1243 AFSFreeNameArray( pCcb->NameArray);
1245 pCcb->NameArray = NULL;
1249 // Decrement the open child handle count
1252 if( pObjectInfo->ParentObjectInformation != NULL)
1255 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1257 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1259 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1260 AFS_TRACE_LEVEL_VERBOSE,
1261 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1262 pObjectInfo->ParentObjectInformation,
1266 AFSReleaseResource( &pFcb->NPFcb->Resource);
1268 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1270 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1271 AFS_TRACE_LEVEL_VERBOSE,
1272 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1279 case AFS_SPECIAL_SHARE_FCB:
1282 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1283 AFS_TRACE_LEVEL_VERBOSE,
1284 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1285 &pFcb->NPFcb->Resource,
1286 PsGetCurrentThread());
1288 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1291 ASSERT( pFcb->OpenHandleCount != 0);
1294 // Decrement the open child handle count
1297 if( pObjectInfo->ParentObjectInformation != NULL &&
1298 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1301 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1303 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1304 AFS_TRACE_LEVEL_VERBOSE,
1305 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1306 pObjectInfo->ParentObjectInformation,
1310 AFSReleaseResource( &pFcb->NPFcb->Resource);
1312 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1314 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1315 AFS_TRACE_LEVEL_VERBOSE,
1316 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1326 AFS_TRACE_LEVEL_WARNING,
1327 "AFSCleanup Processing unknown node type %d\n",
1328 pFcb->Header.NodeTypeCode);
1336 if( pResultCB != NULL)
1339 AFSExFreePool( pResultCB);
1342 if( pFileObject != NULL)
1346 // Setup the fileobject flags to indicate cleanup is complete.
1349 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1353 // Complete the request
1356 AFSCompleteRequest( Irp, ntStatus);
1358 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1363 "EXCEPTION - AFSCleanup\n");
1365 AFSDumpTraceFilesFnc();