Use statx syscall when available - #132144
Conversation
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR updates the Unix PAL to use the Linux statx syscall (when available) to surface file birth/creation time, and adjusts System.IO filesystem tests to account for platforms/filesystems where birth time is (or isn’t) reported.
Changes:
- Add a Linux
statxsyscall path inSystemNative_{Stat,FStat,LStat}to populateFileStatus.BirthTime*when supported by the kernel + filesystem. - Add a runtime probe (
IOInputs.SupportsBirthTime) to detect whether birth time is actually observable on the current Linux environment. - Split/guard Linux creation-time tests based on whether birth time is supported.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/native/libs/System.Native/pal_io.c | Adds statx syscall support to retrieve and expose birth time on Linux with fallback to stat/fstat/lstat. |
| src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/PortedCommon/IOInputs.cs | Adds a Linux probe to determine whether birth time is observable for conditional test gating. |
| src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/File/GetSetTimes.cs | Updates/extends Linux creation-time tests to cover both “birth time unavailable” and “birth time available” behaviors. |
|
Tagging subscribers to this area: @dotnet/area-system-io |
adamsitnik
left a comment
There was a problem hiding this comment.
I don't feel confident about merging this change for RC1/2. I would prefer to just wait for .NET 12 and bump the minimum required glibc version and use statx and the structures provided by libc.
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address the feedback
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@copilot revert the revert NOW and just add the right include and use the |
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Reverted the revert in 30d6acc. The implementation now includes |
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/File/GetSetTimes.cs:87
- This test assumes the underlying Linux filesystem reports a birth time (so that changing LastWriteTime won’t affect CreationTime). On some Linux environments (e.g., filesystems/layers that don’t expose btime),
CreationTimeUtcwill legitimately fall back to the oldest of ctime/mtime, and this assertion can fail even when the implementation is correct. Consider making this aConditionalFactgated on whetherInterop.Sys.StatreportsHasBirthTimefor a newly-created file, and skip otherwise.
[Fact]
[PlatformSpecific(TestPlatforms.Linux)]
public void CreationTimeGet_ReturnsBirthTime_WhenAvailable()
{
// When the birth time is available, it is returned as the CreationTime,
// independently of the write time.
DateTime beforeCreationUtc = DateTime.UtcNow.AddMinutes(-1);
string path = GetExistingItem();
SetLastWriteTimeUtc(path, DateTime.UtcNow.AddMinutes(-30));
Assert.InRange(GetCreationTimeUtc(path), beforeCreationUtc, DateTime.UtcNow.AddMinutes(1));
}
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Addressed in bc6ce5f - documented in |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/File/GetSetTimes.cs:79
- This test is named "WhenAvailable" but it runs unconditionally on Linux. On file systems that don’t report
STATX_BTIME, CreationTime is synthesized from ctime/mtime, and after forcing mtime 30 minutes into the past this assertion will fail. Make the test aConditionalFactand skip when birth time isn’t actually reported by the underlying file system.
[Fact]
[PlatformSpecific(TestPlatforms.Linux)]
public void CreationTimeGet_ReturnsBirthTime_WhenAvailable()
{
// When the birth time is available, it is returned as the CreationTime,
src/native/libs/System.Native/pal_io.c:286
TryStatxFileStatuscurrently treats anystatxfailure as fatal. Ifstatxis blocked (e.g., by seccomp) or the requested flags aren’t accepted and the syscall fails withEPERM/EINVAL, we’ll return -1 and won’t fall back tostat(2)/fstat(2)/lstat(2), potentially breaking file operations that previously worked. Treat these errors as a soft failure and return 0 so the caller can fall back.
return -1;
adamsitnik
left a comment
There was a problem hiding this comment.
💡 Behavioral contract —
SetCreationTimeno longer round-trips on btime-capable Linux filesystemsWith btime now reported, Linux
File.SetCreationTime*still mutates mtime via the existing Unix fallback, butGetCreationTime*will return the real birth time instead of the mtime that was just written. That means the old Linux round-trip behavior disappears on btime-capable filesystems while the call still changesLastWriteTimeas a side effect.This may be an acceptable consequence of exposing the real birth time, especially since Linux has no general API for setting btime. I would still have a human reviewer explicitly confirm the desired behavior and whether docs/tests should acknowledge it.
@copilot what is going to happen when the user calls File.SetCreationTime* on Linux using file system that supports btime? Is the updateCreationTime going to be true:
runtime/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs
Lines 424 to 431 in eaf33d4
and then throw InvalidOperationException here:
We need to ensure that File.SetCreationTime* throws in such situations (and/or consider always throwing on Linux).
Short answer: no, nothing throws today — Why: on non-Apple Unix, private void SetAccessOrWriteTime(SafeFileHandle? handle, string? path, DateTimeOffset time, bool isAccessTime, bool asDirectory) =>
SetAccessOrWriteTimeCore(handle, path, time, isAccessTime, checkCreationTime: false, asDirectory);and So with this PR the observable Linux behavior is: On making it throw — I'd like your call before I implement it, because it's a behavioral break that reaches beyond this PR:
Both options need a breaking-change doc, and given the "one concern per PR" guidance it may be cleaner as a follow-up so this PR stays a pure statx change. Tell me which you want (and whether here or in a follow-up) and I'll do it. Note This comment was generated by GitHub Copilot. |
Pull request created by AI Agent
created to investigate what it would take to fix #131395 without updating minimum required libc version