Windows: Replace ParentObjectInformation pointer
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSClose.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSClose.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSClose
43 //
44 // Description:
45 //
46 //      This function is the IRP_MJ_CLOSE dispatch handler
47 //
48 // Return:
49 //
50 //       A status is returned for the handling of this request
51 //
52
53 NTSTATUS
54 AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
55           IN PIRP Irp)
56 {
57     UNREFERENCED_PARAMETER(LibDeviceObject);
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
60     AFSFcb *pFcb = NULL;
61     AFSDeviceExt *pDeviceExt = NULL;
62     AFSCcb *pCcb = NULL;
63     AFSObjectInfoCB *pObjectInfo = NULL;
64     AFSObjectInfoCB *pParentObjectInfo = NULL;
65     AFSDirectoryCB *pDirCB = NULL;
66     LONG lCount;
67
68     __try
69     {
70
71         if( AFSRDRDeviceObject == NULL)
72         {
73
74             //
75             // Let this through, it's an close on the library control device
76             //
77
78             try_return( ntStatus);
79         }
80
81         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
82
83         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
84
85         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
86
87         if( pFcb == NULL)
88         {
89             try_return( ntStatus);
90         }
91
92         pObjectInfo = pFcb->ObjectInformation;
93
94         //
95         // Perform the close functionality depending on the type of node it is
96         //
97
98         switch( pFcb->Header.NodeTypeCode)
99         {
100
101             case AFS_IOCTL_FCB:
102             {
103
104                 AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
105                 AFSFileID stParentFileId;
106
107                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
108                               AFS_TRACE_LEVEL_VERBOSE,
109                               "AFSClose Acquiring GlobalRoot lock %p EXCL %08lX\n",
110                               &pFcb->NPFcb->Resource,
111                               PsGetCurrentThread());
112
113                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
114                                   TRUE);
115
116                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
117
118                 //
119                 // Send the close to the CM
120                 //
121
122                 RtlZeroMemory( &stPIOCtlClose,
123                                sizeof( AFSPIOCtlOpenCloseRequestCB));
124
125                 stPIOCtlClose.RequestId = pCcb->RequestID;
126
127                 stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
128
129                 RtlZeroMemory( &stParentFileId,
130                                sizeof( AFSFileID));
131
132                 stParentFileId = pObjectInfo->ParentFileId;
133
134                 //
135                 // Issue the close request to the service
136                 //
137
138                 AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
139                                    AFS_REQUEST_FLAG_SYNCHRONOUS,
140                                    &pCcb->AuthGroup,
141                                    NULL,
142                                    &stParentFileId,
143                                    (void *)&stPIOCtlClose,
144                                    sizeof( AFSPIOCtlOpenCloseRequestCB),
145                                    NULL,
146                                    NULL);
147
148                 //
149                 // Remove the Ccb and de-allocate it
150                 //
151
152                 AFSRemoveCcb( pFcb,
153                               pCcb);
154
155                 //
156                 // If this is not the root then decrement the open child reference count
157                 //
158
159                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
160                 {
161
162                     pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
163                                                            &pObjectInfo->ParentFileId);
164                 }
165
166                 if( pParentObjectInfo != NULL &&
167                     pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
168                 {
169
170                     InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
171
172                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
173                                   AFS_TRACE_LEVEL_VERBOSE,
174                                   "AFSClose (IOCtl) Decrement child open ref count on Parent object %p Cnt %d\n",
175                                   pParentObjectInfo,
176                                   pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
177                 }
178
179                 AFSReleaseResource( &pFcb->NPFcb->Resource);
180
181                 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
182
183                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
184                               AFS_TRACE_LEVEL_VERBOSE,
185                               "AFSClose (IOCtl) Decrement count on Fcb %p Cnt %d\n",
186                               pFcb,
187                               lCount);
188
189                 ASSERT( lCount >= 0);
190
191                 break;
192             }
193
194             case AFS_ROOT_ALL:
195             {
196
197                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
198                               AFS_TRACE_LEVEL_VERBOSE,
199                               "AFSClose Acquiring Special Root ALL lock %p EXCL %08lX\n",
200                               &pFcb->NPFcb->Resource,
201                               PsGetCurrentThread());
202
203                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
204                                 TRUE);
205
206                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
207
208                 //
209                 // Remove the Ccb and de-allocate it
210                 //
211
212                 AFSRemoveCcb( pFcb,
213                               pCcb);
214
215                 AFSReleaseResource( &pFcb->NPFcb->Resource);
216
217                 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
218
219                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
220                               AFS_TRACE_LEVEL_VERBOSE,
221                               "AFSClose (RootAll) Decrement count on Fcb %p Cnt %d\n",
222                               pFcb,
223                               lCount);
224
225                 ASSERT( lCount >= 0);
226
227                 break;
228             }
229
230             //
231             // Root, file or directory node
232             //
233
234             case AFS_FILE_FCB:
235             case AFS_ROOT_FCB:
236             case AFS_DIRECTORY_FCB:
237             case AFS_SYMBOLIC_LINK_FCB:
238             case AFS_MOUNT_POINT_FCB:
239             case AFS_DFS_LINK_FCB:
240             case AFS_INVALID_FCB:
241             {
242
243                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
244
245                 //
246                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
247                 //
248
249                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
250                               AFS_TRACE_LEVEL_VERBOSE,
251                               "AFSClose Acquiring Dcb lock %p EXCL %08lX\n",
252                               &pFcb->NPFcb->Resource,
253                               PsGetCurrentThread());
254
255                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
256                                 TRUE);
257
258                 KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
259
260                 if( pFcb->OpenReferenceCount == 1 &&
261                     pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
262                 {
263
264                     SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
265
266                     //
267                     // Attempt to tear down our extent list for the file
268                     // If there are remaining dirty extents then attempt to
269                     // flush them as well
270                     //
271
272                     if( pFcb->Specific.File.ExtentsDirtyCount)
273                     {
274
275                         AFSFlushExtents( pFcb,
276                                          &pCcb->AuthGroup);
277                     }
278
279                     //
280                     // Wait for any outstanding queued flushes to complete
281                     //
282
283                     AFSWaitOnQueuedFlushes( pFcb);
284
285                     ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
286                             pFcb->Specific.File.QueuedFlushCount == 0);
287
288                     AFSReleaseResource( &pFcb->NPFcb->Resource);
289
290                     //
291                     // Tear 'em down, we'll not be needing them again
292                     //
293
294                     AFSTearDownFcbExtents( pFcb,
295                                            &pCcb->AuthGroup);
296                 }
297                 else
298                 {
299
300                     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
301                         pFcb->Specific.File.ExtentsDirtyCount &&
302                         (pCcb->GrantedAccess & FILE_WRITE_DATA))
303                     {
304
305                         AFSFlushExtents( pFcb,
306                                          &pCcb->AuthGroup);
307                     }
308
309                     AFSReleaseResource( &pFcb->NPFcb->Resource);
310                 }
311
312                 pDirCB = pCcb->DirectoryCB;
313
314                 //
315                 // Steal the DirOpenReferenceCount from the Ccb
316                 //
317
318                 pCcb->DirectoryCB = NULL;
319
320                 //
321                 // Object the Parent ObjectInformationCB
322                 //
323
324                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
325                 {
326
327                     pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
328                                                            &pObjectInfo->ParentFileId);
329                 }
330
331                 //
332                 // Remove the Ccb and de-allocate it
333                 //
334
335                 AFSRemoveCcb( pFcb,
336                               pCcb);
337
338                 //
339                 // If this entry is deleted then remove the object from the volume tree
340                 //
341
342                 if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
343                 {
344
345                     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
346                         pObjectInfo->Links == 0)
347                     {
348
349                         //
350                         // Stop anything possibly in process
351                         //
352
353                         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
354                                       AFS_TRACE_LEVEL_VERBOSE,
355                                       "AFSClose Acquiring Fcb extents lock %p EXCL %08lX\n",
356                                       &pFcb->NPFcb->Specific.File.ExtentsResource,
357                                       PsGetCurrentThread());
358
359                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
360                                         TRUE);
361
362                         pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
363
364                         KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
365                                     0,
366                                     FALSE);
367
368                         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
369                                       AFS_TRACE_LEVEL_VERBOSE,
370                                       "AFSClose Releasing Fcb extents lock %p EXCL %08lX\n",
371                                       &pFcb->NPFcb->Specific.File.ExtentsResource,
372                                       PsGetCurrentThread());
373
374                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
375                     }
376
377                     ASSERT( pParentObjectInfo != NULL);
378
379                     if ( pParentObjectInfo != NULL)
380                     {
381                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
382                                         TRUE);
383
384                         AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
385                                         TRUE);
386
387                         lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
388
389                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
390                                       AFS_TRACE_LEVEL_VERBOSE,
391                                       "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
392                                       &pDirCB->NameInformation.FileName,
393                                       pDirCB,
394                                       pCcb,
395                                       lCount);
396
397                         ASSERT( lCount >= 0);
398
399                         if( lCount == 0)
400                         {
401
402                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
403                                           AFS_TRACE_LEVEL_VERBOSE,
404                                           "AFSClose Deleting dir entry %p (%p) for %wZ  FID %08lX-%08lX-%08lX-%08lX\n",
405                                           pDirCB,
406                                           pObjectInfo,
407                                           &pDirCB->NameInformation.FileName,
408                                           pObjectInfo->FileId.Cell,
409                                           pObjectInfo->FileId.Volume,
410                                           pObjectInfo->FileId.Vnode,
411                                           pObjectInfo->FileId.Unique);
412
413                             //
414                             // Remove and delete the directory entry from the parent list
415                             //
416
417                             AFSDeleteDirEntry( pParentObjectInfo,
418                                                pDirCB);
419
420                             AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
421                                               TRUE);
422
423                             if( pObjectInfo->ObjectReferenceCount <= 0)
424                             {
425
426                                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
427                                 {
428
429                                     AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
430                                                   AFS_TRACE_LEVEL_VERBOSE,
431                                                   "AFSClose Removing object %p from volume tree\n",
432                                                   pObjectInfo);
433
434                                     AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
435                                                         &pObjectInfo->TreeEntry);
436
437                                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
438                                 }
439                             }
440
441                             AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
442                         }
443
444                         AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
445
446                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
447                     }
448                 }
449                 else
450                 {
451
452                     lCount = InterlockedDecrement( &pDirCB->DirOpenReferenceCount);
453
454                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
455                                   AFS_TRACE_LEVEL_VERBOSE,
456                                   "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
457                                   &pDirCB->NameInformation.FileName,
458                                   pDirCB,
459                                   pCcb,
460                                   lCount);
461
462                     ASSERT( lCount >= 0);
463                 }
464
465                 //
466                 // If this is not the root then decrement the open child reference count
467                 //
468
469                 if( pObjectInfo != NULL &&
470                     pParentObjectInfo != NULL &&
471                     pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
472                 {
473
474                     InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
475
476                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
477                                   AFS_TRACE_LEVEL_VERBOSE,
478                                   "AFSClose Decrement child open ref count on Parent object %p Cnt %d\n",
479                                   pParentObjectInfo,
480                                   pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
481                 }
482
483                 //
484                 // Decrement the reference count on the Fcb. this is protecting it from teardown.
485                 //
486
487                 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
488
489                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
490                               AFS_TRACE_LEVEL_VERBOSE,
491                               "AFSClose Decrement count on Fcb %p Cnt %d\n",
492                               pFcb,
493                               lCount);
494
495                 ASSERT( lCount >= 0);
496
497                 break;
498             }
499
500             case AFS_SPECIAL_SHARE_FCB:
501             {
502
503                 AFSPipeOpenCloseRequestCB stPipeClose;
504
505                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
506
507                 //
508                 // Object the Parent ObjectInformationCB
509                 //
510
511                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
512                 {
513
514                     pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
515                                                            &pObjectInfo->ParentFileId);
516                 }
517
518                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
519                               AFS_TRACE_LEVEL_VERBOSE,
520                               "AFSClose Acquiring Special Share lock %p EXCL %08lX\n",
521                               &pFcb->NPFcb->Resource,
522                               PsGetCurrentThread());
523
524                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
525                                 TRUE);
526
527                 RtlZeroMemory( &stPipeClose,
528                                sizeof( AFSPipeOpenCloseRequestCB));
529
530                 stPipeClose.RequestId = pCcb->RequestID;
531
532                 stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
533
534                 //
535                 // Issue the open request to the service
536                 //
537
538                 /*
539                 AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
540                                    AFS_REQUEST_FLAG_SYNCHRONOUS,
541                                    &pFcb->AuthGroup,
542                                    &pDirCB->NameInformation.FileName,
543                                    NULL,
544                                    (void *)&stPipeClose,
545                                    sizeof( AFSPipeOpenCloseRequestCB),
546                                    NULL,
547                                    NULL);
548                 */
549
550                 //
551                 // Remove the Ccb and de-allocate it
552                 //
553
554                 AFSRemoveCcb( pFcb,
555                               pCcb);
556
557                 //
558                 // If this is not the root then decrement the open child reference count
559                 //
560
561                 if( pParentObjectInfo != NULL &&
562                     pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount > 0)
563                 {
564
565                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
566
567                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
568                                   AFS_TRACE_LEVEL_VERBOSE,
569                                   "AFSClose (Share) Decrement child open ref count on Parent object %p Cnt %d\n",
570                                   pParentObjectInfo,
571                                   lCount);
572                 }
573
574                 AFSReleaseResource( &pFcb->NPFcb->Resource);
575
576                 lCount = InterlockedDecrement( &pFcb->OpenReferenceCount);
577
578                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
579                               AFS_TRACE_LEVEL_VERBOSE,
580                               "AFSClose (Share) Decrement count on Fcb %p Cnt %d\n",
581                               pFcb,
582                               lCount);
583
584                 ASSERT( lCount >= 0);
585
586                 break;
587             }
588
589             default:
590
591                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
592                               AFS_TRACE_LEVEL_ERROR,
593                               "AFSClose Processing unknown node type %d\n",
594                               pFcb->Header.NodeTypeCode);
595
596                 break;
597         }
598
599 try_exit:
600
601         //
602         // Complete the request
603         //
604
605         AFSCompleteRequest( Irp,
606                             ntStatus);
607     }
608     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
609     {
610
611         AFSDbgLogMsg( 0,
612                       0,
613                       "EXCEPTION - AFSClose\n");
614
615         AFSDumpTraceFilesFnc();
616     }
617
618     if ( pParentObjectInfo != NULL)
619     {
620
621         AFSReleaseObjectInfo( &pParentObjectInfo);
622     }
623
624     return ntStatus;
625 }