Windows: remember when a reparse point is opened
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCreate.cpp
index 6d479f1..a9b9ac9 100644 (file)
@@ -145,6 +145,7 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
     ULONG               ulParseFlags = 0;
     GUID                stAuthGroup;
     ULONG               ulNameProcessingFlags = 0;
+    BOOLEAN             bOpenedReparsePoint = FALSE;
 
     __Enter
     {
@@ -577,20 +578,11 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                               NULL,
                               pParentDirectoryCB->OpenReferenceCount);
 
-                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCreate Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
-                              &pDirectoryCB->NameInformation.FileName,
-                              pDirectoryCB,
-                              NULL,
-                              pDirectoryCB->OpenReferenceCount);
-
                 //
-                // The name array also contains a reference to the pDirectoryCB so we need to remove it
-                // Note that this could decrement the count to zero allowing it to be deleted, hence
-                // don't access the pointer contents beyond here.
+                // Do NOT decrement the reference count on the pDirectoryCB yet.
+                // The BackupEntry below might drop the count to zero leaving
+                // the entry subject to being deleted and we need some of the
+                // contents during later processing
                 //
 
                 AFSBackupEntry( pNameArray);
@@ -613,6 +605,21 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                                                &uniComponentName,
                                                &pFcb,
                                                &pCcb);
+            if( pDirectoryCB != NULL)
+            {
+                //
+                // It is now safe to drop the Reference Count
+                //
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+            }
 
             if( !NT_SUCCESS( ntStatus))
             {
@@ -642,16 +649,22 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
         }
 
         if ( BooleanFlagOn( ulOptions, FILE_OPEN_REPARSE_POINT) &&
-             pDirectoryCB != NULL &&
-             !BooleanFlagOn( pDirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
+             pDirectoryCB != NULL)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSCommonCreate (%08lX) Reparse open request but attribute not set for %wZ Type %08lX\n",
-                          Irp,
-                          &uniFileName,
-                          pDirectoryCB->ObjectInformation->FileType);
+            if( !BooleanFlagOn( pDirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
+            {
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate (%08lX) Reparse open request but attribute not set for %wZ Type %08lX\n",
+                              Irp,
+                              &uniFileName,
+                              pDirectoryCB->ObjectInformation->FileType);
+            }
+            else
+            {
+                bOpenedReparsePoint = TRUE;
+            }
         }
 
         //
@@ -733,23 +746,6 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                               &pParentDirectoryCB->NameInformation.FileName,
                               ntStatus);
             }
-            else
-            {
-
-                //
-                // Reference the new dir entry
-                //
-
-                InterlockedIncrement( &pCcb->DirectoryCB->OpenReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSCreate Increment (Create) count on %wZ DE %p Ccb %p Cnt %d\n",
-                              &pCcb->DirectoryCB->NameInformation.FileName,
-                              pCcb->DirectoryCB,
-                              pCcb,
-                              pCcb->DirectoryCB->OpenReferenceCount);
-            }
 
             //
             // Dereference the parent entry
@@ -1063,6 +1059,11 @@ try_exit:
                     }
                 }
 
+                if( bOpenedReparsePoint)
+                {
+                    SetFlag( pCcb->Flags, CCB_FLAG_MASK_OPENED_REPARSE_POINT);
+                }
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSCreate Count on %wZ DE %p Ccb %p Cnt %d\n",
@@ -1770,6 +1771,43 @@ AFSProcessCreate( IN PIRP               Irp,
 
         pObjectInfo = pDirEntry->ObjectInformation;
 
+        if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
+            pObjectInfo->FileType == AFS_FILE_TYPE_UNKNOWN)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSProcessCreate (%08lX) Evaluating object %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                          Irp,
+                          &pDirEntry->NameInformation.FileName,
+                          pObjectInfo->FileId.Cell,
+                          pObjectInfo->FileId.Volume,
+                          pObjectInfo->FileId.Vnode,
+                          pObjectInfo->FileId.Unique);
+
+            ntStatus = AFSEvaluateNode( AuthGroup,
+                                        pDirEntry);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessCreate (%08lX) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                              Irp,
+                              &pDirEntry->NameInformation.FileName,
+                              pObjectInfo->FileId.Cell,
+                              pObjectInfo->FileId.Volume,
+                              pObjectInfo->FileId.Vnode,
+                              pObjectInfo->FileId.Unique,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
+        }
+
         //
         // We may have raced and the Fcb is already created
         //
@@ -1932,16 +1970,16 @@ AFSProcessCreate( IN PIRP               Irp,
         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSProcessCreate Increment count on Fcb %08lX Cnt %d\n",
-                                                    *Fcb,
-                                                    (*Fcb)->OpenReferenceCount);
+                      *Fcb,
+                      (*Fcb)->OpenReferenceCount);
 
         InterlockedIncrement( &(*Fcb)->OpenHandleCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSProcessCreate Increment handle count on Fcb %08lX Cnt %d\n",
-                                                    (*Fcb),
-                                                    (*Fcb)->OpenHandleCount);
+                      (*Fcb),
+                      (*Fcb)->OpenHandleCount);
 
         //
         // Increment the open reference and handle on the parent node
@@ -2010,6 +2048,13 @@ try_exit:
             if( bFileCreated)
             {
 
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSProcessCreate Create failed, removing DE %p from aprent object %p Status %08lX\n",
+                              pDirEntry,
+                              pParentObjectInfo,
+                              ntStatus);
+
                 //
                 // Remove the dir entry from the parent
                 //
@@ -2017,8 +2062,37 @@ try_exit:
                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                 TRUE);
 
-                AFSDeleteDirEntry( pParentObjectInfo,
-                                   pDirEntry);
+                SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
+
+                //
+                // Decrement the reference added during initialization of the DE
+                //
+
+                InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSProcessCreate Decrement count on %wZ DE %p Cnt %d\n",
+                              &pDirEntry->NameInformation.FileName,
+                              pDirEntry,
+                              pDirEntry->OpenReferenceCount);
+
+                //
+                // Pull the directory entry from the parent
+                //
+
+                AFSRemoveDirNodeFromParent( pParentObjectInfo,
+                                            pDirEntry,
+                                            FALSE); // Leave it in the enum list so the worker cleans it up
+
+                AFSNotifyDelete( pDirEntry,
+                                 FALSE);
+
+                //
+                // Tag the parent as needing verification
+                //
+
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
             }