Windows: Adjust extent release strategy
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.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: AFSCleanup.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSCleanup
43 //
44 // Description:
45 //
46 //      This function is the IRP_MJ_CLEANUP dispatch handler
47 //
48 // Return:
49 //
50 //       A status is returned for the handling of this request
51 //
52
53 NTSTATUS
54 AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
55             IN PIRP Irp)
56 {
57
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     AFSDeviceExt *pDeviceExt = NULL;
60     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
61     AFSFcb *pFcb = NULL;
62     AFSCcb *pCcb = NULL;
63     PFILE_OBJECT pFileObject = NULL;
64     AFSFcb *pRootFcb = NULL;
65     AFSDeviceExt *pControlDeviceExt = NULL;
66     IO_STATUS_BLOCK stIoSB;
67     AFSObjectInfoCB *pObjectInfo = NULL;
68     AFSFileCleanupCB stFileCleanup;
69     AFSFileCleanupResultCB *pResultCB = NULL;
70     ULONG ulResultLen = 0;
71     ULONG   ulNotificationFlags = 0;
72     LONG    lCount;
73
74     __try
75     {
76
77         if( AFSRDRDeviceObject == NULL)
78         {
79
80             //
81             // Let this through, it's a cleanup on the library control device
82             //
83
84             try_return( ntStatus);
85         }
86
87         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
88
89         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
90
91         //
92         // Set some initial variables to make processing easier
93         //
94
95         pFileObject = pIrpSp->FileObject;
96
97         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
98
99         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
100
101         if( pFcb == NULL)
102         {
103             try_return( ntStatus);
104         }
105
106         pObjectInfo = pFcb->ObjectInformation;
107
108         pRootFcb = pObjectInfo->VolumeCB->RootFcb;
109
110         RtlZeroMemory( &stFileCleanup,
111                        sizeof( AFSFileCleanupCB));
112
113         stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
114
115         stFileCleanup.Identifier = (ULONGLONG)pFileObject;
116
117         //
118         // Allocate our return buffer
119         //
120
121         pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
122                                                                         PAGE_SIZE,
123                                                                         AFS_GENERIC_MEMORY_32_TAG);
124
125         if( pResultCB == NULL)
126         {
127
128             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
129         }
130
131         RtlZeroMemory( pResultCB,
132                        PAGE_SIZE);
133
134         ulResultLen = PAGE_SIZE;
135
136
137         //
138         // Perform the cleanup functionality depending on the type of node it is
139         //
140
141         switch( pFcb->Header.NodeTypeCode)
142         {
143
144             case AFS_ROOT_ALL:
145             {
146
147                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
148                               AFS_TRACE_LEVEL_VERBOSE,
149                               "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
150                               &pFcb->NPFcb->Resource,
151                               PsGetCurrentThread());
152
153                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
154                                   TRUE);
155
156                 ASSERT( pFcb->OpenHandleCount != 0);
157
158                 AFSReleaseResource( &pFcb->NPFcb->Resource);
159
160                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
161
162                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
163                               AFS_TRACE_LEVEL_VERBOSE,
164                               "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
165                               pFcb,
166                               lCount);
167
168                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
169                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
170                                     pCcb);
171
172                 break;
173             }
174
175             case AFS_IOCTL_FCB:
176             {
177
178                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
179                               AFS_TRACE_LEVEL_VERBOSE,
180                               "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
181                               &pFcb->NPFcb->Resource,
182                               PsGetCurrentThread());
183
184                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
185                                   TRUE);
186
187                 ASSERT( pFcb->OpenHandleCount != 0);
188
189                 //
190                 // Decrement the open child handle count
191                 //
192
193                 if( pObjectInfo->ParentObjectInformation != NULL &&
194                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
195                 {
196
197                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
198
199                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
200                                   AFS_TRACE_LEVEL_VERBOSE,
201                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
202                                   pObjectInfo->ParentObjectInformation,
203                                   lCount);
204                 }
205
206                 AFSReleaseResource( &pFcb->NPFcb->Resource);
207
208                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
209
210                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
211                               AFS_TRACE_LEVEL_VERBOSE,
212                               "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
213                               pFcb,
214                               lCount);
215
216                 break;
217             }
218
219             //
220             // This Fcb represents a file
221             //
222
223             case AFS_FILE_FCB:
224             {
225
226                 //
227                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
228                 //
229
230                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
231                               AFS_TRACE_LEVEL_VERBOSE,
232                               "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
233                               &pFcb->NPFcb->Resource,
234                               PsGetCurrentThread());
235
236                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
237                                 TRUE);
238
239                 //
240                 // If the handle has write permission ...
241                 //
242
243                 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
244                     CcIsFileCached( pIrpSp->FileObject))
245                 {
246
247                     __try
248                     {
249
250                         CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
251                                       NULL,
252                                       0,
253                                       &stIoSB);
254
255                         if( !NT_SUCCESS( stIoSB.Status))
256                         {
257
258                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
259                                           AFS_TRACE_LEVEL_ERROR,
260                                           "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
261                                           &pCcb->FullFileName,
262                                           pObjectInfo->FileId.Cell,
263                                           pObjectInfo->FileId.Volume,
264                                           pObjectInfo->FileId.Vnode,
265                                           pObjectInfo->FileId.Unique,
266                                           stIoSB.Status,
267                                           stIoSB.Information);
268
269                             ntStatus = stIoSB.Status;
270                         }
271                     }
272                     __except( EXCEPTION_EXECUTE_HANDLER)
273                     {
274
275                         ntStatus = GetExceptionCode();
276                     }
277                 }
278
279                 //
280                 // Uninitialize the cache map. This call is unconditional.
281                 //
282
283                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
284                               AFS_TRACE_LEVEL_VERBOSE,
285                               "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
286                               pFcb,
287                               pFileObject);
288
289                 CcUninitializeCacheMap( pFileObject,
290                                         NULL,
291                                         NULL);
292
293                 //
294                 // Unlock all outstanding locks on the file, again, unconditionally
295                 //
296
297                 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
298                                            pFileObject,
299                                            IoGetRequestorProcess( Irp),
300                                            NULL);
301
302                 //
303                 // Tell the service to unlock all on the file
304                 //
305
306                 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
307
308                 //
309                 // Perform some final common processing
310                 //
311
312                 ASSERT( pFcb->OpenHandleCount != 0);
313
314                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
315                 {
316
317                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
318                 }
319
320                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
321
322                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
323                 {
324
325                     stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
326
327                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
328
329                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
330                     {
331
332                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
333
334                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
335                     }
336
337                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
338                     {
339
340                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
341
342                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
343                     }
344
345                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
346                     {
347
348                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
349
350                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
351                     }
352
353                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
354                     {
355
356                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
357
358                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
359                     }
360                 }
361
362                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
363                 {
364
365                     stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
366                 }
367
368                 //
369                 // If the count has dropped to one and there is a pending delete
370                 // then delete the node.  The final count will be decremented just
371                 // before the Fcb->NPFcb->Resource is released.
372                 //
373
374                 if( pFcb->OpenHandleCount == 1 &&
375                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
376                 {
377
378                     //
379                     // Stop anything possibly in process
380                     //
381
382                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
383                                   AFS_TRACE_LEVEL_VERBOSE,
384                                   "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
385                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
386                                   PsGetCurrentThread());
387
388                     AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
389                                     TRUE);
390
391                     pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
392
393                     KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
394                                 0,
395                                 FALSE);
396
397                     //
398                     // Before telling the server about the deleted file, tear down all extents for
399                     // the file
400                     //
401
402                     AFSTearDownFcbExtents( pFcb,
403                                            &pCcb->AuthGroup);
404
405                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
406                                   AFS_TRACE_LEVEL_VERBOSE,
407                                   "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
408                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
409                                   PsGetCurrentThread());
410
411                     AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
412
413                     ntStatus = STATUS_SUCCESS;
414
415                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
416
417                     //
418                     // Indicate the file access mode that is being released
419                     //
420
421                     stFileCleanup.FileAccess = pCcb->FileAccess;
422
423                     //
424                     // Push the request to the service
425                     //
426
427                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
428                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
429                                                   &pCcb->AuthGroup,
430                                                   &pCcb->DirectoryCB->NameInformation.FileName,
431                                                   &pObjectInfo->FileId,
432                                                   &stFileCleanup,
433                                                   sizeof( AFSFileCleanupCB),
434                                                   pResultCB,
435                                                   &ulResultLen);
436
437                     if( !NT_SUCCESS( ntStatus) &&
438                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
439                     {
440
441                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
442                                       AFS_TRACE_LEVEL_ERROR,
443                                       "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
444                                       &pCcb->FullFileName,
445                                       ntStatus);
446
447                         ntStatus = STATUS_SUCCESS;
448
449                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
450                     }
451                     else
452                     {
453
454                         ntStatus = STATUS_SUCCESS;
455
456                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
457                                       AFS_TRACE_LEVEL_VERBOSE,
458                                       "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
459                                       &pCcb->FullFileName,
460                                       pCcb->DirectoryCB);
461
462                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
463
464                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
465
466                         AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
467                                         TRUE);
468
469                         if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
470                         {
471
472                             SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
473
474                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
475                         }
476                         else
477                         {
478
479                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
480                         }
481
482                         //
483                         // Now that the service has the entry has deleted we need to remove it from the parent
484                         // tree so another lookup on the node will fail
485                         //
486
487                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
488                         {
489
490                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
491                                           AFS_TRACE_LEVEL_VERBOSE,
492                                           "AFSCleanup DE %p for %wZ removing entry\n",
493                                           pCcb->DirectoryCB,
494                                           &pCcb->DirectoryCB->NameInformation.FileName);
495
496                             AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
497                                                 pCcb->DirectoryCB);
498                         }
499                         else
500                         {
501
502                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
503                                           AFS_TRACE_LEVEL_VERBOSE,
504                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
505                                           pCcb->DirectoryCB,
506                                           &pCcb->DirectoryCB->NameInformation.FileName);
507                         }
508
509                         AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
510
511                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
512                                                         pCcb,
513                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
514                                                         (ULONG)FILE_ACTION_REMOVED);
515
516                     }
517                 }
518                 else
519                 {
520
521                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
522                     {
523
524                         ULONG ulNotifyFilter = 0;
525
526                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
527
528                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
529
530                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
531                                                         pCcb,
532                                                         (ULONG)ulNotifyFilter,
533                                                         (ULONG)FILE_ACTION_MODIFIED);
534                     }
535
536                     //
537                     // Attempt to flush any dirty extents to the server. This may be a little
538                     // aggressive, to flush whenever the handle is closed, but it ensures
539                     // coherency.
540                     //
541
542                     if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
543                         pFcb->Specific.File.ExtentsDirtyCount != 0)
544                     {
545
546                         AFSFlushExtents( pFcb,
547                                          &pCcb->AuthGroup);
548                     }
549
550                     if( pFcb->OpenHandleCount == 1)
551                     {
552
553                         //
554                         // Wait for any outstanding queued flushes to complete
555                         //
556
557                         AFSWaitOnQueuedFlushes( pFcb);
558
559                         ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
560
561                         AFSTearDownFcbExtents( pFcb,
562                                                &pCcb->AuthGroup);
563                     }
564
565                     //
566                     // Indicate the file access mode that is being released
567                     //
568
569                     stFileCleanup.FileAccess = pCcb->FileAccess;
570
571                     //
572                     // Push the request to the service
573                     //
574
575                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
576                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
577                                                   &pCcb->AuthGroup,
578                                                   &pCcb->DirectoryCB->NameInformation.FileName,
579                                                   &pObjectInfo->FileId,
580                                                   &stFileCleanup,
581                                                   sizeof( AFSFileCleanupCB),
582                                                   pResultCB,
583                                                   &ulResultLen);
584
585                     if ( NT_SUCCESS( ntStatus))
586                     {
587
588                         if ( pObjectInfo->ParentObjectInformation != NULL)
589                         {
590
591                             AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
592                                             TRUE);
593
594                             if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
595                             {
596
597                                 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
598
599                                 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
600                             }
601
602                             AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
603                         }
604                     }
605
606                     ntStatus = STATUS_SUCCESS;
607                 }
608
609                 //
610                 // Remove the share access at this time since we may not get the close for sometime on this FO.
611                 //
612
613                 IoRemoveShareAccess( pFileObject,
614                                      &pFcb->ShareAccess);
615
616                 //
617                 // We don't need the name array after the user closes the handle on the file
618                 //
619
620                 if( pCcb->NameArray != NULL)
621                 {
622
623                     AFSFreeNameArray( pCcb->NameArray);
624
625                     pCcb->NameArray = NULL;
626                 }
627
628                 //
629                 // Decrement the open child handle count
630                 //
631
632                 if( pObjectInfo->ParentObjectInformation != NULL)
633                 {
634
635                     ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
636
637                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
638
639                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
640                                   AFS_TRACE_LEVEL_VERBOSE,
641                                   "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
642                                   pObjectInfo->ParentObjectInformation,
643                                   lCount);
644                 }
645
646                 AFSReleaseResource( &pFcb->NPFcb->Resource);
647
648                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
649                 {
650                     //
651                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
652                     //
653
654                     InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
655
656                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
657
658                     AFSPerformObjectInvalidate( pObjectInfo,
659                                                 AFS_INVALIDATE_DATA_VERSION);
660                 }
661
662                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
663
664                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
665                               AFS_TRACE_LEVEL_VERBOSE,
666                               "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
667                               pFcb,
668                               lCount);
669
670                 break;
671             }
672
673             //
674             // Root or directory node
675             //
676
677             case AFS_ROOT_FCB:
678             {
679
680                 //
681                 // Set the root Fcb to this node
682                 //
683
684                 pRootFcb = pFcb;
685
686                 //
687                 // Fall through to below
688                 //
689             }
690
691             case AFS_DIRECTORY_FCB:
692             {
693
694                 //
695                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
696                 //
697
698                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
699                               AFS_TRACE_LEVEL_VERBOSE,
700                               "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
701                               &pFcb->NPFcb->Resource,
702                               PsGetCurrentThread());
703
704                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
705                                   TRUE);
706
707                 //
708                 // Perform some final common processing
709                 //
710
711                 ASSERT( pFcb->OpenHandleCount != 0);
712
713                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
714                 {
715
716                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
717                 }
718
719                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
720
721                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
722                 {
723
724                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
725
726                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
727                     {
728
729                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
730
731                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
732                     }
733
734                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
735                     {
736
737                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
738
739                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
740                     }
741
742                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
743                     {
744
745                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
746
747                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
748                     }
749                 }
750
751                 //
752                 // If the count has dropped to one and there is a pending delete
753                 // then delete the node.  The final count will be decremented just
754                 // before the Fcb->NPFcb->Resource is released.
755                 //
756
757                 if( pFcb->OpenHandleCount == 1 &&
758                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
759                 {
760
761                     //
762                     // Try to notify the service about the delete
763                     //
764
765                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
766
767                     //
768                     // Indicate the file access mode that is being released
769                     //
770
771                     stFileCleanup.FileAccess = pCcb->FileAccess;
772
773                     //
774                     // Push the request to the service
775                     //
776
777                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
778                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
779                                                   &pCcb->AuthGroup,
780                                                   &pCcb->DirectoryCB->NameInformation.FileName,
781                                                   &pObjectInfo->FileId,
782                                                   &stFileCleanup,
783                                                   sizeof( AFSFileCleanupCB),
784                                                   pResultCB,
785                                                   &ulResultLen);
786
787                     if( !NT_SUCCESS( ntStatus) &&
788                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
789                     {
790
791                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
792                                       AFS_TRACE_LEVEL_ERROR,
793                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
794                                       &pCcb->FullFileName,
795                                       ntStatus);
796
797                         ntStatus = STATUS_SUCCESS;
798
799                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
800                     }
801                     else
802                     {
803
804                         ntStatus = STATUS_SUCCESS;
805
806                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
807                                       AFS_TRACE_LEVEL_VERBOSE,
808                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
809                                       &pCcb->FullFileName,
810                                       pCcb->DirectoryCB);
811
812                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
813
814                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
815
816                         AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
817                                         TRUE);
818
819                         if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
820                         {
821
822                             SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
823
824                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
825                         }
826                         else
827                         {
828
829                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
830                         }
831
832                         //
833                         // Now that the service has the entry has deleted we need to remove it from the parent
834                         // tree so another lookup on the node will fail
835                         //
836
837                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
838                         {
839
840                             AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
841                                                 pCcb->DirectoryCB);
842                         }
843                         else
844                         {
845
846                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
847                                           AFS_TRACE_LEVEL_VERBOSE,
848                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
849                                           pCcb->DirectoryCB,
850                                           &pCcb->DirectoryCB->NameInformation.FileName);
851                         }
852
853                         AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
854
855                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
856                                                         pCcb,
857                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
858                                                         (ULONG)FILE_ACTION_REMOVED);
859
860                     }
861                 }
862
863                 //
864                 // If there have been any updates to the node then push it to
865                 // the service
866                 //
867
868                 else
869                 {
870
871                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
872                     {
873
874                         ULONG ulNotifyFilter = 0;
875
876                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
877
878                         if(  pObjectInfo->ParentObjectInformation != NULL)
879                         {
880
881                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
882
883                             AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
884                                                             pCcb,
885                                                             (ULONG)ulNotifyFilter,
886                                                             (ULONG)FILE_ACTION_MODIFIED);
887                         }
888                     }
889
890                     //
891                     // Indicate the file access mode that is being released
892                     //
893
894                     stFileCleanup.FileAccess = pCcb->FileAccess;
895
896                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
897                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
898                                                   &pCcb->AuthGroup,
899                                                   &pCcb->DirectoryCB->NameInformation.FileName,
900                                                   &pObjectInfo->FileId,
901                                                   &stFileCleanup,
902                                                   sizeof( AFSFileCleanupCB),
903                                                   pResultCB,
904                                                   &ulResultLen);
905
906                     if ( NT_SUCCESS( ntStatus))
907                     {
908
909                         if ( pObjectInfo->ParentObjectInformation != NULL)
910                         {
911
912                             AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
913                                               TRUE);
914
915                             if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
916                             {
917
918                                 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
919
920                                 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
921                             }
922
923                             AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
924                         }
925                     }
926
927                     ntStatus = STATUS_SUCCESS;
928                 }
929
930                 //
931                 // Release the notification for this directory if there is one
932                 //
933
934                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
935                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
936                                     pCcb);
937
938                 //
939                 // Remove the share access at this time since we may not get the close for sometime on this FO.
940                 //
941
942                 IoRemoveShareAccess( pFileObject,
943                                      &pFcb->ShareAccess);
944
945                 //
946                 // We don't need the name array after the user closes the handle on the file
947                 //
948
949                 if( pCcb->NameArray != NULL)
950                 {
951
952                     AFSFreeNameArray( pCcb->NameArray);
953
954                     pCcb->NameArray = NULL;
955                 }
956
957                 //
958                 // Decrement the open child handle count
959                 //
960
961                 if( pObjectInfo->ParentObjectInformation != NULL)
962                 {
963
964                     ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
965
966                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
967
968                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
969                                   AFS_TRACE_LEVEL_VERBOSE,
970                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
971                                   pObjectInfo->ParentObjectInformation,
972                                   lCount);
973                 }
974
975                 AFSReleaseResource( &pFcb->NPFcb->Resource);
976
977                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
978
979                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
980                               AFS_TRACE_LEVEL_VERBOSE,
981                               "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
982                               pFcb,
983                               lCount);
984
985                 break;
986             }
987
988             case AFS_SYMBOLIC_LINK_FCB:
989             case AFS_MOUNT_POINT_FCB:
990             case AFS_DFS_LINK_FCB:
991             case AFS_INVALID_FCB:
992             {
993
994                 //
995                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
996                 //
997
998                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
999                               AFS_TRACE_LEVEL_VERBOSE,
1000                               "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1001                               &pFcb->NPFcb->Resource,
1002                               PsGetCurrentThread());
1003
1004                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1005                                   TRUE);
1006
1007                 //
1008                 // Perform some final common processing
1009                 //
1010
1011                 ASSERT( pFcb->OpenHandleCount != 0);
1012
1013                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1014                 {
1015
1016                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1017                 }
1018
1019                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1020
1021                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1022                 {
1023
1024                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1025
1026                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1027                     {
1028
1029                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1030
1031                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1032                     }
1033
1034                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1035                     {
1036
1037                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1038
1039                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1040                     }
1041
1042                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1043                     {
1044
1045                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1046
1047                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1048                     }
1049                 }
1050
1051                 //
1052                 // If the count has dropped to one and there is a pending delete
1053                 // then delete the node.  The final count will be decremented just
1054                 // before the Fcb->NPFcb->Resource is released.
1055                 //
1056
1057                 if( pFcb->OpenHandleCount == 1 &&
1058                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1059                 {
1060
1061                     //
1062                     // Try to notify the service about the delete
1063                     //
1064
1065                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1066
1067                     //
1068                     // Indicate the file access mode that is being released
1069                     //
1070
1071                     stFileCleanup.FileAccess = pCcb->FileAccess;
1072
1073                     //
1074                     // Push the request to the service
1075                     //
1076
1077                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1078                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1079                                                   &pCcb->AuthGroup,
1080                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1081                                                   &pObjectInfo->FileId,
1082                                                   &stFileCleanup,
1083                                                   sizeof( AFSFileCleanupCB),
1084                                                   pResultCB,
1085                                                   &ulResultLen);
1086
1087                     if( !NT_SUCCESS( ntStatus) &&
1088                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1089                     {
1090
1091                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1092                                       AFS_TRACE_LEVEL_ERROR,
1093                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1094                                       &pCcb->FullFileName,
1095                                       ntStatus);
1096
1097                         ntStatus = STATUS_SUCCESS;
1098
1099                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1100                     }
1101                     else
1102                     {
1103
1104                         ntStatus = STATUS_SUCCESS;
1105
1106                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1107                                       AFS_TRACE_LEVEL_VERBOSE,
1108                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1109                                       &pCcb->FullFileName,
1110                                       pCcb->DirectoryCB);
1111
1112                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1113
1114                         ASSERT( pObjectInfo->ParentObjectInformation != NULL);
1115
1116                         AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1117                                         TRUE);
1118
1119                         if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1120                         {
1121
1122                             SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1123
1124                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1125                         }
1126                         else
1127                         {
1128                             pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1129                         }
1130
1131                         //
1132                         // Now that the service has the entry has deleted we need to remove it from the parent
1133                         // tree so another lookup on the node will fail
1134                         //
1135
1136                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1137                         {
1138
1139                             AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
1140                                                 pCcb->DirectoryCB);
1141                         }
1142                         else
1143                         {
1144
1145                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1146                                           AFS_TRACE_LEVEL_VERBOSE,
1147                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1148                                           pCcb->DirectoryCB,
1149                                           &pCcb->DirectoryCB->NameInformation.FileName);
1150                         }
1151
1152                         AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1153
1154                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1155                                                         pCcb,
1156                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1157                                                         (ULONG)FILE_ACTION_REMOVED);
1158
1159                     }
1160                 }
1161
1162                 //
1163                 // If there have been any updates to the node then push it to
1164                 // the service
1165                 //
1166
1167                 else
1168                 {
1169
1170                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1171                     {
1172
1173                         ULONG ulNotifyFilter = 0;
1174
1175                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1176
1177                         if(  pObjectInfo->ParentObjectInformation != NULL)
1178                         {
1179
1180                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1181
1182                             AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1183                                                             pCcb,
1184                                                             (ULONG)ulNotifyFilter,
1185                                                             (ULONG)FILE_ACTION_MODIFIED);
1186                         }
1187                     }
1188
1189                     //
1190                     // Indicate the file access mode that is being released
1191                     //
1192
1193                     stFileCleanup.FileAccess = pCcb->FileAccess;
1194
1195                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1196                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1197                                                   &pCcb->AuthGroup,
1198                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1199                                                   &pObjectInfo->FileId,
1200                                                   &stFileCleanup,
1201                                                   sizeof( AFSFileCleanupCB),
1202                                                   pResultCB,
1203                                                   &ulResultLen);
1204
1205                     if ( NT_SUCCESS( ntStatus))
1206                     {
1207
1208                         if ( pObjectInfo->ParentObjectInformation != NULL)
1209                         {
1210
1211                             AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1212                                               TRUE);
1213
1214                             if ( pObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1215                             {
1216
1217                                 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1218
1219                                 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1220                             }
1221
1222                             AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1223                         }
1224                     }
1225
1226                     ntStatus = STATUS_SUCCESS;
1227                 }
1228
1229                 //
1230                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1231                 //
1232
1233                 IoRemoveShareAccess( pFileObject,
1234                                      &pFcb->ShareAccess);
1235
1236                 //
1237                 // We don't need the name array after the user closes the handle on the file
1238                 //
1239
1240                 if( pCcb->NameArray != NULL)
1241                 {
1242
1243                     AFSFreeNameArray( pCcb->NameArray);
1244
1245                     pCcb->NameArray = NULL;
1246                 }
1247
1248                 //
1249                 // Decrement the open child handle count
1250                 //
1251
1252                 if( pObjectInfo->ParentObjectInformation != NULL)
1253                 {
1254
1255                     ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
1256
1257                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1258
1259                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1260                                   AFS_TRACE_LEVEL_VERBOSE,
1261                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1262                                   pObjectInfo->ParentObjectInformation,
1263                                   lCount);
1264                 }
1265
1266                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1267
1268                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1269
1270                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1271                               AFS_TRACE_LEVEL_VERBOSE,
1272                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1273                               pFcb,
1274                               lCount);
1275
1276                 break;
1277             }
1278
1279             case AFS_SPECIAL_SHARE_FCB:
1280             {
1281
1282                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1283                               AFS_TRACE_LEVEL_VERBOSE,
1284                               "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1285                               &pFcb->NPFcb->Resource,
1286                               PsGetCurrentThread());
1287
1288                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1289                                 TRUE);
1290
1291                 ASSERT( pFcb->OpenHandleCount != 0);
1292
1293                 //
1294                 // Decrement the open child handle count
1295                 //
1296
1297                 if( pObjectInfo->ParentObjectInformation != NULL &&
1298                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1299                 {
1300
1301                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
1302
1303                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1304                                   AFS_TRACE_LEVEL_VERBOSE,
1305                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1306                                   pObjectInfo->ParentObjectInformation,
1307                                   lCount);
1308                 }
1309
1310                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1311
1312                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1313
1314                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1315                               AFS_TRACE_LEVEL_VERBOSE,
1316                               "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1317                               pFcb,
1318                               lCount);
1319
1320                 break;
1321             }
1322
1323             default:
1324
1325                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1326                               AFS_TRACE_LEVEL_WARNING,
1327                               "AFSCleanup Processing unknown node type %d\n",
1328                               pFcb->Header.NodeTypeCode);
1329
1330                 break;
1331         }
1332
1333
1334 try_exit:
1335
1336         if( pResultCB != NULL)
1337         {
1338
1339             AFSExFreePool( pResultCB);
1340         }
1341
1342         if( pFileObject != NULL)
1343         {
1344
1345             //
1346             // Setup the fileobject flags to indicate cleanup is complete.
1347             //
1348
1349             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1350         }
1351
1352         //
1353         // Complete the request
1354         //
1355
1356         AFSCompleteRequest( Irp, ntStatus);
1357     }
1358     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1359     {
1360
1361         AFSDbgLogMsg( 0,
1362                       0,
1363                       "EXCEPTION - AFSCleanup\n");
1364
1365         AFSDumpTraceFilesFnc();
1366     }
1367
1368     return ntStatus;
1369 }