2 * Copyright (c) 2008, 2009, 2010, 2011 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.
34 // File: AFSVolume.cpp
37 #include "AFSCommon.h"
40 AFSInitVolume( IN GUID *AuthGroup,
41 IN AFSFileID *RootFid,
42 IN LONG VolumeReferenceReason,
43 OUT AFSVolumeCB **VolumeCB)
46 NTSTATUS ntStatus = STATUS_SUCCESS;
47 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
48 AFSNonPagedVolumeCB *pNonPagedVcb = NULL;
49 AFSVolumeCB *pVolumeCB = NULL;
50 AFSNonPagedObjectInfoCB *pNonPagedObject = NULL;
51 ULONGLONG ullIndex = 0;
52 BOOLEAN bReleaseLocks = FALSE;
53 AFSVolumeInfoCB stVolumeInformation = {0};
54 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
61 // Before grabbing any locks ask the service for the volume information
62 // This may be a waste but we need to get this information prior to
63 // taking any volume tree locks. Don't do this for any 'reserved' cell entries
66 if( RootFid->Cell != 0)
69 RtlZeroMemory( &stVolumeInformation,
70 sizeof( AFSVolumeInfoCB));
72 ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
74 &stVolumeInformation);
76 if( !NT_SUCCESS( ntStatus))
79 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
80 AFS_TRACE_LEVEL_ERROR,
81 "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
84 try_return( ntStatus);
88 // Grab our tree locks and see if we raced with someone else
91 AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
94 AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
99 ullIndex = AFSCreateHighIndex( RootFid);
101 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
103 (AFSBTreeEntry **)&pVolumeCB);
105 if( NT_SUCCESS( ntStatus) &&
110 // So we don't lock with an invalidation call ...
113 lCount = AFSVolumeIncrement( pVolumeCB,
114 VolumeReferenceReason);
116 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
117 AFS_TRACE_LEVEL_VERBOSE,
118 "AFSInitVolume Increment count on volume %p Reason %u Cnt %d\n",
120 VolumeReferenceReason,
123 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
125 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
127 bReleaseLocks = FALSE;
129 AFSAcquireExcl( pVolumeCB->VolumeLock,
132 *VolumeCB = pVolumeCB;
134 try_return( ntStatus);
138 // Revert our status from the above call back to success.
141 ntStatus = STATUS_SUCCESS;
145 // For the global root we allocate out volume node and insert it
146 // into the volume tree ...
149 pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( PagedPool,
150 sizeof( AFSVolumeCB),
151 AFS_VCB_ALLOCATION_TAG);
153 if( pVolumeCB == NULL)
156 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
157 AFS_TRACE_LEVEL_ERROR,
158 "AFSInitVolume Failed to allocate the root volume cb\n"));
160 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
163 RtlZeroMemory( pVolumeCB,
164 sizeof( AFSVolumeCB));
167 // The non paged portion
170 pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
171 sizeof( AFSNonPagedVolumeCB),
172 AFS_VCB_NP_ALLOCATION_TAG);
174 if( pNonPagedVcb == NULL)
177 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
178 AFS_TRACE_LEVEL_ERROR,
179 "AFSInitVolume Failed to allocate the root non paged volume cb\n"));
181 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
184 RtlZeroMemory( pNonPagedVcb,
185 sizeof( AFSNonPagedVolumeCB));
187 ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);
189 ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
191 pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
192 sizeof( AFSNonPagedObjectInfoCB),
193 AFS_NP_OBJECT_INFO_TAG);
195 if( pNonPagedObject == NULL)
198 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
199 AFS_TRACE_LEVEL_ERROR,
200 "AFSInitVolume Failed to allocate the root non paged object cb\n"));
202 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
205 RtlZeroMemory( pNonPagedObject,
206 sizeof( AFSNonPagedObjectInfoCB));
208 ExInitializeResourceLite( &pNonPagedObject->ObjectInfoLock);
210 ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);
212 pVolumeCB->NonPagedVcb = pNonPagedVcb;
214 pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;
216 pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;
218 pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;
220 pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;
222 lCount = AFSVolumeIncrement( pVolumeCB,
223 VolumeReferenceReason);
225 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
226 AFS_TRACE_LEVEL_VERBOSE,
227 "AFSInitVolume Initializing volume %p Reason %u count %d\n",
229 VolumeReferenceReason,
232 AFSAcquireExcl( pVolumeCB->VolumeLock,
235 pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
236 sizeof( AFSDirectoryCB) + sizeof( WCHAR),
239 if( pVolumeCB->DirectoryCB == NULL)
242 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
245 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
246 AFS_TRACE_LEVEL_VERBOSE,
247 "AFSInitVolume AFS_DIR_ENTRY_TAG allocated %p\n",
248 pVolumeCB->DirectoryCB));
250 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
251 sizeof( AFSNonPagedDirectoryCB),
252 AFS_DIR_ENTRY_NP_TAG);
254 if( pNonPagedDirEntry == NULL)
257 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
260 RtlZeroMemory( pVolumeCB->DirectoryCB,
261 sizeof( AFSDirectoryCB) + sizeof( WCHAR));
263 RtlZeroMemory( pNonPagedDirEntry,
264 sizeof( AFSNonPagedDirectoryCB));
266 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
268 pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;
271 // Initialize the non-paged portion of the directory entry
274 KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
275 KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
276 KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);
278 pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;
280 SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);
282 pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell;
283 pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume;
284 pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode;
285 pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique;
286 pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash;
288 pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
290 pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);
292 pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;
294 pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));
296 RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
301 // Copy in the volume information retrieved above
304 RtlCopyMemory( &pVolumeCB->VolumeInformation,
305 &stVolumeInformation,
306 sizeof( AFSVolumeInfoCB));
312 pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;
315 // The ObjectInformation VolumeCB pointer does not obtain
316 // a reference count.
319 pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;
322 // Insert the volume into our volume tree. Don't insert any reserved entries
325 if( RootFid->Cell != 0)
328 pVolumeCB->TreeEntry.HashIndex = ullIndex;
330 if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
333 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;
335 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
340 if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
341 &pVolumeCB->TreeEntry)))
344 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
348 if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
351 pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
356 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;
358 pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
361 pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
364 *VolumeCB = pVolumeCB;
368 if( !NT_SUCCESS( ntStatus))
371 if( pNonPagedVcb != NULL)
374 AFSReleaseResource( pVolumeCB->VolumeLock);
376 ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);
378 ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
380 AFSExFreePoolWithTag( pNonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
383 if( pNonPagedObject != NULL)
386 ExDeleteResourceLite( &pNonPagedObject->ObjectInfoLock);
388 AFSExFreePoolWithTag( pNonPagedObject, AFS_NP_OBJECT_INFO_TAG);
391 if( pVolumeCB != NULL)
394 if( pVolumeCB->DirectoryCB != NULL)
397 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
398 AFS_TRACE_LEVEL_VERBOSE,
399 "AFSInitVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
400 pVolumeCB->DirectoryCB));
402 AFSExFreePoolWithTag( pVolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
405 AFSExFreePoolWithTag( pVolumeCB, AFS_VCB_ALLOCATION_TAG);
408 if( pNonPagedDirEntry != NULL)
411 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
413 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
420 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
422 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
430 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
433 NTSTATUS ntStatus = STATUS_SUCCESS;
434 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
440 ASSERT( VolumeCB->VolumeReferenceCount == 0);
443 // Remove the volume from the tree and list
444 // Don't process the list information for reserved entries
447 if( VolumeCB->ObjectInformation.FileId.Cell != 0)
450 if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
453 AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
454 &VolumeCB->TreeEntry);
457 if( VolumeCB->ListEntry.fLink == NULL)
460 pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;
462 if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
465 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
471 ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
474 if( VolumeCB->ListEntry.bLink == NULL)
477 pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;
479 if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
482 pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
488 ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
493 // Remove any PIOctl objects we have
496 if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
499 if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
502 AFSAcquireExcl( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
505 AFSRemoveFcb( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
507 AFSReleaseResource( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
510 lCount = AFSObjectInfoDecrement( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
511 AFS_OBJECT_REFERENCE_PIOCTL);
513 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
514 AFS_TRACE_LEVEL_VERBOSE,
515 "AFSRemoveVolume Decrement count on object %p Cnt %d\n",
516 VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
519 ASSERT( lCount == 0);
524 AFSDeleteObjectInfo( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
527 ExDeleteResourceLite( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
529 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
531 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
532 AFS_TRACE_LEVEL_VERBOSE,
533 "AFSRemoveVolume (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
534 VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB));
536 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
539 if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
543 // Release the fid in the service
546 AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
550 // Free up the memory
553 if( VolumeCB->NonPagedVcb != NULL)
556 if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
558 AFSReleaseResource( VolumeCB->VolumeLock);
561 ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);
563 ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);
565 AFSExFreePoolWithTag( VolumeCB->NonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
568 if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
571 ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
573 ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);
575 AFSExFreePoolWithTag( VolumeCB->ObjectInformation.NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
578 if( VolumeCB->DirectoryCB != NULL)
581 if( VolumeCB->DirectoryCB->NonPaged != NULL)
584 ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);
586 AFSExFreePoolWithTag( VolumeCB->DirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
589 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
590 AFS_TRACE_LEVEL_VERBOSE,
591 "AFSRemoveVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
592 VolumeCB->DirectoryCB));
594 AFSExFreePoolWithTag( VolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
597 AFSExFreePoolWithTag( VolumeCB, AFS_VCB_ALLOCATION_TAG);
604 AFSVolumeIncrement( IN AFSVolumeCB *VolumeCB,
610 lCount = InterlockedIncrement( &VolumeCB->VolumeReferenceCount);
612 InterlockedIncrement( &VolumeCB->VolumeReferences[ Reason]);
618 AFSVolumeDecrement( IN AFSVolumeCB *VolumeCB,
624 lCount = InterlockedDecrement( &VolumeCB->VolumeReferences[ Reason]);
626 ASSERT( lCount >= 0);
628 lCount = InterlockedDecrement( &VolumeCB->VolumeReferenceCount);
630 ASSERT( lCount >= 0);