fix(ec): don't fabricate a stub .vif when mounting an EC volume (#9951)

When an EC volume's .vif was missing, NewEcVolume wrote a stub holding
only the version. That stub implies the default 10+4 ratio with
DatFileSize=0 and no encode identity, which the custom-ratio resolver
and the startup credibility checks then read as an authoritative config
-- masking the real ratio of a custom-ratio volume and defeating the
byte-exact .vif gate. Mount with in-memory defaults instead and leave
the real .vif to the encoder or a recovery tool. The Rust volume server
already behaves this way.
This commit is contained in:
Chris Lu
2026-06-13 22:15:13 -07:00
committed by GitHub
parent 94357ac6a9
commit 26754fca4d
2 changed files with 35 additions and 2 deletions
+7 -2
View File
@@ -173,8 +173,13 @@ func NewEcVolume(diskType types.DiskType, dir string, dirIdx string, collection
ev.ECContext = NewDefaultECContext(collection, vid)
}
} else {
glog.Warningf("vif file not found,volumeId:%d, filename:%s", vid, vifFileName)
volume_info.SaveVolumeInfo(dataBaseFileName+".vif", &volume_server_pb.VolumeInfo{Version: uint32(ev.Version)})
// Don't fabricate a stub .vif here: a version-only stub implies the
// default 10+4 ratio with DatFileSize=0 and no encode identity, which
// the custom-ratio resolver and the startup credibility checks must not
// mistake for an authoritative config. Mount with in-memory defaults and
// leave the real .vif to the encoder or a recovery tool (the Rust volume
// server already behaves this way).
glog.Warningf("vif file not found, using defaults, volumeId:%d, filename:%s", vid, vifFileName)
ev.ECContext = NewDefaultECContext(collection, vid)
}
@@ -91,3 +91,31 @@ func TestNewEcVolumeLoadsEncodeTsNs(t *testing.T) {
t.Errorf("EncodeTsNs = %d, want %d", ev.EncodeTsNs, tsNs)
}
}
// TestNewEcVolumeDoesNotWriteStubVif pins that mounting an EC volume whose .vif
// is missing does NOT fabricate a stub .vif. A version-only stub would imply
// the default ratio with DatFileSize=0 and no encode identity, which the
// custom-ratio resolver and startup credibility checks must not trust.
func TestNewEcVolumeDoesNotWriteStubVif(t *testing.T) {
dir := t.TempDir()
const vid = needle.VolumeId(124)
base := EcShardFileName("", dir, int(vid))
if err := os.WriteFile(base+".ecx", nil, 0o644); err != nil {
t.Fatalf("write .ecx: %v", err)
}
ev, err := NewEcVolume(types.HardDriveType, dir, dir, "", vid)
if err != nil {
t.Fatalf("NewEcVolume: %v", err)
}
defer ev.Close()
if _, statErr := os.Stat(base + ".vif"); !os.IsNotExist(statErr) {
t.Fatalf("mounting without a .vif must not create one, stat err=%v", statErr)
}
// Mount still succeeds with the build's default EC ratio in memory.
if ev.ECContext == nil || ev.ECContext.DataShards != int(DataShardsCount) {
t.Fatalf("expected default EC context, got %+v", ev.ECContext)
}
}