Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix deterministic MountVolume test failures on ARM64 Helix machines - #126660

Merged
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive
Apr 11, 2026
Merged

Fix deterministic MountVolume test failures on ARM64 Helix machines#126660
danmoseley merged 4 commits into
dotnet:mainfrom
danmoseley:danmose/fix-mountvolume-bogus-drive

Conversation

@danmoseley

@danmoseleydanmoseley commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Note

This PR was created with Copilot assistance.

Fix deterministic MountVolume test failures on ARM64 Helix machines

Fixes#125295, fixes#125624, fixes#126627

Problem

Directory_Delete_MountVolume.RunTest and Directory_ReparsePoints_MountVolume.runTest fail deterministically (~100% of the time, ~750ms duration) on the Windows.11.Arm64.Open Helix machine pool. This is not timing-related and was not addressed by the delay/polling fixes in #125914 or the Unmount resilience fix in #125625 (those PRs fixed real timing issues -- pre-fix failures on other configurations have since expired from AzDO retention, so we can't verify directly, but there is no evidence they were ineffective for their intended purpose).

Root cause: The ARM64 Helix machines have an E:\ drive (likely an Azure resource/temp disk) that passes all DriveInfo checks -- DriveType=Fixed, DriveFormat=NTFS, IsReady=True -- but GetVolumeNameForVolumeMountPoint fails with ERROR_INVALID_PARAMETER (87). The drive has no volume GUID and doesn't support volume mount point operations. IOServices.GetNtfsDriveOtherThanCurrent() returns this drive, and the test crashes trying to use it.

Some ARM64 Helix machines have only C:\ and a CD-ROM (no second drive at all). On those machines, the cross-drive scenarios already skip gracefully and only same-drive scenarios 3.x run.

Evidence

