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 ULONG ulNotificationFlags = 0;
74 if( AFSRDRDeviceObject == NULL)
78 // Let this through, it's a cleanup on the library control device
81 try_return( ntStatus);
84 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
85 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
88 // Set some initial variables to make processing easier
91 pFileObject = pIrpSp->FileObject;
93 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
95 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
99 try_return( ntStatus);
102 pObjectInfo = pFcb->ObjectInformation;
104 pRootFcb = pObjectInfo->VolumeCB->RootFcb;
106 RtlZeroMemory( &stFileCleanup,
107 sizeof( AFSFileCleanupCB));
109 stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
111 stFileCleanup.Identifier = (ULONGLONG)pFileObject;
114 // Perform the cleanup functionality depending on the type of node it is
117 switch( pFcb->Header.NodeTypeCode)
123 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
124 AFS_TRACE_LEVEL_VERBOSE,
125 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
126 &pFcb->NPFcb->Resource,
127 PsGetCurrentThread());
129 AFSAcquireExcl( &pFcb->NPFcb->Resource,
132 ASSERT( pFcb->OpenHandleCount != 0);
134 InterlockedDecrement( &pFcb->OpenHandleCount);
136 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
137 AFS_TRACE_LEVEL_VERBOSE,
138 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
140 pFcb->OpenHandleCount);
142 AFSReleaseResource( &pFcb->NPFcb->Resource);
144 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
145 &pControlDeviceExt->Specific.Control.DirNotifyList,
154 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
155 AFS_TRACE_LEVEL_VERBOSE,
156 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
157 &pFcb->NPFcb->Resource,
158 PsGetCurrentThread());
160 AFSAcquireExcl( &pFcb->NPFcb->Resource,
163 ASSERT( pFcb->OpenHandleCount != 0);
165 InterlockedDecrement( &pFcb->OpenHandleCount);
167 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
168 AFS_TRACE_LEVEL_VERBOSE,
169 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
171 pFcb->OpenHandleCount);
174 // Decrement the open child handle count
177 if( pObjectInfo->ParentObjectInformation != NULL &&
178 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
181 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
183 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
184 AFS_TRACE_LEVEL_VERBOSE,
185 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
186 pObjectInfo->ParentObjectInformation,
187 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
191 // And finally, release the Fcb if we acquired it.
194 AFSReleaseResource( &pFcb->NPFcb->Resource);
200 // This Fcb represents a file
207 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
210 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
211 AFS_TRACE_LEVEL_VERBOSE,
212 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
213 &pFcb->NPFcb->Resource,
214 PsGetCurrentThread());
216 AFSAcquireExcl( &pFcb->NPFcb->Resource,
220 // If the handle has write permission ...
223 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
224 CcIsFileCached( pIrpSp->FileObject))
230 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
235 if( !NT_SUCCESS( stIoSB.Status))
238 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
239 AFS_TRACE_LEVEL_ERROR,
240 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
242 pObjectInfo->FileId.Cell,
243 pObjectInfo->FileId.Volume,
244 pObjectInfo->FileId.Vnode,
245 pObjectInfo->FileId.Unique,
249 ntStatus = stIoSB.Status;
252 __except( EXCEPTION_EXECUTE_HANDLER)
255 ntStatus = GetExceptionCode();
260 // Uninitialize the cache map. This call is unconditional.
263 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
264 AFS_TRACE_LEVEL_VERBOSE,
265 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
269 CcUninitializeCacheMap( pFileObject,
274 // Unlock all outstanding locks on the file, again, unconditionally
277 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
279 IoGetRequestorProcess( Irp),
283 // Tell the service to unlock all on the file
286 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
289 // Perform some final common processing
292 ASSERT( pFcb->OpenHandleCount != 0);
294 InterlockedDecrement( &pFcb->OpenHandleCount);
296 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
297 AFS_TRACE_LEVEL_VERBOSE,
298 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
300 pFcb->OpenHandleCount);
302 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
305 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
308 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
310 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
313 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
315 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
317 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
320 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
322 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
325 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
328 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
330 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
333 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
336 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
338 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
341 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
344 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
346 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
350 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
353 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
357 // If the count has dropped to zero and there is a pending delete
358 // then delete the node
361 if( pFcb->OpenHandleCount == 0 &&
362 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
366 // Stop anything possibly in process
369 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
370 AFS_TRACE_LEVEL_VERBOSE,
371 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
372 &pFcb->NPFcb->Specific.File.ExtentsResource,
373 PsGetCurrentThread());
375 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
378 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
380 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
385 AFS_TRACE_LEVEL_VERBOSE,
386 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
387 &pFcb->NPFcb->Specific.File.ExtentsResource,
388 PsGetCurrentThread());
390 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
393 // Before telling the server about the deleted file, tear down all extents for
397 AFSTearDownFcbExtents( pFcb,
400 ntStatus = STATUS_SUCCESS;
402 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
405 // Indicate the file access mode that is being released
408 stFileCleanup.FileAccess = pCcb->FileAccess;
411 // Push the request to the service
414 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
415 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
417 &pCcb->DirectoryCB->NameInformation.FileName,
418 &pObjectInfo->FileId,
420 sizeof( AFSFileCleanupCB),
424 if( !NT_SUCCESS( ntStatus) &&
425 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
428 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
429 AFS_TRACE_LEVEL_ERROR,
430 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
434 ntStatus = STATUS_SUCCESS;
436 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
441 ntStatus = STATUS_SUCCESS;
443 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
444 AFS_TRACE_LEVEL_VERBOSE,
445 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
449 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
451 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
453 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
455 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
456 (ULONG)FILE_ACTION_REMOVED);
459 // Now that the service has the entry has deleted we need to remove it from the parent
460 // tree so another lookup on the node will fail
463 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
466 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
469 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
470 AFS_TRACE_LEVEL_VERBOSE,
471 "AFSCleanup DE %p for %wZ removing entry\n",
473 &pCcb->DirectoryCB->NameInformation.FileName);
475 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
478 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
483 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
484 AFS_TRACE_LEVEL_VERBOSE,
485 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
487 &pCcb->DirectoryCB->NameInformation.FileName);
494 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
497 ULONG ulNotifyFilter = 0;
499 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
501 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
503 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
505 (ULONG)ulNotifyFilter,
506 (ULONG)FILE_ACTION_MODIFIED);
510 // Attempt to flush any dirty extents to the server. This may be a little
511 // aggressive, to flush whenever the handle is closed, but it ensures
515 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
516 pFcb->Specific.File.ExtentsDirtyCount != 0)
519 AFSFlushExtents( pFcb,
523 if( pFcb->OpenHandleCount == 0)
527 // Wait for any outstanding queued flushes to complete
530 AFSWaitOnQueuedFlushes( pFcb);
532 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
536 // Indicate the file access mode that is being released
539 stFileCleanup.FileAccess = pCcb->FileAccess;
542 // Push the request to the service
545 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
546 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
548 &pCcb->DirectoryCB->NameInformation.FileName,
549 &pObjectInfo->FileId,
551 sizeof( AFSFileCleanupCB),
557 // Remove the share access at this time since we may not get the close for sometime on this FO.
560 IoRemoveShareAccess( pFileObject,
564 // We don't need the name array after the user closes the handle on the file
567 if( pCcb->NameArray != NULL)
570 AFSFreeNameArray( pCcb->NameArray);
572 pCcb->NameArray = NULL;
576 // Decrement the open child handle count
579 if( pObjectInfo->ParentObjectInformation != NULL)
582 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
584 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
586 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
587 AFS_TRACE_LEVEL_VERBOSE,
588 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
589 pObjectInfo->ParentObjectInformation,
590 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
594 // And finally, release the Fcb if we acquired it.
597 AFSReleaseResource( &pFcb->NPFcb->Resource);
603 // Root or directory node
610 // Set the root Fcb to this node
616 // Fall through to below
620 case AFS_DIRECTORY_FCB:
624 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
627 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
630 &pFcb->NPFcb->Resource,
631 PsGetCurrentThread());
633 AFSAcquireExcl( &pFcb->NPFcb->Resource,
637 // Perform some final common processing
640 ASSERT( pFcb->OpenHandleCount != 0);
642 InterlockedDecrement( &pFcb->OpenHandleCount);
644 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
645 AFS_TRACE_LEVEL_VERBOSE,
646 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
648 pFcb->OpenHandleCount);
650 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
653 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
656 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
658 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
661 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
663 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
666 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
668 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
671 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
674 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
676 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
679 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
682 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
684 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
689 // If the count has dropped to zero and there is a pending delete
690 // then delete the node
693 if( pFcb->OpenHandleCount == 0 &&
694 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
698 // Try to notify the service about the delete
701 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
704 // Indicate the file access mode that is being released
707 stFileCleanup.FileAccess = pCcb->FileAccess;
710 // Push the request to the service
713 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
714 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
716 &pCcb->DirectoryCB->NameInformation.FileName,
717 &pObjectInfo->FileId,
719 sizeof( AFSFileCleanupCB),
723 if( !NT_SUCCESS( ntStatus) &&
724 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
727 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
728 AFS_TRACE_LEVEL_ERROR,
729 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
733 ntStatus = STATUS_SUCCESS;
735 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
740 ntStatus = STATUS_SUCCESS;
742 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
743 AFS_TRACE_LEVEL_VERBOSE,
744 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
748 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
750 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
752 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
754 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
755 (ULONG)FILE_ACTION_REMOVED);
758 // Now that the service has the entry has deleted we need to remove it from the parent
759 // tree so another lookup on the node will fail
762 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
765 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
768 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
771 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
776 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
777 AFS_TRACE_LEVEL_VERBOSE,
778 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
780 &pCcb->DirectoryCB->NameInformation.FileName);
786 // If there have been any updates to the node then push it to
793 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
796 ULONG ulNotifyFilter = 0;
798 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
800 if( pObjectInfo->ParentObjectInformation != NULL)
803 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
805 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
807 (ULONG)ulNotifyFilter,
808 (ULONG)FILE_ACTION_MODIFIED);
813 // Indicate the file access mode that is being released
816 stFileCleanup.FileAccess = pCcb->FileAccess;
818 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
819 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
821 &pCcb->DirectoryCB->NameInformation.FileName,
822 &pObjectInfo->FileId,
824 sizeof( AFSFileCleanupCB),
830 // Release the notification for this directory if there is one
833 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
834 &pControlDeviceExt->Specific.Control.DirNotifyList,
838 // Remove the share access at this time since we may not get the close for sometime on this FO.
841 IoRemoveShareAccess( pFileObject,
845 // We don't need the name array after the user closes the handle on the file
848 if( pCcb->NameArray != NULL)
851 AFSFreeNameArray( pCcb->NameArray);
853 pCcb->NameArray = NULL;
857 // Decrement the open child handle count
860 if( pObjectInfo->ParentObjectInformation != NULL)
863 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
865 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
867 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
868 AFS_TRACE_LEVEL_VERBOSE,
869 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
870 pObjectInfo->ParentObjectInformation,
871 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
875 // And finally, release the Fcb if we acquired it.
878 AFSReleaseResource( &pFcb->NPFcb->Resource);
883 case AFS_SYMBOLIC_LINK_FCB:
884 case AFS_MOUNT_POINT_FCB:
885 case AFS_DFS_LINK_FCB:
889 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
892 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
893 AFS_TRACE_LEVEL_VERBOSE,
894 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
895 &pFcb->NPFcb->Resource,
896 PsGetCurrentThread());
898 AFSAcquireExcl( &pFcb->NPFcb->Resource,
902 // Perform some final common processing
905 ASSERT( pFcb->OpenHandleCount != 0);
907 InterlockedDecrement( &pFcb->OpenHandleCount);
909 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
910 AFS_TRACE_LEVEL_VERBOSE,
911 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
913 pFcb->OpenHandleCount);
915 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
918 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
921 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
923 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
926 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
928 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
931 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
933 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
936 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
939 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
941 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
944 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
947 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
949 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
954 // If the count has dropped to zero and there is a pending delete
955 // then delete the node
958 if( pFcb->OpenHandleCount == 0 &&
959 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
963 // Try to notify the service about the delete
966 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
969 // Indicate the file access mode that is being released
972 stFileCleanup.FileAccess = pCcb->FileAccess;
975 // Push the request to the service
978 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
979 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
981 &pCcb->DirectoryCB->NameInformation.FileName,
982 &pObjectInfo->FileId,
984 sizeof( AFSFileCleanupCB),
988 if( !NT_SUCCESS( ntStatus) &&
989 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
992 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
993 AFS_TRACE_LEVEL_ERROR,
994 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
998 ntStatus = STATUS_SUCCESS;
1000 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1005 ntStatus = STATUS_SUCCESS;
1007 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1008 AFS_TRACE_LEVEL_VERBOSE,
1009 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1010 &pCcb->FullFileName,
1013 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1015 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
1017 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1019 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1020 (ULONG)FILE_ACTION_REMOVED);
1023 // Now that the service has the entry has deleted we need to remove it from the parent
1024 // tree so another lookup on the node will fail
1027 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1030 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1033 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1036 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1041 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1042 AFS_TRACE_LEVEL_VERBOSE,
1043 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1045 &pCcb->DirectoryCB->NameInformation.FileName);
1051 // If there have been any updates to the node then push it to
1058 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1061 ULONG ulNotifyFilter = 0;
1063 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1065 if( pObjectInfo->ParentObjectInformation != NULL)
1068 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1070 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1072 (ULONG)ulNotifyFilter,
1073 (ULONG)FILE_ACTION_MODIFIED);
1078 // Indicate the file access mode that is being released
1081 stFileCleanup.FileAccess = pCcb->FileAccess;
1083 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1084 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1086 &pCcb->DirectoryCB->NameInformation.FileName,
1087 &pObjectInfo->FileId,
1089 sizeof( AFSFileCleanupCB),
1095 // Remove the share access at this time since we may not get the close for sometime on this FO.
1098 IoRemoveShareAccess( pFileObject,
1099 &pFcb->ShareAccess);
1102 // We don't need the name array after the user closes the handle on the file
1105 if( pCcb->NameArray != NULL)
1108 AFSFreeNameArray( pCcb->NameArray);
1110 pCcb->NameArray = NULL;
1114 // Decrement the open child handle count
1117 if( pObjectInfo->ParentObjectInformation != NULL)
1120 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1122 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1124 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1125 AFS_TRACE_LEVEL_VERBOSE,
1126 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1127 pObjectInfo->ParentObjectInformation,
1128 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1132 // And finally, release the Fcb if we acquired it.
1135 AFSReleaseResource( &pFcb->NPFcb->Resource);
1140 case AFS_SPECIAL_SHARE_FCB:
1143 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1144 AFS_TRACE_LEVEL_VERBOSE,
1145 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1146 &pFcb->NPFcb->Resource,
1147 PsGetCurrentThread());
1149 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1152 ASSERT( pFcb->OpenHandleCount != 0);
1154 InterlockedDecrement( &pFcb->OpenHandleCount);
1156 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1157 AFS_TRACE_LEVEL_VERBOSE,
1158 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1160 pFcb->OpenHandleCount);
1163 // Decrement the open child handle count
1166 if( pObjectInfo->ParentObjectInformation != NULL &&
1167 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1170 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1175 pObjectInfo->ParentObjectInformation,
1176 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1180 // And finally, release the Fcb if we acquired it.
1183 AFSReleaseResource( &pFcb->NPFcb->Resource);
1190 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1191 AFS_TRACE_LEVEL_WARNING,
1192 "AFSCleanup Processing unknown node type %d\n",
1193 pFcb->Header.NodeTypeCode);
1201 if( pFileObject != NULL)
1205 // Setup the fileobject flags to indicate cleanup is complete.
1208 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1212 // Complete the request
1215 AFSCompleteRequest( Irp, ntStatus);
1217 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
1222 "EXCEPTION - AFSCleanup\n");