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;
76 if( AFSRDRDeviceObject == NULL)
80 // Let this through, it's a cleanup on the library control device
83 try_return( ntStatus);
86 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
87 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
90 // Set some initial variables to make processing easier
93 pFileObject = pIrpSp->FileObject;
95 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
97 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
101 try_return( ntStatus);
104 pObjectInfo = pFcb->ObjectInformation;
106 pRootFcb = pObjectInfo->VolumeCB->RootFcb;
108 RtlZeroMemory( &stFileCleanup,
109 sizeof( AFSFileCleanupCB));
111 stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
113 stFileCleanup.Identifier = (ULONGLONG)pFileObject;
116 // Allocate our return buffer
119 pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
121 AFS_GENERIC_MEMORY_32_TAG);
123 if( pResultCB == NULL)
126 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
129 RtlZeroMemory( pResultCB,
132 ulResultLen = PAGE_SIZE;
136 // Perform the cleanup functionality depending on the type of node it is
139 switch( pFcb->Header.NodeTypeCode)
145 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
146 AFS_TRACE_LEVEL_VERBOSE,
147 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
148 &pFcb->NPFcb->Resource,
149 PsGetCurrentThread());
151 AFSAcquireExcl( &pFcb->NPFcb->Resource,
154 ASSERT( pFcb->OpenHandleCount != 0);
156 InterlockedDecrement( &pFcb->OpenHandleCount);
158 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
159 AFS_TRACE_LEVEL_VERBOSE,
160 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
162 pFcb->OpenHandleCount);
164 AFSReleaseResource( &pFcb->NPFcb->Resource);
166 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
167 &pControlDeviceExt->Specific.Control.DirNotifyList,
176 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
177 AFS_TRACE_LEVEL_VERBOSE,
178 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
179 &pFcb->NPFcb->Resource,
180 PsGetCurrentThread());
182 AFSAcquireExcl( &pFcb->NPFcb->Resource,
185 ASSERT( pFcb->OpenHandleCount != 0);
188 // Decrement the open child handle count
191 if( pObjectInfo->ParentObjectInformation != NULL &&
192 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
195 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
197 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
198 AFS_TRACE_LEVEL_VERBOSE,
199 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
200 pObjectInfo->ParentObjectInformation,
201 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
204 InterlockedDecrement( &pFcb->OpenHandleCount);
206 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
207 AFS_TRACE_LEVEL_VERBOSE,
208 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
210 pFcb->OpenHandleCount);
213 // And finally, release the Fcb if we acquired it.
216 AFSReleaseResource( &pFcb->NPFcb->Resource);
222 // This Fcb represents a file
229 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
232 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
233 AFS_TRACE_LEVEL_VERBOSE,
234 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
235 &pFcb->NPFcb->Resource,
236 PsGetCurrentThread());
238 AFSAcquireExcl( &pFcb->NPFcb->Resource,
242 // If the handle has write permission ...
245 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
246 CcIsFileCached( pIrpSp->FileObject))
252 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
257 if( !NT_SUCCESS( stIoSB.Status))
260 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
261 AFS_TRACE_LEVEL_ERROR,
262 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
264 pObjectInfo->FileId.Cell,
265 pObjectInfo->FileId.Volume,
266 pObjectInfo->FileId.Vnode,
267 pObjectInfo->FileId.Unique,
271 ntStatus = stIoSB.Status;
274 __except( EXCEPTION_EXECUTE_HANDLER)
277 ntStatus = GetExceptionCode();
282 // Uninitialize the cache map. This call is unconditional.
285 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
286 AFS_TRACE_LEVEL_VERBOSE,
287 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
291 CcUninitializeCacheMap( pFileObject,
296 // Unlock all outstanding locks on the file, again, unconditionally
299 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
301 IoGetRequestorProcess( Irp),
305 // Tell the service to unlock all on the file
308 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
311 // Perform some final common processing
314 ASSERT( pFcb->OpenHandleCount != 0);
316 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
319 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
322 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
324 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
327 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
329 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
331 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
334 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
336 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
339 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
342 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
344 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
347 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
350 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
352 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
355 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
358 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
360 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
364 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
367 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
371 // If the count has dropped to one and there is a pending delete
372 // then delete the node. The final count will be decremented just
373 // before the Fcb->NPFcb->Resource is released.
376 if( pFcb->OpenHandleCount == 1 &&
377 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
381 // Stop anything possibly in process
384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
385 AFS_TRACE_LEVEL_VERBOSE,
386 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
387 &pFcb->NPFcb->Specific.File.ExtentsResource,
388 PsGetCurrentThread());
390 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
393 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
395 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
399 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
400 AFS_TRACE_LEVEL_VERBOSE,
401 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
402 &pFcb->NPFcb->Specific.File.ExtentsResource,
403 PsGetCurrentThread());
405 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
408 // Before telling the server about the deleted file, tear down all extents for
412 AFSTearDownFcbExtents( pFcb,
415 ntStatus = STATUS_SUCCESS;
417 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
420 // Indicate the file access mode that is being released
423 stFileCleanup.FileAccess = pCcb->FileAccess;
426 // Push the request to the service
429 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
430 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
432 &pCcb->DirectoryCB->NameInformation.FileName,
433 &pObjectInfo->FileId,
435 sizeof( AFSFileCleanupCB),
439 if( !NT_SUCCESS( ntStatus) &&
440 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
443 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
444 AFS_TRACE_LEVEL_ERROR,
445 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
449 ntStatus = STATUS_SUCCESS;
451 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
456 ntStatus = STATUS_SUCCESS;
458 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
459 AFS_TRACE_LEVEL_VERBOSE,
460 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
464 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
466 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
468 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
470 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
471 (ULONG)FILE_ACTION_REMOVED);
474 // Now that the service has the entry has deleted we need to remove it from the parent
475 // tree so another lookup on the node will fail
478 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
481 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
484 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
485 AFS_TRACE_LEVEL_VERBOSE,
486 "AFSCleanup DE %p for %wZ removing entry\n",
488 &pCcb->DirectoryCB->NameInformation.FileName);
490 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
493 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
498 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
499 AFS_TRACE_LEVEL_VERBOSE,
500 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
502 &pCcb->DirectoryCB->NameInformation.FileName);
509 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
512 ULONG ulNotifyFilter = 0;
514 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
516 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
518 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
520 (ULONG)ulNotifyFilter,
521 (ULONG)FILE_ACTION_MODIFIED);
525 // Attempt to flush any dirty extents to the server. This may be a little
526 // aggressive, to flush whenever the handle is closed, but it ensures
530 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
531 pFcb->Specific.File.ExtentsDirtyCount != 0)
534 AFSFlushExtents( pFcb,
538 if( pFcb->OpenHandleCount == 1)
542 // Wait for any outstanding queued flushes to complete
545 AFSWaitOnQueuedFlushes( pFcb);
547 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
551 // Indicate the file access mode that is being released
554 stFileCleanup.FileAccess = pCcb->FileAccess;
557 // Push the request to the service
560 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
561 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
563 &pCcb->DirectoryCB->NameInformation.FileName,
564 &pObjectInfo->FileId,
566 sizeof( AFSFileCleanupCB),
570 ntStatus = STATUS_SUCCESS;
574 // Remove the share access at this time since we may not get the close for sometime on this FO.
577 IoRemoveShareAccess( pFileObject,
581 // We don't need the name array after the user closes the handle on the file
584 if( pCcb->NameArray != NULL)
587 AFSFreeNameArray( pCcb->NameArray);
589 pCcb->NameArray = NULL;
593 // Decrement the open child handle count
596 if( pObjectInfo->ParentObjectInformation != NULL)
599 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
601 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
603 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
604 AFS_TRACE_LEVEL_VERBOSE,
605 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
606 pObjectInfo->ParentObjectInformation,
607 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
610 InterlockedDecrement( &pFcb->OpenHandleCount);
612 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
613 AFS_TRACE_LEVEL_VERBOSE,
614 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
616 pFcb->OpenHandleCount);
619 // And finally, release the Fcb if we acquired it.
622 AFSReleaseResource( &pFcb->NPFcb->Resource);
628 // Root or directory node
635 // Set the root Fcb to this node
641 // Fall through to below
645 case AFS_DIRECTORY_FCB:
649 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
652 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
653 AFS_TRACE_LEVEL_VERBOSE,
654 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
655 &pFcb->NPFcb->Resource,
656 PsGetCurrentThread());
658 AFSAcquireExcl( &pFcb->NPFcb->Resource,
662 // Perform some final common processing
665 ASSERT( pFcb->OpenHandleCount != 0);
667 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
670 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
673 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
675 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
678 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
680 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
683 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
685 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
688 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
691 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
693 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
696 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
699 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
701 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
706 // If the count has dropped to one and there is a pending delete
707 // then delete the node. The final count will be decremented just
708 // before the Fcb->NPFcb->Resource is released.
711 if( pFcb->OpenHandleCount == 1 &&
712 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
716 // Try to notify the service about the delete
719 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
722 // Indicate the file access mode that is being released
725 stFileCleanup.FileAccess = pCcb->FileAccess;
728 // Push the request to the service
731 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
732 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
734 &pCcb->DirectoryCB->NameInformation.FileName,
735 &pObjectInfo->FileId,
737 sizeof( AFSFileCleanupCB),
741 if( !NT_SUCCESS( ntStatus) &&
742 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
745 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
746 AFS_TRACE_LEVEL_ERROR,
747 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
751 ntStatus = STATUS_SUCCESS;
753 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
758 ntStatus = STATUS_SUCCESS;
760 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
761 AFS_TRACE_LEVEL_VERBOSE,
762 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
766 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
768 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
770 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
772 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
773 (ULONG)FILE_ACTION_REMOVED);
776 // Now that the service has the entry has deleted we need to remove it from the parent
777 // tree so another lookup on the node will fail
780 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
783 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
786 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
789 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
794 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
795 AFS_TRACE_LEVEL_VERBOSE,
796 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
798 &pCcb->DirectoryCB->NameInformation.FileName);
804 // If there have been any updates to the node then push it to
811 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
814 ULONG ulNotifyFilter = 0;
816 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
818 if( pObjectInfo->ParentObjectInformation != NULL)
821 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
823 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
825 (ULONG)ulNotifyFilter,
826 (ULONG)FILE_ACTION_MODIFIED);
831 // Indicate the file access mode that is being released
834 stFileCleanup.FileAccess = pCcb->FileAccess;
836 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
837 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
839 &pCcb->DirectoryCB->NameInformation.FileName,
840 &pObjectInfo->FileId,
842 sizeof( AFSFileCleanupCB),
846 ntStatus = STATUS_SUCCESS;
850 // Release the notification for this directory if there is one
853 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
854 &pControlDeviceExt->Specific.Control.DirNotifyList,
858 // Remove the share access at this time since we may not get the close for sometime on this FO.
861 IoRemoveShareAccess( pFileObject,
865 // We don't need the name array after the user closes the handle on the file
868 if( pCcb->NameArray != NULL)
871 AFSFreeNameArray( pCcb->NameArray);
873 pCcb->NameArray = NULL;
877 // Decrement the open child handle count
880 if( pObjectInfo->ParentObjectInformation != NULL)
883 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
885 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
887 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
888 AFS_TRACE_LEVEL_VERBOSE,
889 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
890 pObjectInfo->ParentObjectInformation,
891 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
894 InterlockedDecrement( &pFcb->OpenHandleCount);
896 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
897 AFS_TRACE_LEVEL_VERBOSE,
898 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
900 pFcb->OpenHandleCount);
903 // And finally, release the Fcb if we acquired it.
906 AFSReleaseResource( &pFcb->NPFcb->Resource);
911 case AFS_SYMBOLIC_LINK_FCB:
912 case AFS_MOUNT_POINT_FCB:
913 case AFS_DFS_LINK_FCB:
914 case AFS_INVALID_FCB:
918 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
921 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
922 AFS_TRACE_LEVEL_VERBOSE,
923 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
924 &pFcb->NPFcb->Resource,
925 PsGetCurrentThread());
927 AFSAcquireExcl( &pFcb->NPFcb->Resource,
931 // Perform some final common processing
934 ASSERT( pFcb->OpenHandleCount != 0);
936 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
939 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
942 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
944 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
947 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
949 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
952 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
954 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
957 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
960 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
962 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
965 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
968 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
970 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
975 // If the count has dropped to one and there is a pending delete
976 // then delete the node. The final count will be decremented just
977 // before the Fcb->NPFcb->Resource is released.
980 if( pFcb->OpenHandleCount == 1 &&
981 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
985 // Try to notify the service about the delete
988 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
991 // Indicate the file access mode that is being released
994 stFileCleanup.FileAccess = pCcb->FileAccess;
997 // Push the request to the service
1000 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1001 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1003 &pCcb->DirectoryCB->NameInformation.FileName,
1004 &pObjectInfo->FileId,
1006 sizeof( AFSFileCleanupCB),
1010 if( !NT_SUCCESS( ntStatus) &&
1011 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1014 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1015 AFS_TRACE_LEVEL_ERROR,
1016 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1017 &pCcb->FullFileName,
1020 ntStatus = STATUS_SUCCESS;
1022 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1027 ntStatus = STATUS_SUCCESS;
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1032 &pCcb->FullFileName,
1035 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1037 ASSERT( pObjectInfo->ParentObjectInformation != NULL);
1039 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1041 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1042 (ULONG)FILE_ACTION_REMOVED);
1045 // Now that the service has the entry has deleted we need to remove it from the parent
1046 // tree so another lookup on the node will fail
1049 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1052 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1055 AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1058 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1063 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1064 AFS_TRACE_LEVEL_VERBOSE,
1065 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1067 &pCcb->DirectoryCB->NameInformation.FileName);
1073 // If there have been any updates to the node then push it to
1080 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1083 ULONG ulNotifyFilter = 0;
1085 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1087 if( pObjectInfo->ParentObjectInformation != NULL)
1090 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1092 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1094 (ULONG)ulNotifyFilter,
1095 (ULONG)FILE_ACTION_MODIFIED);
1100 // Indicate the file access mode that is being released
1103 stFileCleanup.FileAccess = pCcb->FileAccess;
1105 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1106 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1108 &pCcb->DirectoryCB->NameInformation.FileName,
1109 &pObjectInfo->FileId,
1111 sizeof( AFSFileCleanupCB),
1115 ntStatus = STATUS_SUCCESS;
1119 // Remove the share access at this time since we may not get the close for sometime on this FO.
1122 IoRemoveShareAccess( pFileObject,
1123 &pFcb->ShareAccess);
1126 // We don't need the name array after the user closes the handle on the file
1129 if( pCcb->NameArray != NULL)
1132 AFSFreeNameArray( pCcb->NameArray);
1134 pCcb->NameArray = NULL;
1138 // Decrement the open child handle count
1141 if( pObjectInfo->ParentObjectInformation != NULL)
1144 ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1146 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1148 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1149 AFS_TRACE_LEVEL_VERBOSE,
1150 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1151 pObjectInfo->ParentObjectInformation,
1152 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1155 InterlockedDecrement( &pFcb->OpenHandleCount);
1157 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1158 AFS_TRACE_LEVEL_VERBOSE,
1159 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1161 pFcb->OpenHandleCount);
1164 // And finally, release the Fcb if we acquired it.
1167 AFSReleaseResource( &pFcb->NPFcb->Resource);
1172 case AFS_SPECIAL_SHARE_FCB:
1175 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1176 AFS_TRACE_LEVEL_VERBOSE,
1177 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1178 &pFcb->NPFcb->Resource,
1179 PsGetCurrentThread());
1181 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1184 ASSERT( pFcb->OpenHandleCount != 0);
1187 // Decrement the open child handle count
1190 if( pObjectInfo->ParentObjectInformation != NULL &&
1191 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1194 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1196 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1197 AFS_TRACE_LEVEL_VERBOSE,
1198 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1199 pObjectInfo->ParentObjectInformation,
1200 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1203 InterlockedDecrement( &pFcb->OpenHandleCount);
1205 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1206 AFS_TRACE_LEVEL_VERBOSE,
1207 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1209 pFcb->OpenHandleCount);
1212 // And finally, release the Fcb if we acquired it.
1215 AFSReleaseResource( &pFcb->NPFcb->Resource);
1222 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1223 AFS_TRACE_LEVEL_WARNING,
1224 "AFSCleanup Processing unknown node type %d\n",
1225 pFcb->Header.NodeTypeCode);
1233 if( pResultCB != NULL)
1236 AFSExFreePool( pResultCB);
1239 if( pFileObject != NULL)
1243 // Setup the fileobject flags to indicate cleanup is complete.
1246 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1250 // Complete the request
1253 AFSCompleteRequest( Irp, ntStatus);
1255 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
1260 "EXCEPTION - AFSCleanup\n");