Windows: AFSVolumeCB track RefCount reasons
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFcbSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
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.
21  *
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.
33  */
34
35 //
36 // File: AFSFcbSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSInitFcb
43 //
44 // Description:
45 //
46 //      This function performs Fcb initialization
47 //
48 // Return:
49 //
50 //      Return Fcb->NPFcb->Resource held exclusive
51 //
52
53 NTSTATUS
54 AFSInitFcb( IN AFSDirectoryCB  *DirEntry)
55 {
56
57     NTSTATUS ntStatus = STATUS_SUCCESS;
58     AFSFcb *pFcb = NULL;
59     AFSNonPagedFcb *pNPFcb = NULL;
60     USHORT  usFcbLength = 0;
61     AFSObjectInfoCB *pObjectInfo = NULL;
62     AFSVolumeCB *pVolumeCB = NULL;
63
64     __Enter
65     {
66
67         pObjectInfo = DirEntry->ObjectInformation;
68
69         if ( pObjectInfo->Fcb != NULL)
70         {
71
72             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
73                             TRUE);
74
75             try_return( ntStatus = STATUS_SUCCESS);
76         }
77
78         pVolumeCB = pObjectInfo->VolumeCB;
79
80         //
81         // Allocate the Fcb and the nonpaged portion of the Fcb.
82         //
83
84         AFSDbgLogMsg( 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);
92
93         usFcbLength = sizeof( AFSFcb);
94
95         pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
96                                                    usFcbLength,
97                                                    AFS_FCB_ALLOCATION_TAG);
98
99         if( pFcb == NULL)
100         {
101
102             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
103                           AFS_TRACE_LEVEL_ERROR,
104                           "AFSInitFcb Failed to allocate fcb\n");
105
106             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
107         }
108
109         RtlZeroMemory( pFcb,
110                        usFcbLength);
111
112         pFcb->Header.NodeByteSize = usFcbLength;
113
114         pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
115                                                              sizeof( AFSNonPagedFcb),
116                                                              AFS_FCB_NP_ALLOCATION_TAG);
117
118         if( pNPFcb == NULL)
119         {
120
121             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
122                           AFS_TRACE_LEVEL_ERROR,
123                           "AFSInitFcb Failed to allocate non-paged fcb\n");
124
125             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
126         }
127
128         RtlZeroMemory( pNPFcb,
129                        sizeof( AFSNonPagedFcb));
130
131         pNPFcb->Size = sizeof( AFSNonPagedFcb);
132
133         pNPFcb->Type = AFS_NON_PAGED_FCB;
134
135         //
136         // Initialize the advanced header
137         //
138
139         ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
140
141         FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
142
143         //
144         // OK, initialize the entry
145         //
146
147         ExInitializeResourceLite( &pNPFcb->Resource);
148
149         ExInitializeResourceLite( &pNPFcb->PagingResource);
150
151         ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
152
153         ExInitializeResourceLite( &pNPFcb->CcbListLock);
154
155         //
156         // Grab the Fcb for processing
157         //
158
159         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
160                       AFS_TRACE_LEVEL_VERBOSE,
161                       "AFSInitFcb Acquiring Fcb lock %p EXCL %08lX\n",
162                       &pNPFcb->Resource,
163                       PsGetCurrentThread());
164
165         AFSAcquireExcl( &pNPFcb->Resource,
166                         TRUE);
167
168         pFcb->Header.Resource = &pNPFcb->Resource;
169
170         pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
171
172         pFcb->NPFcb = pNPFcb;
173
174         //
175         // Set type specific information
176         //
177
178         if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
179         {
180
181             //
182             // Reset the type to a directory type
183             //
184
185             pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB;
186         }
187         else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
188         {
189
190             pFcb->Header.NodeTypeCode = AFS_FILE_FCB;
191
192             //
193             // Initialize the file specific information
194             //
195
196             FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock,
197                                      NULL,
198                                      NULL);
199
200             //
201             // Initialize the header file sizes to our dir entry information
202             //
203
204             pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
205             pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
206             pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
207
208             //
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).
214             //
215             ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource );
216
217             KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
218                                NotificationEvent,
219                                TRUE );
220
221             for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
222             {
223                 InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]);
224             }
225
226             pNPFcb->Specific.File.DirtyListHead = NULL;
227             pNPFcb->Specific.File.DirtyListTail = NULL;
228
229             ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
230
231             KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent,
232                                SynchronizationEvent,
233                                TRUE);
234
235             KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
236                                NotificationEvent,
237                                TRUE);
238         }
239         else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
240         {
241
242             pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB;
243         }
244         else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL)
245         {
246
247             pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB;
248         }
249         else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
250         {
251
252             pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB;
253         }
254         else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
255         {
256
257             pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB;
258         }
259         else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
260         {
261             pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB;
262         }
263         else
264         {
265             pFcb->Header.NodeTypeCode = AFS_INVALID_FCB;
266         }
267
268         pFcb->ObjectInformation = pObjectInfo;
269
270         AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
271                           TRUE);
272         //
273         // Swap the allocated FCB into the ObjectInformation structure if it
274         // does not already have one.
275         //
276
277         if ( InterlockedCompareExchangePointer( (PVOID *)&pObjectInfo->Fcb, pFcb, NULL) != NULL)
278         {
279
280             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
281                           AFS_TRACE_LEVEL_WARNING,
282                           "AFSInitFcb Raced Fcb %p pFcb %p Name %wZ\n",
283                           pObjectInfo->Fcb,
284                           pFcb,
285                           &DirEntry->NameInformation.FileName);
286
287             AFSDbgLogMsg( 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());
292
293             AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
294
295             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
296                             TRUE);
297
298             try_return( ntStatus = STATUS_REPARSE);
299         }
300
301         AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
302
303         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
304                       AFS_TRACE_LEVEL_VERBOSE,
305                       "AFSInitFcb Initialized Fcb %p Name %wZ\n",
306                       &pObjectInfo->Fcb,
307                       &DirEntry->NameInformation.FileName);
308
309 try_exit:
310
311         if( ntStatus != STATUS_SUCCESS)
312         {
313
314             if ( !NT_SUCCESS( ntStatus))
315             {
316
317                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
318                               AFS_TRACE_LEVEL_ERROR,
319                               "AFSInitFcb Failed to initialize fcb Status %08lX\n",
320                               ntStatus);
321             }
322
323             if( pFcb != NULL)
324             {
325
326                 if( pNPFcb != NULL)
327                 {
328
329                     AFSReleaseResource( &pNPFcb->Resource);
330
331                     FsRtlTeardownPerStreamContexts( &pFcb->Header);
332
333                     if ( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
334                     {
335
336                         FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
337
338                         ExDeleteResourceLite( &pNPFcb->Specific.File.ExtentsResource);
339
340                         ExDeleteResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
341                     }
342
343                     ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
344
345                     ExDeleteResourceLite( &pNPFcb->PagingResource);
346
347                     ExDeleteResourceLite( &pNPFcb->CcbListLock);
348
349                     ExDeleteResourceLite( &pNPFcb->Resource);
350
351                     AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
352                 }
353
354                 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
355             }
356         }
357     }
358
359     return ntStatus;
360 }
361
362 NTSTATUS
363 AFSInitVolume( IN GUID *AuthGroup,
364                IN AFSFileID *RootFid,
365                IN LONG VolumeReferenceReason,
366                OUT AFSVolumeCB **VolumeCB)
367 {
368
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;
378     LONG lCount;
379
380     __Enter
381     {
382
383         //
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
387         //
388
389         if( RootFid->Cell != 0)
390         {
391
392             RtlZeroMemory( &stVolumeInformation,
393                            sizeof( AFSVolumeInfoCB));
394
395             ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
396                                                      RootFid,
397                                                      &stVolumeInformation);
398
399             if( !NT_SUCCESS( ntStatus))
400             {
401
402                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
403                               AFS_TRACE_LEVEL_ERROR,
404                               "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
405                               ntStatus);
406
407                 try_return( ntStatus);
408             }
409
410             //
411             // Grab our tree locks and see if we raced with someone else
412             //
413
414             AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
415                             TRUE);
416
417             AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
418                             TRUE);
419
420             bReleaseLocks = TRUE;
421
422             ullIndex = AFSCreateHighIndex( RootFid);
423
424             ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
425                                            ullIndex,
426                                            (AFSBTreeEntry **)&pVolumeCB);
427
428             if( NT_SUCCESS( ntStatus) &&
429                 pVolumeCB != NULL)
430             {
431
432                 //
433                 // So we don't lock with an invalidation call ...
434                 //
435
436                 lCount = AFSVolumeIncrement( pVolumeCB,
437                                              VolumeReferenceReason);
438
439                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
440                               AFS_TRACE_LEVEL_VERBOSE,
441                               "AFSInitVolume Increment count on volume %p Reason %u Cnt %d\n",
442                               pVolumeCB,
443                               VolumeReferenceReason,
444                               lCount);
445
446                 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
447
448                 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
449
450                 bReleaseLocks = FALSE;
451
452                 AFSAcquireExcl( pVolumeCB->VolumeLock,
453                                 TRUE);
454
455                 *VolumeCB = pVolumeCB;
456
457                 try_return( ntStatus);
458             }
459
460             //
461             // Revert our status from the above call back to success.
462             //
463
464             ntStatus = STATUS_SUCCESS;
465         }
466
467         //
468         // For the global root we allocate out volume node and insert it
469         // into the volume tree ...
470         //
471
472         pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( PagedPool,
473                                                              sizeof( AFSVolumeCB),
474                                                              AFS_VCB_ALLOCATION_TAG);
475
476         if( pVolumeCB == NULL)
477         {
478
479             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
480                           AFS_TRACE_LEVEL_ERROR,
481                           "AFSInitVolume Failed to allocate the root volume cb\n");
482
483             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
484         }
485
486         RtlZeroMemory( pVolumeCB,
487                        sizeof( AFSVolumeCB));
488
489         //
490         // The non paged portion
491         //
492
493         pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
494                                                                         sizeof( AFSNonPagedVolumeCB),
495                                                                         AFS_VCB_NP_ALLOCATION_TAG);
496
497         if( pNonPagedVcb == NULL)
498         {
499
500             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
501                           AFS_TRACE_LEVEL_ERROR,
502                           "AFSInitVolume Failed to allocate the root non paged volume cb\n");
503
504             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
505         }
506
507         RtlZeroMemory( pNonPagedVcb,
508                        sizeof( AFSNonPagedVolumeCB));
509
510         ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);
511
512         ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
513
514         pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
515                                                                                sizeof( AFSNonPagedObjectInfoCB),
516                                                                                AFS_NP_OBJECT_INFO_TAG);
517
518         if( pNonPagedObject == NULL)
519         {
520
521             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
522                           AFS_TRACE_LEVEL_ERROR,
523                           "AFSInitVolume Failed to allocate the root non paged object cb\n");
524
525             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
526         }
527
528         RtlZeroMemory( pNonPagedObject,
529                        sizeof( AFSNonPagedObjectInfoCB));
530
531         ExInitializeResourceLite( &pNonPagedObject->ObjectInfoLock);
532
533         ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);
534
535         pVolumeCB->NonPagedVcb = pNonPagedVcb;
536
537         pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;
538
539         pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;
540
541         pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;
542
543         pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;
544
545         lCount = AFSVolumeIncrement( pVolumeCB,
546                                      VolumeReferenceReason);
547
548         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
549                       AFS_TRACE_LEVEL_VERBOSE,
550                       "AFSInitVolume Initializing volume %p Reason %u count %d\n",
551                       pVolumeCB,
552                       VolumeReferenceReason,
553                       lCount);
554
555         AFSAcquireExcl( pVolumeCB->VolumeLock,
556                         TRUE);
557
558         pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
559                                                                              sizeof( AFSDirectoryCB) + sizeof( WCHAR),
560                                                                              AFS_DIR_ENTRY_TAG);
561
562         if( pVolumeCB->DirectoryCB == NULL)
563         {
564
565             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
566         }
567
568         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
569                       AFS_TRACE_LEVEL_VERBOSE,
570                       "AFSInitVolume AFS_DIR_ENTRY_TAG allocated %p\n",
571                       pVolumeCB->DirectoryCB);
572
573         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
574                                                                                 sizeof( AFSNonPagedDirectoryCB),
575                                                                                 AFS_DIR_ENTRY_NP_TAG);
576
577         if( pNonPagedDirEntry == NULL)
578         {
579
580             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
581         }
582
583         RtlZeroMemory( pVolumeCB->DirectoryCB,
584                        sizeof( AFSDirectoryCB) + sizeof( WCHAR));
585
586         RtlZeroMemory( pNonPagedDirEntry,
587                        sizeof( AFSNonPagedDirectoryCB));
588
589         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
590
591         pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;
592
593         //
594         // Initialize the non-paged portion of the directory entry
595         //
596
597         KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
598         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
599         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);
600
601         pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;
602
603         SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);
604
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;
610
611         pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
612
613         pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);
614
615         pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;
616
617         pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));
618
619         RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
620                        L"\\",
621                        sizeof( WCHAR));
622
623         //
624         // Copy in the volume information retrieved above
625         //
626
627         RtlCopyMemory( &pVolumeCB->VolumeInformation,
628                        &stVolumeInformation,
629                        sizeof( AFSVolumeInfoCB));
630
631         //
632         // Setup pointers
633         //
634
635         pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;
636
637         //
638         // The ObjectInformation VolumeCB pointer does not obtain
639         // a reference count.
640         //
641
642         pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;
643
644         //
645         // Insert the volume into our volume tree. Don't insert any reserved entries
646         //
647
648         if( RootFid->Cell != 0)
649         {
650
651             pVolumeCB->TreeEntry.HashIndex = ullIndex;
652
653             if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
654             {
655
656                 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;
657
658                 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
659             }
660             else
661             {
662
663                 if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
664                                                      &pVolumeCB->TreeEntry)))
665                 {
666
667                     SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
668                 }
669             }
670
671             if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
672             {
673
674                 pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
675             }
676             else
677             {
678
679                 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;
680
681                 pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
682             }
683
684             pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
685         }
686
687         *VolumeCB = pVolumeCB;
688
689 try_exit:
690
691         if( !NT_SUCCESS( ntStatus))
692         {
693
694             if( pNonPagedVcb != NULL)
695             {
696
697                 AFSReleaseResource( pVolumeCB->VolumeLock);
698
699                 ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);
700
701                 ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
702
703                 AFSExFreePoolWithTag( pNonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
704             }
705
706             if( pNonPagedObject != NULL)
707             {
708
709                 ExDeleteResourceLite( &pNonPagedObject->ObjectInfoLock);
710
711                 AFSExFreePoolWithTag( pNonPagedObject, AFS_NP_OBJECT_INFO_TAG);
712             }
713
714             if( pVolumeCB != NULL)
715             {
716
717                 if( pVolumeCB->DirectoryCB != NULL)
718                 {
719
720                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
721                                   AFS_TRACE_LEVEL_VERBOSE,
722                                   "AFSInitVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
723                                   pVolumeCB->DirectoryCB);
724
725                     AFSExFreePoolWithTag( pVolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
726                 }
727
728                 AFSExFreePoolWithTag( pVolumeCB, AFS_VCB_ALLOCATION_TAG);
729             }
730
731             if( pNonPagedDirEntry != NULL)
732             {
733
734                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
735
736                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
737             }
738         }
739
740         if( bReleaseLocks)
741         {
742
743             AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
744
745             AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
746         }
747     }
748
749     return ntStatus;
750 }
751
752 NTSTATUS
753 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
754 {
755
756     NTSTATUS ntStatus = STATUS_SUCCESS;
757     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
758
759     __Enter
760     {
761
762         ASSERT( VolumeCB->VolumeReferenceCount == 0);
763
764         //
765         // Remove the volume from the tree and list
766         // Don't process the list information for reserved entries
767         //
768
769         if( VolumeCB->ObjectInformation.FileId.Cell != 0)
770         {
771
772             if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
773             {
774
775                 AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
776                                     &VolumeCB->TreeEntry);
777             }
778
779             if( VolumeCB->ListEntry.fLink == NULL)
780             {
781
782                 pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;
783
784                 if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
785                 {
786
787                     pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
788                 }
789             }
790             else
791             {
792
793                 ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
794             }
795
796             if( VolumeCB->ListEntry.bLink == NULL)
797             {
798
799                 pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;
800
801                 if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
802                 {
803
804                     pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
805                 }
806             }
807             else
808             {
809
810                 ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
811             }
812         }
813
814         //
815         // Remove any PIOctl objects we have
816         //
817
818         if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
819         {
820
821             if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
822             {
823
824                 AFSAcquireExcl( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
825                                 TRUE);
826
827                 AFSRemoveFcb( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
828
829                 AFSReleaseResource( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
830             }
831
832             AFSDeleteObjectInfo( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
833
834             ExDeleteResourceLite( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
835
836             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
837
838             AFSDbgLogMsg( 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);
842
843             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
844         }
845
846         if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
847         {
848
849             //
850             // Release the fid in the service
851             //
852
853             AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
854         }
855
856         //
857         // Free up the memory
858         //
859
860         if( VolumeCB->NonPagedVcb != NULL)
861         {
862
863             if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
864             {
865                 AFSReleaseResource( VolumeCB->VolumeLock);
866             }
867
868             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);
869
870             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);
871
872             AFSExFreePoolWithTag( VolumeCB->NonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
873         }
874
875         if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
876         {
877
878             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
879
880             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);
881
882             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
883         }
884
885         if( VolumeCB->DirectoryCB != NULL)
886         {
887
888             if( VolumeCB->DirectoryCB->NonPaged != NULL)
889             {
890
891                 ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);
892
893                 AFSExFreePoolWithTag( VolumeCB->DirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
894             }
895
896             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
897                           AFS_TRACE_LEVEL_VERBOSE,
898                           "AFSRemoveVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
899                           VolumeCB->DirectoryCB);
900
901             AFSExFreePoolWithTag( VolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
902         }
903
904         AFSExFreePoolWithTag( VolumeCB, AFS_VCB_ALLOCATION_TAG);
905     }
906
907     return ntStatus;
908 }
909
910 LONG
911 AFSVolumeIncrement( IN AFSVolumeCB *VolumeCB,
912                     IN LONG Reason)
913 {
914
915     LONG lCount;
916
917     lCount = InterlockedIncrement( &VolumeCB->VolumeReferenceCount);
918
919     InterlockedIncrement( &VolumeCB->VolumeReferences[ Reason]);
920
921     return lCount;
922 }
923
924 LONG
925 AFSVolumeDecrement( IN AFSVolumeCB *VolumeCB,
926                     IN LONG Reason)
927 {
928
929     LONG lCount;
930
931     lCount = InterlockedDecrement( &VolumeCB->VolumeReferences[ Reason]);
932
933     ASSERT( lCount >= 0);
934
935     lCount = InterlockedDecrement( &VolumeCB->VolumeReferenceCount);
936
937     ASSERT( lCount >= 0);
938
939     return lCount;
940 }
941
942 //
943 // Function: AFSInitRootFcb
944 //
945 // Description:
946 //
947 //      This function performs Root node Fcb initialization
948 //
949 // Return:
950 //
951 //      A status is returned for the function
952 //
953
954 NTSTATUS
955 AFSInitRootFcb( IN ULONGLONG ProcessID,
956                 IN AFSVolumeCB *VolumeCB)
957 {
958
959     UNREFERENCED_PARAMETER(ProcessID);
960     NTSTATUS ntStatus = STATUS_SUCCESS;
961     AFSFcb *pFcb = NULL;
962     AFSNonPagedFcb *pNPFcb = NULL;
963
964     __Enter
965     {
966
967         //
968         // Initialize the root fcb
969         //
970
971         pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
972                                                    sizeof( AFSFcb),
973                                                    AFS_FCB_ALLOCATION_TAG);
974
975         if( pFcb == NULL)
976         {
977
978             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
979                           AFS_TRACE_LEVEL_ERROR,
980                           "AFSInitRootFcb Failed to allocate the root fcb\n");
981
982             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
983         }
984
985         RtlZeroMemory( pFcb,
986                        sizeof( AFSFcb));
987
988         pFcb->Header.NodeByteSize = sizeof( AFSFcb);
989
990         pFcb->Header.NodeTypeCode = AFS_ROOT_FCB;
991
992         pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
993                                                              sizeof( AFSNonPagedFcb),
994                                                              AFS_FCB_NP_ALLOCATION_TAG);
995
996         if( pNPFcb == NULL)
997         {
998
999             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1000                           AFS_TRACE_LEVEL_ERROR,
1001                           "AFSInitRootFcb Failed to allocate the non-paged fcb\n");
1002
1003             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1004         }
1005
1006         RtlZeroMemory( pNPFcb,
1007                        sizeof( AFSNonPagedFcb));
1008
1009         pNPFcb->Size = sizeof( AFSNonPagedFcb);
1010
1011         pNPFcb->Type = AFS_NON_PAGED_FCB;
1012
1013         //
1014         // OK, initialize the entry
1015         //
1016
1017         ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
1018
1019         FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
1020
1021         ExInitializeResourceLite( &pNPFcb->Resource);
1022
1023         ExInitializeResourceLite( &pNPFcb->PagingResource);
1024
1025         ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
1026
1027         ExInitializeResourceLite( &pNPFcb->CcbListLock);
1028
1029         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1030                       AFS_TRACE_LEVEL_VERBOSE,
1031                       "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
1032                       &pNPFcb->Resource,
1033                       PsGetCurrentThread());
1034
1035         AFSAcquireExcl( &pNPFcb->Resource,
1036                         TRUE);
1037
1038         pFcb->Header.Resource = &pNPFcb->Resource;
1039
1040         pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
1041
1042         pFcb->NPFcb = pNPFcb;
1043
1044         //
1045         // Save the root Fcb in the VolumeCB
1046         //
1047
1048         pFcb->ObjectInformation = &VolumeCB->ObjectInformation;
1049
1050         VolumeCB->ObjectInformation.VolumeCB = VolumeCB;
1051
1052         AFSAcquireShared( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1053                           TRUE);
1054         //
1055         // Swap the allocated FCB into the ObjectInformation structure if it
1056         // does not already have one.
1057         //
1058
1059         if ( InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb, pFcb, NULL) != NULL)
1060         {
1061
1062             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1063                           AFS_TRACE_LEVEL_WARNING,
1064                           "AFSInitRootFcb Raced Fcb %p pFcb %p\n",
1065                           VolumeCB->ObjectInformation.Fcb,
1066                           pFcb);
1067
1068             AFSDbgLogMsg( 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());
1073
1074             AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1075
1076             AFSAcquireExcl( &VolumeCB->ObjectInformation.Fcb->NPFcb->Resource,
1077                             TRUE);
1078
1079             try_return( ntStatus = STATUS_REPARSE);
1080         }
1081
1082         VolumeCB->RootFcb = VolumeCB->ObjectInformation.Fcb;
1083
1084         AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1085
1086         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1087                       AFS_TRACE_LEVEL_VERBOSE,
1088                       "AFSInitRootFcb Initialized Fcb %p\n",
1089                       &VolumeCB->ObjectInformation.Fcb);
1090
1091 try_exit:
1092
1093         if( !NT_SUCCESS( ntStatus) ||
1094             ntStatus == STATUS_REPARSE)
1095         {
1096
1097             if( pFcb != NULL)
1098             {
1099
1100                 if( pNPFcb != NULL)
1101                 {
1102
1103                     AFSReleaseResource( &pNPFcb->Resource);
1104
1105                     FsRtlTeardownPerStreamContexts( &pFcb->Header);
1106
1107                     ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
1108
1109                     ExDeleteResourceLite( &pNPFcb->PagingResource);
1110
1111                     ExDeleteResourceLite( &pNPFcb->CcbListLock);
1112
1113                     ExDeleteResourceLite( &pNPFcb->Resource);
1114
1115                     AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1116                 }
1117
1118                 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1119             }
1120         }
1121     }
1122
1123     return ntStatus;
1124 }
1125
1126 //
1127 // Function: AFSRemoveRootFcb
1128 //
1129 // Description:
1130 //
1131 //      This function performs root Fcb removal/deallocation from
1132 //      the provided VolumeCB object.
1133 //
1134 // Return:
1135 //
1136 //      None
1137 //
1138
1139 void
1140 AFSRemoveRootFcb( IN AFSVolumeCB *VolumeCB)
1141 {
1142     AFSFcb * pRootFcb;
1143
1144     pRootFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb,
1145                                                              NULL,
1146                                                              (PVOID *)&VolumeCB->ObjectInformation.Fcb);
1147
1148     if ( pRootFcb == NULL)
1149     {
1150
1151         return;
1152     }
1153
1154     //
1155     // The Fcb has been disconnected from the ObjectInformation block.
1156     // Clear it from the RootFcb convenience pointer.
1157     //
1158
1159     VolumeCB->RootFcb = NULL;
1160
1161     if( pRootFcb->NPFcb != NULL)
1162     {
1163
1164         //
1165         // Now the resource
1166         //
1167
1168         ExDeleteResourceLite( &pRootFcb->NPFcb->Resource);
1169
1170         ExDeleteResourceLite( &pRootFcb->NPFcb->PagingResource);
1171
1172         ExDeleteResourceLite( &pRootFcb->NPFcb->SectionObjectResource);
1173
1174         ExDeleteResourceLite( &pRootFcb->NPFcb->CcbListLock);
1175
1176         FsRtlTeardownPerStreamContexts( &pRootFcb->Header);
1177
1178         //
1179         // The non paged region
1180         //
1181
1182         AFSExFreePoolWithTag( pRootFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1183
1184         pRootFcb->NPFcb = NULL;
1185     }
1186
1187     //
1188     // And the Fcb itself
1189     //
1190
1191     AFSExFreePoolWithTag( pRootFcb, AFS_FCB_ALLOCATION_TAG);
1192
1193     return;
1194 }
1195
1196 //
1197 // Function: AFSRemoveFcb
1198 //
1199 // Description:
1200 //
1201 //      This function performs Fcb removal/deallocation
1202 //
1203 // Return:
1204 //
1205 //      A status is returned for the function
1206 //
1207
1208 void
1209 AFSRemoveFcb( IN AFSFcb **ppFcb)
1210 {
1211
1212     AFSFcb * pFcb;
1213
1214     pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)ppFcb, NULL, (PVOID)(*ppFcb));
1215
1216     if ( pFcb == NULL)
1217     {
1218
1219         return;
1220     }
1221
1222     ASSERT( pFcb->Header.NodeTypeCode != AFS_ROOT_FCB);
1223
1224     //
1225     // Uninitialize the file lock if it is a file
1226     //
1227
1228     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1229                   AFS_TRACE_LEVEL_VERBOSE,
1230                   "AFSRemoveFcb Removing Fcb %p\n",
1231                   pFcb);
1232
1233     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1234     {
1235
1236         FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
1237
1238         //
1239         // The resource we allocated
1240         //
1241
1242         ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.ExtentsResource );
1243
1244         ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
1245
1246     }
1247     else if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1248     {
1249
1250
1251     }
1252
1253     //
1254     // Tear down the FM specific contexts
1255     //
1256
1257     FsRtlTeardownPerStreamContexts( &pFcb->Header);
1258
1259     //
1260     // Delete the resources
1261     //
1262
1263     ExDeleteResourceLite( &pFcb->NPFcb->Resource);
1264
1265     ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
1266
1267     ExDeleteResourceLite( &pFcb->NPFcb->SectionObjectResource);
1268
1269     ExDeleteResourceLite( &pFcb->NPFcb->CcbListLock);
1270
1271     //
1272     // The non paged region
1273     //
1274
1275     AFSExFreePoolWithTag( pFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1276
1277     //
1278     // And the Fcb itself, which includes the name
1279     //
1280
1281     AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1282
1283     return;
1284 }
1285
1286 NTSTATUS
1287 AFSInitCcb( IN OUT AFSCcb **Ccb,
1288             IN     AFSDirectoryCB *DirectoryCB,
1289             IN     ACCESS_MASK     GrantedAccess,
1290             IN     ULONG           FileAccess)
1291 {
1292
1293     NTSTATUS Status = STATUS_SUCCESS;
1294     AFSCcb *pCcb = NULL;
1295     LONG lCount;
1296
1297     __Enter
1298     {
1299
1300         //
1301         // Allocate our context control block
1302         //
1303
1304         pCcb = (AFSCcb *)AFSExAllocatePoolWithTag( PagedPool,
1305                                                    sizeof( AFSCcb),
1306                                                    AFS_CCB_ALLOCATION_TAG);
1307
1308         if( pCcb == NULL)
1309         {
1310
1311             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1312                           AFS_TRACE_LEVEL_ERROR,
1313                           "AFSInitCcb Failed to allocate Ccb\n");
1314
1315             try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1316         }
1317
1318         RtlZeroMemory( pCcb,
1319                        sizeof( AFSCcb));
1320
1321         pCcb->Size = sizeof( AFSCcb);
1322
1323         pCcb->Type = AFS_CCB;
1324
1325         pCcb->NPCcb = (AFSNonPagedCcb *)AFSExAllocatePoolWithTag( NonPagedPool,
1326                                                      sizeof( AFSNonPagedCcb),
1327                                                      AFS_CCB_NP_ALLOCATION_TAG);
1328
1329         if( pCcb->NPCcb == NULL)
1330         {
1331
1332             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1333                           AFS_TRACE_LEVEL_ERROR,
1334                           "AFSInitCcb Failed to allocate NPCcb\n");
1335
1336             try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1337         }
1338
1339         ExInitializeResourceLite( &pCcb->NPCcb->CcbLock);
1340
1341         pCcb->DirectoryCB = DirectoryCB;
1342
1343         lCount = InterlockedIncrement( &pCcb->DirectoryCB->DirOpenReferenceCount);
1344
1345         AFSDbgLogMsg( 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,
1349                       pCcb->DirectoryCB,
1350                       pCcb,
1351                       lCount);
1352
1353         pCcb->GrantedAccess = GrantedAccess;
1354
1355         pCcb->FileAccess = FileAccess;
1356
1357         //
1358         // Return the Ccb
1359         //
1360
1361         *Ccb = pCcb;
1362
1363 try_exit:
1364
1365         if( !NT_SUCCESS( Status))
1366         {
1367
1368             if( pCcb != NULL)
1369             {
1370
1371                 if ( pCcb->NPCcb != NULL)
1372                 {
1373
1374                     AFSExFreePoolWithTag( pCcb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1375                 }
1376
1377                 AFSExFreePoolWithTag( pCcb, AFS_CCB_ALLOCATION_TAG);
1378             }
1379
1380             *Ccb = NULL;
1381         }
1382     }
1383
1384     return Status;
1385 }
1386
1387 //
1388 // Function: AFSRemoveCcb
1389 //
1390 // Description:
1391 //
1392 //      This function performs Ccb removal/deallocation
1393 //
1394 // Return:
1395 //
1396 //      None
1397 //
1398
1399 void
1400 AFSRemoveCcb( IN AFSFcb *Fcb,
1401               IN AFSCcb *Ccb)
1402 {
1403
1404     LONG lCount;
1405
1406     AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1407                     TRUE);
1408
1409     if( Fcb != NULL &&
1410         BooleanFlagOn( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST))
1411     {
1412
1413         AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1414                         TRUE);
1415
1416         if( Ccb->ListEntry.fLink == NULL)
1417         {
1418
1419             Fcb->CcbListTail = (AFSCcb *)Ccb->ListEntry.bLink;
1420
1421             if( Fcb->CcbListTail != NULL)
1422             {
1423                 Fcb->CcbListTail->ListEntry.fLink = NULL;
1424             }
1425         }
1426         else
1427         {
1428             ((AFSCcb *)(Ccb->ListEntry.fLink))->ListEntry.bLink = Ccb->ListEntry.bLink;
1429         }
1430
1431         if( Ccb->ListEntry.bLink == NULL)
1432         {
1433
1434             Fcb->CcbListHead = (AFSCcb *)Ccb->ListEntry.fLink;
1435
1436             if( Fcb->CcbListHead != NULL)
1437             {
1438                 Fcb->CcbListHead->ListEntry.bLink = NULL;
1439             }
1440         }
1441         else
1442         {
1443             ((AFSCcb *)(Ccb->ListEntry.bLink))->ListEntry.fLink = Ccb->ListEntry.fLink;
1444         }
1445
1446         AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
1447     }
1448
1449     if( Ccb->MaskName.Buffer != NULL)
1450     {
1451
1452         AFSExFreePoolWithTag( Ccb->MaskName.Buffer, AFS_GENERIC_MEMORY_6_TAG);
1453     }
1454
1455     if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_FREE_FULL_PATHNAME))
1456     {
1457
1458         AFSExFreePoolWithTag( Ccb->FullFileName.Buffer, 0);
1459     }
1460
1461     //
1462     // If we have a name array then delete it
1463     //
1464
1465     if( Ccb->NameArray != NULL)
1466     {
1467
1468         AFSFreeNameArray( Ccb->NameArray);
1469
1470         Ccb->NameArray = NULL;
1471     }
1472
1473     if( Ccb->DirectorySnapshot != NULL)
1474     {
1475
1476         AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
1477
1478         Ccb->DirectorySnapshot = NULL;
1479     }
1480
1481     if( Ccb->NotifyMask.Buffer != NULL)
1482     {
1483
1484         AFSExFreePoolWithTag( Ccb->NotifyMask.Buffer, AFS_GENERIC_MEMORY_7_TAG);
1485     }
1486
1487     if ( Ccb->DirectoryCB != NULL)
1488     {
1489
1490         lCount = InterlockedDecrement( &Ccb->DirectoryCB->DirOpenReferenceCount);
1491
1492         AFSDbgLogMsg( 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,
1496                       Ccb->DirectoryCB,
1497                       Ccb,
1498                       lCount);
1499
1500         ASSERT( lCount >= 0);
1501     }
1502
1503     AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1504
1505     //
1506     // Free up the Ccb
1507     //
1508
1509     ExDeleteResourceLite( &Ccb->NPCcb->CcbLock);
1510
1511     AFSExFreePoolWithTag( Ccb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1512
1513     AFSExFreePoolWithTag( Ccb, AFS_CCB_ALLOCATION_TAG);
1514 }
1515
1516 NTSTATUS
1517 AFSInsertCcb( IN AFSFcb *Fcb,
1518               IN AFSCcb *Ccb)
1519 {
1520
1521     NTSTATUS ntStatus = STATUS_SUCCESS;
1522
1523     AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1524                     TRUE);
1525
1526     AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1527                     TRUE);
1528
1529     if( Fcb->CcbListHead == NULL)
1530     {
1531         Fcb->CcbListHead = Ccb;
1532     }
1533     else
1534     {
1535         Fcb->CcbListTail->ListEntry.fLink = (void *)Ccb;
1536
1537         Ccb->ListEntry.bLink = (void *)Fcb->CcbListTail;
1538     }
1539
1540     Fcb->CcbListTail = Ccb;
1541
1542     SetFlag( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST);
1543
1544     AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1545
1546     AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
1547
1548     return ntStatus;
1549 }