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 AFSObjectInfoCB *pParentObjectInfo = NULL;
69 AFSFileCleanupCB stFileCleanup;
70 AFSFileCleanupResultCB *pResultCB = NULL;
71 ULONG ulResultLen = 0;
72 ULONG ulNotificationFlags = 0;
78 if( AFSRDRDeviceObject == NULL)
82 // Let this through, it's a cleanup on the library control device
85 try_return( ntStatus);
88 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
90 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
93 // Set some initial variables to make processing easier
96 pFileObject = pIrpSp->FileObject;
98 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
100 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
104 try_return( ntStatus);
107 pObjectInfo = pFcb->ObjectInformation;
109 pRootFcb = pObjectInfo->VolumeCB->RootFcb;
111 RtlZeroMemory( &stFileCleanup,
112 sizeof( AFSFileCleanupCB));
114 stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
116 stFileCleanup.Identifier = (ULONGLONG)pFileObject;
119 // Allocate our return buffer
122 pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
124 AFS_GENERIC_MEMORY_32_TAG);
126 if( pResultCB == NULL)
129 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
132 RtlZeroMemory( pResultCB,
135 ulResultLen = PAGE_SIZE;
139 // Perform the cleanup functionality depending on the type of node it is
142 switch( pFcb->Header.NodeTypeCode)
148 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
149 AFS_TRACE_LEVEL_VERBOSE,
150 "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
151 &pFcb->NPFcb->Resource,
152 PsGetCurrentThread());
154 AFSAcquireExcl( &pFcb->NPFcb->Resource,
157 ASSERT( pFcb->OpenHandleCount != 0);
159 AFSReleaseResource( &pFcb->NPFcb->Resource);
161 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
163 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
164 AFS_TRACE_LEVEL_VERBOSE,
165 "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
169 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
170 &pControlDeviceExt->Specific.Control.DirNotifyList,
179 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
180 AFS_TRACE_LEVEL_VERBOSE,
181 "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
182 &pFcb->NPFcb->Resource,
183 PsGetCurrentThread());
185 AFSAcquireExcl( &pFcb->NPFcb->Resource,
188 ASSERT( pFcb->OpenHandleCount != 0);
191 // Decrement the open child handle count
194 if( pObjectInfo->ParentObjectInformation != NULL &&
195 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
198 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
200 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
201 AFS_TRACE_LEVEL_VERBOSE,
202 "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
203 pObjectInfo->ParentObjectInformation,
207 AFSReleaseResource( &pFcb->NPFcb->Resource);
209 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
211 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
212 AFS_TRACE_LEVEL_VERBOSE,
213 "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
221 // This Fcb represents a file
228 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
231 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
232 AFS_TRACE_LEVEL_VERBOSE,
233 "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
234 &pFcb->NPFcb->Resource,
235 PsGetCurrentThread());
237 AFSAcquireExcl( &pFcb->NPFcb->Resource,
241 // If the handle has write permission ...
244 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
245 CcIsFileCached( pIrpSp->FileObject))
251 CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
256 if( !NT_SUCCESS( stIoSB.Status))
259 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
260 AFS_TRACE_LEVEL_ERROR,
261 "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
263 pObjectInfo->FileId.Cell,
264 pObjectInfo->FileId.Volume,
265 pObjectInfo->FileId.Vnode,
266 pObjectInfo->FileId.Unique,
270 ntStatus = stIoSB.Status;
273 __except( EXCEPTION_EXECUTE_HANDLER)
276 ntStatus = GetExceptionCode();
281 // Uninitialize the cache map. This call is unconditional.
284 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
285 AFS_TRACE_LEVEL_VERBOSE,
286 "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
290 CcUninitializeCacheMap( pFileObject,
295 // Unlock all outstanding locks on the file, again, unconditionally
298 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
300 IoGetRequestorProcess( Irp),
304 // Tell the service to unlock all on the file
307 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
310 // Perform some final common processing
313 ASSERT( pFcb->OpenHandleCount != 0);
315 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
318 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
321 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
323 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
326 stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
328 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
330 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
333 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
335 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
338 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
341 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
343 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
346 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
349 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
351 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
354 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
357 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
359 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
363 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
366 stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
370 // If the count has dropped to one and there is a pending delete
371 // then delete the node. The final count will be decremented just
372 // before the Fcb->NPFcb->Resource is released.
375 if( pFcb->OpenHandleCount == 1 &&
376 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
380 // Stop anything possibly in process
383 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
384 AFS_TRACE_LEVEL_VERBOSE,
385 "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
386 &pFcb->NPFcb->Specific.File.ExtentsResource,
387 PsGetCurrentThread());
389 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
392 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
394 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
399 // Before telling the server about the deleted file, tear down all extents for
403 AFSTearDownFcbExtents( pFcb,
406 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
407 AFS_TRACE_LEVEL_VERBOSE,
408 "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
409 &pFcb->NPFcb->Specific.File.ExtentsResource,
410 PsGetCurrentThread());
412 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
414 ntStatus = STATUS_SUCCESS;
416 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
419 // Indicate the file access mode that is being released
422 stFileCleanup.FileAccess = pCcb->FileAccess;
425 // Push the request to the service
428 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
429 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
431 &pCcb->DirectoryCB->NameInformation.FileName,
432 &pObjectInfo->FileId,
434 sizeof( AFSFileCleanupCB),
438 if( !NT_SUCCESS( ntStatus) &&
439 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
442 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
443 AFS_TRACE_LEVEL_ERROR,
444 "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
448 ntStatus = STATUS_SUCCESS;
450 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
455 ntStatus = STATUS_SUCCESS;
457 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
458 AFS_TRACE_LEVEL_VERBOSE,
459 "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
463 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
465 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
467 ASSERT( pParentObjectInfo != NULL);
469 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
472 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
475 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
477 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
482 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
486 // Now that the service has the entry has deleted we need to remove it from the parent
487 // tree so another lookup on the node will fail
490 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
493 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
494 AFS_TRACE_LEVEL_VERBOSE,
495 "AFSCleanup DE %p for %wZ removing entry\n",
497 &pCcb->DirectoryCB->NameInformation.FileName);
499 AFSRemoveNameEntry( pParentObjectInfo,
505 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
506 AFS_TRACE_LEVEL_VERBOSE,
507 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
509 &pCcb->DirectoryCB->NameInformation.FileName);
512 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
514 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
516 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
517 (ULONG)FILE_ACTION_REMOVED);
524 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
527 ULONG ulNotifyFilter = 0;
529 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
531 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
533 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
535 (ULONG)ulNotifyFilter,
536 (ULONG)FILE_ACTION_MODIFIED);
540 // Attempt to flush any dirty extents to the server. This may be a little
541 // aggressive, to flush whenever the handle is closed, but it ensures
545 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
546 pFcb->Specific.File.ExtentsDirtyCount != 0)
549 AFSFlushExtents( pFcb,
553 if( pFcb->OpenHandleCount == 1)
557 // Wait for any outstanding queued flushes to complete
560 AFSWaitOnQueuedFlushes( pFcb);
562 ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
564 AFSTearDownFcbExtents( pFcb,
569 // Indicate the file access mode that is being released
572 stFileCleanup.FileAccess = pCcb->FileAccess;
575 // Push the request to the service
578 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
579 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
581 &pCcb->DirectoryCB->NameInformation.FileName,
582 &pObjectInfo->FileId,
584 sizeof( AFSFileCleanupCB),
588 if ( NT_SUCCESS( ntStatus))
591 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
593 if ( pParentObjectInfo != NULL)
596 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
599 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
602 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
604 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
607 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
611 ntStatus = STATUS_SUCCESS;
615 // Remove the share access at this time since we may not get the close for sometime on this FO.
618 IoRemoveShareAccess( pFileObject,
622 // We don't need the name array after the user closes the handle on the file
625 if( pCcb->NameArray != NULL)
628 AFSFreeNameArray( pCcb->NameArray);
630 pCcb->NameArray = NULL;
634 // Decrement the open child handle count
637 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
639 if( pParentObjectInfo != NULL)
642 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
644 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
646 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
647 AFS_TRACE_LEVEL_VERBOSE,
648 "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
653 AFSReleaseResource( &pFcb->NPFcb->Resource);
655 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
658 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
661 AFSObjectInfoIncrement( pObjectInfo);
663 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
665 AFSPerformObjectInvalidate( pObjectInfo,
666 AFS_INVALIDATE_DATA_VERSION);
669 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
671 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
672 AFS_TRACE_LEVEL_VERBOSE,
673 "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
681 // Root or directory node
688 // Set the root Fcb to this node
694 // Fall through to below
698 case AFS_DIRECTORY_FCB:
702 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
705 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
706 AFS_TRACE_LEVEL_VERBOSE,
707 "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
708 &pFcb->NPFcb->Resource,
709 PsGetCurrentThread());
711 AFSAcquireExcl( &pFcb->NPFcb->Resource,
715 // Perform some final common processing
718 ASSERT( pFcb->OpenHandleCount != 0);
720 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
723 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
726 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
728 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
731 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
733 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
736 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
738 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
741 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
744 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
746 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
749 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
752 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
754 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
759 // If the count has dropped to one and there is a pending delete
760 // then delete the node. The final count will be decremented just
761 // before the Fcb->NPFcb->Resource is released.
764 if( pFcb->OpenHandleCount == 1 &&
765 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
769 // Try to notify the service about the delete
772 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
775 // Indicate the file access mode that is being released
778 stFileCleanup.FileAccess = pCcb->FileAccess;
781 // Push the request to the service
784 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
785 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
787 &pCcb->DirectoryCB->NameInformation.FileName,
788 &pObjectInfo->FileId,
790 sizeof( AFSFileCleanupCB),
794 if( !NT_SUCCESS( ntStatus) &&
795 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
798 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
799 AFS_TRACE_LEVEL_ERROR,
800 "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
804 ntStatus = STATUS_SUCCESS;
806 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
811 ntStatus = STATUS_SUCCESS;
813 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
814 AFS_TRACE_LEVEL_VERBOSE,
815 "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
819 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
821 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
823 ASSERT( pParentObjectInfo != NULL);
825 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
828 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
831 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
833 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
838 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
842 // Now that the service has the entry has deleted we need to remove it from the parent
843 // tree so another lookup on the node will fail
846 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
849 AFSRemoveNameEntry( pParentObjectInfo,
855 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
856 AFS_TRACE_LEVEL_VERBOSE,
857 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
859 &pCcb->DirectoryCB->NameInformation.FileName);
862 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
864 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
866 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
867 (ULONG)FILE_ACTION_REMOVED);
873 // If there have been any updates to the node then push it to
880 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
883 ULONG ulNotifyFilter = 0;
885 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
887 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
889 if( pParentObjectInfo != NULL)
892 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
894 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
896 (ULONG)ulNotifyFilter,
897 (ULONG)FILE_ACTION_MODIFIED);
902 // Indicate the file access mode that is being released
905 stFileCleanup.FileAccess = pCcb->FileAccess;
907 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
908 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
910 &pCcb->DirectoryCB->NameInformation.FileName,
911 &pObjectInfo->FileId,
913 sizeof( AFSFileCleanupCB),
917 if ( NT_SUCCESS( ntStatus))
920 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
922 if ( pParentObjectInfo != NULL)
925 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
928 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
931 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
933 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
936 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
940 ntStatus = STATUS_SUCCESS;
944 // Release the notification for this directory if there is one
947 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
948 &pControlDeviceExt->Specific.Control.DirNotifyList,
952 // Remove the share access at this time since we may not get the close for sometime on this FO.
955 IoRemoveShareAccess( pFileObject,
959 // We don't need the name array after the user closes the handle on the file
962 if( pCcb->NameArray != NULL)
965 AFSFreeNameArray( pCcb->NameArray);
967 pCcb->NameArray = NULL;
971 // Decrement the open child handle count
974 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
976 if( pParentObjectInfo != NULL)
979 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
981 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
983 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
984 AFS_TRACE_LEVEL_VERBOSE,
985 "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
990 AFSReleaseResource( &pFcb->NPFcb->Resource);
992 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
994 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
995 AFS_TRACE_LEVEL_VERBOSE,
996 "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
1003 case AFS_SYMBOLIC_LINK_FCB:
1004 case AFS_MOUNT_POINT_FCB:
1005 case AFS_DFS_LINK_FCB:
1006 case AFS_INVALID_FCB:
1010 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1013 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1014 AFS_TRACE_LEVEL_VERBOSE,
1015 "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1016 &pFcb->NPFcb->Resource,
1017 PsGetCurrentThread());
1019 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1023 // Perform some final common processing
1026 ASSERT( pFcb->OpenHandleCount != 0);
1028 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1031 stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1034 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1036 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1039 stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1041 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1044 stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1046 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1049 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1052 stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1054 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1057 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1060 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1062 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1067 // If the count has dropped to one and there is a pending delete
1068 // then delete the node. The final count will be decremented just
1069 // before the Fcb->NPFcb->Resource is released.
1072 if( pFcb->OpenHandleCount == 1 &&
1073 BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1077 // Try to notify the service about the delete
1080 ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1083 // Indicate the file access mode that is being released
1086 stFileCleanup.FileAccess = pCcb->FileAccess;
1089 // Push the request to the service
1092 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1093 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1095 &pCcb->DirectoryCB->NameInformation.FileName,
1096 &pObjectInfo->FileId,
1098 sizeof( AFSFileCleanupCB),
1102 if( !NT_SUCCESS( ntStatus) &&
1103 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1106 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1107 AFS_TRACE_LEVEL_ERROR,
1108 "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1109 &pCcb->FullFileName,
1112 ntStatus = STATUS_SUCCESS;
1114 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1119 ntStatus = STATUS_SUCCESS;
1121 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1122 AFS_TRACE_LEVEL_VERBOSE,
1123 "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1124 &pCcb->FullFileName,
1127 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1129 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1131 ASSERT( pParentObjectInfo != NULL);
1133 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1136 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1139 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1141 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1145 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1149 // Now that the service has the entry has deleted we need to remove it from the parent
1150 // tree so another lookup on the node will fail
1153 if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1156 AFSRemoveNameEntry( pParentObjectInfo,
1162 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1163 AFS_TRACE_LEVEL_VERBOSE,
1164 "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1166 &pCcb->DirectoryCB->NameInformation.FileName);
1169 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1171 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1173 (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1174 (ULONG)FILE_ACTION_REMOVED);
1180 // If there have been any updates to the node then push it to
1187 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1190 ULONG ulNotifyFilter = 0;
1192 ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1194 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1196 if( pParentObjectInfo != NULL)
1199 ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1201 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1203 (ULONG)ulNotifyFilter,
1204 (ULONG)FILE_ACTION_MODIFIED);
1209 // Indicate the file access mode that is being released
1212 stFileCleanup.FileAccess = pCcb->FileAccess;
1214 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1215 ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1217 &pCcb->DirectoryCB->NameInformation.FileName,
1218 &pObjectInfo->FileId,
1220 sizeof( AFSFileCleanupCB),
1224 if ( NT_SUCCESS( ntStatus))
1227 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1229 if ( pParentObjectInfo != NULL)
1232 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1235 if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1238 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1240 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1243 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1247 ntStatus = STATUS_SUCCESS;
1251 // Remove the share access at this time since we may not get the close for sometime on this FO.
1254 IoRemoveShareAccess( pFileObject,
1255 &pFcb->ShareAccess);
1258 // We don't need the name array after the user closes the handle on the file
1261 if( pCcb->NameArray != NULL)
1264 AFSFreeNameArray( pCcb->NameArray);
1266 pCcb->NameArray = NULL;
1270 // Decrement the open child handle count
1273 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1275 if( pParentObjectInfo != NULL)
1278 ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1280 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1282 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1283 AFS_TRACE_LEVEL_VERBOSE,
1284 "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1289 AFSReleaseResource( &pFcb->NPFcb->Resource);
1291 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1293 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1294 AFS_TRACE_LEVEL_VERBOSE,
1295 "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1302 case AFS_SPECIAL_SHARE_FCB:
1305 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1306 AFS_TRACE_LEVEL_VERBOSE,
1307 "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1308 &pFcb->NPFcb->Resource,
1309 PsGetCurrentThread());
1311 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1314 ASSERT( pFcb->OpenHandleCount != 0);
1317 // Decrement the open child handle count
1320 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1322 if( pParentObjectInfo != NULL &&
1323 pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1326 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1328 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1329 AFS_TRACE_LEVEL_VERBOSE,
1330 "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1335 AFSReleaseResource( &pFcb->NPFcb->Resource);
1337 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1339 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1340 AFS_TRACE_LEVEL_VERBOSE,
1341 "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1350 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1351 AFS_TRACE_LEVEL_WARNING,
1352 "AFSCleanup Processing unknown node type %d\n",
1353 pFcb->Header.NodeTypeCode);
1361 if( pResultCB != NULL)
1364 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1367 if( pFileObject != NULL)
1371 // Setup the fileobject flags to indicate cleanup is complete.
1374 SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1378 // Complete the request
1381 AFSCompleteRequest( Irp, ntStatus);
1383 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1388 "EXCEPTION - AFSCleanup\n");
1390 AFSDumpTraceFilesFnc();