959aad96f175970c9620ddc4d0c901040e2a663d
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSClose.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: AFSClose.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSClose
43 //
44 // Description:
45 //
46 //      This function is the IRP_MJ_CLOSE dispatch handler
47 //
48 // Return:
49 //
50 //       A status is returned for the handling of this request
51 //
52
53 NTSTATUS
54 AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
55           IN PIRP Irp)
56 {
57
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     ULONG ulRequestType = 0;
60     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
61     AFSFcb *pFcb = NULL;
62     AFSDeviceExt *pDeviceExt = NULL;
63     AFSCcb *pCcb = NULL;
64     AFSObjectInfoCB *pObjectInfo = NULL;
65     AFSDirectoryCB *pDirCB = NULL;
66
67     __try
68     {
69
70         if( AFSRDRDeviceObject == NULL)
71         {
72
73             //
74             // Let this through, it's an close on the library control device
75             //
76
77             try_return( ntStatus);
78         }
79
80         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
81
82         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
83
84         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
85
86         if( pFcb == NULL)
87         {
88             try_return( ntStatus);
89         }
90
91         pObjectInfo = pFcb->ObjectInformation;
92
93         //
94         // Perform the close functionality depending on the type of node it is
95         //
96
97         switch( pFcb->Header.NodeTypeCode)
98         {
99
100             case AFS_IOCTL_FCB:
101             {
102
103                 AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
104                 AFSFileID stParentFileId;
105
106                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
107                               AFS_TRACE_LEVEL_VERBOSE,
108                               "AFSClose Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
109                               &pFcb->NPFcb->Resource,
110                               PsGetCurrentThread());
111
112                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
113                                   TRUE);
114
115                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
116
117                 //
118                 // Send the close to the CM
119                 //
120
121                 RtlZeroMemory( &stPIOCtlClose,
122                                sizeof( AFSPIOCtlOpenCloseRequestCB));
123
124                 stPIOCtlClose.RequestId = pCcb->RequestID;
125
126                 stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
127
128                 RtlZeroMemory( &stParentFileId,
129                                sizeof( AFSFileID));
130
131                 stParentFileId = pObjectInfo->ParentObjectInformation->FileId;
132
133                 //
134                 // Issue the close request to the service
135                 //
136
137                 AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
138                                    AFS_REQUEST_FLAG_SYNCHRONOUS,
139                                    &pFcb->AuthGroup,
140                                    NULL,
141                                    &stParentFileId,
142                                    (void *)&stPIOCtlClose,
143                                    sizeof( AFSPIOCtlOpenCloseRequestCB),
144                                    NULL,
145                                    NULL);
146
147                 pDirCB = pCcb->DirectoryCB;
148
149                 //
150                 // Remove the Ccb and de-allocate it
151                 //
152
153                 ntStatus = AFSRemoveCcb( pCcb);
154
155                 if( !NT_SUCCESS( ntStatus))
156                 {
157
158                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
159                                   AFS_TRACE_LEVEL_WARNING,
160                                   "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
161
162                     //
163                     // We can't actually fail a close operation so reset the status
164                     //
165
166                     ntStatus = STATUS_SUCCESS;
167                 }
168
169                 ASSERT( pDirCB->OpenReferenceCount > 0);
170
171                 InterlockedDecrement( &pDirCB->OpenReferenceCount);
172
173                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
174                               AFS_TRACE_LEVEL_VERBOSE,
175                               "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
176                               &pDirCB->NameInformation.FileName,
177                               pDirCB,
178                               pCcb,
179                               pDirCB->OpenReferenceCount);
180
181                 //
182                 // If this is not the root then decrement the open child reference count
183                 //
184
185                 if( pObjectInfo->ParentObjectInformation != NULL &&
186                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
187                 {
188
189                     InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
190
191                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
192                                   AFS_TRACE_LEVEL_VERBOSE,
193                                   "AFSClose (IOCtl) Decrement child open ref count on Parent object %08lX Cnt %d\n",
194                                   pObjectInfo->ParentObjectInformation,
195                                   pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
196                 }
197
198                 AFSReleaseResource( &pFcb->NPFcb->Resource);
199
200                 ASSERT( pFcb->OpenReferenceCount != 0);
201
202                 InterlockedDecrement( &pFcb->OpenReferenceCount);
203
204                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
205                               AFS_TRACE_LEVEL_VERBOSE,
206                               "AFSClose (IOCtl) Decrement count on Fcb %08lX Cnt %d\n",
207                               pFcb,
208                               pFcb->OpenReferenceCount);
209
210                 break;
211             }
212
213             case AFS_ROOT_ALL:
214             {
215
216                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
217                               AFS_TRACE_LEVEL_VERBOSE,
218                               "AFSClose Acquiring Special Root ALL lock %08lX EXCL %08lX\n",
219                               &pFcb->NPFcb->Resource,
220                               PsGetCurrentThread());
221
222                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
223                                 TRUE);
224
225                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
226
227                 pDirCB = pCcb->DirectoryCB;
228
229                 //
230                 // Remove the Ccb and de-allocate it
231                 //
232
233                 ntStatus = AFSRemoveCcb( pCcb);
234
235                 if( !NT_SUCCESS( ntStatus))
236                 {
237
238                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
239                                   AFS_TRACE_LEVEL_WARNING,
240                                   "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
241
242                     //
243                     // We can't actually fail a close operation so reset the status
244                     //
245
246                     ntStatus = STATUS_SUCCESS;
247                 }
248
249                 ASSERT( pDirCB->OpenReferenceCount > 0);
250
251                 InterlockedDecrement( &pDirCB->OpenReferenceCount);
252
253                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
254                               AFS_TRACE_LEVEL_VERBOSE,
255                               "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n",
256                               &pDirCB->NameInformation.FileName,
257                               pDirCB,
258                               pCcb,
259                               pDirCB->OpenReferenceCount);
260
261                 AFSReleaseResource( &pFcb->NPFcb->Resource);
262
263                 ASSERT( pFcb->OpenReferenceCount > 0);
264
265                 InterlockedDecrement( &pFcb->OpenReferenceCount);
266
267                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
268                               AFS_TRACE_LEVEL_VERBOSE,
269                               "AFSClose (RootAll) Decrement count on Fcb %08lX Cnt %d\n",
270                               pFcb,
271                               pFcb->OpenReferenceCount);
272
273                 break;
274             }
275
276             //
277             // Root, file or directory node
278             //
279
280             case AFS_FILE_FCB:
281             case AFS_ROOT_FCB:
282             case AFS_DIRECTORY_FCB:
283             case AFS_SYMBOLIC_LINK_FCB:
284             case AFS_MOUNT_POINT_FCB:
285             case AFS_DFS_LINK_FCB:
286             {
287
288                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
289
290                 //
291                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
292                 //
293
294                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
295                               AFS_TRACE_LEVEL_VERBOSE,
296                               "AFSClose Acquiring Dcb lock %08lX EXCL %08lX\n",
297                               &pFcb->NPFcb->Resource,
298                               PsGetCurrentThread());
299
300                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
301                                 TRUE);
302
303                 KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
304
305                 pDirCB = pCcb->DirectoryCB;
306
307                 //
308                 // Remove the Ccb and de-allocate it
309                 //
310
311                 ntStatus = AFSRemoveCcb( pCcb);
312
313                 if( !NT_SUCCESS( ntStatus))
314                 {
315
316                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
317                                   AFS_TRACE_LEVEL_WARNING,
318                                   "AFSClose Failed to remove Ccb from Fcb Status %08lX\n",
319                                   ntStatus);
320
321                     //
322                     // We can't actually fail a close operation so reset the status
323                     //
324
325                     ntStatus = STATUS_SUCCESS;
326                 }
327
328                 //
329                 // If this entry is deleted then remove the object from the volume tree
330                 //
331
332                 if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
333                 {
334
335                     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
336                     {
337
338                         //
339                         // Stop anything possibly in process
340                         //
341
342                         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
343                                       AFS_TRACE_LEVEL_VERBOSE,
344                                       "AFSClose Acquiring Fcb extents lock %08lX EXCL %08lX\n",
345                                       &pFcb->NPFcb->Specific.File.ExtentsResource,
346                                       PsGetCurrentThread());
347
348                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
349                                         TRUE);
350
351                         pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
352
353                         KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
354                                     0,
355                                     FALSE);
356
357                         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
358                                       AFS_TRACE_LEVEL_VERBOSE,
359                                       "AFSClose Releasing Fcb extents lock %08lX EXCL %08lX\n",
360                                       &pFcb->NPFcb->Specific.File.ExtentsResource,
361                                       PsGetCurrentThread());
362
363                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
364                     }
365
366                     AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
367                                     TRUE);
368
369                     AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
370                                     TRUE);
371
372                     if ( pDirCB->OpenReferenceCount == 0)
373                     {
374                         AFSDbgLogMsg( 0,
375                                       0,
376                                       "AFSClose (Other) OpenReferenceCount is Zero on DE %08lX Ccb %08lX FileName %wZ\n",
377                                       pDirCB,
378                                       pCcb,
379                                       &pDirCB->NameInformation.FileName);
380                     }
381
382                     ASSERT( pDirCB->OpenReferenceCount > 0);
383
384                     InterlockedDecrement( &pDirCB->OpenReferenceCount);
385
386                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
387                                   AFS_TRACE_LEVEL_VERBOSE,
388                                   "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
389                                   &pDirCB->NameInformation.FileName,
390                                   pDirCB,
391                                   pCcb,
392                                   pDirCB->OpenReferenceCount);
393
394                     if( pDirCB->OpenReferenceCount == 0)
395                     {
396
397                         AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
398                                       AFS_TRACE_LEVEL_VERBOSE,
399                                       "AFSClose Deleting dir entry %08lX (%08lX) for %wZ\n",
400                                       pDirCB,
401                                       pObjectInfo,
402                                       &pDirCB->NameInformation.FileName);
403
404                         //
405                         // Remove and delete the directory entry from the parent list
406                         //
407
408                         AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation,
409                                            pDirCB);
410
411                         if( pObjectInfo->ObjectReferenceCount == 0)
412                         {
413
414                             if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
415                             {
416
417                                 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
418                                               AFS_TRACE_LEVEL_VERBOSE,
419                                               "AFSClose Removing object %08lX from volume tree\n",
420                                               pObjectInfo);
421
422                                 AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
423                                                     &pObjectInfo->TreeEntry);
424
425                                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
426                             }
427
428                             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
429                         }
430                     }
431
432                     AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
433
434                     AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
435                 }
436                 else
437                 {
438
439                     ASSERT( pDirCB->OpenReferenceCount > 0);
440
441                     InterlockedDecrement( &pDirCB->OpenReferenceCount);
442
443                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
444                                   AFS_TRACE_LEVEL_VERBOSE,
445                                   "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
446                                   &pDirCB->NameInformation.FileName,
447                                   pDirCB,
448                                   pCcb,
449                                   pDirCB->OpenReferenceCount);
450                 }
451
452                 //
453                 // If this is not the root then decrement the open child reference count
454                 //
455
456                 if( pObjectInfo != NULL &&
457                     pObjectInfo->ParentObjectInformation != NULL &&
458                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
459                 {
460
461                     InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
462
463                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
464                                   AFS_TRACE_LEVEL_VERBOSE,
465                                   "AFSClose Decrement child open ref count on Parent object %08lX Cnt %d\n",
466                                   pObjectInfo->ParentObjectInformation,
467                                   pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
468                 }
469
470                 if( pFcb->OpenReferenceCount == 1 &&
471                     pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
472                 {
473
474                     SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
475
476                     //
477                     // Attempt to tear down our extent list for the file
478                     // If there are remaining dirty extents then attempt to
479                     // flush them as well
480                     //
481
482                     if( pFcb->Specific.File.ExtentsDirtyCount)
483                     {
484
485                         AFSFlushExtents( pFcb);
486                     }
487
488                     //
489                     // Wait for any outstanding queued flushes to complete
490                     //
491
492                     AFSWaitOnQueuedFlushes( pFcb);
493
494                     ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
495                             pFcb->Specific.File.QueuedFlushCount == 0);
496
497                     AFSReleaseResource( &pFcb->NPFcb->Resource);
498
499                     //
500                     // Tear 'em down, we'll not be needing them again
501                     //
502
503                     if( AFSTearDownFcbExtents( pFcb))
504                     {
505
506                         //
507                         // Indicate to the service that the file required complete flushing to the
508                         // server.
509                         //
510
511                         AFSProcessRequest( AFS_REQUEST_TYPE_FLUSH_FILE,
512                                            AFS_REQUEST_FLAG_SYNCHRONOUS,
513                                            &pFcb->AuthGroup,
514                                            NULL,
515                                            &pFcb->ObjectInformation->FileId,
516                                            NULL,
517                                            0,
518                                            NULL,
519                                            NULL);
520                     }
521                 }
522                 else
523                 {
524
525                     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
526                     {
527
528                         if( pFcb->Specific.File.ExtentsDirtyCount)
529                         {
530
531                             AFSFlushExtents( pFcb);
532                         }
533                     }
534
535                     AFSReleaseResource( &pFcb->NPFcb->Resource);
536                 }
537
538                 //
539                 // Decrement the reference count on the Fcb. this is protecting it from teardown.
540                 //
541
542                 ASSERT( pFcb->OpenReferenceCount != 0);
543
544                 InterlockedDecrement( &pFcb->OpenReferenceCount);
545
546                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
547                               AFS_TRACE_LEVEL_VERBOSE,
548                               "AFSClose Decrement count on Fcb %08lX Cnt %d\n",
549                               pFcb,
550                               pFcb->OpenReferenceCount);
551
552                 break;
553             }
554
555             case AFS_SPECIAL_SHARE_FCB:
556             {
557
558                 AFSPipeOpenCloseRequestCB stPipeClose;
559
560                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
561                               AFS_TRACE_LEVEL_VERBOSE,
562                               "AFSClose Acquiring Special Share lock %08lX EXCL %08lX\n",
563                               &pFcb->NPFcb->Resource,
564                               PsGetCurrentThread());
565
566                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
567                                 TRUE);
568
569                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
570
571                 pDirCB = pCcb->DirectoryCB;
572
573                 RtlZeroMemory( &stPipeClose,
574                                sizeof( AFSPipeOpenCloseRequestCB));
575
576                 stPipeClose.RequestId = pCcb->RequestID;
577
578                 stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
579
580                 //
581                 // Issue the open request to the service
582                 //
583
584                 /*
585                 AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
586                                    AFS_REQUEST_FLAG_SYNCHRONOUS,
587                                    &pFcb->AuthGroup,
588                                    &pDirCB->NameInformation.FileName,
589                                    NULL,
590                                    (void *)&stPipeClose,
591                                    sizeof( AFSPipeOpenCloseRequestCB),
592                                    NULL,
593                                    NULL);
594                 */
595
596                 //
597                 // Remove the Ccb and de-allocate it
598                 //
599
600                 ntStatus = AFSRemoveCcb( pCcb);
601
602                 if( !NT_SUCCESS( ntStatus))
603                 {
604
605                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
606                                   AFS_TRACE_LEVEL_WARNING,
607                                   "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
608
609                     //
610                     // We can't actually fail a close operation so reset the status
611                     //
612
613                     ntStatus = STATUS_SUCCESS;
614                 }
615
616                 ASSERT( pDirCB->OpenReferenceCount > 0);
617
618                 InterlockedDecrement( &pDirCB->OpenReferenceCount);
619
620                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
621                               AFS_TRACE_LEVEL_VERBOSE,
622                               "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
623                               &pDirCB->NameInformation.FileName,
624                               pDirCB,
625                               pCcb,
626                               pDirCB->OpenReferenceCount);
627
628                 //
629                 // If this is not the root then decrement the open child reference count
630                 //
631
632                 if( pObjectInfo->ParentObjectInformation != NULL &&
633                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
634                 {
635
636                     InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
637
638                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
639                                   AFS_TRACE_LEVEL_VERBOSE,
640                                   "AFSClose (Share) Decrement child open ref count on Parent object %08lX Cnt %d\n",
641                                   pObjectInfo->ParentObjectInformation,
642                                   pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
643                 }
644
645                 AFSReleaseResource( &pFcb->NPFcb->Resource);
646
647                 ASSERT( pFcb->OpenReferenceCount != 0);
648
649                 InterlockedDecrement( &pFcb->OpenReferenceCount);
650
651                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
652                               AFS_TRACE_LEVEL_VERBOSE,
653                               "AFSClose (Share) Decrement count on Fcb %08lX Cnt %d\n",
654                               pFcb,
655                               pFcb->OpenReferenceCount);
656
657                 break;
658             }
659
660             default:
661
662                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
663                               AFS_TRACE_LEVEL_ERROR,
664                               "AFSClose Processing unknown node type %d\n",
665                               pFcb->Header.NodeTypeCode);
666
667                 break;
668         }
669
670 try_exit:
671
672         //
673         // Complete the request
674         //
675
676         AFSCompleteRequest( Irp,
677                             ntStatus);
678     }
679     __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
680     {
681
682         AFSDbgLogMsg( 0,
683                       0,
684                       "EXCEPTION - AFSClose\n");
685     }
686
687     return ntStatus;
688 }