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