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: AFSFcbSupport.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitFcb
46 // This function performs Fcb initialization
50 // Return Fcb->NPFcb->Resource held exclusive
54 AFSInitFcb( IN AFSDirectoryCB *DirEntry)
57 NTSTATUS ntStatus = STATUS_SUCCESS;
59 AFSNonPagedFcb *pNPFcb = NULL;
60 USHORT usFcbLength = 0;
61 AFSObjectInfoCB *pObjectInfo = NULL;
62 AFSVolumeCB *pVolumeCB = NULL;
67 pObjectInfo = DirEntry->ObjectInformation;
69 if ( pObjectInfo->Fcb != NULL)
72 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
75 try_return( ntStatus = STATUS_SUCCESS);
78 pVolumeCB = pObjectInfo->VolumeCB;
81 // Allocate the Fcb and the nonpaged portion of the Fcb.
84 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
85 AFS_TRACE_LEVEL_VERBOSE_2,
86 "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
87 &DirEntry->NameInformation.FileName,
88 pObjectInfo->FileId.Cell,
89 pObjectInfo->FileId.Volume,
90 pObjectInfo->FileId.Vnode,
91 pObjectInfo->FileId.Unique));
93 usFcbLength = sizeof( AFSFcb);
95 pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
97 AFS_FCB_ALLOCATION_TAG);
102 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
103 AFS_TRACE_LEVEL_ERROR,
104 "AFSInitFcb Failed to allocate fcb\n"));
106 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
112 pFcb->Header.NodeByteSize = usFcbLength;
114 pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
115 sizeof( AFSNonPagedFcb),
116 AFS_FCB_NP_ALLOCATION_TAG);
121 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
122 AFS_TRACE_LEVEL_ERROR,
123 "AFSInitFcb Failed to allocate non-paged fcb\n"));
125 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
128 RtlZeroMemory( pNPFcb,
129 sizeof( AFSNonPagedFcb));
131 pNPFcb->Size = sizeof( AFSNonPagedFcb);
133 pNPFcb->Type = AFS_NON_PAGED_FCB;
136 // Initialize the advanced header
139 ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
141 FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
144 // OK, initialize the entry
147 ExInitializeResourceLite( &pNPFcb->Resource);
149 ExInitializeResourceLite( &pNPFcb->PagingResource);
151 ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
153 ExInitializeResourceLite( &pNPFcb->CcbListLock);
156 // Grab the Fcb for processing
159 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
160 AFS_TRACE_LEVEL_VERBOSE,
161 "AFSInitFcb Acquiring Fcb lock %p EXCL %08lX\n",
163 PsGetCurrentThread()));
165 AFSAcquireExcl( &pNPFcb->Resource,
168 pFcb->Header.Resource = &pNPFcb->Resource;
170 pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
172 pFcb->NPFcb = pNPFcb;
175 // Set type specific information
178 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
182 // Reset the type to a directory type
185 pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB;
187 else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
190 pFcb->Header.NodeTypeCode = AFS_FILE_FCB;
193 // Initialize the file specific information
196 FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock,
201 // Initialize the header file sizes to our dir entry information
204 pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
205 pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
206 pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
209 // Initialize the Extents resources and so forth. The
210 // quiescent state is that no one has the extents for
211 // IO (do the extents are not busy) and there is no
212 // extents request outstanding (and hence the "last
213 // one" is complete).
215 ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource );
217 KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
221 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
223 InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]);
226 pNPFcb->Specific.File.DirtyListHead = NULL;
227 pNPFcb->Specific.File.DirtyListTail = NULL;
229 ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
231 KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent,
232 SynchronizationEvent,
235 KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
239 else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
242 pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB;
244 else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL)
247 pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB;
249 else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
252 pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB;
254 else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
257 pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB;
259 else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
261 pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB;
265 pFcb->Header.NodeTypeCode = AFS_INVALID_FCB;
268 pFcb->ObjectInformation = pObjectInfo;
270 AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
273 // Swap the allocated FCB into the ObjectInformation structure if it
274 // does not already have one.
277 if ( InterlockedCompareExchangePointer( (PVOID *)&pObjectInfo->Fcb, pFcb, NULL) != NULL)
280 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
281 AFS_TRACE_LEVEL_WARNING,
282 "AFSInitFcb Raced Fcb %p pFcb %p Name %wZ\n",
285 &DirEntry->NameInformation.FileName));
287 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
288 AFS_TRACE_LEVEL_VERBOSE,
289 "AFSInitFcb Acquiring Fcb lock %p EXCL %08lX\n",
290 &pObjectInfo->Fcb->NPFcb->Resource,
291 PsGetCurrentThread()));
293 AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
295 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
298 try_return( ntStatus = STATUS_REPARSE);
301 AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
303 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
304 AFS_TRACE_LEVEL_VERBOSE,
305 "AFSInitFcb Initialized Fcb %p Name %wZ\n",
307 &DirEntry->NameInformation.FileName));
311 if( ntStatus != STATUS_SUCCESS)
314 if ( !NT_SUCCESS( ntStatus))
317 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
318 AFS_TRACE_LEVEL_ERROR,
319 "AFSInitFcb Failed to initialize fcb Status %08lX\n",
329 AFSReleaseResource( &pNPFcb->Resource);
331 FsRtlTeardownPerStreamContexts( &pFcb->Header);
333 if ( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
336 FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
338 ExDeleteResourceLite( &pNPFcb->Specific.File.ExtentsResource);
340 ExDeleteResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
343 ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
345 ExDeleteResourceLite( &pNPFcb->PagingResource);
347 ExDeleteResourceLite( &pNPFcb->CcbListLock);
349 ExDeleteResourceLite( &pNPFcb->Resource);
351 AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
354 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
363 AFSInitVolume( IN GUID *AuthGroup,
364 IN AFSFileID *RootFid,
365 IN LONG VolumeReferenceReason,
366 OUT AFSVolumeCB **VolumeCB)
369 NTSTATUS ntStatus = STATUS_SUCCESS;
370 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
371 AFSNonPagedVolumeCB *pNonPagedVcb = NULL;
372 AFSVolumeCB *pVolumeCB = NULL;
373 AFSNonPagedObjectInfoCB *pNonPagedObject = NULL;
374 ULONGLONG ullIndex = 0;
375 BOOLEAN bReleaseLocks = FALSE;
376 AFSVolumeInfoCB stVolumeInformation = {0};
377 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
384 // Before grabbing any locks ask the service for the volume information
385 // This may be a waste but we need to get this information prior to
386 // taking any volume tree locks. Don't do this for any 'reserved' cell entries
389 if( RootFid->Cell != 0)
392 RtlZeroMemory( &stVolumeInformation,
393 sizeof( AFSVolumeInfoCB));
395 ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
397 &stVolumeInformation);
399 if( !NT_SUCCESS( ntStatus))
402 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
403 AFS_TRACE_LEVEL_ERROR,
404 "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
407 try_return( ntStatus);
411 // Grab our tree locks and see if we raced with someone else
414 AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
417 AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
420 bReleaseLocks = TRUE;
422 ullIndex = AFSCreateHighIndex( RootFid);
424 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
426 (AFSBTreeEntry **)&pVolumeCB);
428 if( NT_SUCCESS( ntStatus) &&
433 // So we don't lock with an invalidation call ...
436 lCount = AFSVolumeIncrement( pVolumeCB,
437 VolumeReferenceReason);
439 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
440 AFS_TRACE_LEVEL_VERBOSE,
441 "AFSInitVolume Increment count on volume %p Reason %u Cnt %d\n",
443 VolumeReferenceReason,
446 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
448 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
450 bReleaseLocks = FALSE;
452 AFSAcquireExcl( pVolumeCB->VolumeLock,
455 *VolumeCB = pVolumeCB;
457 try_return( ntStatus);
461 // Revert our status from the above call back to success.
464 ntStatus = STATUS_SUCCESS;
468 // For the global root we allocate out volume node and insert it
469 // into the volume tree ...
472 pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( PagedPool,
473 sizeof( AFSVolumeCB),
474 AFS_VCB_ALLOCATION_TAG);
476 if( pVolumeCB == NULL)
479 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
480 AFS_TRACE_LEVEL_ERROR,
481 "AFSInitVolume Failed to allocate the root volume cb\n"));
483 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
486 RtlZeroMemory( pVolumeCB,
487 sizeof( AFSVolumeCB));
490 // The non paged portion
493 pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
494 sizeof( AFSNonPagedVolumeCB),
495 AFS_VCB_NP_ALLOCATION_TAG);
497 if( pNonPagedVcb == NULL)
500 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
501 AFS_TRACE_LEVEL_ERROR,
502 "AFSInitVolume Failed to allocate the root non paged volume cb\n"));
504 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
507 RtlZeroMemory( pNonPagedVcb,
508 sizeof( AFSNonPagedVolumeCB));
510 ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);
512 ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
514 pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
515 sizeof( AFSNonPagedObjectInfoCB),
516 AFS_NP_OBJECT_INFO_TAG);
518 if( pNonPagedObject == NULL)
521 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
522 AFS_TRACE_LEVEL_ERROR,
523 "AFSInitVolume Failed to allocate the root non paged object cb\n"));
525 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
528 RtlZeroMemory( pNonPagedObject,
529 sizeof( AFSNonPagedObjectInfoCB));
531 ExInitializeResourceLite( &pNonPagedObject->ObjectInfoLock);
533 ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);
535 pVolumeCB->NonPagedVcb = pNonPagedVcb;
537 pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;
539 pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;
541 pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;
543 pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;
545 lCount = AFSVolumeIncrement( pVolumeCB,
546 VolumeReferenceReason);
548 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
549 AFS_TRACE_LEVEL_VERBOSE,
550 "AFSInitVolume Initializing volume %p Reason %u count %d\n",
552 VolumeReferenceReason,
555 AFSAcquireExcl( pVolumeCB->VolumeLock,
558 pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
559 sizeof( AFSDirectoryCB) + sizeof( WCHAR),
562 if( pVolumeCB->DirectoryCB == NULL)
565 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
568 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
569 AFS_TRACE_LEVEL_VERBOSE,
570 "AFSInitVolume AFS_DIR_ENTRY_TAG allocated %p\n",
571 pVolumeCB->DirectoryCB));
573 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
574 sizeof( AFSNonPagedDirectoryCB),
575 AFS_DIR_ENTRY_NP_TAG);
577 if( pNonPagedDirEntry == NULL)
580 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
583 RtlZeroMemory( pVolumeCB->DirectoryCB,
584 sizeof( AFSDirectoryCB) + sizeof( WCHAR));
586 RtlZeroMemory( pNonPagedDirEntry,
587 sizeof( AFSNonPagedDirectoryCB));
589 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
591 pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;
594 // Initialize the non-paged portion of the directory entry
597 KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
598 KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
599 KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);
601 pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;
603 SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);
605 pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell;
606 pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume;
607 pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode;
608 pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique;
609 pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash;
611 pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
613 pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);
615 pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;
617 pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));
619 RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
624 // Copy in the volume information retrieved above
627 RtlCopyMemory( &pVolumeCB->VolumeInformation,
628 &stVolumeInformation,
629 sizeof( AFSVolumeInfoCB));
635 pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;
638 // The ObjectInformation VolumeCB pointer does not obtain
639 // a reference count.
642 pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;
645 // Insert the volume into our volume tree. Don't insert any reserved entries
648 if( RootFid->Cell != 0)
651 pVolumeCB->TreeEntry.HashIndex = ullIndex;
653 if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
656 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;
658 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
663 if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
664 &pVolumeCB->TreeEntry)))
667 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
671 if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
674 pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
679 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;
681 pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
684 pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
687 *VolumeCB = pVolumeCB;
691 if( !NT_SUCCESS( ntStatus))
694 if( pNonPagedVcb != NULL)
697 AFSReleaseResource( pVolumeCB->VolumeLock);
699 ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);
701 ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
703 AFSExFreePoolWithTag( pNonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
706 if( pNonPagedObject != NULL)
709 ExDeleteResourceLite( &pNonPagedObject->ObjectInfoLock);
711 AFSExFreePoolWithTag( pNonPagedObject, AFS_NP_OBJECT_INFO_TAG);
714 if( pVolumeCB != NULL)
717 if( pVolumeCB->DirectoryCB != NULL)
720 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
721 AFS_TRACE_LEVEL_VERBOSE,
722 "AFSInitVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
723 pVolumeCB->DirectoryCB));
725 AFSExFreePoolWithTag( pVolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
728 AFSExFreePoolWithTag( pVolumeCB, AFS_VCB_ALLOCATION_TAG);
731 if( pNonPagedDirEntry != NULL)
734 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
736 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
743 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
745 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
753 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
756 NTSTATUS ntStatus = STATUS_SUCCESS;
757 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
762 ASSERT( VolumeCB->VolumeReferenceCount == 0);
765 // Remove the volume from the tree and list
766 // Don't process the list information for reserved entries
769 if( VolumeCB->ObjectInformation.FileId.Cell != 0)
772 if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
775 AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
776 &VolumeCB->TreeEntry);
779 if( VolumeCB->ListEntry.fLink == NULL)
782 pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;
784 if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
787 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
793 ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
796 if( VolumeCB->ListEntry.bLink == NULL)
799 pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;
801 if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
804 pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
810 ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
815 // Remove any PIOctl objects we have
818 if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
821 if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
824 AFSAcquireExcl( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
827 AFSRemoveFcb( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
829 AFSReleaseResource( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
832 AFSDeleteObjectInfo( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
834 ExDeleteResourceLite( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
836 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
838 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
839 AFS_TRACE_LEVEL_VERBOSE,
840 "AFSRemoveVolume (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
841 VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB));
843 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
846 if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
850 // Release the fid in the service
853 AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
857 // Free up the memory
860 if( VolumeCB->NonPagedVcb != NULL)
863 if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
865 AFSReleaseResource( VolumeCB->VolumeLock);
868 ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);
870 ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);
872 AFSExFreePoolWithTag( VolumeCB->NonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
875 if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
878 ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
880 ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);
882 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
885 if( VolumeCB->DirectoryCB != NULL)
888 if( VolumeCB->DirectoryCB->NonPaged != NULL)
891 ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);
893 AFSExFreePoolWithTag( VolumeCB->DirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
896 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
897 AFS_TRACE_LEVEL_VERBOSE,
898 "AFSRemoveVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
899 VolumeCB->DirectoryCB));
901 AFSExFreePoolWithTag( VolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
904 AFSExFreePoolWithTag( VolumeCB, AFS_VCB_ALLOCATION_TAG);
911 AFSVolumeIncrement( IN AFSVolumeCB *VolumeCB,
917 lCount = InterlockedIncrement( &VolumeCB->VolumeReferenceCount);
919 InterlockedIncrement( &VolumeCB->VolumeReferences[ Reason]);
925 AFSVolumeDecrement( IN AFSVolumeCB *VolumeCB,
931 lCount = InterlockedDecrement( &VolumeCB->VolumeReferences[ Reason]);
933 ASSERT( lCount >= 0);
935 lCount = InterlockedDecrement( &VolumeCB->VolumeReferenceCount);
937 ASSERT( lCount >= 0);
943 // Function: AFSInitRootFcb
947 // This function performs Root node Fcb initialization
951 // A status is returned for the function
955 AFSInitRootFcb( IN ULONGLONG ProcessID,
956 IN AFSVolumeCB *VolumeCB)
959 UNREFERENCED_PARAMETER(ProcessID);
960 NTSTATUS ntStatus = STATUS_SUCCESS;
962 AFSNonPagedFcb *pNPFcb = NULL;
968 // Initialize the root fcb
971 pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
973 AFS_FCB_ALLOCATION_TAG);
978 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
979 AFS_TRACE_LEVEL_ERROR,
980 "AFSInitRootFcb Failed to allocate the root fcb\n"));
982 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
988 pFcb->Header.NodeByteSize = sizeof( AFSFcb);
990 pFcb->Header.NodeTypeCode = AFS_ROOT_FCB;
992 pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
993 sizeof( AFSNonPagedFcb),
994 AFS_FCB_NP_ALLOCATION_TAG);
999 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1000 AFS_TRACE_LEVEL_ERROR,
1001 "AFSInitRootFcb Failed to allocate the non-paged fcb\n"));
1003 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1006 RtlZeroMemory( pNPFcb,
1007 sizeof( AFSNonPagedFcb));
1009 pNPFcb->Size = sizeof( AFSNonPagedFcb);
1011 pNPFcb->Type = AFS_NON_PAGED_FCB;
1014 // OK, initialize the entry
1017 ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
1019 FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
1021 ExInitializeResourceLite( &pNPFcb->Resource);
1023 ExInitializeResourceLite( &pNPFcb->PagingResource);
1025 ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
1027 ExInitializeResourceLite( &pNPFcb->CcbListLock);
1029 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
1033 PsGetCurrentThread()));
1035 AFSAcquireExcl( &pNPFcb->Resource,
1038 pFcb->Header.Resource = &pNPFcb->Resource;
1040 pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
1042 pFcb->NPFcb = pNPFcb;
1045 // Save the root Fcb in the VolumeCB
1048 pFcb->ObjectInformation = &VolumeCB->ObjectInformation;
1050 VolumeCB->ObjectInformation.VolumeCB = VolumeCB;
1052 AFSAcquireShared( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1055 // Swap the allocated FCB into the ObjectInformation structure if it
1056 // does not already have one.
1059 if ( InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb, pFcb, NULL) != NULL)
1062 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1063 AFS_TRACE_LEVEL_WARNING,
1064 "AFSInitRootFcb Raced Fcb %p pFcb %p\n",
1065 VolumeCB->ObjectInformation.Fcb,
1068 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1069 AFS_TRACE_LEVEL_VERBOSE,
1070 "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
1071 &VolumeCB->ObjectInformation.Fcb->NPFcb->Resource,
1072 PsGetCurrentThread()));
1074 AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1076 AFSAcquireExcl( &VolumeCB->ObjectInformation.Fcb->NPFcb->Resource,
1079 try_return( ntStatus = STATUS_REPARSE);
1082 VolumeCB->RootFcb = VolumeCB->ObjectInformation.Fcb;
1084 AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1086 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1087 AFS_TRACE_LEVEL_VERBOSE,
1088 "AFSInitRootFcb Initialized Fcb %p\n",
1089 &VolumeCB->ObjectInformation.Fcb));
1093 if( !NT_SUCCESS( ntStatus) ||
1094 ntStatus == STATUS_REPARSE)
1103 AFSReleaseResource( &pNPFcb->Resource);
1105 FsRtlTeardownPerStreamContexts( &pFcb->Header);
1107 ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
1109 ExDeleteResourceLite( &pNPFcb->PagingResource);
1111 ExDeleteResourceLite( &pNPFcb->CcbListLock);
1113 ExDeleteResourceLite( &pNPFcb->Resource);
1115 AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1118 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1127 // Function: AFSRemoveRootFcb
1131 // This function performs root Fcb removal/deallocation from
1132 // the provided VolumeCB object.
1140 AFSRemoveRootFcb( IN AFSVolumeCB *VolumeCB)
1144 pRootFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb,
1146 (PVOID *)&VolumeCB->ObjectInformation.Fcb);
1148 if ( pRootFcb == NULL)
1155 // The Fcb has been disconnected from the ObjectInformation block.
1156 // Clear it from the RootFcb convenience pointer.
1159 VolumeCB->RootFcb = NULL;
1161 if( pRootFcb->NPFcb != NULL)
1168 ExDeleteResourceLite( &pRootFcb->NPFcb->Resource);
1170 ExDeleteResourceLite( &pRootFcb->NPFcb->PagingResource);
1172 ExDeleteResourceLite( &pRootFcb->NPFcb->SectionObjectResource);
1174 ExDeleteResourceLite( &pRootFcb->NPFcb->CcbListLock);
1176 FsRtlTeardownPerStreamContexts( &pRootFcb->Header);
1179 // The non paged region
1182 AFSExFreePoolWithTag( pRootFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1184 pRootFcb->NPFcb = NULL;
1188 // And the Fcb itself
1191 AFSExFreePoolWithTag( pRootFcb, AFS_FCB_ALLOCATION_TAG);
1197 // Function: AFSRemoveFcb
1201 // This function performs Fcb removal/deallocation
1205 // A status is returned for the function
1209 AFSRemoveFcb( IN AFSFcb **ppFcb)
1214 pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)ppFcb, NULL, (PVOID)(*ppFcb));
1222 ASSERT( pFcb->Header.NodeTypeCode != AFS_ROOT_FCB);
1225 // Uninitialize the file lock if it is a file
1228 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1229 AFS_TRACE_LEVEL_VERBOSE,
1230 "AFSRemoveFcb Removing Fcb %p\n",
1233 if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1236 FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
1239 // The resource we allocated
1242 ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.ExtentsResource );
1244 ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
1247 else if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1254 // Tear down the FM specific contexts
1257 FsRtlTeardownPerStreamContexts( &pFcb->Header);
1260 // Delete the resources
1263 ExDeleteResourceLite( &pFcb->NPFcb->Resource);
1265 ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
1267 ExDeleteResourceLite( &pFcb->NPFcb->SectionObjectResource);
1269 ExDeleteResourceLite( &pFcb->NPFcb->CcbListLock);
1272 // The non paged region
1275 AFSExFreePoolWithTag( pFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1278 // And the Fcb itself, which includes the name
1281 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1287 AFSInitCcb( IN OUT AFSCcb **Ccb,
1288 IN AFSDirectoryCB *DirectoryCB,
1289 IN ACCESS_MASK GrantedAccess,
1290 IN ULONG FileAccess)
1293 NTSTATUS Status = STATUS_SUCCESS;
1294 AFSCcb *pCcb = NULL;
1301 // Allocate our context control block
1304 pCcb = (AFSCcb *)AFSExAllocatePoolWithTag( PagedPool,
1306 AFS_CCB_ALLOCATION_TAG);
1311 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1312 AFS_TRACE_LEVEL_ERROR,
1313 "AFSInitCcb Failed to allocate Ccb\n"));
1315 try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1318 RtlZeroMemory( pCcb,
1321 pCcb->Size = sizeof( AFSCcb);
1323 pCcb->Type = AFS_CCB;
1325 pCcb->NPCcb = (AFSNonPagedCcb *)AFSExAllocatePoolWithTag( NonPagedPool,
1326 sizeof( AFSNonPagedCcb),
1327 AFS_CCB_NP_ALLOCATION_TAG);
1329 if( pCcb->NPCcb == NULL)
1332 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1333 AFS_TRACE_LEVEL_ERROR,
1334 "AFSInitCcb Failed to allocate NPCcb\n"));
1336 try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1339 ExInitializeResourceLite( &pCcb->NPCcb->CcbLock);
1341 pCcb->DirectoryCB = DirectoryCB;
1343 lCount = InterlockedIncrement( &pCcb->DirectoryCB->DirOpenReferenceCount);
1345 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1346 AFS_TRACE_LEVEL_VERBOSE,
1347 "AFSInitCcb Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1348 &pCcb->DirectoryCB->NameInformation.FileName,
1353 pCcb->GrantedAccess = GrantedAccess;
1355 pCcb->FileAccess = FileAccess;
1365 if( !NT_SUCCESS( Status))
1371 if ( pCcb->NPCcb != NULL)
1374 AFSExFreePoolWithTag( pCcb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1377 AFSExFreePoolWithTag( pCcb, AFS_CCB_ALLOCATION_TAG);
1388 // Function: AFSRemoveCcb
1392 // This function performs Ccb removal/deallocation
1400 AFSRemoveCcb( IN AFSFcb *Fcb,
1406 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1410 BooleanFlagOn( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST))
1413 AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1416 if( Ccb->ListEntry.fLink == NULL)
1419 Fcb->CcbListTail = (AFSCcb *)Ccb->ListEntry.bLink;
1421 if( Fcb->CcbListTail != NULL)
1423 Fcb->CcbListTail->ListEntry.fLink = NULL;
1428 ((AFSCcb *)(Ccb->ListEntry.fLink))->ListEntry.bLink = Ccb->ListEntry.bLink;
1431 if( Ccb->ListEntry.bLink == NULL)
1434 Fcb->CcbListHead = (AFSCcb *)Ccb->ListEntry.fLink;
1436 if( Fcb->CcbListHead != NULL)
1438 Fcb->CcbListHead->ListEntry.bLink = NULL;
1443 ((AFSCcb *)(Ccb->ListEntry.bLink))->ListEntry.fLink = Ccb->ListEntry.fLink;
1446 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
1449 if( Ccb->MaskName.Buffer != NULL)
1452 AFSExFreePoolWithTag( Ccb->MaskName.Buffer, AFS_GENERIC_MEMORY_6_TAG);
1455 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_FREE_FULL_PATHNAME))
1458 AFSExFreePoolWithTag( Ccb->FullFileName.Buffer, 0);
1462 // If we have a name array then delete it
1465 if( Ccb->NameArray != NULL)
1468 AFSFreeNameArray( Ccb->NameArray);
1470 Ccb->NameArray = NULL;
1473 if( Ccb->DirectorySnapshot != NULL)
1476 AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
1478 Ccb->DirectorySnapshot = NULL;
1481 if( Ccb->NotifyMask.Buffer != NULL)
1484 AFSExFreePoolWithTag( Ccb->NotifyMask.Buffer, AFS_GENERIC_MEMORY_7_TAG);
1487 if ( Ccb->DirectoryCB != NULL)
1490 lCount = InterlockedDecrement( &Ccb->DirectoryCB->DirOpenReferenceCount);
1492 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1493 AFS_TRACE_LEVEL_VERBOSE,
1494 "AFSRemoveCcb Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1495 &Ccb->DirectoryCB->NameInformation.FileName,
1500 ASSERT( lCount >= 0);
1503 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1509 ExDeleteResourceLite( &Ccb->NPCcb->CcbLock);
1511 AFSExFreePoolWithTag( Ccb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1513 AFSExFreePoolWithTag( Ccb, AFS_CCB_ALLOCATION_TAG);
1517 AFSInsertCcb( IN AFSFcb *Fcb,
1521 NTSTATUS ntStatus = STATUS_SUCCESS;
1523 AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1526 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1529 if( Fcb->CcbListHead == NULL)
1531 Fcb->CcbListHead = Ccb;
1535 Fcb->CcbListTail->ListEntry.fLink = (void *)Ccb;
1537 Ccb->ListEntry.bLink = (void *)Fcb->CcbListTail;
1540 Fcb->CcbListTail = Ccb;
1542 SetFlag( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST);
1544 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1546 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);