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 // Uninitialize the cache map. This call is unconditional.
223 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
224 AFS_TRACE_LEVEL_VERBOSE,
225 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
229 CcUninitializeCacheMap( pFileObject,
234 // Unlock all outstanding locks on the file, again, unconditionally
237 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
239 IoGetRequestorProcess( Irp),
243 // Tell the service to unlock all on the file
246 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
249 // Perform some final common processing
252 ASSERT( pFcb->OpenHandleCount != 0);
254 InterlockedDecrement( &pFcb->OpenHandleCount);
256 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
257 AFS_TRACE_LEVEL_VERBOSE,
258 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
260 pFcb->OpenHandleCount);
262 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
265 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
268 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
270 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
273 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
275 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
277 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
280 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
282 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
285 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
288 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
290 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
293 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
296 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
298 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
301 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
304 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
306 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
310 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
313 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
317 // If the count has dropped to zero and there is a pending delete
318 // then delete the node
321 if( pFcb->OpenHandleCount == 0 &&
322 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
326 // Stop anything possibly in process
329 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
330 AFS_TRACE_LEVEL_VERBOSE,
331 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
332 &pFcb->NPFcb->Specific.File.ExtentsResource,
333 PsGetCurrentThread());
335 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
338 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
340 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
344 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
345 AFS_TRACE_LEVEL_VERBOSE,
346 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
347 &pFcb->NPFcb->Specific.File.ExtentsResource,
348 PsGetCurrentThread());
350 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
353 // Before telling the server about the deleted file, tear down all extents for
357 AFSTearDownFcbExtents( pFcb,
360 ntStatus = STATUS_SUCCESS;
362 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
365 // Indicate the file access mode that is being released
368 stFileCleanup.FileAccess = pCcb->FileAccess;
371 // Push the request to the service
374 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
375 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
377 &pCcb->DirectoryCB->NameInformation.FileName,
378 &pObjectInfo->FileId,
380 sizeof( AFSFileCleanupCB),
384 if( !NT_SUCCESS( ntStatus) &&
385 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
388 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
389 AFS_TRACE_LEVEL_ERROR,
390 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
394 ntStatus = STATUS_SUCCESS;
396 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
401 ntStatus = STATUS_SUCCESS;
403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
404 AFS_TRACE_LEVEL_VERBOSE,
405 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
409 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
411 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
413 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
415 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
416 (ULONG)FILE_ACTION_REMOVED);
419 // Now that the service has the entry has deleted we need to remove it from the parent
420 // tree so another lookup on the node will fail
423 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
426 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
429 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
430 AFS_TRACE_LEVEL_VERBOSE,
431 "AFSCleanup DE %p for %wZ removing entry\n",
433 &pCcb->DirectoryCB->NameInformation.FileName);
435 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
438 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
443 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
444 AFS_TRACE_LEVEL_VERBOSE,
445 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
447 &pCcb->DirectoryCB->NameInformation.FileName);
454 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
457 ULONG ulNotifyFilter = 0;
459 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
461 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
463 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
465 (ULONG)ulNotifyFilter,
466 (ULONG)FILE_ACTION_MODIFIED);
470 // Flush out any dirty pages on every handle close to reduce strain on the afs cache
473 if( CcIsFileCached( pIrpSp->FileObject))
479 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
484 if( !NT_SUCCESS( stIoSB.Status))
487 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
488 AFS_TRACE_LEVEL_ERROR,
489 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
491 pObjectInfo->FileId.Cell,
492 pObjectInfo->FileId.Volume,
493 pObjectInfo->FileId.Vnode,
494 pObjectInfo->FileId.Unique,
498 ntStatus = stIoSB.Status;
501 __except( EXCEPTION_EXECUTE_HANDLER)
504 ntStatus = GetExceptionCode();
509 // Attempt to flush any dirty extents to the server. This may be a little
510 // aggressive, to flush whenever the handle is closed, but it ensures
514 if( pFcb->Specific.File.ExtentsDirtyCount)
517 AFSFlushExtents( pFcb,
521 if( pFcb->OpenHandleCount == 0)
525 // Wait for any outstanding queued flushes to complete
528 AFSWaitOnQueuedFlushes( pFcb);
530 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
534 // Indicate the file access mode that is being released
537 stFileCleanup.FileAccess = pCcb->FileAccess;
540 // Push the request to the service
543 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
544 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
546 &pCcb->DirectoryCB->NameInformation.FileName,
547 &pObjectInfo->FileId,
549 sizeof( AFSFileCleanupCB),
555 // Remove the share access at this time since we may not get the close for sometime on this FO.
558 IoRemoveShareAccess( pFileObject,
562 // We don't need the name array after the user closes the handle on the file
565 if( pCcb->NameArray != NULL)
568 AFSFreeNameArray( pCcb->NameArray);
570 pCcb->NameArray = NULL;
574 // Decrement the open child handle count
577 if( pObjectInfo->ParentObjectInformation != NULL)
580 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
582 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
584 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
585 AFS_TRACE_LEVEL_VERBOSE,
586 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
587 pObjectInfo->ParentObjectInformation,
588 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
592 // And finally, release the Fcb if we acquired it.
595 AFSReleaseResource( &pFcb->NPFcb->Resource);
601 // Root or directory node
608 // Set the root Fcb to this node
614 // Fall through to below
618 case AFS_DIRECTORY_FCB:
622 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
625 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
626 AFS_TRACE_LEVEL_VERBOSE,
627 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
628 &pFcb->NPFcb->Resource,
629 PsGetCurrentThread());
631 AFSAcquireExcl( &pFcb->NPFcb->Resource,
635 // Perform some final common processing
638 ASSERT( pFcb->OpenHandleCount != 0);
640 InterlockedDecrement( &pFcb->OpenHandleCount);
642 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
643 AFS_TRACE_LEVEL_VERBOSE,
644 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
646 pFcb->OpenHandleCount);
648 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
651 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
654 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
656 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
659 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
661 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
664 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
666 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
669 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
672 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
674 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
677 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
680 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
682 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
687 // If the count has dropped to zero and there is a pending delete
688 // then delete the node
691 if( pFcb->OpenHandleCount == 0 &&
692 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
696 // Try to notify the service about the delete
699 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
702 // Indicate the file access mode that is being released
705 stFileCleanup.FileAccess = pCcb->FileAccess;
708 // Push the request to the service
711 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
712 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
714 &pCcb->DirectoryCB->NameInformation.FileName,
715 &pObjectInfo->FileId,
717 sizeof( AFSFileCleanupCB),
721 if( !NT_SUCCESS( ntStatus) &&
722 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
725 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
726 AFS_TRACE_LEVEL_ERROR,
727 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
731 ntStatus = STATUS_SUCCESS;
733 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
738 ntStatus = STATUS_SUCCESS;
740 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
741 AFS_TRACE_LEVEL_VERBOSE,
742 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
746 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
748 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
750 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
752 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
753 (ULONG)FILE_ACTION_REMOVED);
756 // Now that the service has the entry has deleted we need to remove it from the parent
757 // tree so another lookup on the node will fail
760 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
763 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
766 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
769 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
774 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
775 AFS_TRACE_LEVEL_VERBOSE,
776 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
778 &pCcb->DirectoryCB->NameInformation.FileName);
784 // If there have been any updates to the node then push it to
791 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
794 ULONG ulNotifyFilter = 0;
796 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
798 if( pObjectInfo->ParentObjectInformation != NULL)
801 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
803 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
805 (ULONG)ulNotifyFilter,
806 (ULONG)FILE_ACTION_MODIFIED);
811 // Indicate the file access mode that is being released
814 stFileCleanup.FileAccess = pCcb->FileAccess;
816 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
817 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
819 &pCcb->DirectoryCB->NameInformation.FileName,
820 &pObjectInfo->FileId,
822 sizeof( AFSFileCleanupCB),
828 // Release the notification for this directory if there is one
831 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
832 &pControlDeviceExt->Specific.Control.DirNotifyList,
836 // Remove the share access at this time since we may not get the close for sometime on this FO.
839 IoRemoveShareAccess( pFileObject,
843 // We don't need the name array after the user closes the handle on the file
846 if( pCcb->NameArray != NULL)
849 AFSFreeNameArray( pCcb->NameArray);
851 pCcb->NameArray = NULL;
855 // Decrement the open child handle count
858 if( pObjectInfo->ParentObjectInformation != NULL)
861 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
863 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
865 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
866 AFS_TRACE_LEVEL_VERBOSE,
867 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
868 pObjectInfo->ParentObjectInformation,
869 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
873 // And finally, release the Fcb if we acquired it.
876 AFSReleaseResource( &pFcb->NPFcb->Resource);
881 case AFS_SYMBOLIC_LINK_FCB:
882 case AFS_MOUNT_POINT_FCB:
883 case AFS_DFS_LINK_FCB:
887 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
890 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
893 &pFcb->NPFcb->Resource,
894 PsGetCurrentThread());
896 AFSAcquireExcl( &pFcb->NPFcb->Resource,
900 // Perform some final common processing
903 ASSERT( pFcb->OpenHandleCount != 0);
905 InterlockedDecrement( &pFcb->OpenHandleCount);
907 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
908 AFS_TRACE_LEVEL_VERBOSE,
909 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
911 pFcb->OpenHandleCount);
913 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
916 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
919 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
921 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
924 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
926 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
929 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
931 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
934 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
937 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
939 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
942 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
945 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
947 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
952 // If the count has dropped to zero and there is a pending delete
953 // then delete the node
956 if( pFcb->OpenHandleCount == 0 &&
957 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
961 // Try to notify the service about the delete
964 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
967 // Indicate the file access mode that is being released
970 stFileCleanup.FileAccess = pCcb->FileAccess;
973 // Push the request to the service
976 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
977 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
979 &pCcb->DirectoryCB->NameInformation.FileName,
980 &pObjectInfo->FileId,
982 sizeof( AFSFileCleanupCB),
986 if( !NT_SUCCESS( ntStatus) &&
987 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991 AFS_TRACE_LEVEL_ERROR,
992 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
996 ntStatus = STATUS_SUCCESS;
998 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1003 ntStatus = STATUS_SUCCESS;
1005 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1006 AFS_TRACE_LEVEL_VERBOSE,
1007 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1008 &pCcb->FullFileName,
1011 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1013 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
1015 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1017 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1018 (ULONG)FILE_ACTION_REMOVED);
1021 // Now that the service has the entry has deleted we need to remove it from the parent
1022 // tree so another lookup on the node will fail
1025 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1028 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1031 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1034 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1039 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1040 AFS_TRACE_LEVEL_VERBOSE,
1041 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1043 &pCcb->DirectoryCB->NameInformation.FileName);
1049 // If there have been any updates to the node then push it to
1056 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1059 ULONG ulNotifyFilter = 0;
1061 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1063 if( pObjectInfo->ParentObjectInformation != NULL)
1066 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1068 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1070 (ULONG)ulNotifyFilter,
1071 (ULONG)FILE_ACTION_MODIFIED);
1076 // Indicate the file access mode that is being released
1079 stFileCleanup.FileAccess = pCcb->FileAccess;
1081 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1082 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1084 &pCcb->DirectoryCB->NameInformation.FileName,
1085 &pObjectInfo->FileId,
1087 sizeof( AFSFileCleanupCB),
1093 // Remove the share access at this time since we may not get the close for sometime on this FO.
1096 IoRemoveShareAccess( pFileObject,
1097 &pFcb->ShareAccess);
1100 // We don't need the name array after the user closes the handle on the file
1103 if( pCcb->NameArray != NULL)
1106 AFSFreeNameArray( pCcb->NameArray);
1108 pCcb->NameArray = NULL;
1112 // Decrement the open child handle count
1115 if( pObjectInfo->ParentObjectInformation != NULL)
1118 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1120 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1122 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1123 AFS_TRACE_LEVEL_VERBOSE,
1124 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1125 pObjectInfo->ParentObjectInformation,
1126 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1130 // And finally, release the Fcb if we acquired it.
1133 AFSReleaseResource( &pFcb->NPFcb->Resource);
1138 case AFS_SPECIAL_SHARE_FCB:
1141 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1142 AFS_TRACE_LEVEL_VERBOSE,
1143 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1144 &pFcb->NPFcb->Resource,
1145 PsGetCurrentThread());
1147 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1150 ASSERT( pFcb->OpenHandleCount != 0);
1152 InterlockedDecrement( &pFcb->OpenHandleCount);
1154 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1158 pFcb->OpenHandleCount);
1161 // Decrement the open child handle count
1164 if( pObjectInfo->ParentObjectInformation != NULL &&
1165 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1168 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1170 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1171 AFS_TRACE_LEVEL_VERBOSE,
1172 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1173 pObjectInfo->ParentObjectInformation,
1174 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1178 // And finally, release the Fcb if we acquired it.
1181 AFSReleaseResource( &pFcb->NPFcb->Resource);
1188 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1189 AFS_TRACE_LEVEL_WARNING,
1190 "AFSCleanup Processing unknown node type %d\n",
1191 pFcb->Header.NodeTypeCode);
1199 if( pFileObject != NULL)
1203 // Setup the fileobject flags to indicate cleanup is complete.
1206 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1210 // Complete the request
1213 AFSCompleteRequest( Irp, ntStatus);
1215 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
1220 "EXCEPTION - AFSCleanup\n");