Windows: AFSSetFileLinkInfo() DirOpenReferenceCount handling
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 29 Dec 2012 05:44:27 +0000 (00:44 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Thu, 31 Jan 2013 19:24:08 +0000 (11:24 -0800)
AFSSetFileLinkInfo() would leak a DirOpenReferenceCount when
pNewTargetDirEntry is not NULL upon exit.  It also did not
properly handle a STATUS_REPARSE response from AFSNotifyHardLink().
The AFSInsertDirectoryNode() call should not be performed when
the result is STATUS_REPARSE since that means the entry already
exists.

Change-Id: Ibbf497cb4c3c412e4f95cdffc6025f03f0e2ed8b
Reviewed-on: http://gerrit.openafs.org/8857
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/lib/AFSFileInfo.cpp

index e083c82..786df07 100644 (file)
@@ -2465,7 +2465,7 @@ AFSSetFileLinkInfo( IN PIRP Irp)
                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
                           &pTargetDirEntry->NameInformation.FileName,
                           pTargetDirEntry,
-                          pTargetDirEntry->DirOpenReferenceCount);
+                          lCount);
 
             //
             // Pull the directory entry from the parent
@@ -2498,7 +2498,8 @@ AFSSetFileLinkInfo( IN PIRP Irp)
                                       pFileLinkInfo->ReplaceIfExists,
                                       &pNewTargetDirEntry);
 
-        if( !NT_SUCCESS( ntStatus))
+        if( ntStatus != STATUS_REPARSE &&
+            !NT_SUCCESS( ntStatus))
         {
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -2511,9 +2512,13 @@ AFSSetFileLinkInfo( IN PIRP Irp)
             try_return( ntStatus);
         }
 
-        AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
-                                pNewTargetDirEntry,
-                                TRUE);
+        if ( ntStatus != STATUS_REPARSE)
+        {
+
+            AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
+                                    pNewTargetDirEntry,
+                                    TRUE);
+        }
 
         //
         // Send notification for the target link file
@@ -2552,6 +2557,10 @@ AFSSetFileLinkInfo( IN PIRP Irp)
         if( pTargetDirEntry != NULL)
         {
 
+            //
+            // Release DirOpenReferenceCount obtained above
+            //
+
             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
@@ -2565,6 +2574,26 @@ AFSSetFileLinkInfo( IN PIRP Irp)
             ASSERT( lCount >= 0);
         }
 
+        if( pNewTargetDirEntry != NULL)
+        {
+
+            //
+            // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
+            //
+
+            lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pNewTargetDirEntry->NameInformation.FileName,
+                          pNewTargetDirEntry,
+                          pSrcCcb,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
         if( bReleaseTargetDirLock)
         {