Skip to content

df: round the total row once, from the summed bytes - #14522

Open
TanbirRamim wants to merge 2 commits into
uutils:mainfrom
TanbirRamim:df-total-round-once
Open

df: round the total row once, from the summed bytes#14522
TanbirRamim wants to merge 2 commits into
uutils:mainfrom
TanbirRamim:df-total-round-once

Conversation

@TanbirRamim

Copy link
Copy Markdown

df --total summed the block counts of the rows, each already rounded up to the block size, instead of rounding the summed bytes once like GNU df does. With -B 100G on my machine GNU reports a total of 19 blocks where the rows add up to 24; we printed 24. With a block size larger than every filesystem the total degenerates into a count of filesystems, and -h then multiplied that count back by the block size and overflowed (attempt to multiply with overflow, exit 134).

This goes back to keeping the raw byte counts in the rows and rounding at output time. #10438 had moved away from that so the total would match the sum of the displayed rows, but GNU does not do that either, so test_total now allows for the rounding difference.

Fixes #14459

The total row added up the block counts of the rows, each of which is
already rounded up to the block size, instead of rounding the summed bytes
once the way GNU df does. With a block size larger than the filesystems,
every non-empty row is one block, so the total became a count of
filesystems, and the human-readable output then multiplied that count
back by the block size and overflowed.

Keep the raw byte counts in the rows, sum those for the total row, and
round at output time like every other row.

Fixes uutils#14459
Copilot AI lite review requested due to automatic review settings September 12, 2026 20:53

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.

🟡 Changes recommended

Unresolved moderate findings remain in total formatting and regression-test assertions.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Updates df --total to sum raw bytes before rounding, matching GNU behavior and avoiding large-block-size overflow.

Changes:

  • Accumulates raw byte totals and rounds once at output.
  • Adds regression coverage for rounding and human-readable large block sizes.
  • Updates integration expectations for per-row rounding differences.
File summaries
File Summary
tests/by-util/test_df.rs Updates total assertions and adds regression coverage; exact-value, deterministic-filesystem, and versioned GNU-reference adjustments remain requested.
src/uu/df/src/table.rs Aggregates raw bytes and formats totals; explicit -B with -h still needs GNU-compatible precedence and output handling.
Review details

Suppressed comments (3)

src/uu/df/src/table.rs:270

  • When -h is combined with an explicit -B, this branch still formats the raw total as human-readable and ignores the requested block size. For the linked issue's reproducer GNU prints 1 block, while this remains an E-suffixed byte value; the new integration test only checks that it does not panic. Make the -B/-h precedence consistent with GNU and assert the resulting output.
        let s = if let Some(h) = self.options.human_readable {
            to_magnitude_and_suffix(bytes.into(), SuffixType::HumanReadable(h), true)
        } else {
            let BlockSize::Bytes(d) = self.options.block_size;
            bytes.div_ceil(d).to_string()

tests/by-util/test_df.rs:502

  • The regression test says the total should be one block, but <= 1 also accepts zero, so a broken or missing total accumulator could still pass. Assert the exact expected value.
    assert!(total <= 1, "total row reports {total} blocks");

tests/by-util/test_df.rs:490

  • This command sums every mounted filesystem, so a fixed 10-exabyte block size does not guarantee a one-block total: on a host whose included filesystems exceed 10 EB, correct output is 2 or more and this test fails. Restrict the command to a known filesystem (for example, append .) and assert the expected result, or use only the deterministic table fixture for this regression.
            "--block-size=10000000000000000000",
        ])
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/by-util/test_df.rs
Run them on the filesystem of the current directory only, so the one row
and the total are both exactly one block, and name the GNU version the
rounding was compared against.
Copilot AI review requested due to automatic review settings September 12, 2026 21:19

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.

🟡 Changes recommended

A critical total-formatting issue and a regression-test coverage gap remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

tests/by-util/test_df.rs:496

  • This test only invokes df for ., so it normally has one filesystem row. The removed BytesCell implementation would also print 1 for both that row and the total, meaning this assertion does not exercise rounding across rows. Use a deterministic multi-filesystem fixture (or make the command-level test assert a real multi-row case) so the regression can fail again.
    let values: Vec<&str> = output.lines().skip(1).map(str::trim).collect();
    assert_eq!(values, vec!["1", "1"]);
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/uu/df/src/table.rs
bytes_column.bytes
};
to_magnitude_and_suffix(size.into(), SuffixType::HumanReadable(h), true)
to_magnitude_and_suffix(bytes.into(), SuffixType::HumanReadable(h), true)
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/misc/io-errors (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/seq/seq-epipe is now passing!
Congrats! The gnu test tests/tail/pipe-f is now passing!
Note: The gnu test tests/env/env-signal-handler was skipped on 'main' but is now failing.

@codspeed-hq

codspeed-hq Bot commented Sep 12, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 3.66%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 366 untouched benchmarks
⏩ 50 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation du_all_wide_tree[(5000, 500)] 38.6 ms 37.2 ms +3.66%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing TanbirRamim:df-total-round-once (8ff66fb) with main (4bae306)2

Open in CodSpeed

Footnotes

  1. 50 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.

  2. No successful run was found on main (92076ab) during the generation of this report, so 4bae306 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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: the --total row sums per-filesystem rounded-up block counts — wrong totals in release, attempt to multiply with overflow with -h (exit 134)

2 participants