Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ tikv-jemallocator = { version = "0.6", default-features = false }
axum-extra = { version = "0.12", default-features = false }
papaya = { version = "0.2", default-features = false }
tempfile = { version = "3", default-features = false }
fs4 = { version = "0.13.1", default-features = false }
fs4 = { version = "1.0.0", default-features = false }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve quota-based disk limits on Windows

This upgrade resolves to fs4 1.1.0, whose Windows total_space now reports the full volume capacity while available_space remains caller/quota-scoped. The retry queue still combines those two values in lib/saluki-io/src/net/util/retry/queue/persisted.rs::on_disk_bytes_limit as available_space - total_space * (1 - storage_max_disk_ratio), so on quota-enabled Windows volumes (for example a 10 GB quota on a 1 TB disk with the default 80% ratio) the reserved amount is based on 1 TB and the limit saturates to 0, preventing persistence even though the user has quota space available. The dependency bump needs either pinning before that behavior change or adjusting the limit calculation to use comparable quota/volume values.

Useful? React with 👍 / 👎.

@tobz tobz Jun 11, 2026

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.

Looking at this locally, I agree that using fs4 1.10 (really, 1.0.1 and later) would very likely break things on Windows when quotas were in use. Just to drive it home, laying it all out in sort of a "if this, then that" way with tabular data:

A 1 TB volume, with the agent's data directory on it. I'll use the default storage_max_disk_ratio = 0.8 (so the queue reserves the bottom 20% of "total" as headroom). Two physical situations:

  • No quota: 512 GB actually free on the volume.
  • Per-user quota on the agent's account: limit 160 GB, 32 GB already used → 128 GB free to the caller (and still 512 GB free volume-wide).

Raw Windows values in each situation:

(quoted field names abbreviated to better fit in a PR comment)

FreeBytesAvailCaller TotalNumBytes TotalNumFreeBytes Volume Size
No quota 512 GB 1000 GB 512 GB 1000 GB
Quota 128 GB 160 GB (= quota limit) 512 GB 1000 GB

How it flows through on_disk_bytes_limit

We calculate the following values:

  • total = TotalNumBytes
  • available = FreeBytesAvailCaller
  • reserved = total * 0.2
  • available_adj = (available_space − reserved).ceil()
  • limit = min(max_on_disk_bytes, available_adj)
Case total available reserved available_adj limit
A. No quota, 0.13.1 1000 GB 512 GB 200 GB 312 GB 312 GB
B. No quota, 1.1.0 1000 GB 512 GB 200 GB 312 GB 312 GB
C. Quota, 0.13.1 160 GB 128 GB 32 GB 96 GB 96 GB
D. Quota, 1.1.0 1000 GB 128 GB 200 GB −72 GB 0

Two takeaways from the table:

  • No quota → no change. A vs. B are identical (312 GB). On a quota-free volume, TotalNumBytes already equals the full volume, so swapping it for cluster geometry changes nothing. This is why the bug is invisible on most Windows hosts and on all of Linux.
  • Quota → regression. C (96 GB, scales sensibly to the quota) becomes D (0). The breakage is that reserved is now computed off the 1 TB physical disk (200 GB) while available is the 128 GB quota free — the reservation alone is bigger than the caller's entire free quota, so the subtraction goes negative and clamps to 0.

Forgive the clanker output being pasted verbatim, but it did a reasonable job explaining this succinctly.

fnv = { version = "1", default-features = false }
twox-hash = { version = "2", features = ["xxhash64"] }
shake = { version = "0.1", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ float-cmp,https://github.com/mikedilger/float-cmp,MIT,Mike Dilger <mike@mikedilg
fnv,https://github.com/servo/rust-fnv,Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
foldhash,https://github.com/orlp/foldhash,Zlib,Orson Peters <orsonpeters@gmail.com>
form_urlencoded,https://github.com/servo/rust-url,MIT OR Apache-2.0,The rust-url developers
fs4,https://github.com/al8n/fs4-rs,MIT OR Apache-2.0,"Dan Burkert <dan@danburkert.com>, Al Liu <scygliu1@gmail.com>"
fs4,https://github.com/al8n/fs4,MIT OR Apache-2.0,"Dan Burkert <dan@danburkert.com>, Al Liu <scygliu1@gmail.com>"
futures,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures Authors
futures-channel,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-channel Authors
futures-core,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-core Authors
Expand Down
Loading