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 AFSDirectoryCB *pDirCB = NULL;
70 if( AFSRDRDeviceObject == NULL)
74 // Let this through, it's an close on the library control device
77 try_return( ntStatus);
80 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
82 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
84 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
88 try_return( ntStatus);
91 pObjectInfo = pFcb->ObjectInformation;
94 // Perform the close functionality depending on the type of node it is
97 switch( pFcb->Header.NodeTypeCode)
103 AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
104 AFSFileID stParentFileId;
106 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
107 AFS_TRACE_LEVEL_VERBOSE,
108 "AFSClose Acquiring GlobalRoot lock %p EXCL %08lX\n",
109 &pFcb->NPFcb->Resource,
110 PsGetCurrentThread());
112 AFSAcquireExcl( &pFcb->NPFcb->Resource,
115 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
118 // Send the close to the CM
121 RtlZeroMemory( &stPIOCtlClose,
122 sizeof( AFSPIOCtlOpenCloseRequestCB));
124 stPIOCtlClose.RequestId = pCcb->RequestID;
126 stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
128 RtlZeroMemory( &stParentFileId,
131 stParentFileId = pObjectInfo->ParentObjectInformation->FileId;
134 // Issue the close request to the service
137 AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
138 AFS_REQUEST_FLAG_SYNCHRONOUS,
142 (void *)&stPIOCtlClose,
143 sizeof( AFSPIOCtlOpenCloseRequestCB),
147 pDirCB = pCcb->DirectoryCB;
150 // Remove the Ccb and de-allocate it
156 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
158 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
159 AFS_TRACE_LEVEL_VERBOSE,
160 "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
161 &pDirCB->NameInformation.FileName,
166 ASSERT( lCount >= 0);
169 // If this is not the root then decrement the open child reference count
172 if( pObjectInfo->ParentObjectInformation != NULL &&
173 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
176 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
178 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
179 AFS_TRACE_LEVEL_VERBOSE,
180 "AFSClose (IOCtl) Decrement child open ref count on Parent object %p Cnt %d\n",
181 pObjectInfo->ParentObjectInformation,
182 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
185 AFSReleaseResource( &pFcb->NPFcb->Resource);
187 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
189 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
190 AFS_TRACE_LEVEL_VERBOSE,
191 "AFSClose (IOCtl) Decrement count on Fcb %p Cnt %d\n",
195 ASSERT( lCount >= 0);
203 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
204 AFS_TRACE_LEVEL_VERBOSE,
205 "AFSClose Acquiring Special Root ALL lock %p EXCL %08lX\n",
206 &pFcb->NPFcb->Resource,
207 PsGetCurrentThread());
209 AFSAcquireExcl( &pFcb->NPFcb->Resource,
212 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
214 pDirCB = pCcb->DirectoryCB;
217 // Remove the Ccb and de-allocate it
223 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
225 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
226 AFS_TRACE_LEVEL_VERBOSE,
227 "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n",
228 &pDirCB->NameInformation.FileName,
233 ASSERT( lCount >= 0);
235 AFSReleaseResource( &pFcb->NPFcb->Resource);
237 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
239 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
240 AFS_TRACE_LEVEL_VERBOSE,
241 "AFSClose (RootAll) Decrement count on Fcb %p Cnt %d\n",
245 ASSERT( lCount >= 0);
251 // Root, file or directory node
256 case AFS_DIRECTORY_FCB:
257 case AFS_SYMBOLIC_LINK_FCB:
258 case AFS_MOUNT_POINT_FCB:
259 case AFS_DFS_LINK_FCB:
260 case AFS_INVALID_FCB:
263 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
266 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
269 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
270 AFS_TRACE_LEVEL_VERBOSE,
271 "AFSClose Acquiring Dcb lock %p EXCL %08lX\n",
272 &pFcb->NPFcb->Resource,
273 PsGetCurrentThread());
275 AFSAcquireExcl( &pFcb->NPFcb->Resource,
278 KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
280 if( pFcb->OpenReferenceCount == 1 &&
281 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
284 SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
287 // Attempt to tear down our extent list for the file
288 // If there are remaining dirty extents then attempt to
289 // flush them as well
292 if( pFcb->Specific.File.ExtentsDirtyCount)
295 AFSFlushExtents( pFcb,
300 // Wait for any outstanding queued flushes to complete
303 AFSWaitOnQueuedFlushes( pFcb);
305 ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
306 pFcb->Specific.File.QueuedFlushCount == 0);
308 AFSReleaseResource( &pFcb->NPFcb->Resource);
311 // Tear 'em down, we'll not be needing them again
314 AFSTearDownFcbExtents( pFcb,
320 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
321 pFcb->Specific.File.ExtentsDirtyCount &&
322 (pCcb->GrantedAccess & FILE_WRITE_DATA))
325 AFSFlushExtents( pFcb,
329 AFSReleaseResource( &pFcb->NPFcb->Resource);
332 pDirCB = pCcb->DirectoryCB;
335 // Remove the Ccb and de-allocate it
342 // If this entry is deleted then remove the object from the volume tree
345 if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
348 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
349 pObjectInfo->Links == 0)
353 // Stop anything possibly in process
356 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
357 AFS_TRACE_LEVEL_VERBOSE,
358 "AFSClose Acquiring Fcb extents lock %p EXCL %08lX\n",
359 &pFcb->NPFcb->Specific.File.ExtentsResource,
360 PsGetCurrentThread());
362 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
365 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
367 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
371 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
372 AFS_TRACE_LEVEL_VERBOSE,
373 "AFSClose Releasing Fcb extents lock %p EXCL %08lX\n",
374 &pFcb->NPFcb->Specific.File.ExtentsResource,
375 PsGetCurrentThread());
377 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
380 AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
383 AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
386 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
388 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
389 AFS_TRACE_LEVEL_VERBOSE,
390 "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
391 &pDirCB->NameInformation.FileName,
396 ASSERT( lCount >= 0);
401 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
402 AFS_TRACE_LEVEL_VERBOSE,
403 "AFSClose Deleting dir entry %p (%p) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
406 &pDirCB->NameInformation.FileName,
407 pObjectInfo->FileId.Cell,
408 pObjectInfo->FileId.Volume,
409 pObjectInfo->FileId.Vnode,
410 pObjectInfo->FileId.Unique);
413 // Remove and delete the directory entry from the parent list
416 AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation,
419 AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
422 if( pObjectInfo->ObjectReferenceCount <= 0)
425 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
428 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
429 AFS_TRACE_LEVEL_VERBOSE,
430 "AFSClose Removing object %p from volume tree\n",
433 AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
434 &pObjectInfo->TreeEntry);
436 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
440 AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
443 AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
445 AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
450 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
452 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
453 AFS_TRACE_LEVEL_VERBOSE,
454 "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
455 &pDirCB->NameInformation.FileName,
460 ASSERT( lCount >= 0);
464 // If this is not the root then decrement the open child reference count
467 if( pObjectInfo != NULL &&
468 pObjectInfo->ParentObjectInformation != NULL &&
469 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
472 InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
474 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
475 AFS_TRACE_LEVEL_VERBOSE,
476 "AFSClose Decrement child open ref count on Parent object %p Cnt %d\n",
477 pObjectInfo->ParentObjectInformation,
478 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
482 // Decrement the reference count on the Fcb. this is protecting it from teardown.
485 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
487 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
488 AFS_TRACE_LEVEL_VERBOSE,
489 "AFSClose Decrement count on Fcb %p Cnt %d\n",
493 ASSERT( lCount >= 0);
498 case AFS_SPECIAL_SHARE_FCB:
501 AFSPipeOpenCloseRequestCB stPipeClose;
503 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
505 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
506 AFS_TRACE_LEVEL_VERBOSE,
507 "AFSClose Acquiring Special Share lock %p EXCL %08lX\n",
508 &pFcb->NPFcb->Resource,
509 PsGetCurrentThread());
511 AFSAcquireExcl( &pFcb->NPFcb->Resource,
514 RtlZeroMemory( &stPipeClose,
515 sizeof( AFSPipeOpenCloseRequestCB));
517 stPipeClose.RequestId = pCcb->RequestID;
519 stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
522 // Issue the open request to the service
526 AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
527 AFS_REQUEST_FLAG_SYNCHRONOUS,
529 &pDirCB->NameInformation.FileName,
531 (void *)&stPipeClose,
532 sizeof( AFSPipeOpenCloseRequestCB),
537 pDirCB = pCcb->DirectoryCB;
540 // Remove the Ccb and de-allocate it
546 lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
548 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
549 AFS_TRACE_LEVEL_VERBOSE,
550 "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
551 &pDirCB->NameInformation.FileName,
556 ASSERT( lCount >= 0);
559 // If this is not the root then decrement the open child reference count
562 if( pObjectInfo->ParentObjectInformation != NULL &&
563 pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
566 lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
568 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
569 AFS_TRACE_LEVEL_VERBOSE,
570 "AFSClose (Share) Decrement child open ref count on Parent object %p Cnt %d\n",
571 pObjectInfo->ParentObjectInformation,
575 AFSReleaseResource( &pFcb->NPFcb->Resource);
577 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
579 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
580 AFS_TRACE_LEVEL_VERBOSE,
581 "AFSClose (Share) Decrement count on Fcb %p Cnt %d\n",
585 ASSERT( lCount >= 0);
592 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
593 AFS_TRACE_LEVEL_ERROR,
594 "AFSClose Processing unknown node type %d\n",
595 pFcb->Header.NodeTypeCode);
603 // Complete the request
606 AFSCompleteRequest( Irp,
609 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
614 "EXCEPTION - AFSClose\n");
616 AFSDumpTraceFilesFnc();