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