Analyzed Helix console logs from 5 post-fix builds (all arm64-NativeAOT-Win11, same C:\ volume GUID). Every failure shows the identical pattern:

  • Scenario 1: GetVolumeNameForVolumeMountPoint("E:\") -> error 87
  • Scenario 2: SetVolumeMountPoint onto E:\ succeeds but path traversal through the mount point fails with DirectoryNotFoundException
  • Scenarios 3.x (same-drive): Always pass

Reproduced locally by removing the real E: drive letter and creating SUBST E: which exhibits identical error 87 behavior.

Changes

  1. IOServices.GetNtfsDriveOtherThan(): After the existing Fixed/Ready/NTFS checks, also verify the drive has a volume GUID via GetVolumeNameForVolumeMountPoint. Drives without one (SUBST drives, Azure resource disks) are skipped.

  2. DumpDriveInformation diagnostic test: New Helix-only test (following the DescriptionNameTests.DumpRuntimeInformationToConsole pattern) that dumps all drives with their volume GUIDs to the console log. Makes future drive-related CI issues immediately diagnosable from the same Helix work item log.

  3. GetVolumeNameForVolumeMountPoint P/Invoke in DllImports.cs: Uses char[] (not StringBuilder) because this file uses LibraryImport which does not support StringBuilder.

Local validation

ScenarioBefore fixAfter fix
SUBST E: (no volume GUID)Error 87 / DirectoryNotFoundExceptionPass (SUBST filtered, scenarios 3.x run)
Real NTFS E:Pass (all scenarios)Pass (all scenarios)
Single-drive machineScenarios 1/2 skip, 3.x passSame -- no change

CopilotAI review requested due to automatic review settings April 8, 2026 20:49
@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-ioslikesimulator

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-android

@danmoseley

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

2 similar comments
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses deterministic failures in Windows MountVolume-related filesystem tests on ARM64 Helix by improving second-drive selection and adding Helix diagnostics to make drive/volume issues easier to diagnose from logs.

Changes:

  • Filter candidate “other NTFS drives” to only those that support volume mount point operations (via GetVolumeNameForVolumeMountPoint).
  • Add a Helix-only diagnostic test that logs drive details and volume GUID availability.
  • Improve Mount/Unmount error messages by using P/Invoke error messages instead of raw codes, and add a Helix guard for missing second-drive scenarios.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojAdds the new DumpDriveInformation.cs test file to the project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csEnhances NTFS drive selection by skipping drives without a volume GUID/mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke used to validate mount-point support.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csNew Helix-only diagnostic test that prints drive and volume GUID information to the console log.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds a Helix check to fail when a suitable second NTFS drive can’t be found.
src/libraries/Common/tests/System/IO/ReparsePointUtilities.csImproves mount/unmount exception messages by using P/Invoke error message APIs.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/IO/ReparsePointUtilities.cs:260

  • Marshal.GetLastPInvokeError() / Marshal.GetLastPInvokeErrorMessage() are not available on .NET Framework. Since this file is compiled for NETFRAMEWORK in some test projects, this change will break those builds unless guarded (e.g., keep GetLastWin32Error() on NETFRAMEWORK and format the message via Win32Exception).
 bool r = DeleteVolumeMountPoint(mountPoint);
if (!r)
{
int error = Marshal.GetLastPInvokeError();
// Ignore expected cleanup errors: 4390 (ERROR_NOT_A_REPARSE_POINT),
// 3 (ERROR_PATH_NOT_FOUND), 2 (ERROR_FILE_NOT_FOUND)
if (error != 4390 && error != 3 && error != 2)
throw new Exception(string.Format("DeleteVolumeMountPoint({0}) failed: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
Console.WriteLine(string.Format("Ignoring expected error while unmounting {0}: {1}", mountPoint, Marshal.GetLastPInvokeErrorMessage()));
  • Files reviewed: 7/7 changed files
  • Comments generated: 4

@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch 2 times, most recently from e6a88d1 to cafd910CompareApril 8, 2026 21:09
CopilotAI review requested due to automatic review settings April 8, 2026 21:09

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the System.IO mount-volume tests on Windows 11 ARM64 Helix machines by avoiding “fixed/NTFS/ready” drives that don’t actually support volume mount-point operations (no volume GUID), and by adding Helix-focused diagnostics/guards to keep cross-drive scenarios from silently becoming dead code.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to also require a successful GetVolumeNameForVolumeMountPoint (volume GUID present) before selecting a “usable” NTFS drive.
  • Add Helix-only hard-fail guards in both mount-volume tests when no suitable second NTFS drive is available.
  • Add a Helix-only diagnostic test to dump drive and volume GUID information into Helix logs.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new DumpDriveInformation.cs test file in the test project.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring a volume GUID (mount-point capable).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke via LibraryImport.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only diagnostic logging of drive details + selected “other NTFS drive”.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/ReparsePoints_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.csAdds Helix guard that fails when no suitable second NTFS drive is found.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

IOServices.GetNtfsDriveOtherThan() now verifies drives have a volume GUID
via GetVolumeNameForVolumeMountPoint before returning them. This filters out
SUBST drives and Azure resource disks that report as Fixed/NTFS/Ready but
don't support volume mount point operations (error 87).
Also:
- Assert.Fail on Helix when no suitable second drive found (prevents silent skip)
- Added DumpDriveInformation diagnostic test for Helix console logs
Fixesdotnet#125295Fixesdotnet#125624Fixesdotnet#126627
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
danmoseleyforce-pushed the danmose/fix-mountvolume-bogus-drive branch from cafd910 to 8ccebe9CompareApril 8, 2026 21:18
@danmoseley
danmoseley marked this pull request as draft April 9, 2026 02:27
… Assert.Fail
LibraryImport source generator does not support StringBuilder parameters -
the CI dump showed VolumeGUID=\ because the output buffer was never
populated. Switch to char[] which LibraryImport handles correctly.
Remove Assert.Fail on Helix when no second drive found - some ARM64 Helix
machines legitimately have only C:\ and a CD-ROM. The cross-drive scenarios
skip gracefully in that case (existing behavior). The DumpDriveInformation
test still provides diagnostics in the Helix log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 02:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses deterministic failures in the MountVolume-related filesystem tests on Windows 11 ARM64 Helix machines by ensuring the “other NTFS drive” selection skips fixed/NTFS/ready drives that don’t actually support volume mount point operations (e.g., drives without a volume GUID).

Changes:

  • Update IOServices.GetNtfsDriveOtherThan(...) to additionally require that candidate drives have a volume GUID via GetVolumeNameForVolumeMountPoint.
  • Add a GetVolumeNameForVolumeMountPointWLibraryImport to the test DllImports helpers.
  • Add a Helix-only diagnostic test (DumpDriveInformation) and wire it into the test project to print drive/volume details to the Helix console log.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test source file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring successful GetVolumeNameForVolumeMountPoint (i.e., a volume GUID exists).
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds GetVolumeNameForVolumeMountPointW P/Invoke for drive capability detection and diagnostics.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging test that dumps drive properties and (on Windows) volume GUID availability to aid CI diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 9, 2026 03:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to address deterministic MountVolume-related test failures on Windows ARM64 Helix agents by ensuring the “other NTFS drive” selection excludes drives that don’t support volume mount point operations, and by adding Helix-only diagnostics to quickly identify problematic drives.

Changes:

  • Update IOServices.GetNtfsDriveOtherThan() to require a successful GetVolumeNameForVolumeMountPoint call (filters out drives without a usable volume GUID).
  • Add a new kernel32 P/Invoke (GetVolumeNameForVolumeMountPointW) to the test DllImports.
  • Add a Helix-only diagnostic “test” that prints drive properties and volume GUID availability to the console, and include it in the test project.
Show a summary per file
FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csprojIncludes the new diagnostic test file in the test project compilation list.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOServices.csFilters candidate NTFS drives by requiring GetVolumeNameForVolumeMountPoint success.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/DllImports.csAdds P/Invoke for GetVolumeNameForVolumeMountPointW.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DumpDriveInformation.csAdds Helix-only logging of drive info + volume GUID presence for future diagnosis.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @danmoseley !

@danmoseley
danmoseley merged commit 280fb74 into dotnet:mainApr 11, 2026
85 of 95 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants

@danmoseley@adamsitnik