Windows: AFSPrimaryVolumeWorkerThread reorg
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSVolume.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011, 2012, 2013 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, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16  *   nor the names of their contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission from Kernel Drivers, LLC and Your File System, Inc.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 //
34 // File: AFSVolume.cpp
35 //
36
37 #include "AFSCommon.h"
38
39 NTSTATUS
40 AFSInitVolume( IN GUID *AuthGroup,
41                IN AFSFileID *RootFid,
42                IN LONG VolumeReferenceReason,
43                OUT AFSVolumeCB **VolumeCB)
44 {
45
46     NTSTATUS ntStatus = STATUS_SUCCESS;
47     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
48     AFSNonPagedVolumeCB *pNonPagedVcb = NULL;
49     AFSVolumeCB *pVolumeCB = NULL;
50     AFSNonPagedObjectInfoCB *pNonPagedObject = NULL;
51     ULONGLONG ullIndex = 0;
52     BOOLEAN bReleaseLocks = FALSE;
53     AFSVolumeInfoCB stVolumeInformation = {0};
54     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
55     LONG lCount;
56
57     __Enter
58     {
59
60         //
61         // Before grabbing any locks ask the service for the volume information
62         // This may be a waste but we need to get this information prior to
63         // taking any volume tree locks. Don't do this for any 'reserved' cell entries
64         //
65
66         if( RootFid->Cell != 0)
67         {
68
69             RtlZeroMemory( &stVolumeInformation,
70                            sizeof( AFSVolumeInfoCB));
71
72             ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
73                                                      RootFid,
74                                                      &stVolumeInformation);
75
76             if( !NT_SUCCESS( ntStatus))
77             {
78
79                 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
80                               AFS_TRACE_LEVEL_ERROR,
81                               "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
82                               ntStatus));
83
84                 try_return( ntStatus);
85             }
86
87             //
88             // Grab our tree locks and see if we raced with someone else
89             //
90
91             AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
92                             TRUE);
93
94             AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
95                             TRUE);
96
97             bReleaseLocks = TRUE;
98
99             ullIndex = AFSCreateHighIndex( RootFid);
100
101             ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
102                                            ullIndex,
103                                            (AFSBTreeEntry **)&pVolumeCB);
104
105             if( NT_SUCCESS( ntStatus) &&
106                 pVolumeCB != NULL)
107             {
108
109                 //
110                 // So we don't lock with an invalidation call ...
111                 //
112
113                 lCount = AFSVolumeIncrement( pVolumeCB,
114                                              VolumeReferenceReason);
115
116                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
117                               AFS_TRACE_LEVEL_VERBOSE,
118                               "AFSInitVolume Increment count on volume %p Reason %u Cnt %d\n",
119                               pVolumeCB,
120                               VolumeReferenceReason,
121                               lCount));
122
123                 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
124
125                 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
126
127                 bReleaseLocks = FALSE;
128
129                 AFSAcquireExcl( pVolumeCB->VolumeLock,
130                                 TRUE);
131
132                 *VolumeCB = pVolumeCB;
133
134                 try_return( ntStatus);
135             }
136
137             //
138             // Revert our status from the above call back to success.
139             //
140
141             ntStatus = STATUS_SUCCESS;
142         }
143
144         //
145         // For the global root we allocate out volume node and insert it
146         // into the volume tree ...
147         //
148
149         pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( PagedPool,
150                                                              sizeof( AFSVolumeCB),
151                                                              AFS_VCB_ALLOCATION_TAG);
152
153         if( pVolumeCB == NULL)
154         {
155
156             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
157                           AFS_TRACE_LEVEL_ERROR,
158                           "AFSInitVolume Failed to allocate the root volume cb\n"));
159
160             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
161         }
162
163         RtlZeroMemory( pVolumeCB,
164                        sizeof( AFSVolumeCB));
165
166         //
167         // The non paged portion
168         //
169
170         pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
171                                                                         sizeof( AFSNonPagedVolumeCB),
172                                                                         AFS_VCB_NP_ALLOCATION_TAG);
173
174         if( pNonPagedVcb == NULL)
175         {
176
177             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
178                           AFS_TRACE_LEVEL_ERROR,
179                           "AFSInitVolume Failed to allocate the root non paged volume cb\n"));
180
181             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
182         }
183
184         RtlZeroMemory( pNonPagedVcb,
185                        sizeof( AFSNonPagedVolumeCB));
186
187         ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);
188
189         ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
190
191         pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
192                                                                                sizeof( AFSNonPagedObjectInfoCB),
193                                                                                AFS_NP_OBJECT_INFO_TAG);
194
195         if( pNonPagedObject == NULL)
196         {
197
198             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
199                           AFS_TRACE_LEVEL_ERROR,
200                           "AFSInitVolume Failed to allocate the root non paged object cb\n"));
201
202             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
203         }
204
205         RtlZeroMemory( pNonPagedObject,
206                        sizeof( AFSNonPagedObjectInfoCB));
207
208         ExInitializeResourceLite( &pNonPagedObject->ObjectInfoLock);
209
210         ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);
211
212         pVolumeCB->NonPagedVcb = pNonPagedVcb;
213
214         pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;
215
216         pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;
217
218         pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;
219
220         pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;
221
222         lCount = AFSVolumeIncrement( pVolumeCB,
223                                      VolumeReferenceReason);
224
225         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
226                       AFS_TRACE_LEVEL_VERBOSE,
227                       "AFSInitVolume Initializing volume %p Reason %u count %d\n",
228                       pVolumeCB,
229                       VolumeReferenceReason,
230                       lCount));
231
232         AFSAcquireExcl( pVolumeCB->VolumeLock,
233                         TRUE);
234
235         pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
236                                                                              sizeof( AFSDirectoryCB) + sizeof( WCHAR),
237                                                                              AFS_DIR_ENTRY_TAG);
238
239         if( pVolumeCB->DirectoryCB == NULL)
240         {
241
242             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
243         }
244
245         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
246                       AFS_TRACE_LEVEL_VERBOSE,
247                       "AFSInitVolume AFS_DIR_ENTRY_TAG allocated %p\n",
248                       pVolumeCB->DirectoryCB));
249
250         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
251                                                                                 sizeof( AFSNonPagedDirectoryCB),
252                                                                                 AFS_DIR_ENTRY_NP_TAG);
253
254         if( pNonPagedDirEntry == NULL)
255         {
256
257             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
258         }
259
260         RtlZeroMemory( pVolumeCB->DirectoryCB,
261                        sizeof( AFSDirectoryCB) + sizeof( WCHAR));
262
263         RtlZeroMemory( pNonPagedDirEntry,
264                        sizeof( AFSNonPagedDirectoryCB));
265
266         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
267
268         pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;
269
270         //
271         // Initialize the non-paged portion of the directory entry
272         //
273
274         KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
275         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
276         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);
277
278         pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;
279
280         SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);
281
282         pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell;
283         pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume;
284         pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode;
285         pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique;
286         pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash;
287
288         pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
289
290         pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);
291
292         pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;
293
294         pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));
295
296         RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
297                        L"\\",
298                        sizeof( WCHAR));
299
300         //
301         // Copy in the volume information retrieved above
302         //
303
304         RtlCopyMemory( &pVolumeCB->VolumeInformation,
305                        &stVolumeInformation,
306                        sizeof( AFSVolumeInfoCB));
307
308         //
309         // Setup pointers
310         //
311
312         pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;
313
314         //
315         // The ObjectInformation VolumeCB pointer does not obtain
316         // a reference count.
317         //
318
319         pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;
320
321         //
322         // Insert the volume into our volume tree. Don't insert any reserved entries
323         //
324
325         if( RootFid->Cell != 0)
326         {
327
328             pVolumeCB->TreeEntry.HashIndex = ullIndex;
329
330             if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
331             {
332
333                 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;
334
335                 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
336             }
337             else
338             {
339
340                 if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
341                                                      &pVolumeCB->TreeEntry)))
342                 {
343
344                     SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
345                 }
346             }
347
348             if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
349             {
350
351                 pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
352             }
353             else
354             {
355
356                 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;
357
358                 pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
359             }
360
361             pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
362         }
363
364         *VolumeCB = pVolumeCB;
365
366 try_exit:
367
368         if( !NT_SUCCESS( ntStatus))
369         {
370
371             if( pNonPagedVcb != NULL)
372             {
373
374                 AFSReleaseResource( pVolumeCB->VolumeLock);
375
376                 ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);
377
378                 ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
379
380                 AFSExFreePoolWithTag( pNonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
381             }
382
383             if( pNonPagedObject != NULL)
384             {
385
386                 ExDeleteResourceLite( &pNonPagedObject->ObjectInfoLock);
387
388                 AFSExFreePoolWithTag( pNonPagedObject, AFS_NP_OBJECT_INFO_TAG);
389             }
390
391             if( pVolumeCB != NULL)
392             {
393
394                 if( pVolumeCB->DirectoryCB != NULL)
395                 {
396
397                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
398                                   AFS_TRACE_LEVEL_VERBOSE,
399                                   "AFSInitVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
400                                   pVolumeCB->DirectoryCB));
401
402                     AFSExFreePoolWithTag( pVolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
403                 }
404
405                 AFSExFreePoolWithTag( pVolumeCB, AFS_VCB_ALLOCATION_TAG);
406             }
407
408             if( pNonPagedDirEntry != NULL)
409             {
410
411                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
412
413                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
414             }
415         }
416
417         if( bReleaseLocks)
418         {
419
420             AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
421
422             AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
423         }
424     }
425
426     return ntStatus;
427 }
428
429 NTSTATUS
430 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
431 {
432
433     NTSTATUS ntStatus = STATUS_SUCCESS;
434     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
435     LONG lCount;
436
437     __Enter
438     {
439
440         ASSERT( VolumeCB->VolumeReferenceCount == 0);
441
442         //
443         // Remove the volume from the tree and list
444         // Don't process the list information for reserved entries
445         //
446
447         if( VolumeCB->ObjectInformation.FileId.Cell != 0)
448         {
449
450             if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
451             {
452
453                 AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
454                                     &VolumeCB->TreeEntry);
455             }
456
457             if( VolumeCB->ListEntry.fLink == NULL)
458             {
459
460                 pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;
461
462                 if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
463                 {
464
465                     pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
466                 }
467             }
468             else
469             {
470
471                 ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
472             }
473
474             if( VolumeCB->ListEntry.bLink == NULL)
475             {
476
477                 pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;
478
479                 if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
480                 {
481
482                     pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
483                 }
484             }
485             else
486             {
487
488                 ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
489             }
490         }
491
492         //
493         // Remove any PIOctl objects we have
494         //
495
496         if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
497         {
498
499             if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
500             {
501
502                 AFSAcquireExcl( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
503                                 TRUE);
504
505                 AFSRemoveFcb( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
506
507                 AFSReleaseResource( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
508             }
509
510             lCount = AFSObjectInfoDecrement( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
511                                              AFS_OBJECT_REFERENCE_PIOCTL);
512
513             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
514                           AFS_TRACE_LEVEL_VERBOSE,
515                           "AFSRemoveVolume Decrement count on object %p Cnt %d\n",
516                           VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
517                           lCount));
518
519             ASSERT( lCount == 0);
520
521             if ( lCount == 0)
522             {
523
524                 AFSDeleteObjectInfo( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
525             }
526
527             ExDeleteResourceLite( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
528
529             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
530
531             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
532                           AFS_TRACE_LEVEL_VERBOSE,
533                           "AFSRemoveVolume (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
534                           VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB));
535
536             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
537         }
538
539         if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
540         {
541
542             //
543             // Release the fid in the service
544             //
545
546             AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
547         }
548
549         //
550         // Free up the memory
551         //
552
553         if( VolumeCB->NonPagedVcb != NULL)
554         {
555
556             if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
557             {
558                 AFSReleaseResource( VolumeCB->VolumeLock);
559             }
560
561             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);
562
563             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);
564
565             AFSExFreePoolWithTag( VolumeCB->NonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
566         }
567
568         if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
569         {
570
571             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
572
573             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);
574
575             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
576         }
577
578         if( VolumeCB->DirectoryCB != NULL)
579         {
580
581             if( VolumeCB->DirectoryCB->NonPaged != NULL)
582             {
583
584                 ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);
585
586                 AFSExFreePoolWithTag( VolumeCB->DirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
587             }
588
589             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
590                           AFS_TRACE_LEVEL_VERBOSE,
591                           "AFSRemoveVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
592                           VolumeCB->DirectoryCB));
593
594             AFSExFreePoolWithTag( VolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
595         }
596
597         AFSExFreePoolWithTag( VolumeCB, AFS_VCB_ALLOCATION_TAG);
598     }
599
600     return ntStatus;
601 }
602
603 LONG
604 AFSVolumeIncrement( IN AFSVolumeCB *VolumeCB,
605                     IN LONG Reason)
606 {
607
608     LONG lCount;
609
610     lCount = InterlockedIncrement( &VolumeCB->VolumeReferenceCount);
611
612     InterlockedIncrement( &VolumeCB->VolumeReferences[ Reason]);
613
614     return lCount;
615 }
616
617 LONG
618 AFSVolumeDecrement( IN AFSVolumeCB *VolumeCB,
619                     IN LONG Reason)
620 {
621
622     LONG lCount;
623
624     lCount = InterlockedDecrement( &VolumeCB->VolumeReferences[ Reason]);
625
626     ASSERT( lCount >= 0);
627
628     lCount = InterlockedDecrement( &VolumeCB->VolumeReferenceCount);
629
630     ASSERT( lCount >= 0);
631
632     return lCount;
633 }