Skip to content

fix(du): use getdents64 on Linux to avoid EOVERFLOW on 32-bit architectures#11902

Open
mattsu2020 wants to merge 6 commits intouutils:mainfrom
mattsu2020:du_fix
Open

fix(du): use getdents64 on Linux to avoid EOVERFLOW on 32-bit architectures#11902
mattsu2020 wants to merge 6 commits intouutils:mainfrom
mattsu2020:du_fix

Conversation

@mattsu2020
Copy link
Copy Markdown
Contributor

@mattsu2020 mattsu2020 commented Apr 19, 2026

Summary

  • Fix du producing "Value too large for defined data type" (EOVERFLOW) on 32-bit Linux (i686) when reading directories
  • Replace nix::dir::Dir (which calls libc::readdir() with 32-bit d_ino) with rustix::fs::RawDir (which calls getdents64 syscall with 64-bit d_ino/d_off) on Linux/Android
  • This also fixes all other utilities using DirFd::read_dir(): rm, chmod, chown, install

Root Cause

On 32-bit glibc, libc::readdir() uses struct dirent with 32-bit d_ino. Modern filesystems (XFS, Btrfs, ext4+inode64) can return inode numbers exceeding 2^32, causing EOVERFLOW.

Fix

Use rustix::fs::RawDir on Linux which calls the getdents64 syscall directly, always using 64-bit directory entry fields. rustix with fs feature is already an unconditional dependency of uucore, so no new dependencies are needed.

On non-Linux Unix (macOS, BSDs), the existing nix::dir::Dir implementation is retained.

Test

  • cargo check -p uucore passes
  • cargo check -p uu_du passes
  • cargo test -p uu_du — all tests pass
  • cargo test -p uu_rm — all tests pass
  • cargo test -p uu_chmod — all tests pass
  • cargo test -p coreutils -- du — all 112 du integration tests pass

Closes #11848

…ctures

On 32-bit Linux (i686), du fails with "Value too large for defined data
type" (EOVERFLOW) when reading directories. The root cause is nix::dir::Dir
calling libc::readdir(), which uses 32-bit d_ino on 32-bit glibc. Modern
filesystems can return inode numbers exceeding 32 bits.

Replace nix::dir::Dir with rustix::fs::RawDir on Linux, which calls
getdents64 syscall directly with 64-bit d_ino/d_off. This fixes du and
all other utilities using DirFd::read_dir() (rm, chmod, chown, install).

Closes uutils#11848
rustix::io::Errno implements From<Errno> for std::io::Error,
so use io::Error::from instead of the invalid `as i32` cast.
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 19, 2026

Merging this PR will improve performance by 40.59%

⚡ 6 improved benchmarks
✅ 293 untouched benchmarks
⏩ 56 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation du_all_wide_tree[(5000, 500)] 16.3 ms 15.1 ms +7.83%
Simulation du_deep_tree[(100, 3)] 1,085.5 µs 994.6 µs +9.13%
Simulation du_wide_tree[(5000, 500)] 9.3 ms 8.3 ms +12.07%
Simulation du_summarize_balanced_tree[(5, 4, 10)] 6.6 ms 5.4 ms +23.71%
Simulation du_max_depth_balanced_tree[(6, 4, 10)] 25.2 ms 20.3 ms +24.25%
Simulation rm_recursive_tree 11.9 ms 8.5 ms +40.59%

Comparing mattsu2020:du_fix (d4e3fe5) with main (0366d3c)

Open in CodSpeed

Footnotes

  1. 56 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 19, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tail/symlink (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cut/cut-huge-range is now passing!
Congrats! The gnu test tests/tail/pipe-f is now passing!

@oech3
Copy link
Copy Markdown
Contributor

oech3 commented Apr 19, 2026

Merging this PR will improve performance by 40.59%

What happened?

@oech3
Copy link
Copy Markdown
Contributor

oech3 commented Apr 19, 2026

Would you add comment why cannot we use rustix at other unix?
Is it able to request API to rustix's upstream?

@xtqqczze
Copy link
Copy Markdown
Contributor

⚡ Simulation rm_recursive_tree 11.9 ms 8.5 ms +40.59%

@oech3 The benchmark contains 46897 system calls in HEAD but 70335 system calls in BASE. Since system calls are not instrumented in CodSpeed, be careful interpreting this result.

@oech3
Copy link
Copy Markdown
Contributor

oech3 commented Apr 19, 2026

perf is near with mimalloc. Does mimalloc increase num of syscalls too by same reason with this?

@xtqqczze
Copy link
Copy Markdown
Contributor

perf is near with mimalloc. Does mimalloc increase num of syscalls too by same reason with this?

70334 system calls with mimalloc (#11866) so no change

@xtqqczze
Copy link
Copy Markdown
Contributor

@oech Could you run benchmarks with hyperfine?

// Helper function to read directory entries.
// On Linux, use rustix::fs::RawDir which calls getdents64 directly,
// avoiding EOVERFLOW on 32-bit architectures where libc readdir() uses
// 32-bit d_ino (Issue #11848).
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.

In general please use full URL instead of (Issue #11848). But since this PR will close that issue I think you could remove the reference.

Comment thread src/uucore/src/lib/features/safe_traversal.rs Outdated
mattsu2020 and others added 3 commits April 21, 2026 07:29
Co-authored-by: xtqqczze <45661989+xtqqczze@users.noreply.github.com>
Remove issue reference from comment explaining use of rustix::fs::RawDir on Linux.
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 21, 2026

Unable to generate the performance report

There was an internal error while processing the run's data. We're working on fixing the issue. Feel free to contact us on Discord or at support@codspeed.io if the issue persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

du: "Value too large for defined data type" for directories on 32-bit architectures (0.8.0 regression)

3 participants