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