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