Compare commits

...

4 Commits

Author SHA1 Message Date
唐小鸭 f429676a3e chore(release): prepare 1.0.0-rc.3 2026-08-17 11:58:25 +08:00
Zhengchao An a9691b6797 chore: adjudicate 19 bare dead_code allows across six leaf crates (#6161)
backlog#1823 step 10, batch 1 of the repo-wide item-allow sweep. 227 bare #[allow(dead_code)] remain across 83 files; this takes the 19 in utils, notify, checksums, policy, keystone and trusted-proxies, which are small enough to verify end to end.

Removing all 19 first, before writing any reason, matters: 8 of them suppress nothing. Every allow in utils, one in policy and three in notify sit on items that are publicly reachable, so dead_code never applied to them — the same shape as the swift module and kms's dek.rs. Writing a reason onto a no-op allow would dress noise up as considered judgement, so those are simply deleted.

Three items are genuinely dead and go with their allows: notify's new_target_id_set, the AWS metadata fetcher's get_metadata_token, and policy's empty `pub struct Value;`, none of which is referenced anywhere in the tree.

The remaining eight keep an allow, now saying why the item survives rather than who calls it. Two are exercised only by their own crate's tests (checksums' MD5_HEADER_NAME, policy's is_match_as_pattern_prefix). Four are fields written but never read back: keystone's verify_ssl, parsed from config after the reqwest client is already built; keystone's client handle, which keeps the Keystone client alive for the mapper's lifetime; the AWS IMDS endpoint, kept beside the client while requests build their own URLs; and notify's rules_map, whose own comment retains it for snapshot-time judgements no code performs.

checksums' Md5 needed the most care. Crc32, Sha256 and seven others each have an arm in ChecksumAlgorithm::into_impl, and Md5 has none, which reads like a missing algorithm. It is not: ChecksumAlgorithm has no Md5 variant at all. S3 carries Content-MD5 as its own header, separate from the x-amz-checksum-* family, and this impl exists so both paths share the Checksum trait. The reason records that, so the next reader does not re-derive it.

One measurement note for anyone continuing this sweep: cargo does not re-emit warnings for cached compilations, so a per-crate loop of `cargo check -p <crate>` under-reports. checksums showed zero that way while actually carrying three. Touch the sources and check the crates in one invocation, then attribute by path.

Verification: the six crates are warning-free under cargo check --tests; clippy --lib --tests -D warnings clean; cargo nextest run 1096 passed; make pre-commit exit 0.

Ref rustfs/backlog#1823 (step 10).
2026-08-17 11:34:47 +08:00
Zhengchao An 7db3882777 chore(obs): adjudicate 19 bare dead_code allows (#6162)
backlog#1823 step 10, batch 2. Eighteen of the nineteen suppress nothing and are deleted; one was real and keeps an allow that now says why.

Rotation::Never is constructed only by the rolling-appender tests at rolling.rs:456, 477 and 498, so the lib target reports it as never constructed. Its allow is restored with that reason.

Finding it corrected the method used for batch 1. Removing all nineteen and running cargo check -p rustfs-obs --tests reported zero warnings even after touching every source file, while clippy --lib --tests -D warnings caught Rotation::Never. cargo's warning output is not a reliable completeness check — it does not re-emit for cached compilations, and touching the sources did not cover the lib target here. Later batches should treat clippy -D warnings as the gate; batch 1's six crates were re-checked under clippy and are clean.

Taken with #6086, which cleared this crate's 44 module-level blankets and left six real items, obs has now had 63 dead-code suppressions examined, of which seven were suppressing anything at all. The rest sat on items that are publicly reachable, where dead_code never applied — the same shape as the swift module and kms's dek.rs.

Verification: clippy --lib --tests -D warnings clean in the default, gpu and pyroscope lanes; cargo nextest run -p rustfs-obs 324 passed; make pre-commit exit 0.

Ref rustfs/backlog#1823 (step 10).
2026-08-17 11:32:23 +08:00
houseme 3f3e3f4f05 perf(get): avoid memory body stream wrapper (#6163)
Use MemoryTrackedBytesStream directly as an s3s ByteStream so in-memory GET bodies avoid the generic StreamingBlob::wrap adapter while preserving exact remaining length, request lifecycle tracking, and length-mismatch failure semantics.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-17 10:45:24 +08:00
33 changed files with 174 additions and 200 deletions
Generated
+47 -47
View File
@@ -3764,7 +3764,7 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "e2e_test"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"anyhow",
"astral-tokio-tar",
@@ -9093,7 +9093,7 @@ dependencies = [
[[package]]
name = "rustfs"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"aes-gcm",
"anyhow",
@@ -9231,7 +9231,7 @@ dependencies = [
[[package]]
name = "rustfs-audit"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"const-str",
@@ -9254,7 +9254,7 @@ dependencies = [
[[package]]
name = "rustfs-checksums"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"base64-simd",
"bytes",
@@ -9270,7 +9270,7 @@ dependencies = [
[[package]]
name = "rustfs-common"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"chrono",
"hotpath",
@@ -9288,7 +9288,7 @@ dependencies = [
[[package]]
name = "rustfs-concurrency"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"insta",
@@ -9301,7 +9301,7 @@ dependencies = [
[[package]]
name = "rustfs-config"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"const-str",
"hotpath",
@@ -9311,7 +9311,7 @@ dependencies = [
[[package]]
name = "rustfs-credentials"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"base64-simd",
"hmac 0.13.0",
@@ -9325,7 +9325,7 @@ dependencies = [
[[package]]
name = "rustfs-crypto"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"aes-gcm",
"argon2",
@@ -9346,7 +9346,7 @@ dependencies = [
[[package]]
name = "rustfs-data-usage"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"rmp-serde",
@@ -9356,7 +9356,7 @@ dependencies = [
[[package]]
name = "rustfs-ecstore"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"async-channel",
@@ -9495,7 +9495,7 @@ dependencies = [
[[package]]
name = "rustfs-extension-schema"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"serde",
@@ -9505,7 +9505,7 @@ dependencies = [
[[package]]
name = "rustfs-filemeta"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"byteorder",
@@ -9532,7 +9532,7 @@ dependencies = [
[[package]]
name = "rustfs-heal"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"base64 0.23.1",
@@ -9563,7 +9563,7 @@ dependencies = [
[[package]]
name = "rustfs-iam"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"async-trait",
@@ -9604,7 +9604,7 @@ dependencies = [
[[package]]
name = "rustfs-io-core"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"bytes",
"hotpath",
@@ -9617,7 +9617,7 @@ dependencies = [
[[package]]
name = "rustfs-io-metrics"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"criterion",
"hotpath",
@@ -9681,7 +9681,7 @@ dependencies = [
[[package]]
name = "rustfs-keystone"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"bytes",
"futures",
@@ -9708,7 +9708,7 @@ dependencies = [
[[package]]
name = "rustfs-kms"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"aes-gcm",
"anyhow",
@@ -9757,7 +9757,7 @@ dependencies = [
[[package]]
name = "rustfs-lifecycle"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"hotpath",
@@ -9780,7 +9780,7 @@ dependencies = [
[[package]]
name = "rustfs-lock"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"compact_str",
@@ -9803,7 +9803,7 @@ dependencies = [
[[package]]
name = "rustfs-log-analyzer"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"chrono",
"flate2",
@@ -9822,7 +9822,7 @@ dependencies = [
[[package]]
name = "rustfs-madmin"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"humantime",
@@ -9837,7 +9837,7 @@ dependencies = [
[[package]]
name = "rustfs-notify"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"async-trait",
@@ -9872,7 +9872,7 @@ dependencies = [
[[package]]
name = "rustfs-object-capacity"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"criterion",
"futures",
@@ -9892,7 +9892,7 @@ dependencies = [
[[package]]
name = "rustfs-object-data-cache"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"bytes",
"criterion",
@@ -9909,7 +9909,7 @@ dependencies = [
[[package]]
name = "rustfs-obs"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"chrono",
"crossbeam-channel",
@@ -9964,7 +9964,7 @@ dependencies = [
[[package]]
name = "rustfs-policy"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"base64-simd",
@@ -9995,7 +9995,7 @@ dependencies = [
[[package]]
name = "rustfs-protocols"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"astral-tokio-tar",
"async-compression",
@@ -10057,7 +10057,7 @@ dependencies = [
[[package]]
name = "rustfs-protos"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"flatbuffers",
"hotpath",
@@ -10081,7 +10081,7 @@ dependencies = [
[[package]]
name = "rustfs-replication"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"byteorder",
"bytes",
@@ -10099,7 +10099,7 @@ dependencies = [
[[package]]
name = "rustfs-rio"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"aes-gcm",
"arc-swap",
@@ -10137,7 +10137,7 @@ dependencies = [
[[package]]
name = "rustfs-rio-v2"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"aes-gcm",
"bytes",
@@ -10160,7 +10160,7 @@ dependencies = [
[[package]]
name = "rustfs-s3-ops"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"rustfs-s3-types",
@@ -10168,7 +10168,7 @@ dependencies = [
[[package]]
name = "rustfs-s3-types"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"serde",
@@ -10177,7 +10177,7 @@ dependencies = [
[[package]]
name = "rustfs-s3select-api"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"bytes",
@@ -10207,7 +10207,7 @@ dependencies = [
[[package]]
name = "rustfs-s3select-query"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-recursion",
"async-trait",
@@ -10226,7 +10226,7 @@ dependencies = [
[[package]]
name = "rustfs-scanner"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"bytes",
@@ -10266,7 +10266,7 @@ dependencies = [
[[package]]
name = "rustfs-security-governance"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"thiserror 2.0.20",
@@ -10274,7 +10274,7 @@ dependencies = [
[[package]]
name = "rustfs-signer"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"base64-simd",
"bytes",
@@ -10292,7 +10292,7 @@ dependencies = [
[[package]]
name = "rustfs-storage-api"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"hotpath",
@@ -10307,7 +10307,7 @@ dependencies = [
[[package]]
name = "rustfs-targets"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"async-nats",
@@ -10361,7 +10361,7 @@ dependencies = [
[[package]]
name = "rustfs-test-utils"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"hotpath",
"rustfs-data-usage",
@@ -10377,7 +10377,7 @@ dependencies = [
[[package]]
name = "rustfs-tls-runtime"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"arc-swap",
"hotpath",
@@ -10398,7 +10398,7 @@ dependencies = [
[[package]]
name = "rustfs-trusted-proxies"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"async-trait",
"axum",
@@ -10435,7 +10435,7 @@ dependencies = [
[[package]]
name = "rustfs-utils"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"base64-simd",
"blake2",
@@ -10477,7 +10477,7 @@ dependencies = [
[[package]]
name = "rustfs-zip"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"astral-tokio-tar",
"async-compression",
+47 -47
View File
@@ -69,7 +69,7 @@ edition = "2024"
license = "Apache-2.0"
repository = "https://github.com/rustfs/rustfs"
rust-version = "1.97.1"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
homepage = "https://rustfs.com"
description = "RustFS is a high-performance distributed object storage software built using Rust, one of the most popular languages worldwide. "
keywords = ["RustFS", "Minio", "object-storage", "filesystem", "s3"]
@@ -86,52 +86,52 @@ redundant_clone = "warn"
[workspace.dependencies]
# RustFS Internal Crates
rustfs = { path = "./rustfs", version = "1.0.0-rc.2" }
rustfs-heal = { path = "crates/heal", version = "1.0.0-rc.2" }
rustfs-audit = { path = "crates/audit", version = "1.0.0-rc.2" }
rustfs-checksums = { path = "crates/checksums", version = "1.0.0-rc.2" }
rustfs-common = { path = "crates/common", version = "1.0.0-rc.2" }
rustfs-data-usage = { path = "crates/data-usage", version = "1.0.0-rc.2" }
rustfs-config = { path = "./crates/config", version = "1.0.0-rc.2" }
rustfs-concurrency = { path = "./crates/concurrency", version = "1.0.0-rc.2" }
rustfs-credentials = { path = "crates/credentials", version = "1.0.0-rc.2" }
rustfs-crypto = { path = "crates/crypto", version = "1.0.0-rc.2" }
rustfs-ecstore = { path = "crates/ecstore", version = "1.0.0-rc.2" }
rustfs-filemeta = { path = "crates/filemeta", version = "1.0.0-rc.2" }
rustfs-iam = { path = "crates/iam", version = "1.0.0-rc.2" }
rustfs-keystone = { path = "crates/keystone", version = "1.0.0-rc.2" }
rustfs-lifecycle = { path = "crates/lifecycle", version = "1.0.0-rc.2" }
rustfs-kms = { path = "crates/kms", version = "1.0.0-rc.2" }
rustfs-lock = { path = "crates/lock", version = "1.0.0-rc.2" }
rustfs-madmin = { path = "crates/madmin", version = "1.0.0-rc.2" }
rustfs-notify = { path = "crates/notify", version = "1.0.0-rc.2" }
rustfs-io-metrics = { path = "crates/io-metrics", version = "1.0.0-rc.2" }
rustfs-io-core = { path = "crates/io-core", version = "1.0.0-rc.2" }
rustfs-object-capacity = { path = "crates/object-capacity", version = "1.0.0-rc.2" }
rustfs-object-data-cache = { path = "crates/object-data-cache", version = "1.0.0-rc.2", default-features = false }
rustfs-log-analyzer = { path = "crates/log-analyzer", version = "1.0.0-rc.2" }
rustfs-obs = { path = "crates/obs", version = "1.0.0-rc.2" }
rustfs-policy = { path = "crates/policy", version = "1.0.0-rc.2" }
rustfs-protos = { path = "crates/protos", version = "1.0.0-rc.2" }
rustfs-protocols = { path = "crates/protocols", version = "1.0.0-rc.2" }
rustfs-replication = { path = "crates/replication", version = "1.0.0-rc.2" }
rustfs-rio = { path = "crates/rio", version = "1.0.0-rc.2" }
rustfs-rio-v2 = { path = "crates/rio-v2", version = "1.0.0-rc.2" }
rustfs-s3-types = { path = "crates/s3-types", version = "1.0.0-rc.2" }
rustfs-s3-ops = { path = "crates/s3-ops", version = "1.0.0-rc.2" }
rustfs-s3select-api = { path = "crates/s3select-api", version = "1.0.0-rc.2" }
rustfs-s3select-query = { path = "crates/s3select-query", version = "1.0.0-rc.2" }
rustfs-scanner = { path = "crates/scanner", version = "1.0.0-rc.2" }
rustfs-security-governance = { path = "crates/security-governance", version = "1.0.0-rc.2" }
rustfs-extension-schema = { path = "crates/extension-schema", version = "1.0.0-rc.2" }
rustfs-signer = { path = "crates/signer", version = "1.0.0-rc.2" }
rustfs-storage-api = { path = "crates/storage-api", version = "1.0.0-rc.2" }
rustfs-trusted-proxies = { path = "crates/trusted-proxies", version = "1.0.0-rc.2" }
rustfs-targets = { path = "crates/targets", version = "1.0.0-rc.2" }
rustfs-test-utils = { path = "crates/test-utils", version = "1.0.0-rc.2" }
rustfs-tls-runtime = { path = "crates/tls-runtime", version = "1.0.0-rc.2" }
rustfs-utils = { path = "crates/utils", version = "1.0.0-rc.2" }
rustfs-zip = { path = "./crates/zip", version = "1.0.0-rc.2" }
rustfs = { path = "./rustfs", version = "1.0.0-rc.3" }
rustfs-heal = { path = "crates/heal", version = "1.0.0-rc.3" }
rustfs-audit = { path = "crates/audit", version = "1.0.0-rc.3" }
rustfs-checksums = { path = "crates/checksums", version = "1.0.0-rc.3" }
rustfs-common = { path = "crates/common", version = "1.0.0-rc.3" }
rustfs-data-usage = { path = "crates/data-usage", version = "1.0.0-rc.3" }
rustfs-config = { path = "./crates/config", version = "1.0.0-rc.3" }
rustfs-concurrency = { path = "./crates/concurrency", version = "1.0.0-rc.3" }
rustfs-credentials = { path = "crates/credentials", version = "1.0.0-rc.3" }
rustfs-crypto = { path = "crates/crypto", version = "1.0.0-rc.3" }
rustfs-ecstore = { path = "crates/ecstore", version = "1.0.0-rc.3" }
rustfs-filemeta = { path = "crates/filemeta", version = "1.0.0-rc.3" }
rustfs-iam = { path = "crates/iam", version = "1.0.0-rc.3" }
rustfs-keystone = { path = "crates/keystone", version = "1.0.0-rc.3" }
rustfs-lifecycle = { path = "crates/lifecycle", version = "1.0.0-rc.3" }
rustfs-kms = { path = "crates/kms", version = "1.0.0-rc.3" }
rustfs-lock = { path = "crates/lock", version = "1.0.0-rc.3" }
rustfs-madmin = { path = "crates/madmin", version = "1.0.0-rc.3" }
rustfs-notify = { path = "crates/notify", version = "1.0.0-rc.3" }
rustfs-io-metrics = { path = "crates/io-metrics", version = "1.0.0-rc.3" }
rustfs-io-core = { path = "crates/io-core", version = "1.0.0-rc.3" }
rustfs-object-capacity = { path = "crates/object-capacity", version = "1.0.0-rc.3" }
rustfs-object-data-cache = { path = "crates/object-data-cache", version = "1.0.0-rc.3", default-features = false }
rustfs-log-analyzer = { path = "crates/log-analyzer", version = "1.0.0-rc.3" }
rustfs-obs = { path = "crates/obs", version = "1.0.0-rc.3" }
rustfs-policy = { path = "crates/policy", version = "1.0.0-rc.3" }
rustfs-protos = { path = "crates/protos", version = "1.0.0-rc.3" }
rustfs-protocols = { path = "crates/protocols", version = "1.0.0-rc.3" }
rustfs-replication = { path = "crates/replication", version = "1.0.0-rc.3" }
rustfs-rio = { path = "crates/rio", version = "1.0.0-rc.3" }
rustfs-rio-v2 = { path = "crates/rio-v2", version = "1.0.0-rc.3" }
rustfs-s3-types = { path = "crates/s3-types", version = "1.0.0-rc.3" }
rustfs-s3-ops = { path = "crates/s3-ops", version = "1.0.0-rc.3" }
rustfs-s3select-api = { path = "crates/s3select-api", version = "1.0.0-rc.3" }
rustfs-s3select-query = { path = "crates/s3select-query", version = "1.0.0-rc.3" }
rustfs-scanner = { path = "crates/scanner", version = "1.0.0-rc.3" }
rustfs-security-governance = { path = "crates/security-governance", version = "1.0.0-rc.3" }
rustfs-extension-schema = { path = "crates/extension-schema", version = "1.0.0-rc.3" }
rustfs-signer = { path = "crates/signer", version = "1.0.0-rc.3" }
rustfs-storage-api = { path = "crates/storage-api", version = "1.0.0-rc.3" }
rustfs-trusted-proxies = { path = "crates/trusted-proxies", version = "1.0.0-rc.3" }
rustfs-targets = { path = "crates/targets", version = "1.0.0-rc.3" }
rustfs-test-utils = { path = "crates/test-utils", version = "1.0.0-rc.3" }
rustfs-tls-runtime = { path = "crates/tls-runtime", version = "1.0.0-rc.3" }
rustfs-utils = { path = "crates/utils", version = "1.0.0-rc.3" }
rustfs-zip = { path = "./crates/zip", version = "1.0.0-rc.3" }
# Async Runtime and Networking
async-channel = "2.5.0"
+1 -1
View File
@@ -116,7 +116,7 @@ chown -R 10001:10001 data logs
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:latest
# Using specific version
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:1.0.0-rc.2
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:1.0.0-rc.3
```
If you use [podman](https://github.com/containers/podman) instead of docker, you can install the RustFS with the below command
+1 -1
View File
@@ -113,7 +113,7 @@ chown -R 10001:10001 data logs
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:latest
# 使用指定版本运行
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:1.0.0-rc.2
docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:1.0.0-rc.3
```
如果您通过绑定挂载启用 TLS 证书目录,也请用同样方式准备该目录:
+4 -1
View File
@@ -38,7 +38,10 @@ pub const XXHASH_3_HEADER_NAME: &str = "x-amz-checksum-xxhash3";
pub const XXHASH_64_HEADER_NAME: &str = "x-amz-checksum-xxhash64";
pub const XXHASH_128_HEADER_NAME: &str = "x-amz-checksum-xxhash128";
#[allow(dead_code)]
#[allow(
dead_code,
reason = "Content-MD5 wire name, resolved by header_name() below and asserted by this crate's tests (backlog#1823)"
)]
pub(crate) static MD5_HEADER_NAME: &str = "content-md5";
pub const CHECKSUM_ALGORITHMS_IN_PRIORITY_ORDER: [&str; 5] =
+8 -2
View File
@@ -476,13 +476,19 @@ impl Checksum for Xxhash64 {
}
}
#[allow(dead_code)]
#[derive(Debug, Default)]
#[allow(
dead_code,
reason = "Content-MD5 is not a ChecksumAlgorithm variant and has no arm in into_impl: S3 carries it as its own header, separate from the x-amz-checksum-* family. This impl exists so the two paths share the Checksum trait, and is asserted by this crate's tests (backlog#1823)"
)]
struct Md5 {
hasher: md5::Md5,
}
#[allow(dead_code)]
#[allow(
dead_code,
reason = "Content-MD5 is not a ChecksumAlgorithm variant and has no arm in into_impl: S3 carries it as its own header, separate from the x-amz-checksum-* family. This impl exists so the two paths share the Checksum trait, and is asserted by this crate's tests (backlog#1823)"
)]
impl Md5 {
fn update(&mut self, bytes: &[u8]) {
use md5::Digest;
+4 -1
View File
@@ -31,7 +31,10 @@ pub struct KeystoneClient {
admin_password: Option<String>,
admin_project: Option<String>,
admin_domain: String,
#[allow(dead_code)]
#[allow(
dead_code,
reason = "TLS verification flag parsed from config; the reqwest client is built before it is consulted, so nothing reads it back (backlog#1823)"
)]
verify_ssl: bool,
/// Request timeout applied to the underlying HTTP client.
timeout: std::time::Duration,
+4 -1
View File
@@ -20,7 +20,10 @@ use tracing::{debug, info};
/// Maps Keystone identities to RustFS concepts
pub struct KeystoneIdentityMapper {
#[allow(dead_code)]
#[allow(
dead_code,
reason = "keeps the Keystone client alive for the mapper's lifetime; the mapping paths do not call through it yet (backlog#1823)"
)]
client: Arc<KeystoneClient>,
role_policy_map: HashMap<String, String>,
enable_tenant_prefix: bool,
+4 -1
View File
@@ -40,7 +40,10 @@ impl RuleEvents for RuleView {
#[derive(Debug)]
struct CompiledRules {
// Keep RulesMap (can be used later if you want to make more complex judgments during the snapshot reading phase)
#[allow(dead_code)]
#[allow(
dead_code,
reason = "speculative retention: the comment above keeps it for richer snapshot-time judgements that no code performs yet (backlog#1823)"
)]
rules_map: RulesMap,
// for RulesContainer::iter_rules
rule_views: Vec<RuleView>,
-3
View File
@@ -187,7 +187,6 @@ impl RulesMap {
/// # Parameters
/// * `event_name` - The EventName from which to remove the rule.
/// * `pattern` - The pattern of the rule to be removed.
#[allow(dead_code)]
pub fn remove_rule(&mut self, event_name: &EventName, pattern: &str) {
let mut remove_event = false;
@@ -209,7 +208,6 @@ impl RulesMap {
///
/// # Parameters
/// * `event_names` - A slice of EventNames to be removed.
#[allow(dead_code)]
pub fn remove_rules(&mut self, event_names: &[EventName]) {
for event_name in event_names {
self.map.remove(event_name);
@@ -223,7 +221,6 @@ impl RulesMap {
/// * `event_name` - The EventName to update.
/// * `pattern` - The pattern of the rule to be updated.
/// * `target_id` - The TargetID to be added.
#[allow(dead_code)]
pub fn update_rule(&mut self, event_name: EventName, pattern: String, target_id: TargetID) {
self.map.entry(event_name).or_default().add(pattern, target_id);
self.total_events_mask |= event_name.mask(); // Update only the relevant bitmask
-6
View File
@@ -18,12 +18,6 @@ use rustfs_targets::arn::TargetID;
/// TargetIDSet - A collection representation of TargetID.
pub type TargetIdSet = HashSet<TargetID>;
/// Provides a Go-like method for TargetIdSet (can be implemented as trait if needed)
#[allow(dead_code)]
pub(crate) fn new_target_id_set(target_ids: Vec<TargetID>) -> TargetIdSet {
target_ids.into_iter().collect()
}
// HashSet has built-in clone, union, difference and other operations.
// But the Go version of the method returns a new Set, and the HashSet method is usually iterator or modify itself.
// If you need to exactly match Go's API style, you can add wrapper functions.
-1
View File
@@ -17,7 +17,6 @@ use std::time::Duration;
/// Environment variable key for the global default metrics interval (seconds).
pub const ENV_DEFAULT_METRICS_INTERVAL: &str = "RUSTFS_METRICS_DEFAULT_INTERVAL_SEC";
/// Default interval for metrics collection if not specified otherwise.
#[allow(dead_code)]
pub const DEFAULT_METRICS_INTERVAL: Duration = Duration::from_secs(60);
/// Environment variable key for cluster metrics interval (seconds).
-3
View File
@@ -145,21 +145,18 @@ impl PrometheusMetric {
}
#[inline]
#[allow(dead_code)]
pub fn with_label(mut self, key: &'static str, value: impl Into<Cow<'static, str>>) -> Self {
self.labels.push((key, value.into()));
self
}
#[inline]
#[allow(dead_code)]
pub fn with_label_owned(mut self, key: &'static str, value: String) -> Self {
self.labels.push((key, Cow::Owned(value)));
self
}
#[inline]
#[allow(dead_code)]
pub fn with_labels(mut self, labels: Vec<(&'static str, Cow<'static, str>)>) -> Self {
self.labels = labels;
self
@@ -16,7 +16,6 @@ use crate::{MetricName, MetricNamespace, MetricSubsystem, MetricType};
use std::collections::HashSet;
/// MetricDescriptor - Metric descriptors
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MetricDescriptor {
pub name: MetricName,
@@ -52,7 +51,6 @@ impl MetricDescriptor {
}
/// Get the full metric name in Prometheus style: <namespace>_<subsystem>_<name>
#[allow(dead_code)]
pub fn get_full_metric_name(&self) -> String {
let namespace = self.namespace.as_str();
let formatted_subsystem = self.subsystem.as_str();
@@ -61,7 +59,6 @@ impl MetricDescriptor {
}
/// check whether the label is in the label set
#[allow(dead_code)]
pub fn has_label(&mut self, label: &str) -> bool {
self.get_label_set().contains(label)
}
@@ -13,7 +13,6 @@
// limitations under the License.
/// The metric name is the individual name of the metric
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MetricName {
// The generic metric name
@@ -443,7 +442,6 @@ pub enum MetricName {
}
impl MetricName {
#[allow(dead_code)]
pub fn as_str(&self) -> String {
match self {
Self::AuthTotal => "auth_total".to_string(),
@@ -13,7 +13,6 @@
// limitations under the License.
/// MetricType - Indicates the type of indicator
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MetricType {
Counter,
@@ -23,7 +22,6 @@ pub enum MetricType {
impl MetricType {
/// convert the metric type to a string representation
#[allow(dead_code)]
pub fn as_str(&self) -> &'static str {
match self {
Self::Counter => "counter",
@@ -34,7 +32,6 @@ impl MetricType {
/// Convert the metric type to the Prometheus value type
/// In a Rust implementation, this might return the corresponding Prometheus Rust client type
#[allow(dead_code)]
pub fn as_prom(&self) -> &'static str {
match self {
Self::Counter => "counter.",
@@ -56,7 +56,6 @@ pub fn new_gauge_md(
}
/// create a new histogram indicator descriptor
#[allow(dead_code)]
pub fn new_histogram_md(
name: impl Into<MetricName>,
help: impl Into<String>,
@@ -19,7 +19,6 @@ pub enum MetricNamespace {
}
impl MetricNamespace {
#[allow(dead_code)]
pub fn as_str(&self) -> &'static str {
match self {
Self::RustFS => "rustfs",
@@ -14,7 +14,6 @@
/// Format the path to the metric name format
/// Replace '/' and '-' with '_'
#[allow(dead_code)]
pub fn format_path_to_metric_name(path: &str) -> String {
path.trim_start_matches('/').replace(['/', '-'], "_")
}
@@ -102,7 +102,6 @@ impl MetricSubsystem {
}
/// Get the formatted metric name format string
#[allow(dead_code)]
pub fn as_str(&self) -> String {
format_path_to_metric_name(self.path())
}
@@ -151,7 +150,6 @@ impl MetricSubsystem {
}
/// A convenient way to create custom subsystems directly
#[allow(dead_code)]
pub fn new(path: impl Into<String>) -> Self {
Self::Custom(path.into())
}
@@ -176,7 +174,6 @@ impl std::fmt::Display for MetricSubsystem {
}
}
#[allow(dead_code)]
pub mod subsystems {
use super::MetricSubsystem;
+4 -1
View File
@@ -38,7 +38,10 @@ pub enum Rotation {
Minutely,
Hourly,
Daily,
#[allow(dead_code)]
#[allow(
dead_code,
reason = "constructed only by this file's rolling-appender tests; the lib target cannot see them (backlog#1823)"
)]
Never,
}
-4
View File
@@ -219,10 +219,6 @@ impl PartialEq for Functions {
}
}
#[derive(Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct Value;
#[cfg(test)]
mod tests {
use crate::policy::Functions;
+4 -2
View File
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[allow(dead_code)]
pub fn is_simple_match<P, N>(pattern: P, name: N) -> bool
where
P: AsRef<str>,
@@ -29,7 +28,10 @@ where
inner_match(pattern, name, false)
}
#[allow(dead_code)]
#[allow(
dead_code,
reason = "prefix-matcher asserted by this file's tests; no production caller yet (backlog#1823)"
)]
pub fn is_match_as_pattern_prefix<P, N>(pattern: P, text: N) -> bool
where
P: AsRef<str>,
@@ -27,6 +27,10 @@ use crate::CloudMetadataFetcher;
#[derive(Debug, Clone)]
pub struct AwsMetadataFetcher {
client: Client,
#[allow(
dead_code,
reason = "IMDS endpoint retained beside the client it configures; requests build their own URLs (backlog#1823)"
)]
metadata_endpoint: String,
}
@@ -46,55 +50,6 @@ impl AwsMetadataFetcher {
metadata_endpoint: "http://169.254.169.254".to_string(),
}
}
/// Retrieves an IMDSv2 token for secure metadata access.
#[allow(dead_code)]
async fn get_metadata_token(&self) -> Result<String, AppError> {
let url = format!("{}/latest/api/token", self.metadata_endpoint);
match self
.client
.put(&url)
.header("X-aws-ec2-metadata-token-ttl-seconds", "21600")
.send()
.await
{
Ok(response) => {
if response.status().is_success() {
let token = response
.text()
.await
.map_err(|e| AppError::cloud(format!("Failed to read IMDSv2 token: {}", e)))?;
Ok(token)
} else {
debug!(
event = "trusted_proxies.cloud_metadata",
component = "trusted_proxies",
subsystem = "aws_metadata",
provider = "aws",
operation = "imdsv2_token",
result = "http_error",
status = %response.status(),
"trusted proxy cloud metadata request failed"
);
Err(AppError::cloud("Failed to obtain IMDSv2 token"))
}
}
Err(e) => {
debug!(
event = "trusted_proxies.cloud_metadata",
component = "trusted_proxies",
subsystem = "aws_metadata",
provider = "aws",
operation = "imdsv2_token",
result = "request_failed",
error = %e,
"trusted proxy cloud metadata request failed"
);
Err(AppError::cloud(format!("IMDSv2 request failed: {}", e)))
}
}
}
}
#[async_trait]
-1
View File
@@ -68,7 +68,6 @@ pub fn is_env_set(key: &str) -> bool {
}
/// Returns a list of all proxy-related environment variables and their current values.
#[allow(dead_code)]
pub fn get_all_proxy_env_vars() -> Vec<(String, String)> {
let vars = [
ENV_TRUSTED_PROXY_ENABLED,
-1
View File
@@ -68,7 +68,6 @@ pub async fn read_full_or_eof<R: AsyncRead + Send + Sync + Unpin>(
/// Read exactly buf.len() bytes into buf, or return an error if EOF is reached before any bytes are read.
/// Like Go's io.ReadFull.
#[allow(dead_code)]
pub async fn read_full<R: AsyncRead + Send + Sync + Unpin>(reader: R, buf: &mut [u8]) -> std::io::Result<usize> {
match read_full_or_eof(reader, buf).await? {
Some(n) => Ok(n),
-1
View File
@@ -431,7 +431,6 @@ pub fn parse_and_resolve_address(addr_str: &str) -> std::io::Result<SocketAddr>
Ok(resolved_addr)
}
#[allow(dead_code)]
pub fn bytes_stream<S, E>(stream: S, content_length: usize) -> impl Stream<Item = Result<Bytes, E>> + Send + 'static
where
S: Stream<Item = Result<Bytes, E>> + Send + 'static,
-1
View File
@@ -16,7 +16,6 @@
///
/// The table follows Linux `include/uapi/linux/magic.h`; filesystem magic
/// values without a stable Linux uapi source stay `UNKNOWN`.
#[allow(dead_code)]
pub(crate) fn get_fs_type(fs_type: u64) -> &'static str {
// Magic numbers for various filesystems.
match fs_type {
-1
View File
@@ -70,7 +70,6 @@ pub fn is_dir_object(object: &str) -> bool {
///
/// If the object name ends with `GLOBAL_DIR_SUFFIX`, it is replaced with a slash.
/// Otherwise, the name is returned as is.
#[allow(dead_code)]
pub fn decode_dir_object(object: &str) -> String {
if has_suffix(object, GLOBAL_DIR_SUFFIX) {
format!("{}{}", object.trim_end_matches(GLOBAL_DIR_SUFFIX), SLASH_SEPARATOR)
+1 -1
View File
@@ -59,7 +59,7 @@
{
default = rustPlatform.buildRustPackage {
pname = "rustfs";
version = "1.0.0-rc.2";
version = "1.0.0-rc.3";
src = ./.;
+2 -2
View File
@@ -2,8 +2,8 @@ apiVersion: v2
name: rustfs
description: RustFS helm chart to deploy RustFS on kubernetes cluster.
type: application
version: "1.0.0-rc.2"
appVersion: "1.0.0-rc.2"
version: "1.0.0-rc.3"
appVersion: "1.0.0-rc.3"
home: https://rustfs.com
icon: https://media.sys.truenas.net/apps/rustfs/icons/icon.svg
maintainers:
+5 -2
View File
@@ -1,9 +1,9 @@
%global _enable_debug_packages 0
%global _empty_manifest_terminate_build 0
%global prerelease rc.2
%global prerelease rc.3
Name: rustfs
Version: 1.0.0
Release: rc.2
Release: rc.3
Summary: High-performance distributed object storage for MinIO alternative
License: Apache-2.0
@@ -58,6 +58,9 @@ install %_builddir/%{name}-%{version}-%{prerelease}/target/%_arch/%_arch-unknown
%_bindir/rustfs
%changelog
* Mon Aug 17 2026 唐小鸭 <tangtang1251@qq.com>
- Update RPM package to RustFS 1.0.0-rc.3
* Fri Aug 14 2026 overtrue <anzhengchao@gmail.com>
- Update RPM package to RustFS 1.0.0-rc.2
+34 -5
View File
@@ -1074,7 +1074,7 @@ where
}
impl futures::Stream for MemoryTrackedBytesStream {
type Item = std::io::Result<Bytes>;
type Item = Result<Bytes, S3StdError>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
@@ -1105,7 +1105,8 @@ impl futures::Stream for MemoryTrackedBytesStream {
return Poll::Ready(Some(Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("materialized GET body length mismatch: expected {}, got {}", this.expected, actual),
))));
)
.into())));
}
let Some(bytes) = this.bytes.take() else {
@@ -1132,6 +1133,16 @@ impl futures::Stream for MemoryTrackedBytesStream {
}
}
impl ByteStream for MemoryTrackedBytesStream {
fn remaining_length(&self) -> RemainingLength {
if self.emitted || self.bytes.is_none() {
RemainingLength::new_exact(0)
} else {
RemainingLength::new_exact(self.expected)
}
}
}
impl Drop for MemoryTrackedBytesStream {
fn drop(&mut self) {
if self.lifecycle.is_finished() {
@@ -4149,7 +4160,7 @@ impl DefaultObjectUsecase {
let bytes_len = bytes.len();
let guard = rustfs_io_metrics::track_get_object_buffered_bytes(bytes_len);
let remaining = usize::try_from(response_content_length.max(0)).unwrap_or(usize::MAX);
let blob = StreamingBlob::wrap(MemoryTrackedBytesStream::new(bytes, remaining, source, guard, lifecycle));
let blob = StreamingBlob::new(MemoryTrackedBytesStream::new(bytes, remaining, source, guard, lifecycle));
if let Some(handoff_start) = handoff_start {
rustfs_io_metrics::record_get_object_response_handoff(
"single_chunk",
@@ -12882,7 +12893,10 @@ mod tests {
.await
.expect("mismatched memory body must yield an item")
.expect_err("a short memory body must fail the stream instead of serving a truncated body");
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
assert_eq!(
err.downcast_ref::<std::io::Error>().map(std::io::Error::kind),
Some(std::io::ErrorKind::InvalidData)
);
assert!(stream.next().await.is_none(), "stream must terminate after the error");
}
@@ -12901,7 +12915,22 @@ mod tests {
.await
.expect("mismatched memory body must yield an item")
.expect_err("an over-long memory body must fail the stream instead of serving mismatched bytes");
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
assert_eq!(
err.downcast_ref::<std::io::Error>().map(std::io::Error::kind),
Some(std::io::ErrorKind::InvalidData)
);
}
#[test]
fn memory_blob_preserves_exact_remaining_length() {
let blob = DefaultObjectUsecase::build_memory_bytes_blob(
Bytes::from_static(b"hello"),
5,
GET_MEMORY_BODY_SOURCE_BUFFERED_BODY,
GetObjectBodyLifecycle::disabled(),
);
assert_eq!(blob.remaining_length().exact(), Some(5));
}
#[tokio::test]