Commit Graph
100 Commits
Author SHA1 Message Date
安正超andGitHub af291afb91 chore(dev): streamline local verification gates (#3410) 2026-06-13 21:51:33 +08:00
安正超andGitHub 982812614f test: preserve background config reload assumptions (#3409) 2026-06-13 21:39:02 +08:00
安正超andGitHub 6b1e114b39 feat(obs): add metrics runtime controller status (#3408) 2026-06-13 20:48:34 +08:00
安正超andGitHub 76b375c478 feat(runtime): add allocator reclaim controller status (#3406) 2026-06-13 19:03:49 +08:00
安正超andGitHub 624de31143 feat(runtime): add memory observability controller pilot (#3405) 2026-06-13 17:42:06 +08:00
8f8064df80 feat(runtime): add memory observability status snapshot (#3397)
Co-authored-by: houseme <[email protected]>
2026-06-13 10:02:16 +08:00
安正超andGitHub f7bf4fd3e1 feat(targets): gate external plugin flow (#3393) 2026-06-12 22:17:54 +08:00
5f7c991359 feat(targets): add extension hook diagnostics contracts (#3390)
Co-authored-by: houseme <[email protected]>
2026-06-12 21:17:34 +08:00
安正超andGitHub e80b72ae79 feat(targets): gate sidecar runtime policy (#3388)
* feat(targets): gate sidecar runtime policy

* fix(admin): add extension route policy specs
2026-06-12 17:42:12 +08:00
安正超andGitHub 434b71e569 feat(extension): add admin views (#3386) 2026-06-12 15:54:42 +08:00
安正超andGitHub 1e7c376586 feat(targets): add extension schema adapter (#3385) 2026-06-12 15:27:55 +08:00
安正超andGitHub 7d6d56a547 feat(extension): add schema contracts (#3384) 2026-06-12 15:07:17 +08:00
安正超andGitHub 249a0b56ea feat(targets): require plugin artifact attestations (#3383) 2026-06-12 14:13:41 +08:00
安正超andGitHub 8df38ea12c ci(docker): add release image scan report (#3382) 2026-06-12 13:11:59 +08:00
安正超andGitHub 212a0913be ci(release): emit sbom and provenance assets (#3381) 2026-06-12 12:56:02 +08:00
安正超andGitHub 99e68f82a2 ci(audit): report unpinned workflow actions (#3379) 2026-06-12 11:33:23 +08:00
安正超andGitHub fc32b76c0e fix: avoid mutating signed request headers (#3378) 2026-06-12 11:13:34 +08:00
安正超andGitHub 559bf9d9d7 ci(audit): wire cargo deny supply-chain gate (#3377) 2026-06-12 11:11:40 +08:00
安正超andGitHub 08c586d843 security(admin): reject unknown JSON ingress fields (#3376) 2026-06-12 10:21:50 +08:00
安正超andGitHub c3055f9335 security(kms): require explicit dev defaults opt-in (#3369)
* security(kms): require explicit dev defaults opt-in

* test(kms): satisfy clippy dev defaults checks
2026-06-12 07:05:20 +08:00
a85cc0354c refactor(storage-api): remove namespace lock from StorageAPI (#3365)
* refactor(storage-api): remove namespace lock from StorageAPI

* test(scanner): wait for runtime budget cancellation

---------

Co-authored-by: loverustfs <[email protected]>
2026-06-11 22:42:12 +08:00
安正超andGitHub 7146c893cb refactor(storage-api): remove legacy bucket DTO re-export (#3364) 2026-06-11 21:24:56 +08:00
安正超andGitHub a0b6636b61 refactor(config): remove legacy accessor re-export (#3362) 2026-06-11 19:32:57 +08:00
安正超andGitHub b4524033e3 refactor(config): move global config accessors (#3360) 2026-06-11 19:16:02 +08:00
安正超andGitHub ed3851782c refactor(config): remove legacy model re-export (#3357) 2026-06-11 18:09:01 +08:00
安正超andGitHub 69549634ea refactor(config): migrate scanner config consumer (#3356) 2026-06-11 17:30:26 +08:00
安正超andGitHub ca58d7f0ec refactor(config): migrate server config consumers (#3353) 2026-06-11 17:04:50 +08:00
安正超andGitHub 2205991180 refactor(config): extract server config model (#3351) 2026-06-11 16:11:17 +08:00
安正超andGitHub dd50359161 refactor(storage): narrow table catalog bounds (#3350) 2026-06-11 14:32:28 +08:00
2ead90d31b fix(security): add authorization check to ListRemoteTargetHandler (GHSA-796f-j7xp-hwf4) (#3346)
fix(security): add authorization check to ListRemoteTargetHandler

ListRemoteTargetHandler only verified that request credentials existed
but did not check whether the caller has replication or administrator
permissions. This allowed any authenticated user to list remote
replication target configuration, potentially leaking remote target
credentials (accessKey, secretKey, sessionToken).

Add validate_replication_admin_request() call with
GetBucketTargetAction, consistent with the other replication admin
handlers that already perform this check.

Fixes: GHSA-796f-j7xp-hwf4

Co-authored-by: houseme <[email protected]>
2026-06-11 05:50:14 +00:00
d60deba9b6 fix(security): add IAM authorization to FTP read/metadata/cwd handlers (GHSA-3g29-xff2-92vp) (#3347)
fix(security): add IAM authorization to FTP read/metadata/cwd handlers

The FTP frontend's get() (RETR), metadata() (SIZE/MDTM), and cwd()
(CWD) handlers dispatched directly to the storage backend without
calling authorize_operation(). This allowed any authenticated FTP user,
including those with explicit Deny policies, to read arbitrary objects
and probe bucket existence regardless of IAM policy.

Add authorize_operation() calls matching the pattern used by the
write-path handlers (put, del, list, rmd) and the WebDAV driver:
- get(): S3Action::GetObject
- metadata() for files: S3Action::HeadObject
- metadata() for directories: S3Action::HeadBucket
- cwd(): S3Action::HeadBucket

Fixes: GHSA-3g29-xff2-92vp

Co-authored-by: houseme <[email protected]>
2026-06-11 05:48:53 +00:00
安正超andGitHub d4ee44f49f refactor(scanner): narrow cache storage bounds (#3348) 2026-06-11 13:52:35 +08:00
安正超andGitHub 2f7cc7cb9e refactor(storage): narrow resync metadata bounds (#3345) 2026-06-11 04:41:15 +00:00
安正超andGitHub 686068d8bd refactor(storage): narrow metadata bounds (#3343) 2026-06-11 12:04:02 +08:00
安正超andGitHub 6b86e3875c refactor(storage): remove old admin surfaces (#3340) 2026-06-11 11:28:09 +08:00
安正超andGitHub 87968275a7 refactor(storage): route maintenance inventory reads (#3337) 2026-06-11 10:32:48 +08:00
安正超andGitHub f325b9f714 refactor(ecstore): route admin read internals (#3336) 2026-06-11 08:43:42 +08:00
安正超andGitHub 94c53af264 refactor(storage): use admin API for observability reads (#3335) 2026-06-11 08:13:15 +08:00
安正超andGitHub 8ae0cad667 refactor(admin): use storage admin reads (#3334) 2026-06-11 07:48:38 +08:00
安正超andGitHub b48d7b1fa5 refactor(admin): use storage admin info (#3333) 2026-06-11 07:12:35 +08:00
安正超andGitHub 8a90bda16a refactor(admin): use storage admin drive counts (#3332) 2026-06-11 06:36:18 +08:00
安正超andGitHub 4b1714438e feat(storage-api): bind ecstore admin contract (#3331) 2026-06-11 05:49:14 +08:00
安正超andGitHub d9ddd1bedc feat(storage-api): add disk inventory contract (#3330) 2026-06-10 16:33:31 +00:00
bb5d9565a6 feat(storage-api): add bucket DTO contract (#3314)
* feat(storage-api): add bucket DTO contract

* ci(build): increase workflow timeout to 90 minutes

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: houseme <[email protected]>
2026-06-10 07:16:14 +00:00
安正超andGitHub 0dc99a1abb docs: inventory KMS development defaults (#3304) 2026-06-10 12:46:08 +08:00
安正超andGitHub f80162b5c9 docs: decide config model boundary (#3307) 2026-06-10 10:02:53 +08:00
安正超andGitHub a73c90c811 security: redact IAM and target debug secrets (#3306) 2026-06-10 09:03:50 +08:00
安正超andGitHub 3795d44b86 feat(storage-api): add error code contract (#3313) 2026-06-10 09:03:29 +08:00
安正超andGitHub 5fef105484 docs: define background controller contract (#3312) 2026-06-10 07:30:21 +08:00
安正超andGitHub bc95b9fb9e test: guard table catalog ingress unknown fields (#3308) 2026-06-09 20:06:36 +00:00
安正超andGitHub 45391ac776 feat(storage-api): add contract crate (#3310) 2026-06-09 20:06:15 +00:00
安正超andGitHub f9a5e6d7e6 docs: inventory background services (#3311) 2026-06-10 04:05:33 +08:00
安正超andGitHub 03eb10b07f feat: add KMS config redaction safeguards (#3303) 2026-06-09 14:08:58 +00:00
安正超andGitHub f5bb034ec8 feat(kms): migrate KMS handlers to dedicated actions (#3298)
feat: migrate KMS handlers to dedicated actions
2026-06-09 12:01:02 +00:00
安正超andGitHub 4fec606dc4 feat: add KMS action taxonomy (#3294) 2026-06-09 05:06:15 +00:00
安正超andGitHub b9a3a2245a feat: add admin route policy inventory (#3286)
* feat: add admin route policy inventory

* fix: align table route policy actions

* fix: align load table route policy action
2026-06-09 02:17:50 +00:00
3d0e6ce0da feat: add security governance policy contracts (#3271)
* feat: add security governance policy contracts

* fix: require signatures for release assets

* docs: update policy verification counts

---------

Co-authored-by: houseme <[email protected]>
2026-06-08 02:42:03 +00:00
78df276d25 fix: return 503 on lock contention instead of 500 (#3274)
* fix(ecstore): skip hidden metadata in walk limit

* fix(ecstore): match walk limit to visible versions

* fix(ecstore): avoid decoding all versions for limit

* fix: return 503 on lock contention instead of 500

When concurrent PUTs to the same key contend for the namespace write
lock, lock timeout and conflict errors were wrapped as
StorageError::other(...) → StorageError::Io(...), which fell through
to S3ErrorCode::InternalError (500) in the error mapping.

Only QuorumNotReached was correctly mapped to ServiceUnavailable (503);
all other lock errors (Timeout, AlreadyLocked, etc.) became 500.

Fix: map_namespace_lock_error now returns StorageError::Lock(err) for
non-quorum lock errors, and StorageError::Lock is mapped to
S3ErrorCode::ServiceUnavailable in the HTTP error conversion.

Affected paths:
- crates/ecstore/src/set_disk/lock.rs
- crates/ecstore/src/store/object.rs
- crates/ecstore/src/store/bucket.rs (make_bucket, delete_bucket)
- rustfs/src/app/object_usecase.rs (copy_object)

Regression test: test_concurrent_put_same_key_never_returns_500

* test: fail on unexpected lock contention errors

---------

Co-authored-by: houseme <[email protected]>
2026-06-08 02:20:21 +00:00
安正超andGitHub 7a9bf707ee feat: add security governance contract types (#3270) 2026-06-07 23:14:11 +00:00
安正超andGitHub c03c0ebc36 test: add admin route matrix guard (#3268) 2026-06-08 05:30:18 +08:00
dee550a831 ci: add architecture migration rule checks (#3264)
Co-authored-by: houseme <[email protected]>
2026-06-07 16:23:38 +00:00
安正超andGitHub 6f4d0b54a1 fix(ci): install ripgrep for script checks (#3260) 2026-06-07 22:03:25 +08:00
安正超andGitHub 4254633c9e docs: update security advisory lessons (#3262) 2026-06-07 22:02:56 +08:00
安正超andGitHub e5b2bcc088 docs: complete config helper inventory (#3261) 2026-06-07 22:02:21 +08:00
安正超andGitHub 3c71d5ef1c docs: inventory ecstore config consumers (#3259) 2026-06-07 21:44:55 +08:00
安正超andGitHub 241e45d3b0 docs: add admin route action snapshot (#3258) 2026-06-07 21:20:16 +08:00
安正超andGitHub 0f9584c8d9 docs: add startup timeline baseline (#3256) 2026-06-07 20:18:30 +08:00
安正超andGitHub ae9d25879d ci: stabilize architecture layer guard (#3255) 2026-06-07 19:26:35 +08:00
安正超andGitHub 069d1e5a75 test: bypass proxy for embedded readiness probe (#3254) 2026-06-07 09:04:29 +00:00
安正超andGitHub f8aa4fa221 docs: add architecture migration guardrails (#3253) 2026-06-07 14:43:55 +08:00
安正超andGitHub e2fe99d8bc refactor(ecstore): add server configuration accessors (#3238)
* refactor(ecstore): add server configuration accessors

Phase 4 of global singleton consolidation. Add ECStore accessor
methods for server-level configuration globals.

New methods:
- port() — delegates to global_rustfs_port()
- host() — delegates to GLOBAL_RUSTFS_HOST
- addr() — delegates to GLOBAL_RUSTFS_ADDR
- region() — delegates to get_global_region()
- endpoints() — delegates to get_global_endpoints()
- server_config() — delegates to get_global_server_config()
- storage_class() — delegates to get_global_storage_class()
- tier_config_mgr() — delegates to get_global_tier_config_mgr()
- notification_system() — delegates to get_global_notification_sys()
- bucket_metadata_sys() — delegates to get_global_bucket_metadata_sys()

1160 tests pass, clippy clean, formatting clean.

* fix(ecstore): avoid duplicate server accessors
2026-06-06 21:38:45 +08:00
安正超andGitHub 60f14cb0f1 fix(bucket-encryption): populate default KMS key for SSE-KMS without key ID (#3225)
* fix(bucket-encryption): populate default KMS key for SSE-KMS without key ID

When PutBucketEncryption receives SSE-KMS configuration without a specific
KMS key ID, query the KMS service for the default key and populate
KMSMasterKeyID before storing. This ensures GetBucketEncryption responses
include the key ID, which S3 clients like mc rely on to distinguish SSE-KMS
from SSE-S3 in their display logic.

Fixes #3039

* test(kms): cover empty bucket encryption key ID

* fix(bucket-encryption): require default KMS key
2026-06-06 02:57:48 +00:00
安正超andGitHub 06acf49672 refactor(ecstore): add accessor methods for service globals (#3226)
* refactor(ecstore): add accessor methods for service globals

Phase 3 of global singleton consolidation. Add ECStore accessor
methods that delegate to process-global service singletons,
providing a unified API through ECStore.

New methods:
- notification_system() — delegates to notification_sys global
- bucket_metadata_sys() — delegates to bucket metadata global
- endpoints() — delegates to endpoints global
- region() — delegates to region global
- tier_config_mgr() — delegates to tier config global
- server_config() — delegates to server config global
- storage_class() — delegates to storage class global

1161 tests pass, clippy clean, formatting clean.

* fix: use imported functions instead of fully-qualified paths

Address review comments: use imported functions instead of
crate:: paths to avoid unused import warnings.

1160 tests pass, clippy clean.

* fix(ecstore): remove unused service imports
2026-06-05 15:29:38 +00:00
安正超andGitHub 4d50c72e4c fix(ecstore): skip hidden metadata in walk limit (#3224)
* fix(ecstore): skip hidden metadata in walk limit

* fix(ecstore): match walk limit to visible versions

* fix(ecstore): avoid decoding all versions for limit
2026-06-05 13:50:02 +00:00
安正超andGitHub 8185376b90 refactor(ecstore): migrate config globals into ECStore struct fields (#3219)
* refactor(ecstore): migrate config globals into ECStore struct fields

Phase 2 of global singleton consolidation. Add server_config and
storage_class fields to ECStore, sharing the same underlying data
as the process-global LazyLock statics.

New ECStore fields:
- server_config: RwLock<Option<Config>>
- storage_class: RwLock<storageclass::Config>

New async accessor methods:
- get_server_config() / set_server_config()
- get_storage_class() / set_storage_class()

Fields initialized with defaults in ECStore::new(), synced from
globals after init() completes. Global functions preserved for
backward compatibility.

1160 tests pass, clippy clean, full workspace compiles.

* fix: address PR #3219 review comments - delegate to globals

Accessors now delegate to process-global statics to avoid state drift:
- get_server_config() delegates to get_global_server_config()
- set_server_config() updates both global and local field
- get_storage_class() delegates to get_global_storage_class()
- set_storage_class() updates both global and local field
- Removed stale sync code from init()
- Changed fields to std::sync::RwLock for sync access

1160 tests pass.

* fix: correct import order for cargo fmt

* fix: simplify config accessors - delegate to globals without local state

Remove local server_config and storage_class fields from ECStore.
Accessors now purely delegate to process-global statics, eliminating
the state drift risk identified in review.

1160 tests pass, formatting clean.
2026-06-05 01:06:08 +00:00
1dd3839a9f fix(signer): address post-merge review comments (#3216)
* fix: address PR #3150 review comments

- Restore get_host_addr as best-effort wrapper (String return type)
- Replace bare expect("err") with descriptive messages in unsigned trailer
- Simplify aws-chunked header construction
- 20 signer + 96 io-core tests pass

* fix(signer): preserve host fallback

* fix(signer): avoid signer fallback panics

---------

Co-authored-by: houseme <[email protected]>
2026-06-04 22:45:50 +00:00
d6120f5788 refactor(ecstore): migrate mutable globals into ECStore struct fields (#3214)
* refactor(ecstore): migrate mutable globals into ECStore struct fields

Phase 1 of global singleton consolidation. Move mutable globals from
lazy_static into ECStore struct fields as the first step toward
dependency injection and multi-instance support.

New ECStore fields:
- is_erasure, is_dist_erasure, is_erasure_sd (erasure type flags)
- local_disk_map, local_disk_id_map, local_disk_set_drives
- root_disk_threshold
- tier_config_mgr, event_notifier, bucket_monitor

New accessor methods:
- is_erasure(), is_dist_erasure(), is_erasure_sd()
- update_erasure_type()
- tier_config_mgr(), event_notifier(), bucket_monitor()

Global functions in global.rs preserved for backward compatibility.
1151 ecstore tests pass.

* fix: address PR #3214 review comments

- Sync ECStore fields from globals after init()
- Enforce DistErasure => is_erasure invariant in update_erasure_type()
- Change bucket_monitor from Option to OnceLock for deferred initialization
- Restrict TypeLocalDiskSetDrives to pub(crate)
- 1151 tests pass

* fix: address PR #3150 review comments

- Restore get_host_addr as best-effort wrapper (String return type)
- Replace bare expect("err") with descriptive messages in unsigned trailer
- Simplify aws-chunked header construction
- 20 signer + 96 io-core tests pass

* fix(ecstore): format store imports

* fix(ecstore): keep migrated accessors in sync

* fix(signer): preserve host fallback and unsigned trailer errors

* fix(ecstore): defer migrated global accessors

* fix(signer): box unsigned trailer signing errors

* fix(ecstore): avoid lock awaits during sync

* fix(ecstore): narrow phase one globals

---------

Co-authored-by: houseme <[email protected]>
2026-06-04 17:27:21 +00:00
3bd89944c2 perf(erasure): remove UUID from clone + increase encode inflight budget (#3212)
* perf(erasure): remove UUID from clone + increase encode inflight budget

Two targeted optimizations for the erasure encoding hot path:

1. Erasure::clone() no longer generates Uuid::new_v4() per clone.
   The _id field is unused in the hot path; reusing the original ID
   eliminates a CSPRNG call per block encode (100 calls for a 100MB
   object with 1MB blocks).

2. Default RUSTFS_ERASURE_ENCODE_MAX_INFLIGHT_BYTES raised from 8MB
   to 32MB. This increases the encode pipeline depth from ~5 to ~20
   blocks, allowing more read-ahead between the encoder and disk
   writer stages. The per-request memory bound is still controlled
   by the 8-block hard cap and the env var override.

3. Added encode_data_owned() utility method for zero-copy encoding
   when the caller already owns a heap buffer (Vec<u8> → BytesMut
   via Bytes::try_into_mut). Not used in the hot path yet but
   available for future callers.

All 1157 ecstore tests pass. Criterion micro-benchmarks show no
regression (< 2% variance). Single-machine warp E2E tests were
inconclusive due to high variance; a dedicated multi-disk test
environment is needed for reliable E2E comparison.

Ref: https://github.com/rustfs/backlog/issues/659

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* chore: update Cargo.lock

* fix(erasure): align encode inflight cap and tests

---------

Co-authored-by: Claude Opus 4.7 <[email protected]>
2026-06-04 13:49:36 +00:00
7b57d5b217 perf(signer): reduce String allocations in V4 signing path (#3197)
* perf(signer): reduce String allocations in V4 signing path

- v4_ignored_headers: HashMap<String, bool> -> HashSet<&'static str>
- Header lookups: k.to_string() -> k.as_str() (zero-copy)
- Query params: Vec<(String, String)> -> Vec<(&str, &str)> (zero-copy)
- Canonical request: single String with push_str instead of 6 intermediate Strings + join
- 20 signer tests pass

* fix(signer): align ignored header set type

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 15:40:35 +00:00
0fb02049ac fix(ecstore): remove dead _buf field from Erasure struct (#3196)
* fix(ecstore): remove dead _buf field from Erasure struct

_buf was allocated in new(), clone(), and Default but never read or written.
Each clone() was allocating block_size bytes (typically 10MB) for nothing.

- Remove _buf from struct, Default, Clone, new_with_options
- 51 erasure tests pass

* fix: remove empty line after doc comment

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 15:40:29 +00:00
a63aaf933d fix(notify): normalize lock ordering to prevent deadlock (#3199)
* fix(notify): normalize lock ordering to prevent deadlock

replace_targets() and shutdown() acquired target_list before replay_workers,
opposite to runtime_view.rs order. This is an ABBA deadlock pattern.

- Swap to replay_workers -> target_list order (canonical)
- Add lock order comments
- 82 notify tests pass

* docs(notify): update runtime facade lock order

* docs(notify): clarify runtime facade lock order

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 15:37:59 +00:00
1838922f07 fix(security): add deny_unknown_fields to deserialization structs (#3198)
* fix(security): add deny_unknown_fields to deserialization structs

Prevent silent acceptance of malformed or adversarial payloads.

- policy: Policy, BucketPolicy, Statement, BPStatement, PrincipalObject
- notify: S3KeyFilter custom deserializer rejects unknown child elements
- update: VersionInfo (remote HTTP response)

26 policy + 82 notify tests pass.

* fix(update): keep version response forward compatible

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 15:33:28 +00:00
0dbf0b13a8 fix(lock): align distributed acquisition retries (#3177)
* fix(lock): align distributed acquisition retries

* fix(lock): retry remote lock RPC timeouts

* fix(lock): quiet retryable acquisition logs

* fix(lock): enforce attempt acquisition deadline

* fix(ci): install unzip in setup action

* fix(lock): handle acquisition review followups

* fix(ci): use nextest install-action shorthand

* fix(lock): preserve hard failures on attempt timeout

* fix(lock): retry attempt timeout when quorum remains possible

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 01:58:47 +00:00
d817bd4449 fix(ci): stabilize Rust setup action (#3163)
* fix(ecstore): restore windows endpoint validation build

* fix(ci): install unzip for protoc setup

* fix(ci): use nextest install-action shorthand

* fix(ci): restore cargo-nextest action ref

---------

Co-authored-by: houseme <[email protected]>
2026-06-03 01:51:30 +00:00
安正超andGitHub ae2d3c4025 ci: restore ubicloud runners for heavy jobs (#3183) 2026-06-03 08:38:17 +08:00
安正超andGitHub 14aaab9406 ci: use hosted runners for light jobs (#3181) 2026-06-02 23:17:56 +08:00
安正超andGitHub 7cc730d9c0 ci: isolate s3 test runner state (#3180) 2026-06-02 22:40:37 +08:00
安正超andGitHub 97dd825468 fix(ecstore): optimize ObjectInfo clone and fix critical TODOs (#3149)
* fix(ecstore): optimize ObjectInfo clone and fix critical TODOs

## ObjectInfo hot-path clone optimization (issue #653 item 2)
- Wrap user_defined (HashMap), user_tags (String), parts (Vec) in Arc
- Clone cost reduced from ~20 heap allocations to O(1) ref count bump
- Updated 11 downstream access sites with explicit deref where needed

## Critical TODO/FIXME fixes (issue #653 item 7)
- rpc/peer_s3_client.rs: descriptive error message for empty peer response
- set_disk/write.rs: concurrent rollback deletes via tokio::spawn + join_all
- store_list_objects.rs: resolved FIXME with explanation + 4 regression tests
- store/bucket.rs: namespace write locks for make_bucket and delete_bucket

Skipped TODOs (too risky without broader context):
- multipart.rs:30 nslock — causes lock timeout in existing tests
- bucket.rs:88 cached list_bucket — needs cache invalidation strategy
- bucket.rs:149 replication delete — needs replication subsystem integration

1134 tests pass (1 flaky under parallel execution, passes individually).

* fix: address PR #3149 review comments

- Preserve NamespaceLockQuorumUnavailable variant in bucket create/delete
- Fix cancellation test to actually test cancellation (keep senders open)
- Update ObjectInfo consumers in app/ for Arc-backed fields
- Update bucket_usecase.rs user_tags to Arc<String>

* fix: update ObjectInfo Arc consumers

* fix: address ecstore merge review comments

* fix: cancel blocked merge output sends

* fix(ecstore): satisfy ObjectInfo clone clippy
2026-06-01 00:44:58 +00:00
安正超andGitHub bd571a575f fix(io-core,signer): replace unwrap() with proper error handling (#3150)
* fix(io-core,signer): replace unwrap() with proper error handling

## io-core (issue #653 item 1)
- pool.rs: replace 8 .lock().unwrap() with poisoned recovery
- pool.rs: replace semaphore acquire unwrap with graceful fallback
- deadlock_detector.rs: replace 5 .lock().unwrap() with match/ok

## signer (issue #653 item 1)
- Add SignV2Error enum, try_pre_sign_v2, try_sign_v2
- Replace 14 unwrap() in v2 signing with ? propagation
- Add try_streaming_sign_v4, replace 5 expect("err") with descriptive errors
- get_host_addr returns Result instead of panicking

All backward-compat wrappers preserved. 95 io-core + 18 signer tests pass.

* fix: address signer and pool review comments

* test: update signer v2 string-to-sign test

* fix: address signer and pool review followups

* fix: tighten signer host and pool fallback
2026-05-31 23:40:20 +00:00
a14657f517 fix(scanner,data-usage): fix add() logic inversion and usize underflow in reduce_children_of (#3142)
* fix(scanner,data-usage): fix add() logic inversion and usize underflow in reduce_children_of

Bug #1: add() had inverted logic — returned early when children were present,
making the recursive child traversal dead code. Leaf compaction path was
completely non-functional. Fixed by recursing into children when present and
collecting leaves only at leaf nodes.

Bug #2: reduce_children_of used  which underflows in debug
(panic) or release (wraps to usize::MAX, compacts entire cache). Fixed with
saturating_sub.

Both bugs existed identically in crates/scanner and crates/data-usage.

Added 5 tests covering add() subtree traversal, edge cases, and
reduce_children_of compaction behavior.

Closes rustfs/backlog#652

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* fix: collect internal nodes as compaction candidates, not leaves

The previous fix for add() collected leaf nodes (children empty) as
compaction candidates. This is incorrect: total_children_rec returns 0
for leaves, so compacting them never decrements  — the
compaction loop makes no progress.

Collect internal nodes (children non-empty) instead. Compacting an
internal node removes its subtree via delete_recursive, which actually
reduces the total child count. Leaf nodes are skipped since they have
no children to remove.

Updated tests to match the corrected semantics.

* refactor: rename leaves→candidates, add data-usage regression tests

- Rename misleading  variable/parameter to  in
  add() and reduce_children_of() for both crates
- Add 4 regression tests in crates/data-usage covering add() candidate
  selection and reduce_children_of() compaction + saturating_sub

* fix: address data usage compaction review feedback

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: houseme <[email protected]>
2026-05-31 21:52:53 +00:00
安正超andGitHub 81b899e9c6 docs: update security advisory lessons (#3143) 2026-05-31 23:01:35 +08:00
安正超andGitHub b5e565c0ce chore(agents): add Rust code quality rules and skill (#3144)
* docs: update security advisory lessons

* chore(agents): add Rust code quality rules and skill

Add rules derived from full-project code review (48 findings across
7 dimensions) to prevent recurring issues in agent-generated code.

AGENTS.md changes:
- crates/AGENTS.md: error type design, concurrency, recursion safety,
  type casting, test quality rules
- root AGENTS.md: serde safety, naming conventions
- crates/ecstore/AGENTS.md: allocation discipline, lock ordering,
  recursion safety, dead code policy
- crates/notify/AGENTS.md: lock ordering for runtime_view/facade

Skill changes:
- code-change-verification: add Rust-specific checks (unwrap, as cast,
  clone, lock order, recursion, error types, test assertions)
- security-advisory-lessons: add serde deserialization safety pattern
- NEW rust-code-quality: automated scan + manual review checklist
2026-05-31 22:19:36 +08:00
e12d63234a test(targets): cover Kafka check SASL validation (#3136)
test(targets): cover kafka check sasl validation

Co-authored-by: houseme <[email protected]>
2026-05-31 04:47:21 +00:00
cf55743579 perf: reduce spawn_blocking contention in PUT path (#3132)
* perf: reduce spawn_blocking contention in PUT path (~23% throughput gain)

Flame graph profiling identified tokio blocking pool mutex contention
as the #1 bottleneck (17.3% of CPU time). Each spawn_blocking call must
acquire parking_lot::raw_mutex to enqueue work. With 16 concurrent PUTs
× 4 disks × 3+ spawn_blocking per disk, this became a serialization point.

Optimizations applied:
- Merge make_dir_all + file write into single spawn_blocking
- Merge read_file + parse + write + rename into single spawn_blocking
  for inline objects (small files)
- Optimize reliable_rename to try rename first, mkdir only on ENOENT
- Optimize remove/remove_std to try remove_file first, EISDIR fallback
- Add encode_inline_small fast path for small objects
- Parallelize bitrot writer creation with join_all

Benchmark (4KiB PUT, 4-disk EC, 16 concurrent, 8 rounds, randomized A/B):
  Baseline: ~950 obj/s → Optimized: ~1173 obj/s (+23%)

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: address review comments

- Return old_data_dir for non-inline rename_data path (was incorrectly None)
- Restore delete_all cleanup of PUT temp data on failure paths
- Fix cargo fmt formatting

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* style: apply rustfmt from stable 1.96.0

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: collapse nested if-let chains for clippy compliance

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: address Copilot review comments

- fs.rs: handle macOS EPERM from remove_file on directories
- os.rs: restore NotFound=Ok(()) semantics on first rename attempt
- local.rs: use try-rename-then-mkdir pattern for inline rename_data

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* test: add unit tests for encode_inline_small fast path

* test: fix comment and line length in encode_inline_small tests

* fix: revert reliable_rename and write_all_internal to match original

Restore the original reliable_rename logic (check parent exists, then
rename in loop) and the original write_all_internal (make_dir_all outside
spawn_blocking). The optimization changes caused a CI-only test failure
in capacity_dirty_scope_test that could not be reproduced locally.

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: update comment and fix formatting for CI

- Fix macOS/BSD comment to accurately say macOS only
- Fix encode_inline_small test formatting to match rustfmt 1.96.0

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: propagate inline rename errors

* fix: retry rename when parent missing

---------

Co-authored-by: Claude Opus 4.7 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-05-31 01:28:48 +00:00
安正超andGitHub 97cd19becc fix(sse): handle case-insensitive encryption metadata (#3127)
* fix(sse): handle case-insensitive encryption metadata

* test(ecstore): cover case-insensitive managed material resolution
2026-05-30 02:38:53 +00:00
ac97ceb744 fix(config): restore default credential startup (#3114)
* fix(config): restore default credential startup

* fix: align e2e credentials with server env

* fix(config): restore default credential consistency

---------

Co-authored-by: houseme <[email protected]>
2026-05-29 11:52:46 +00:00
b436272642 fix: tolerate stalled listing readers after quorum (#3110)
Co-authored-by: loverustfs <[email protected]>
2026-05-29 08:57:57 +08:00
d9c683decc fix: retry namespace lock quorum contention (#3098)
* fix: retry namespace lock quorum contention

* fix(lock): treat remote lock rpc failures as hard

* fix(lock): classify lock contention timeout and avoid hard rollback blocks

* fix(lock): handle namespace lock quorum timeouts

* fix(lock): refine quorum contention handling

* fix(lock): refine unrecoverable quorum handling logs

* fix: address namespace lock quorum review feedback

* test: stabilize batch quorum timing tests

* fix(lock): classify remote quorum failures

* fix: drop remote lock timeout grace period

* fix: satisfy clippy on lock quorum error

* fix: classify remote lock rpc timeouts as hard failures

* fix: fast fail impossible lock quorum attempts

* fix: retry on transient timeout with pending cleanup

* fix: evict remote lock timeout connections

* refactor: avoid duplicate timeout eviction warning

---------

Co-authored-by: houseme <[email protected]>
2026-05-28 01:35:00 +00:00
overtrue f77e979e4a fix: satisfy clippy for Snowball traversal test 2026-05-28 09:16:00 +08:00
overtrue 95836a0a4d fix: reject Snowball extract path traversal 2026-05-28 08:32:13 +08:00