Windows: AFSLocateNameEntry OutVolumeCB can be NULL
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCreate.cpp
index bff8341..87415b3 100644 (file)
@@ -144,7 +144,10 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
     AFSNameArrayHdr    *pNameArray = NULL;
     AFSVolumeCB        *pVolumeCB = NULL;
     LONG                VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
+    AFSVolumeCB        *pNewVolumeCB = NULL;
+    LONG                NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
     AFSDirectoryCB     *pParentDirectoryCB = NULL, *pDirectoryCB = NULL;
+    AFSDirectoryCB     *pNewParentDirectoryCB = NULL;
     BOOLEAN             bReleaseParentDir = FALSE, bReleaseDir = FALSE;
     ULONG               ulParseFlags = 0;
     GUID                stAuthGroup = {0};
@@ -443,12 +446,78 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                                            &uniParsedFileName,
                                            pNameArray,
                                            ulNameProcessingFlags,
-                                           &pVolumeCB,
-                                           &VolumeReferenceReason,
-                                           &pParentDirectoryCB,
+                                           pVolumeCB,
+                                           pParentDirectoryCB,
+                                           &pNewVolumeCB,
+                                           &NewVolumeReferenceReason,
+                                           &pNewParentDirectoryCB,
                                            &pDirectoryCB,
                                            &uniComponentName);
 
+            if ( pNewVolumeCB != NULL)
+            {
+
+                //
+                // AFSLocateNameEntry returns pNewVolumeCB with a reference held
+                // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
+                // the reference on pVolumeCB that was held prior to the call.
+                // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
+                // will be released second.
+                //
+
+                lCount = AFSVolumeDecrement( pVolumeCB,
+                                             VolumeReferenceReason);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate Decrement count on volume %p Reason %u Cnt %d\n",
+                              pVolumeCB,
+                              VolumeReferenceReason,
+                              lCount);
+
+                pVolumeCB = pNewVolumeCB;
+
+                pNewVolumeCB = NULL;
+
+                VolumeReferenceReason = NewVolumeReferenceReason;
+
+                NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
+
+                bReleaseVolume = (pVolumeCB != NULL);
+            }
+
+            //
+            // AFSLocateNameEntry does not alter the reference count of
+            // pParentDirectoryCB and it returns pNewParentDirectoryCB with
+            // a reference held.
+            //
+
+            if ( bReleaseParentDir)
+            {
+
+                lCount = InterlockedDecrement( &pParentDirectoryCB->DirOpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate DecrementX count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pParentDirectoryCB->NameInformation.FileName,
+                              pParentDirectoryCB,
+                              pCcb,
+                              lCount);
+            }
+
+            pParentDirectoryCB = pNewParentDirectoryCB;
+
+            pNewParentDirectoryCB = NULL;
+
+            bReleaseParentDir = (pParentDirectoryCB != NULL);
+
+            if ( pDirectoryCB)
+            {
+
+                bReleaseDir = TRUE;
+            }
+
             if( !NT_SUCCESS( ntStatus) &&
                 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
             {
@@ -470,17 +539,6 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                               &uniFileName,
                               ntStatus);
 
-                //
-                // We released any root volume locks in AFSLocateNameEntry on failure
-                // other than STATUS_OBJECT_NAME_NOT_FOUND
-                //
-
-                bReleaseVolume = FALSE;
-
-                bReleaseParentDir = FALSE;
-
-                VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
-
                 try_return( ntStatus);
             }
 
@@ -499,14 +557,6 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
 
                 Irp->IoStatus.Information = IO_REPARSE;
 
-                //
-                // We released the volume lock above
-                //
-
-                bReleaseVolume = FALSE;
-
-                bReleaseParentDir = FALSE;
-
                 try_return( ntStatus);
             }
 
@@ -563,23 +613,6 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                     try_return( ntStatus);
                 }
             }
