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