2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 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
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "AFSCommon.h"
44 // This function is the IRP_MJ_CLOSE dispatch handler
48 // A status is returned for the handling of this request
52 AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
55 UNREFERENCED_PARAMETER(LibDeviceObject);
56 NTSTATUS ntStatus = STATUS_SUCCESS;
57 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
59 AFSDeviceExt *pDeviceExt = NULL;
61 AFSObjectInfoCB *pObjectInfo = NULL;
62 AFSObjectInfoCB *pParentObjectInfo = NULL;
63 AFSDirectoryCB *pDirCB = NULL;
69 if( AFSRDRDeviceObject == NULL)
73 // Let this through, it's an close on the library control device
76 try_return( ntStatus);
79 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
81 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
83 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
87 try_return( ntStatus);
90 pObjectInfo = pFcb->ObjectInformation;
93 // Perform the close functionality depending on the type of node it is
96 switch( pFcb->Header.NodeTypeCode)
102 AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
103 AFSFileID stParentFileId;
105 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
106 AFS_TRACE_LEVEL_VERBOSE,
107 "AFSClose Acquiring GlobalRoot lock %p EXCL %08lX\n",
108 &pFcb->NPFcb->Resource,
109 PsGetCurrentThread()));
111 AFSAcquireExcl( &pFcb->NPFcb->Resource,
114 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
116 pIrpSp->FileObject->FsContext2 = NULL;
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 pIrpSp->FileObject->FsContext = NULL;
186 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
188 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
189 AFS_TRACE_LEVEL_VERBOSE,
190 "AFSClose (IOCtl) Decrement count on Fcb %p Cnt %d\n",
194 ASSERT( lCount >= 0);
202 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
203 AFS_TRACE_LEVEL_VERBOSE,
204 "AFSClose Acquiring Special Root ALL lock %p EXCL %08lX\n",
205 &pFcb->NPFcb->Resource,
206 PsGetCurrentThread()));
208 AFSAcquireExcl( &pFcb->NPFcb->Resource,
211 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
213 pIrpSp->FileObject->FsContext2;
216 // Remove the Ccb and de-allocate it
222 AFSReleaseResource( &pFcb->NPFcb->Resource);
224 pIrpSp->FileObject->FsContext = NULL;
226 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
228 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
229 AFS_TRACE_LEVEL_VERBOSE,
230 "AFSClose (RootAll) Decrement count on Fcb %p Cnt %d\n",
234 ASSERT( lCount >= 0);
240 // Root, file or directory node
245 case AFS_DIRECTORY_FCB:
246 case AFS_SYMBOLIC_LINK_FCB:
247 case AFS_MOUNT_POINT_FCB:
248 case AFS_DFS_LINK_FCB:
249 case AFS_INVALID_FCB:
252 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
254 pIrpSp->FileObject->FsContext2 = NULL;
257 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
260 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
261 AFS_TRACE_LEVEL_VERBOSE,
262 "AFSClose Acquiring Dcb lock %p EXCL %08lX\n",
263 &pFcb->NPFcb->Resource,
264 PsGetCurrentThread()));
266 AFSAcquireExcl( &pFcb->NPFcb->Resource,
269 KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
271 if( pFcb->OpenReferenceCount == 1 &&
272 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
275 SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
277 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
281 // Attempt to tear down our extent list for the file
282 // If there are remaining dirty extents then attempt to
283 // flush them as well
286 if( pFcb->Specific.File.ExtentsDirtyCount)
289 AFSFlushExtents( pFcb,
294 // Wait for any outstanding queued flushes to complete
297 AFSWaitOnQueuedFlushes( pFcb);
299 ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
300 pFcb->Specific.File.QueuedFlushCount == 0);
302 AFSReleaseResource( &pFcb->NPFcb->Resource);
305 // Tear 'em down, we'll not be needing them again
308 AFSTearDownFcbExtents( pFcb,
314 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
315 pFcb->Specific.File.ExtentsDirtyCount &&
316 (pCcb->GrantedAccess & FILE_WRITE_DATA))
319 AFSFlushExtents( pFcb,
323 AFSReleaseResource( &pFcb->NPFcb->Resource);
329 AFSReleaseResource( &pFcb->NPFcb->Resource);
332 pDirCB = pCcb->DirectoryCB;
335 // Steal the DirOpenReferenceCount from the Ccb
338 pCcb->DirectoryCB = NULL;
341 // Object the Parent ObjectInformationCB
344 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
347 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
348 &pObjectInfo->ParentFileId,
353 // Remove the Ccb and de-allocate it
360 // If this entry is deleted then remove the object from the volume tree
363 if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
366 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
367 pObjectInfo->Links == 0)
371 // Stop anything possibly in process
374 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
375 AFS_TRACE_LEVEL_VERBOSE,
376 "AFSClose Acquiring Fcb extents lock %p EXCL %08lX\n",
377 &pFcb->NPFcb->Specific.File.ExtentsResource,
378 PsGetCurrentThread()));
380 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
383 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
385 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
389 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
390 AFS_TRACE_LEVEL_VERBOSE,
391 "AFSClose Releasing Fcb extents lock %p EXCL %08lX\n",
392 &pFcb->NPFcb->Specific.File.ExtentsResource,
393 PsGetCurrentThread()));
395 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
398 ASSERT( pParentObjectInfo != NULL);
400 if ( pParentObjectInfo != NULL)
402 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
405 AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
408 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
410 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
411 AFS_TRACE_LEVEL_VERBOSE,
412 "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
413 &pDirCB->NameInformation.FileName,
418 ASSERT( lCount >= 0);
421 pDirCB->NameArrayReferenceCount <= 0)
424 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
425 AFS_TRACE_LEVEL_VERBOSE,
426 "AFSClose Deleting dir entry %p (%p) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
429 &pDirCB->NameInformation.FileName,
430 pObjectInfo->FileId.Cell,
431 pObjectInfo->FileId.Volume,
432 pObjectInfo->FileId.Vnode,
433 pObjectInfo->FileId.Unique));
436 // Remove and delete the directory entry from the parent list
439 AFSDeleteDirEntry( pParentObjectInfo,
442 AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
445 if( pObjectInfo->ObjectReferenceCount <= 0)
448 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
451 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
452 AFS_TRACE_LEVEL_VERBOSE,
453 "AFSClose Removing object %p from volume tree\n",
456 AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
457 &pObjectInfo->TreeEntry);
459 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
463 AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
466 AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
468 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
474 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
476 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
477 AFS_TRACE_LEVEL_VERBOSE,
478 "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
479 &pDirCB->NameInformation.FileName,
484 ASSERT( lCount >= 0);
488 // If this is not the root then decrement the open child reference count
491 if( pObjectInfo != NULL &&
492 pParentObjectInfo != NULL &&
493 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
496 InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
498 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
499 AFS_TRACE_LEVEL_VERBOSE,
500 "AFSClose Decrement child open ref count on Parent object %p Cnt %d\n",
502 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount));
505 pIrpSp->FileObject->FsContext = NULL;
508 // Decrement the reference count on the Fcb. this is protecting it from teardown.
511 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
513 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
514 AFS_TRACE_LEVEL_VERBOSE,
515 "AFSClose Decrement count on Fcb %p Cnt %d\n",
519 ASSERT( lCount >= 0);
524 case AFS_SPECIAL_SHARE_FCB:
527 AFSPipeOpenCloseRequestCB stPipeClose;
529 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
531 pIrpSp->FileObject->FsContext2 = NULL;
534 // Object the Parent ObjectInformationCB
537 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
540 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
541 &pObjectInfo->ParentFileId,
545 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
546 AFS_TRACE_LEVEL_VERBOSE,
547 "AFSClose Acquiring Special Share lock %p EXCL %08lX\n",
548 &pFcb->NPFcb->Resource,
549 PsGetCurrentThread()));
551 AFSAcquireExcl( &pFcb->NPFcb->Resource,
554 RtlZeroMemory( &stPipeClose,
555 sizeof( AFSPipeOpenCloseRequestCB));
557 stPipeClose.RequestId = pCcb->RequestID;
559 stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
562 // Remove the Ccb and de-allocate it
569 // If this is not the root then decrement the open child reference count
572 if( pParentObjectInfo != NULL &&
573 pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
576 lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
578 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
579 AFS_TRACE_LEVEL_VERBOSE,
580 "AFSClose (Share) Decrement child open ref count on Parent object %p Cnt %d\n",
585 AFSReleaseResource( &pFcb->NPFcb->Resource);
587 pIrpSp->FileObject->FsContext = NULL;
589 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
591 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
592 AFS_TRACE_LEVEL_VERBOSE,
593 "AFSClose (Share) Decrement count on Fcb %p Cnt %d\n",
597 ASSERT( lCount >= 0);
605 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
606 AFS_TRACE_LEVEL_ERROR,
607 "AFSClose Processing unknown node type %d\n",
608 pFcb->Header.NodeTypeCode));
617 // Complete the request
620 AFSCompleteRequest( Irp,
623 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
628 "EXCEPTION - AFSClose\n"));
630 AFSDumpTraceFilesFnc();
633 if ( pParentObjectInfo != NULL)
636 AFSReleaseObjectInfo( &pParentObjectInfo);