Skip to content

vault maintenance (defrag, resize, health, dynamic index)#88

Merged
Adel-Ayoub merged 24 commits into
devfrom
76-evfs-maintenance
Mar 17, 2026
Merged

vault maintenance (defrag, resize, health, dynamic index)#88
Adel-Ayoub merged 24 commits into
devfrom
76-evfs-maintenance

Conversation

@Adel-Ayoub

Copy link
Copy Markdown
Collaborator

Summary

  • Vault defragmentation with per-move WAL crash safety and secure erase
  • Vault resize (grow/shrink) with shadow index + WAL relocation
  • Vault health check with consistency invariant (used + free_list + unallocated == total)
  • Dynamic index sizing — scales with capacity (64KB per MB, min 64KB, max 16MB)
  • Dart VaultService wrappers (defragment, resize, health) + 7 integration tests
  • Production hardening: fsync ordering, OOM guards, bounds checks, allocation caps
  • FRB codegen regenerated, dart analyze clean

What changed

Rust core

  • format.rs: compute_index_size(capacity), VaultHeader.index_size field (bytes 8-11), dynamic layout
    functions
  • wal.rs: MAX_SNAPSHOT_SIZE aligned to MAX_INDEX_PAD_SIZE
  • mod.rs: vault_defragment(), vault_resize(), vault_health() APIs
  • helpers.rs: flush_index, read_encrypted_index, capacity_from_file_size accept dynamic sizes
  • types.rs: VaultHandle.index_pad_size, DefragResult, VaultHealthInfo (with is_consistent)

Dart

  • vault_service.dart: defragment(), resize(), health() static methods
  • evfs_test.dart: 7 new integration tests (defrag compact, defrag no-op, grow, shrink, shrink-reject, health
    fresh, health lifecycle)
  • FRB bridge regenerated, imports fixed

Security

  • No new info leak — index_size deterministic from file size
  • MIN_INDEX_PAD_SIZE (64KB) / MAX_INDEX_PAD_SIZE (16MB) bounds
  • OOM guards: header validation, read_encrypted_index cap, WAL snapshot cap
  • Header tampering → AEAD fails (DoS only, no data leak)

Test plan

  • 284/284 Rust tests pass
  • cargo clippy -- -D warnings clean
  • FRB codegen regenerated
  • dart analyze — no issues found

Adel-Ayoub and others added 24 commits March 11, 2026 16:20
  DefragMove struct, plan_defrag(), apply_move(), complete_defrag(),
  needs_defrag() methods with 7 unit tests.
  DefragResult struct, vault_defragment() with crash-safe per-move
  WAL protection, post-commit secure erase of stale ciphertext,
  per-move checkpoint. 11 integration tests.
  Add #[frb(non_opaque)] to DefragResult, per-move secure erase of
  stale ciphertext tail (after WAL commit), per-move WAL checkpoint,
  WalOp::WriteSegment in defrag + crash recovery test.
For now there's no functionality, it will be broken down into two
different functions.
  Resize: WAL recovery now skips shadow write (position depends on capacity
  which may differ after interrupted resize). Post-recovery reconciliation
  fixes file size and shadow when index.capacity != actual file size.
  Removed redundant shadow reads/writes and WAL reopens during grow/shrink.

  Defrag: prevent data corruption on crash during overlapping moves (gap <
  segment size). Save segment data to {vault}.defrag backup before
  overlapping writes. vault_open restores from backup when both .defrag and
  uncommitted WAL exist; deletes stale backup otherwise.

  Added tests: same-capacity no-op, shrink-after-defrag, mid-grow crash
  recovery, overlapping defrag move crash recovery.
  Remove noisy comments, fix silent u32 truncation with try_from,
  add #[frb(non_opaque)] to VaultCapacityInfo, delegate vault_capacity()
  to health() to eliminate duplication, make types module public for FRB
  codegen, and add missing test assertions + full-capacity edge case.
  Replace fixed 64KB INDEX_PAD_SIZE with capacity-proportional index.
  Header stores index_size (bytes 8-11) so vault_open reads it back.

  - compute_index_size(): 64KB per MB, min 64KB, max 16MB cap
  - VaultHeader gains index_size field (u32)
  - Layout functions (shadow_index_offset, wal_region_offset,
    total_vault_size, data_region_offset) take dynamic index_pad_size
  - VaultHandle stores index_pad_size for all operations
  - SegmentIndex::to_bytes(pad_size) accepts dynamic pad size
  - read_encrypted_index validates allocation size (OOM guard)
  - WAL MAX_SNAPSHOT_SIZE aligned to MAX_INDEX_PAD_SIZE + overhead
  - 5 new tests: header roundtrip, compute_index_size edge cases
  - 284/284 tests pass, clippy clean
…izing

fix(evfs): scale segment index size with vault capacity
@Adel-Ayoub Adel-Ayoub merged commit 2129227 into dev Mar 17, 2026
5 checks passed
@Adel-Ayoub Adel-Ayoub deleted the 76-evfs-maintenance branch March 17, 2026 12:51
@Adel2411 Adel2411 linked an issue Mar 22, 2026 that may be closed by this pull request
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EVFS] Vault maintenance: defragmentation, resize, and health check

3 participants