Skip to content

df: report an over-mounted device instead of falling back to statfs - #15977

Merged
sylvestre merged 2 commits into
uutils:mainfrom
montezuma-p:df-overmounted-error
Nov 4, 2026
Merged

sylvestre merged 2 commits into
uutils:mainfrom
montezuma-p:df-overmounted-error

Conversation

@montezuma-p

Copy link
Copy Markdown
Contributor

df DEVICE printed the row of the file system holding the device node (usually /dev) and exited 0 when the device's mount point was over-mounted, or when that mount point could not be statfs'd. The statfs fallback added for a mount table with no entry covering the path ran on every error of the lookup, including FsError::OverMounted.

This moves the decision into Filesystem::from_path(), the only place that can tell "no entry covers the path" from an error about the mount that was found, and lets the latter reach the caller as it did in 0.10.0. Three unit tests with a synthetic mount table cover the over-mounted case, the unreachable mount point, and the fallback still working when nothing covers the path.

Fixes #15799

Copilot AI balanced review requested due to automatic review settings October 29, 2026 15:34

Copilot AI 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.

🟢 Approval recommended

No active review issues were identified for the change restricting df’s statfs fallback to operands without a matching mount-table entry.

No open issues 🎉

What changed in this PR

Fixes #15799 by restricting df’s statfs fallback to cases where no mount-table entry covers the operand, preserving errors for over-mounted devices and inaccessible mount points.

Changes:

  • Moves the fallback decision into Filesystem::from_path().
  • Removes the Unix caller’s catch-all fallback.
  • Adds three unit tests covering over-mount errors, mount-point statfs failures, and successful fallback.
File Description
src/​uu/​df/​src/​platform/​unix.rs Removes catch-all fallback, exposes the fallback helper, and adds regression tests.
src/​uu/​df/​src/​filesystem.rs Limits fallback to missing mount entries and documents error propagation.

Review effort: Balanced

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/df/over-mount-device is no longer failing!

Comment thread src/uu/df/src/platform/unix.rs Outdated

assert_eq!(
filesystem_for_path(&mounts, false, "/dev/null").unwrap_err(),
FsError::MountMissing

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.

exit 1 now, good, but the user gets "no file systems processed" here while GNU says "Permission denied" on the mount point
maybe keep the io error for a follow-up?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in this PR (8c44d93): when statfs fails on the mount point, df now reports it like GNU, e.g. df: /mnt: Permission denied, and still exits 1.

@montezuma-p
montezuma-p requested review from sylvestre and a balanced review from Copilot November 3, 2026 22:59
`df DEVICE` printed the row of the file system holding the device node
(usually `/dev`) and exited 0 when the device's mount point was
over-mounted, or when its mount point could not be statfs'd. The statfs
fallback in `filesystem_for_path()` ran on every error of the mount
table lookup, not only when no entry covered the operand.

Move the decision into `Filesystem::from_path()`, the one place that can
tell "no entry covers the path" from an error about the mount that was
found, and let the latter reach the caller as before.

Fixes uutils#15799
Like GNU, print the statfs error for the mount point, e.g.
"Permission denied", instead of "no file systems processed".
@sylvestre
sylvestre force-pushed the df-overmounted-error branch from 8c44d93 to 47b7daf Compare November 3, 2026 23:05

Copilot AI 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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

4 open issues

Review effort: Lite

Comment on lines +154 to +160
match mount_info_from_path(mounts, &path, canonicalize) {
Ok(mount_info) => platform::filesystem_from_mount(mounts, mount_info, Some(file)),
// Only an empty lookup may fall back to `statfs`: an error about
// the mount that was found is the answer for `path`.
Err(FsError::MountMissing) => platform::from_path_direct_with_mounts(mounts, path),
Err(e) => Err(e),
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Filesystem::from_path() is #[cfg(unix)], as is FsError::StatFailed, so Windows never compiles this arm or references from_path_direct_with_mounts.

Comment on lines +49 to +54
/// `statfs` failed on the mount point at `path` with `error`.
#[cfg(not(windows))]
StatFailed {
path: OsString,
error: String,
},
Comment on lines +133 to +136
/// longest mount directory is returned. If no element of `mounts`
/// covers `path`, the filesystem is looked up through `statfs`
/// instead. An error about the mount that was found, such as
/// [`FsError::OverMounted`], is returned as is.

assert!(matches!(
filesystem_for_path(&mounts, false, "/dev/null").unwrap_err(),
FsError::StatFailed { path, .. } if path == "/non-existent-dir"
Copilot AI balanced review requested due to automatic review settings November 3, 2026 23:17

Copilot AI 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.

Comment on lines +26 to 33
/// The path `statfs` is called on to query the filesystem at `mount_info`.
fn stat_path(mount_info: &MountInfo) -> &OsStr {
if mount_info.mount_dir.is_empty() {
mount_info.dev_name.as_ref()
} else {
mount_info.mount_dir.as_os_str()
};
Some(FsUsage::new(statfs(stat_path).ok()?))
}
}

assert!(matches!(
filesystem_for_path(&mounts, false, "/dev/null").unwrap_err(),
FsError::StatFailed { path, .. } if path == "/non-existent-dir"
@sylvestre
sylvestre merged commit 56cb9ea into uutils:main Nov 4, 2026
99 checks passed
@sylvestre

Copy link
Copy Markdown
Contributor

Thanks for your PR

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.

df: statfs fallback swallows over-mounted device error, prints wrong row

3 participants