Commit Graph

5734 Commits

Author SHA1 Message Date
houseme 5a5a759176 Merge branch 'main' into fix/b5-t6-a4-metadata-lww 2026-08-23 12:29:23 +08:00
Zhengchao An b6ba89d9e4 docs(testing): document CI gate matrix (#6412) 2026-08-23 12:09:06 +08:00
houseme 648d5166e2 feat(allocator): replace mimalloc/libmimalloc-sys with rustfs-mimalloc/rustfs-mimalloc-sys (#6404)
Replace the upstream xonatius/mimalloc_rust.git fork (mimalloc + libmimalloc-sys)
with the published rustfs-mimalloc (v0.5.0) and rustfs-mimalloc-sys (v0.5.0) crates
from crates.io.

The new crates are based on mimalloc V3 (v3.5.0) and provide:
- MiMalloc global allocator with safe API (collect, stats_json, process_info)
- Heap management and arena operations (heap module)
- Full FFI bindings to mimalloc V3

Changes:
- Workspace deps: mimalloc + libmimalloc-sys (git) → rustfs-mimalloc + rustfs-mimalloc-sys (crates.io)
- allocator_reclaim.rs: libmimalloc_sys::mi_collect → rustfs_mimalloc::MiMalloc::collect
- memory_observability.rs: raw FFI mi_stats_get_json → MiMalloc::stats_json()
- main.rs: heap ownership tests use Heap::contains() (V3 API)
- deny.toml: remove xonatius/mimalloc_rust.git from allow-git

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-23 12:07:25 +08:00
houseme 84eb5aebef fix(ecstore): remove inline write debug noise (#6408)
* fix(ecstore): remove inline write debug noise

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ecstore): satisfy warning-as-error lints

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-23 12:07:20 +08:00
cxymds 20d1266496 fix(heal): fence format repair during pool transitions (#6342)
* fix(heal): fence format repair during pool transitions

* fix(heal): fence format writes during transitions
2026-08-23 04:24:48 +08:00
唐小鸭 f7003dfddd fix(admin): four site-replication interop correctness fixes (B5-rc T2) (#6399)
* fix(admin): send versioningEnabled on site replication make-bucket ops

The outbound make-with-versioning bucket-op query only carried
operation/createdAt/lockEnabled. MinIO's own create-bucket hook sends
versioningEnabled=true on this op, so align the outbound query with
MinIO's site-replication make-bucket wire contract. Route both outbound
builders (bootstrap plan and create-bucket hook) through one shared
builder that always appends versioningEnabled=true. RustFS's own inbound
handler force-enables versioning either way, so RustFS-to-RustFS
behavior is unchanged; the MinIO release verified against
(RELEASE.2025-09-07) also force-enables versioning regardless of the
flag, so this aligns the wire contract rather than changing observable
behavior there.

* fix(admin): propagate purge-deleted-bucket errors in site replication

The purge-deleted-bucket branch of the peer bucket-ops handler dropped
the delete_bucket error and answered 200, so a peer-driven purge that
failed (disk full, quorum loss) was reported as success while the
bucket survived on this site. Tolerate only bucket-not-found (the purge
raced an earlier replay or a local delete) and propagate every other
error through ApiError like the sibling delete branches do.

* fix(admin): derive fallback site deployment ID with UUIDv5

deployment_id_for_endpoint used DefaultHasher, whose algorithm is not
guaranteed stable across Rust releases. The fallback fires when a peer
response carries an empty deploymentID; the result is persisted in
site-replication state, used for collision disambiguation, and
broadcast to peers, so a toolchain bump could re-derive a different ID
for the same endpoint. Note that the add preflight currently rejects
that case upstream of this fallback. Derive UUIDv5 (NAMESPACE_URL) over
the canonical endpoint instead, and log a structured warn when a peer
metainfo response arrives without a deploymentID. Already persisted
fallback IDs are non-empty and therefore never re-derived, so existing
state is unaffected.

* fix(admin): stream site replication devnull body without 1MB cap

The site-replication devnull endpoint buffered the request body through
read_plain_admin_body, which enforces the 1MB admin body cap. MinIO
peers stream multi-megabyte probe bodies to this endpoint during site
netperf link checks and expect an unbounded discard, so any larger
probe got a 400 and was misreported as a broken link. Stream and
discard the body chunk by chunk with no size cap instead, mirroring
MinIO's io.Discard drain. The response stays 204 with an empty body.
2026-08-23 04:24:04 +08:00
Zhengchao An 2d7120460b test(e2e): remove fake KMS suite results (#6401) 2026-08-23 01:45:15 +08:00
Zhengchao An b91845c98c ci: align cache writer and reader keys (#6398) 2026-08-23 01:44:50 +08:00
Zhengchao An 7ba6f8cb33 test(e2e): fix cluster nightly oracles (#6397) 2026-08-23 01:44:35 +08:00
Zhengchao An f44b30c61a ci(perf): fix nightly regression baseline (#6389) 2026-08-23 01:43:52 +08:00
Zhengchao An c6590182ed ci(mint): pin manual image default (#6387) 2026-08-23 01:43:27 +08:00
Zhengchao An 6d85a9c6a8 ci(s3tests): stabilize HAProxy request handling (#6386) 2026-08-23 01:42:58 +08:00
Zhengchao An 26e6508b64 fix(ecstore): reject equal-time latest identity conflicts before index fallback (#6374) 2026-08-23 01:42:11 +08:00
GatewayJ 51e369be6c fix(policy): accept legacy bucket policy ID field (#6362) 2026-08-23 01:40:44 +08:00
Zhengchao An ddc4120c82 ci: detect incomplete and stale scheduled validations (#6357) 2026-08-23 01:40:28 +08:00
cxymds 87235ffd28 perf(ecstore): bound decommission entry workers (#6360) 2026-08-23 01:40:03 +08:00
cxymds 62c465ecef fix(heal): supervise scheduler task panics (#6351) 2026-08-23 01:39:06 +08:00
houseme f1b92af4a3 feat(ecstore): coalesce GET ReadVersion RPCs (#6395) 2026-08-23 01:15:38 +08:00
Zhengchao An 7c1a76dfd9 fix(ecstore): fence deletes against decommission commits (#6363)
* fix(ecstore): fence deletes against decommission commits

* fix(ecstore): preserve decommission target write locks

* fix(ecstore): preserve delete markers during source cleanup

* fix(ecstore): route batch delete markers to active pools

* fix(ecstore): preserve batch delete pool errors

* fix(ecstore): retain source-set lock during cleanup

* test(ecstore): exercise decommission delete fences

* test(ecstore): finish decommission delete fence scenario

* fix(ecstore): reuse fixed fence for reverse decommission

* fix(ecstore): fence decommission commit loss

* fix(ecstore): annotate batch delete fallback

* test(ecstore): fix decommission fence fixtures

* fix(ecstore): unblock decommission delete fences

* fix(ecstore): preserve distributed decommission set locks

* fix(ecstore): match decommission lock backend domain

* test(ecstore): align decommission fence barriers

* fix(ecstore): satisfy delete fence lint checks

* fix(rebalance): preserve access-denied delete errors
2026-08-23 00:40:38 +08:00
Zhengchao An 3ddf1a81ac test(kms): replace 33 hard-coded startup sleeps with readiness probe (#6349)
* refactor(e2e/kms): replace fixed startup sleeps with KMS readiness probe

Replace 33 hard-coded sleep(3s) / sleep(2s) startup waits in KMS e2e tests
with an active readiness probe (wait_for_kms_ready) that polls the KMS
status endpoint with exponential backoff (200ms→1s, 5s budget).

This cuts per-test startup latency from a fixed 3s to ~200-500ms while
remaining robust against slow CI machines.

Non-startup sleeps (ILM polling loops, fault-recovery detection delays,
test-runner inter-test pauses) are left untouched.

* style: cargo fmt

* fix(kms): use .expect() instead of ? in test functions that return ()

7 call sites of wait_for_kms_ready() used ? in async test functions
that return () instead of Result. Changed to .expect("KMS ready").

* fix(kms): enforce readiness probe deadline

* fix(kms): validate readiness backend status
2026-08-22 16:35:57 +00:00
唐小鸭 290662bc3a test(e2e): drop serial_test from receiver LWW e2e
main removed the serial_test dependency from e2e_test (#6344); the test
uses an ephemeral-port RustFSTestEnvironment and needs no cross-test
serialization, so the attribute and import go.
2026-08-23 00:26:43 +08:00
Zhengchao An cc412914d5 feat(connect): emit durable heartbeats (#6383) 2026-08-22 16:03:23 +00:00
cxymds 2fccfdeabe fix(scanner): fence timed out scan cycles (#6352)
* fix(scanner): fence timed out scan cycles

* fix(scanner): cancel scan workers with cycle scope

* fix(scanner): reject persisted timer overflow

* fix(scanner): reject terminal leadership epochs

* fix(scanner): reject trailing cycle state bytes
2026-08-22 14:38:18 +00:00
Zhengchao An 9815694301 fix(ecstore): supervise decommission worker cleanup (#6372) 2026-08-22 14:33:24 +00:00
houseme 0e79106c2f fix(storageclass): use div_ceil for inline threshold to match shard size calc (#6390)
The inline_block threshold used floor division (DEFAULT_INLINE_OBJECT_BUDGET
/ data_shards) while shard_file_size uses ceiling division (div_ceil). For
EC 12:4 with 256KiB objects, this caused a 1-byte discrepancy:
- inline_block = 262144 / 12 = 21845 (floor)
- shard_file_size = 262144.div_ceil(12) = 21846 (ceil)
- should_inline(21846, 12, false) = false (wrong!)

Fix by using div_ceil for the inline_block calculation, so both sides
use the same rounding and the inline path is correctly triggered.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-22 22:05:20 +08:00
Zhengchao An 12a9e654b5 refactor(data-usage): rename ReplicationStats to ReplicationTargetUsage (#6345)
* refactor(data-usage): ReplicationStats -> ReplicationTargetUsage

Rename the data-usage crate's ReplicationStats to ReplicationTargetUsage.
Serde field names are byte-identical (only the Rust type name changed;
field identifiers that rmp encodes are untouched). An rmp round-trip test
guards against future drift.

Scanner test imports updated to match.

* style: cargo fmt
2026-08-22 13:56:58 +00:00
Zhengchao An 6b5e0feef6 test(e2e): wait for heal peers after node rejoin (#6359) 2026-08-22 13:52:08 +00:00
cxymds da90d02c15 test(ecstore): cover suspended-owner heal semantics (#6348)
* test(ecstore): cover suspended-owner heal semantics

* test(heal): cover suspended owner production path
2026-08-22 20:45:03 +08:00
唐小鸭 a930152d5a fix(admin): expose per-target disableProxy through remote target admin API (#6376)
The read-proxy selector already honors a target's disable_proxy flag
(PR #6172), but the admin API still rejected the field, so the only way
to set it was importing a MinIO-written bucket-targets.json.

- move disableProxy from REMOTE_TARGET_UNSUPPORTED_FIELDS to
  REMOTE_TARGET_WRITABLE_FIELDS (set-remote-target create accepts it)
- add TargetUpdateOp::Proxy so set-remote-target?update=true&proxy=true
  overlays only the proxy group (MinIO TargetUpdateType parity)
- bump REMOTE_TARGET_CAPABILITY_CONTRACT_VERSION 1 -> 2 and update the
  runtime capability pin tests
- keep edge/edgeSyncBeforeExpiry rejected (no implementation behind them)
- pin that a published TargetClient carries disable_proxy, the field the
  proxy-target selector consults

Refs rustfs/backlog#1950
2026-08-22 20:43:52 +08:00
cxymds f9d45e41e1 fix(quota): account compressed deletes by committed size (#6365) 2026-08-22 11:39:01 +00:00
cxymds 04e1ea227a fix(scanner): isolate corrupt cycle state (#6354)
* fix(scanner): isolate corrupt cycle state

* fix(scanner): preserve newer state during recovery reset

* fix(scanner): fence recovery reset state

* fix(scanner): reject terminal recovery epochs

* fix(scanner): reject trailing cycle state bytes

* fix(scanner): reject terminal leadership epochs

* fix(scanner): retain recovery wake notifications

* fix(scanner): recover from oversized markers
2026-08-22 11:11:48 +00:00
Zhengchao An 1a3be70d98 fix(ecstore): preserve remote delete error types (#6371) 2026-08-22 17:07:02 +08:00
cxymds 8679570c2a fix(heal): retain displaced task status (#6370) 2026-08-22 08:23:40 +00:00
Zhengchao An 7143697a5f fix(rpc): bound internode concurrency under multipart load (#6368) 2026-08-22 06:42:10 +00:00
cxymds a34310a58f fix(ecstore): fail closed on unresolved decommission entries (#6367)
* fix(ecstore): fail closed on unresolved decommission entries

* perf(ecstore): avoid successful listing name clone
2026-08-22 14:12:28 +08:00
cxymds 2e60029079 perf(ecstore): throttle decommission checkpoints (#6356) 2026-08-22 13:49:23 +08:00
Zhengchao An 2c3e68ad89 ci: let feature validation jobs finish (#6364) 2026-08-22 04:09:21 +00:00
houseme 2f0918f60b feat(disk): fsync dedicated blocking pool (default-off) (#6366) 2026-08-22 11:24:24 +08:00
Zhengchao An 5b951de2b7 test(ci): bound s3-tests failure logs (#6361) 2026-08-22 02:58:01 +00:00
Zhengchao An 98c4675617 refactor(e2e): consolidate duplicated helper functions into common.rs (#6355) 2026-08-22 01:10:14 +00:00
Zhengchao An eec34331de chore(madmin): remove dead trace structs, keep TraceType only (#6343)
chore(madmin): remove dead trace structs, keep TraceType bitflag helper only

TraceInfo, TraceInfoLegacy, TraceHTTPStats, TraceCallStats, TraceRequestInfo,
TraceResponseInfo, StorageStats, and OSStats are unreferenced outside trace.rs.
Trim to TraceType + its bitflag operations which are actively used by
service_commands.rs and profile_admin.rs.

-139 lines (215 -> 76 lines)
2026-08-22 01:01:24 +00:00
Zhengchao An 5d820df79c chore(obs): rename ReplicationStats to ReplicationMetricsSnapshot (#6344)
* chore(obs): ReplicationStats -> ReplicationMetricsSnapshot, BucketReplicationStats -> BucketReplicationMetricsSnapshot

Rename in-obs-crate ReplicationStats and BucketReplicationStats to
ReplicationMetricsSnapshot and BucketReplicationMetricsSnapshot respectively.
No serde impact (these types are Prometheus metric collectors, not serialized).
No external consumers found outside the obs crate.

* cleanup: remove #[serial] annotations from e2e_test, scanner, lifecycle, and object-capacity crates

Remove no-op #[serial] attributes (nextest ignores serial_test) and the
serial_test dependency from four crates. All tests already use temp_env
for env-var isolation, making #[serial] purely redundant.

Crates cleaned:
- e2e_test (37 annotations, 9 imports, removed serial_test dep)
- rustfs-scanner (115 annotations across 7 files, removed serial_test dep)
- rustfs-lifecycle (46 annotations, removed serial_test dep)
- rustfs-object-capacity (38 annotations, removed serial_test dep)

Also converted scanner/tests/lifecycle_integration_test.rs
with_forced_immediate_enqueue_timeout helper from unsafe raw
env::set_var/remove_var to temp_env::async_with_vars for proper
isolation, and added async_closure feature to scanner's temp-env dep.

* fix(lifecycle): restore #[serial] on 2 tests that read env vars without temp_env

eval_inner_expires_latest_object_after_days_due and
eval_inner_does_not_panic_on_many_equal_due_events call eval_inner()
which reads ENV_ILM_PROCESS_TIME via std::env::var(). Without #[serial]
they race with other tests that set these vars via temp_env.

* style: cargo fmt
2026-08-22 00:30:30 +00:00
Zhengchao An 37c5ce1399 docs(agents): streamline instruction routing (#6358) 2026-08-22 08:19:53 +08:00
Zhengchao An 61b5edf16e chore(ecstore): standardize 24 bare TODO/FIXME to tracked format (#6346) 2026-08-22 07:09:32 +08:00
Zhengchao An ab5d433fe1 feat(connect): add registration and credential rotation (#6353) 2026-08-22 07:07:29 +08:00
Zhengchao An bc07cfd115 ci: harden test selection and nightly coverage (#6341) 2026-08-21 15:04:08 +00:00
Zhengchao An bce5922aef feat(connect): answer offline enrolment challenges without a network (#6335) 2026-08-21 13:16:18 +00:00
唐小鸭 858cf20d9a fix(replication): keep first-replication miss quiet in multipart LWW log
Version-absent is the normal first delivery of a version, not a
degraded comparison skip; only real read errors (quorum loss) warrant
the warn added in the previous commit.
2026-08-21 19:35:22 +08:00
唐小鸭 66e63d20dd fix(replication): surface skipped multipart LWW comparison at warn level
When the complete-multipart LWW gate cannot read the destination
version (quorum error), the inbound metadata is applied without
comparison — the exact overwrite rustfs/backlog#1953 exists to prevent.
Keep the fail-open semantics (failing the complete would loop through
MRF) but log the degraded path at warn so operators can see it; the
version-absent first replication keeps riding the same branch.
2026-08-21 19:33:59 +08:00
唐小鸭 81ef2882df fix(replication): apply receiver-side LWW to inbound metadata categories
Metadata-only replication reuses the whole-object PUT/multipart
transports, so in active-active topologies an inbound authorized
replication write carried the source's tags, retention, and legal hold
verbatim and unconditionally overwrote a category the destination had
modified more recently — both sites ended permanently diverged while
reporting COMPLETED (rustfs/backlog#1953, audit A4/P1-6).

The receiver now judges each category independently under the object
write lock: when the destination version's stored internal timestamp is
strictly newer than the inbound source timestamp, the local category
values and timestamp are kept; the rest of the write proceeds per the
inbound metadata and the object-level result stays successful, so a
local win never feeds an MRF retry loop. When the inbound category wins,
its internal timestamp key is pinned to the source-authored time instead
of the receiver-now() value stamped by the object-lock eval_metadata
path. No stored timestamp (pre-P1-6 data) or no inbound timestamp keeps
today's overwrite behavior.

The put_object hook reuses the existing commit-lock WORM-gate read (no
extra fanout); complete_multipart_upload adds one gated read under its
held lock, and the sender's complete options now carry the three
category timestamps so the multipart transport gets the same receiver
behavior. Local wins restore the timestamp via insert_str so a
MinIO-written single-key version still yields both compatibility keys.
2026-08-21 19:29:26 +08:00