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();
112 // Perform the cleanup functionality depending on the type of node it is
115 switch( pFcb->Header.NodeTypeCode)
121 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
122 AFS_TRACE_LEVEL_VERBOSE,
123 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
124 &pFcb->NPFcb->Resource,
125 PsGetCurrentThread());
127 AFSAcquireExcl( &pFcb->NPFcb->Resource,
130 ASSERT( pFcb->OpenHandleCount != 0);
132 InterlockedDecrement( &pFcb->OpenHandleCount);
134 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
135 AFS_TRACE_LEVEL_VERBOSE,
136 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
138 pFcb->OpenHandleCount);
140 AFSReleaseResource( &pFcb->NPFcb->Resource);
142 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
143 &pControlDeviceExt->Specific.Control.DirNotifyList,
152 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
153 AFS_TRACE_LEVEL_VERBOSE,
154 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
155 &pFcb->NPFcb->Resource,
156 PsGetCurrentThread());
158 AFSAcquireExcl( &pFcb->NPFcb->Resource,
161 ASSERT( pFcb->OpenHandleCount != 0);
163 InterlockedDecrement( &pFcb->OpenHandleCount);
165 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
166 AFS_TRACE_LEVEL_VERBOSE,
167 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
169 pFcb->OpenHandleCount);
172 // Decrement the open child handle count
175 if( pObjectInfo->ParentObjectInformation != NULL &&
176 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
179 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
181 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
182 AFS_TRACE_LEVEL_VERBOSE,
183 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
184 pObjectInfo->ParentObjectInformation,
185 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
189 // And finally, release the Fcb if we acquired it.
192 AFSReleaseResource( &pFcb->NPFcb->Resource);
198 // This Fcb represents a file
205 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
208 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
209 AFS_TRACE_LEVEL_VERBOSE,
210 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
211 &pFcb->NPFcb->Resource,
212 PsGetCurrentThread());
214 AFSAcquireExcl( &pFcb->NPFcb->Resource,
218 // Uninitialize the cache map. This call is unconditional.
221 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
222 AFS_TRACE_LEVEL_VERBOSE,
223 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
227 CcUninitializeCacheMap( pFileObject,
232 // Unlock all outstanding locks on the file, again, unconditionally
235 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
237 IoGetRequestorProcess( Irp),
241 // Tell the service to unlock all on the file
244 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
247 // Perform some final common processing
250 ASSERT( pFcb->OpenHandleCount != 0);
252 InterlockedDecrement( &pFcb->OpenHandleCount);
254 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
255 AFS_TRACE_LEVEL_VERBOSE,
256 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
258 pFcb->OpenHandleCount);
260 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
263 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
266 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
268 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
271 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
273 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
275 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
278 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
280 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
283 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
286 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
288 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
291 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
294 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
296 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
299 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
302 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
304 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
308 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
311 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
315 // If the count has dropped to zero and there is a pending delete
316 // then delete the node
319 if( pFcb->OpenHandleCount == 0 &&
320 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
324 // Stop anything possibly in process
327 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
328 AFS_TRACE_LEVEL_VERBOSE,
329 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
330 &pFcb->NPFcb->Specific.File.ExtentsResource,
331 PsGetCurrentThread());
333 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
336 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
338 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
342 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
343 AFS_TRACE_LEVEL_VERBOSE,
344 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
345 &pFcb->NPFcb->Specific.File.ExtentsResource,
346 PsGetCurrentThread());
348 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
351 // Before telling the server about the deleted file, tear down all extents for
355 AFSTearDownFcbExtents( pFcb);
357 ntStatus = STATUS_SUCCESS;
359 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
362 // Push the request to the service
365 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
366 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
368 &pCcb->DirectoryCB->NameInformation.FileName,
369 &pObjectInfo->FileId,
371 sizeof( AFSFileCleanupCB),
375 if( !NT_SUCCESS( ntStatus) &&
376 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
379 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
380 AFS_TRACE_LEVEL_ERROR,
381 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
385 ntStatus = STATUS_SUCCESS;
387 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
392 ntStatus = STATUS_SUCCESS;
394 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
395 AFS_TRACE_LEVEL_VERBOSE,
396 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
400 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
402 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
404 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
406 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
407 (ULONG)FILE_ACTION_REMOVED);
410 // Now that the service has the entry has deleted we need to remove it from the parent
411 // tree so another lookup on the node will fail
414 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
417 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
420 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
421 AFS_TRACE_LEVEL_VERBOSE,
422 "AFSCleanup DE %p for %wZ removing entry\n",
424 &pCcb->DirectoryCB->NameInformation.FileName);
426 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
429 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
435 AFS_TRACE_LEVEL_VERBOSE,
436 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
438 &pCcb->DirectoryCB->NameInformation.FileName);
445 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
448 ULONG ulNotifyFilter = 0;
450 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
452 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
454 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
456 (ULONG)ulNotifyFilter,
457 (ULONG)FILE_ACTION_MODIFIED);
461 // Flush out any dirty pages on every handle close to reduce strain on the afs cache
464 if( CcIsFileCached( pIrpSp->FileObject))
470 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
475 if( !NT_SUCCESS( stIoSB.Status))
478 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
479 AFS_TRACE_LEVEL_ERROR,
480 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
482 pObjectInfo->FileId.Cell,
483 pObjectInfo->FileId.Volume,
484 pObjectInfo->FileId.Vnode,
485 pObjectInfo->FileId.Unique,
489 ntStatus = stIoSB.Status;
492 __except( EXCEPTION_EXECUTE_HANDLER)
495 ntStatus = GetExceptionCode();
500 // Attempt to flush any dirty extents to the server. This may be a little
501 // aggressive, to flush whenever the handle is closed, but it ensures
505 if( pFcb->Specific.File.ExtentsDirtyCount)
508 AFSFlushExtents( pFcb);
511 if( pFcb->OpenHandleCount == 0)
515 // Wait for any outstanding queued flushes to complete
518 AFSWaitOnQueuedFlushes( pFcb);
520 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
524 // Push the request to the service
527 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
528 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
530 &pCcb->DirectoryCB->NameInformation.FileName,
531 &pObjectInfo->FileId,
533 sizeof( AFSFileCleanupCB),
539 // Remove the share access at this time since we may not get the close for sometime on this FO.
542 IoRemoveShareAccess( pFileObject,
546 // We don't need the name array after the user closes the handle on the file
549 if( pCcb->NameArray != NULL)
552 AFSFreeNameArray( pCcb->NameArray);
554 pCcb->NameArray = NULL;
558 // Decrement the open child handle count
561 if( pObjectInfo->ParentObjectInformation != NULL)
564 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
566 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
568 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
569 AFS_TRACE_LEVEL_VERBOSE,
570 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
571 pObjectInfo->ParentObjectInformation,
572 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
576 // And finally, release the Fcb if we acquired it.
579 AFSReleaseResource( &pFcb->NPFcb->Resource);
585 // Root or directory node
592 // Set the root Fcb to this node
598 // Fall through to below
602 case AFS_DIRECTORY_FCB:
606 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
609 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
610 AFS_TRACE_LEVEL_VERBOSE,
611 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
612 &pFcb->NPFcb->Resource,
613 PsGetCurrentThread());
615 AFSAcquireExcl( &pFcb->NPFcb->Resource,
619 // Perform some final common processing
622 ASSERT( pFcb->OpenHandleCount != 0);
624 InterlockedDecrement( &pFcb->OpenHandleCount);
626 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
627 AFS_TRACE_LEVEL_VERBOSE,
628 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
630 pFcb->OpenHandleCount);
632 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
635 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
638 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
640 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
643 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
645 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
648 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
650 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
653 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
656 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
658 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
661 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
664 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
666 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
671 // If the count has dropped to zero and there is a pending delete
672 // then delete the node
675 if( pFcb->OpenHandleCount == 0 &&
676 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
680 // Try to notify the service about the delete
683 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
686 // Push the request to the service
689 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
690 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
692 &pCcb->DirectoryCB->NameInformation.FileName,
693 &pObjectInfo->FileId,
695 sizeof( AFSFileCleanupCB),
699 if( !NT_SUCCESS( ntStatus) &&
700 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
703 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
704 AFS_TRACE_LEVEL_ERROR,
705 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
709 ntStatus = STATUS_SUCCESS;
711 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
716 ntStatus = STATUS_SUCCESS;
718 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
719 AFS_TRACE_LEVEL_VERBOSE,
720 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
724 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
726 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
728 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
730 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
731 (ULONG)FILE_ACTION_REMOVED);
734 // Now that the service has the entry has deleted we need to remove it from the parent
735 // tree so another lookup on the node will fail
738 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
741 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
744 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
747 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
752 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
753 AFS_TRACE_LEVEL_VERBOSE,
754 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
756 &pCcb->DirectoryCB->NameInformation.FileName);
762 // If there have been any updates to the node then push it to
769 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
772 ULONG ulNotifyFilter = 0;
774 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
776 if( pObjectInfo->ParentObjectInformation != NULL)
779 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
781 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
783 (ULONG)ulNotifyFilter,
784 (ULONG)FILE_ACTION_MODIFIED);
788 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
789 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
791 &pCcb->DirectoryCB->NameInformation.FileName,
792 &pObjectInfo->FileId,
794 sizeof( AFSFileCleanupCB),
800 // Release the notification for this directory if there is one
803 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
804 &pControlDeviceExt->Specific.Control.DirNotifyList,
808 // Remove the share access at this time since we may not get the close for sometime on this FO.
811 IoRemoveShareAccess( pFileObject,
815 // We don't need the name array after the user closes the handle on the file
818 if( pCcb->NameArray != NULL)
821 AFSFreeNameArray( pCcb->NameArray);
823 pCcb->NameArray = NULL;
827 // Decrement the open child handle count
830 if( pObjectInfo->ParentObjectInformation != NULL)
833 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
835 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
837 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
838 AFS_TRACE_LEVEL_VERBOSE,
839 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
840 pObjectInfo->ParentObjectInformation,
841 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
845 // And finally, release the Fcb if we acquired it.
848 AFSReleaseResource( &pFcb->NPFcb->Resource);
853 case AFS_SYMBOLIC_LINK_FCB:
854 case AFS_MOUNT_POINT_FCB:
855 case AFS_DFS_LINK_FCB:
859 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
862 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
863 AFS_TRACE_LEVEL_VERBOSE,
864 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
865 &pFcb->NPFcb->Resource,
866 PsGetCurrentThread());
868 AFSAcquireExcl( &pFcb->NPFcb->Resource,
872 // Perform some final common processing
875 ASSERT( pFcb->OpenHandleCount != 0);
877 InterlockedDecrement( &pFcb->OpenHandleCount);
879 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
880 AFS_TRACE_LEVEL_VERBOSE,
881 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
883 pFcb->OpenHandleCount);
885 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
888 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
891 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
893 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
896 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
898 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
901 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
903 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
906 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
909 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
911 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
914 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
917 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
919 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
924 // If the count has dropped to zero and there is a pending delete
925 // then delete the node
928 if( pFcb->OpenHandleCount == 0 &&
929 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
933 // Try to notify the service about the delete
936 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
939 // Push the request to the service
942 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
943 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
945 &pCcb->DirectoryCB->NameInformation.FileName,
946 &pObjectInfo->FileId,
948 sizeof( AFSFileCleanupCB),
952 if( !NT_SUCCESS( ntStatus) &&
953 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
956 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
957 AFS_TRACE_LEVEL_ERROR,
958 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
962 ntStatus = STATUS_SUCCESS;
964 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
969 ntStatus = STATUS_SUCCESS;
971 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
972 AFS_TRACE_LEVEL_VERBOSE,
973 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
977 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
979 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
981 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
983 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
984 (ULONG)FILE_ACTION_REMOVED);
987 // Now that the service has the entry has deleted we need to remove it from the parent
988 // tree so another lookup on the node will fail
991 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
994 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
997 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1000 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1005 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1006 AFS_TRACE_LEVEL_VERBOSE,
1007 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1009 &pCcb->DirectoryCB->NameInformation.FileName);
1015 // If there have been any updates to the node then push it to
1022 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1025 ULONG ulNotifyFilter = 0;
1027 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1029 if( pObjectInfo->ParentObjectInformation != NULL)
1032 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1034 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1036 (ULONG)ulNotifyFilter,
1037 (ULONG)FILE_ACTION_MODIFIED);
1041 AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1042 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1044 &pCcb->DirectoryCB->NameInformation.FileName,
1045 &pObjectInfo->FileId,
1047 sizeof( AFSFileCleanupCB),
1053 // Remove the share access at this time since we may not get the close for sometime on this FO.
1056 IoRemoveShareAccess( pFileObject,
1057 &pFcb->ShareAccess);
1060 // We don't need the name array after the user closes the handle on the file
1063 if( pCcb->NameArray != NULL)
1066 AFSFreeNameArray( pCcb->NameArray);
1068 pCcb->NameArray = NULL;
1072 // Decrement the open child handle count
1075 if( pObjectInfo->ParentObjectInformation != NULL)
1078 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1080 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1082 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1083 AFS_TRACE_LEVEL_VERBOSE,
1084 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1085 pObjectInfo->ParentObjectInformation,
1086 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1090 // And finally, release the Fcb if we acquired it.
1093 AFSReleaseResource( &pFcb->NPFcb->Resource);
1098 case AFS_SPECIAL_SHARE_FCB:
1101 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1102 AFS_TRACE_LEVEL_VERBOSE,
1103 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1104 &pFcb->NPFcb->Resource,
1105 PsGetCurrentThread());
1107 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1110 ASSERT( pFcb->OpenHandleCount != 0);
1112 InterlockedDecrement( &pFcb->OpenHandleCount);
1114 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1115 AFS_TRACE_LEVEL_VERBOSE,
1116 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1118 pFcb->OpenHandleCount);
1121 // Decrement the open child handle count
1124 if( pObjectInfo->ParentObjectInformation != NULL &&
1125 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1128 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1130 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1131 AFS_TRACE_LEVEL_VERBOSE,
1132 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1133 pObjectInfo->ParentObjectInformation,
1134 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1138 // And finally, release the Fcb if we acquired it.
1141 AFSReleaseResource( &pFcb->NPFcb->Resource);
1148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1149 AFS_TRACE_LEVEL_WARNING,
1150 "AFSCleanup Processing unknown node type %d\n",
1151 pFcb->Header.NodeTypeCode);
1159 if( pFileObject != NULL)
1163 // Setup the fileobject flags to indicate cleanup is complete.
1166 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1170 // Complete the request
1173 AFSCompleteRequest( Irp, ntStatus);
1175 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
1180 "EXCEPTION - AFSCleanup\n");