* ec: let the encode's balance see a migrating volume's shards across disk-type buckets Shard generation writes beside the source .dat, so a cross-tier encode (source on hdd, -diskType=ssd) leaves the fresh shards in the source disk-type bucket. The encode's internal balance ingested only the target bucket, saw no shards, and planned no moves; the spread guard then correctly aborted the encode (and before that guard existed, the shards silently stayed clumped on the generation host in the wrong tier). EcBalance now takes the encode batch as migratingVolumeIds and ingests those volumes' shards from every bucket, while everything else keeps the bucket filter so a plain ec.balance never drags deliberately tiered shards onto another disk type. The in-memory model delete also becomes bucket-agnostic: a node holds a given shard in exactly one bucket, and a bucket-scoped delete missed cross-bucket moves in the dry-run model. * volume: decode reads shard 0 from its resolved path, not the EC volume's base dir On a multi-disk server a volume's shards can sit on several disks; the store registers each shard with its own path and CollectEcShards resolves them, but FindDatFileSize derived the .ec00 path from the EcVolume's base directory. When shard 0 lived on a sibling disk, VolumeEcShardsToVolume failed with 'open ...ec00: no such file or directory' and ec.decode aborted. * ec: decode re-copies shards the topology claims but the target does not hold An interrupted earlier decode or balance can leave the master believing the decode target holds a shard whose file never landed: the mount registered but the partial copy was cleaned, or the file was swept. The collect step took the topology's word for it, excluded the shard from the copy set, and the decode failed with 'missing shard'. Probe the target's live inventory (VolumeEcShardsInfo) and treat anything it cannot serve as still-to-copy. * ec: decode discovers shards across disk-type buckets Shards sit wherever encode generation and balance left them: a cross-tier encode leaves them in the source disk-type bucket, a partial migration straddles buckets. ec.decode scoped its shard discovery to the -diskType bucket and reported a decodable volume as having no shards at all. Union across buckets, the way the encode's shard verification already does. * test: EC chaos lifecycle harness Randomized, seeded sequences of the EC lifecycle against a live cluster in the production-shaped layout: multiple data disks per server, a separate -dir.idx directory so .ecx/.ecj sidecars are shared across disks, and a tagged ssd tier. Operations cover encode (hdd and ssd targets), balance, shard damage plus rebuild, decode, re-encode, deletes, scrub, tier moves, crash-restarts, sidecar fault injections (a data-dir .vif pushed into the shared idx dir; a stale-generation shard planted beside a newer encode), and interruptions: a real weed shell subprocess killed mid-encode, mid-decode, and mid-balance, with the recovery re-run required to converge. One invariant holds after every step: every stored byte reads back identical and every deleted needle stays deleted. EC_CHAOS_SEED and EC_CHAOS_STEPS make runs reproducible and scalable. A known gap is tolerated and logged rather than fixed here: a shard mounted on two disks of one node (orphan adoption after an interrupted copy) is invisible to ec.balance's dedup and unaddressable by ec.shard.unmount's shard@address form, so no cleanup path exists yet. * test: fail payload-corruption checks on the test goroutine t.Fatalf inside require.Eventually's condition runs on the poller's goroutine, where Goexit kills only that goroutine and the corruption message can be lost behind a generic timeout. Record the mismatch, end the polling, and fail on the test goroutine. Also assert the full shard count in the cross-bucket decode-discovery test.
Erasure Coding Integration Tests
This directory contains integration tests for the EC (Erasure Coding) encoding volume location timing bug fix.
The Bug
The bug caused double storage usage during EC encoding because:
- Silent failure: Functions returned
nilinstead of proper error messages - Timing race condition: Volume locations were collected AFTER EC encoding when master metadata was already updated
- Missing cleanup: Original volumes weren't being deleted after EC encoding
This resulted in both original .dat files AND EC .ec00-.ec13 files coexisting, effectively doubling storage usage.
The Fix
The fix addresses all three issues:
- Fixed silent failures: Updated
doDeleteVolumes()anddoEcEncode()to return proper errors - Fixed timing race condition: Created
doDeleteVolumesWithLocations()that uses pre-collected volume locations - Enhanced cleanup: Volume locations are now collected BEFORE EC encoding, preventing the race condition
Integration Tests
TestECEncodingVolumeLocationTimingBug
The main integration test that:
- Simulates master timing race condition: Tests what happens when volume locations are read from master AFTER EC encoding has updated the metadata
- Verifies fix effectiveness: Checks for the "Collecting volume locations...before EC encoding" message that proves the fix is working
- Tests multi-server distribution: Runs EC encoding with 6 volume servers to test shard distribution
- Validates cleanup: Ensures original volumes are properly cleaned up after EC encoding
TestECEncodingMasterTimingRaceCondition
A focused test that specifically targets the master metadata timing race condition:
- Simulates the exact race condition: Tests volume location collection timing relative to master metadata updates
- Detects timing fix: Verifies that volume locations are collected BEFORE EC encoding starts
- Demonstrates bug impact: Shows what happens when volume locations are unavailable after master metadata update
TestECEncodingRegressionPrevention
Regression tests that ensure:
- Function signatures: Fixed functions still exist and return proper errors
- Timing patterns: Volume location collection happens in the correct order
Test Architecture
The tests use:
- Real SeaweedFS cluster: 1 master server + 6 volume servers
- Multi-server setup: Tests realistic EC shard distribution across multiple servers
- Timing simulation: Goroutines and delays to simulate race conditions
- Output validation: Checks for specific log messages that prove the fix is working
Why Integration Tests Were Necessary
Unit tests could not catch this bug because:
- Race condition: The bug only occurred in real-world timing scenarios
- Master-volume server interaction: Required actual master metadata updates
- File system operations: Needed real volume creation and EC shard generation
- Cleanup timing: Required testing the sequence of operations in correct order
The integration tests successfully catch the timing bug by:
- Testing real command execution: Uses actual
ec.encodeshell command - Simulating race conditions: Creates timing scenarios that expose the bug
- Validating output messages: Checks for the key "Collecting volume locations...before EC encoding" message
- Monitoring cleanup behavior: Ensures original volumes are properly deleted
Running the Tests
# Run all integration tests
go test -v
# Run only the main timing test
go test -v -run TestECEncodingVolumeLocationTimingBug
# Run only the race condition test
go test -v -run TestECEncodingMasterTimingRaceCondition
# Skip integration tests (short mode)
go test -v -short
Manual Testing with Makefile
A Makefile is provided for manual EC testing.
Requirements: curl, jq (command-line JSON processor)
# Quick start: start cluster and populate data
make setup
# Open weed shell to run EC commands
make shell
# Individual targets
make start # Start test cluster (master + 6 volume servers + filer)
make stop # Stop test cluster
make populate # Populate ~300MB of test data
make status # Show cluster and EC shard status
make clean # Stop cluster and remove all test data
make help # Show all targets
EC Rebalance Limited Slots (Unit Test)
The "no free ec shard slots" issue is tested with a unit test that works directly on topology data structures without requiring a running cluster.
Location: weed/shell/ec_rebalance_slots_test.go
Tests included:
TestECRebalanceWithLimitedSlots: Tests a topology with 6 servers, 7 EC volumes (98 shards)TestECRebalanceZeroFreeSlots: Reproduces the exact 0 free slots scenario
Known Issue: When volume servers are at capacity (volumeCount == maxVolumeCount),
the rebalance step fails with "no free ec shard slots" instead of recognizing that
moving shards frees slots on source servers.
Test Results
With the fix: Shows "Collecting volume locations for N volumes before EC encoding..." message Without the fix: No collection message, potential timing race condition
The tests demonstrate that the fix prevents the volume location timing bug that caused double storage usage in EC encoding operations.