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.
39 #include "AFSCommon.h"
46 // This function is the IRP_MJ_CLOSE dispatch handler
50 // A status is returned for the handling of this request
54 AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
57 UNREFERENCED_PARAMETER(LibDeviceObject);
58 NTSTATUS ntStatus = STATUS_SUCCESS;
59 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
61 AFSDeviceExt *pDeviceExt = NULL;
63 AFSObjectInfoCB *pObjectInfo = NULL;
64 AFSObjectInfoCB *pParentObjectInfo = NULL;
65 AFSDirectoryCB *pDirCB = NULL;
71 if( AFSRDRDeviceObject == NULL)
75 // Let this through, it's an close on the library control device
78 try_return( ntStatus);
81 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
83 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
85 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
89 try_return( ntStatus);
92 pObjectInfo = pFcb->ObjectInformation;
95 // Perform the close functionality depending on the type of node it is
98 switch( pFcb->Header.NodeTypeCode)
104 AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
105 AFSFileID stParentFileId;
107 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
108 AFS_TRACE_LEVEL_VERBOSE,
109 "AFSClose Acquiring GlobalRoot lock %p EXCL %08lX\n",
110 &pFcb->NPFcb->Resource,
111 PsGetCurrentThread()));
113 AFSAcquireExcl( &pFcb->NPFcb->Resource,
116 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
119 // Send the close to the CM
122 RtlZeroMemory( &stPIOCtlClose,
123 sizeof( AFSPIOCtlOpenCloseRequestCB));
125 stPIOCtlClose.RequestId = pCcb->RequestID;
127 stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
129 RtlZeroMemory( &stParentFileId,
132 stParentFileId = pObjectInfo->ParentFileId;
135 // Issue the close request to the service
138 AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
139 AFS_REQUEST_FLAG_SYNCHRONOUS,
145 (void *)&stPIOCtlClose,
146 sizeof( AFSPIOCtlOpenCloseRequestCB),
151 // Remove the Ccb and de-allocate it
158 // If this is not the root then decrement the open child reference count
161 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
164 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
165 &pObjectInfo->ParentFileId,
169 if( pParentObjectInfo != NULL &&
170 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
173 InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
175 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
176 AFS_TRACE_LEVEL_VERBOSE,
177 "AFSClose (IOCtl) Decrement child open ref count on Parent object %p Cnt %d\n",
179 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount));
182 AFSReleaseResource( &pFcb->NPFcb->Resource);
184 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
186 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
187 AFS_TRACE_LEVEL_VERBOSE,
188 "AFSClose (IOCtl) Decrement count on Fcb %p Cnt %d\n",
192 ASSERT( lCount >= 0);
200 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
201 AFS_TRACE_LEVEL_VERBOSE,
202 "AFSClose Acquiring Special Root ALL lock %p EXCL %08lX\n",
203 &pFcb->NPFcb->Resource,
204 PsGetCurrentThread()));
206 AFSAcquireExcl( &pFcb->NPFcb->Resource,
209 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
212 // Remove the Ccb and de-allocate it
218 AFSReleaseResource( &pFcb->NPFcb->Resource);
220 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
222 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
223 AFS_TRACE_LEVEL_VERBOSE,
224 "AFSClose (RootAll) Decrement count on Fcb %p Cnt %d\n",
228 ASSERT( lCount >= 0);
234 // Root, file or directory node
239 case AFS_DIRECTORY_FCB:
240 case AFS_SYMBOLIC_LINK_FCB:
241 case AFS_MOUNT_POINT_FCB:
242 case AFS_DFS_LINK_FCB:
243 case AFS_INVALID_FCB:
246 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
249 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
252 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
253 AFS_TRACE_LEVEL_VERBOSE,
254 "AFSClose Acquiring Dcb lock %p EXCL %08lX\n",
255 &pFcb->NPFcb->Resource,
256 PsGetCurrentThread()));
258 AFSAcquireExcl( &pFcb->NPFcb->Resource,
261 KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
263 if( pFcb->OpenReferenceCount == 1 &&
264 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
267 SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
270 // Attempt to tear down our extent list for the file
271 // If there are remaining dirty extents then attempt to
272 // flush them as well
275 if( pFcb->Specific.File.ExtentsDirtyCount)
278 AFSFlushExtents( pFcb,
283 // Wait for any outstanding queued flushes to complete
286 AFSWaitOnQueuedFlushes( pFcb);
288 ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
289 pFcb->Specific.File.QueuedFlushCount == 0);
291 AFSReleaseResource( &pFcb->NPFcb->Resource);
294 // Tear 'em down, we'll not be needing them again
297 AFSTearDownFcbExtents( pFcb,
303 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
304 pFcb->Specific.File.ExtentsDirtyCount &&
305 (pCcb->GrantedAccess & FILE_WRITE_DATA))
308 AFSFlushExtents( pFcb,
312 AFSReleaseResource( &pFcb->NPFcb->Resource);
315 pDirCB = pCcb->DirectoryCB;
318 // Steal the DirOpenReferenceCount from the Ccb
321 pCcb->DirectoryCB = NULL;
324 // Object the Parent ObjectInformationCB
327 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
330 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
331 &pObjectInfo->ParentFileId,
336 // Remove the Ccb and de-allocate it
343 // If this entry is deleted then remove the object from the volume tree
346 if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
349 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
350 pObjectInfo->Links == 0)
354 // Stop anything possibly in process
357 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
358 AFS_TRACE_LEVEL_VERBOSE,
359 "AFSClose Acquiring Fcb extents lock %p EXCL %08lX\n",
360 &pFcb->NPFcb->Specific.File.ExtentsResource,
361 PsGetCurrentThread()));
363 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
366 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
368 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
372 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
373 AFS_TRACE_LEVEL_VERBOSE,
374 "AFSClose Releasing Fcb extents lock %p EXCL %08lX\n",
375 &pFcb->NPFcb->Specific.File.ExtentsResource,
376 PsGetCurrentThread()));
378 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
381 ASSERT( pParentObjectInfo != NULL);
383 if ( pParentObjectInfo != NULL)
385 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
388 AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
391 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
393 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
394 AFS_TRACE_LEVEL_VERBOSE,
395 "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
396 &pDirCB->NameInformation.FileName,
401 ASSERT( lCount >= 0);
404 pDirCB->NameArrayReferenceCount <= 0)
407 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
408 AFS_TRACE_LEVEL_VERBOSE,
409 "AFSClose Deleting dir entry %p (%p) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
412 &pDirCB->NameInformation.FileName,
413 pObjectInfo->FileId.Cell,
414 pObjectInfo->FileId.Volume,
415 pObjectInfo->FileId.Vnode,
416 pObjectInfo->FileId.Unique));
419 // Remove and delete the directory entry from the parent list
422 AFSDeleteDirEntry( pParentObjectInfo,
425 AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
428 if( pObjectInfo->ObjectReferenceCount <= 0)
431 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
434 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
435 AFS_TRACE_LEVEL_VERBOSE,
436 "AFSClose Removing object %p from volume tree\n",
439 AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
440 &pObjectInfo->TreeEntry);
442 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
446 AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
449 AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
451 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
457 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
459 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
460 AFS_TRACE_LEVEL_VERBOSE,
461 "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
462 &pDirCB->NameInformation.FileName,
467 ASSERT( lCount >= 0);
471 // If this is not the root then decrement the open child reference count
474 if( pObjectInfo != NULL &&
475 pParentObjectInfo != NULL &&
476 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
479 InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
481 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
482 AFS_TRACE_LEVEL_VERBOSE,
483 "AFSClose Decrement child open ref count on Parent object %p Cnt %d\n",
485 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount));
489 // Decrement the reference count on the Fcb. this is protecting it from teardown.
492 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
494 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
495 AFS_TRACE_LEVEL_VERBOSE,
496 "AFSClose Decrement count on Fcb %p Cnt %d\n",
500 ASSERT( lCount >= 0);
505 case AFS_SPECIAL_SHARE_FCB:
508 AFSPipeOpenCloseRequestCB stPipeClose;
510 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
513 // Object the Parent ObjectInformationCB
516 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
519 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
520 &pObjectInfo->ParentFileId,
524 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
525 AFS_TRACE_LEVEL_VERBOSE,
526 "AFSClose Acquiring Special Share lock %p EXCL %08lX\n",
527 &pFcb->NPFcb->Resource,
528 PsGetCurrentThread()));
530 AFSAcquireExcl( &pFcb->NPFcb->Resource,
533 RtlZeroMemory( &stPipeClose,
534 sizeof( AFSPipeOpenCloseRequestCB));
536 stPipeClose.RequestId = pCcb->RequestID;
538 stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
541 // Issue the open request to the service
545 AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
546 AFS_REQUEST_FLAG_SYNCHRONOUS,
548 &pDirCB->NameInformation.FileName,
552 (void *)&stPipeClose,
553 sizeof( AFSPipeOpenCloseRequestCB),
559 // Remove the Ccb and de-allocate it
566 // If this is not the root then decrement the open child reference count
569 if( pParentObjectInfo != NULL &&
570 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
573 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
575 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
576 AFS_TRACE_LEVEL_VERBOSE,
577 "AFSClose (Share) Decrement child open ref count on Parent object %p Cnt %d\n",
582 AFSReleaseResource( &pFcb->NPFcb->Resource);
584 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
586 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
587 AFS_TRACE_LEVEL_VERBOSE,
588 "AFSClose (Share) Decrement count on Fcb %p Cnt %d\n",
592 ASSERT( lCount >= 0);
599 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
600 AFS_TRACE_LEVEL_ERROR,
601 "AFSClose Processing unknown node type %d\n",
602 pFcb->Header.NodeTypeCode));
610 // Complete the request
613 AFSCompleteRequest( Irp,
616 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
621 "EXCEPTION - AFSClose\n"));
623 AFSDumpTraceFilesFnc();
626 if ( pParentObjectInfo != NULL)
629 AFSReleaseObjectInfo( &pParentObjectInfo);