-            else
-            {
-
-                //
-                // AFSLocateNameEntry succeeded.  The parent directory reference
-                // has been released and if there is a directory returned, it is
-                // referenced.
-                //
-
-                bReleaseParentDir = FALSE;
-
-                if ( pDirectoryCB)
-                {
-
-                    bReleaseDir = TRUE;
-                }
-            }
         }
 
         //
@@ -1001,13 +1034,15 @@ try_exit:
                     SetFlag( pCcb->Flags, CCB_FLAG_MASK_OPENED_REPARSE_POINT);
                 }
 
+                lCount = pCcb->DirectoryCB->DirOpenReferenceCount;
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSCommonCreate Count on %wZ DE %p Ccb %p Cnt %d\n",
                               &pCcb->DirectoryCB->NameInformation.FileName,
                               pCcb->DirectoryCB,
                               pCcb,
-                              lCount = pCcb->DirectoryCB->DirOpenReferenceCount);
+                              lCount);
 
                 ASSERT( lCount >= 0);
 
@@ -1379,6 +1414,8 @@ AFSOpenRoot( IN PIRP Irp,
                                       AuthGroup,
                                       NULL,
                                       &VolumeCB->ObjectInformation.FileId,
+                                      VolumeCB->VolumeInformation.Cell,
+                                      VolumeCB->VolumeInformation.CellLength,
                                       (void *)&stOpenCB,
                                       sizeof( AFSFileOpenCB),
                                       (void *)&stOpenResultCB,
@@ -1426,28 +1463,22 @@ AFSOpenRoot( IN PIRP Irp,
             AFSAcquireExcl( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
                             TRUE);
 
-            if( !BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
-            {
+            ntStatus = AFSEnumerateDirectory( AuthGroup,
+                                              &VolumeCB->ObjectInformation,
+                                              TRUE);
 
-                ntStatus = AFSEnumerateDirectory( AuthGroup,
-                                                  &VolumeCB->ObjectInformation,
-                                                  TRUE);
-
-                if( !NT_SUCCESS( ntStatus))
-                {
-
-                    AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
+            if( !NT_SUCCESS( ntStatus))
+            {
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_ERROR,
-                                  "AFSOpenRoot (%p) Failed to enumerate directory Status %08lX\n",
-                                  Irp,
-                                  ntStatus);
+                AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
 
-                    try_return( ntStatus);
-                }
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSOpenRoot (%p) Failed to enumerate directory Status %08lX\n",
+                              Irp,
+                              ntStatus);
 
-                SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
+                try_return( ntStatus);
             }
 
             AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
@@ -2719,6 +2750,8 @@ AFSProcessOpen( IN PIRP Irp,
                                       AuthGroup,
                                       &DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
+                                      pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                      pObjectInfo->VolumeCB->VolumeInformation.CellLength,
                                       (void *)&stOpenCB,
                                       sizeof( AFSFileOpenCB),
                                       (void *)&stOpenResultCB,
@@ -2912,6 +2945,8 @@ try_exit:
                                    AuthGroup,
                                    &DirectoryCB->NameInformation.FileName,
                                    &pObjectInfo->FileId,
+                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
+                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
                                    (void *)&stReleaseFileAccess,
                                    sizeof( AFSFileAccessReleaseCB),
                                    NULL,
@@ -3534,6 +3569,8 @@ AFSOpenIOCtlFcb( IN PIRP Irp,
                                       AuthGroup,
                                       NULL,
                                       &stFileID,
+                                      NULL,
+                                      0,
                                       (void *)&stPIOCtlOpen,
                                       sizeof( AFSPIOCtlOpenCloseRequestCB),
                                       NULL,
@@ -3775,6 +3812,8 @@ AFSOpenSpecialShareFcb( IN PIRP Irp,
                                       AuthGroup,
                                       &DirectoryCB->NameInformation.FileName,
                                       NULL,
+                                      NULL,
+                                      0,
                                       (void *)&stPipeOpen,
                                       sizeof( AFSPipeOpenCloseRequestCB),
                                       NULL,