mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-16 03:20:50 +02:00
filer: fingerprint every read-relevant chunk field
The layout binding hashed only offset and file id, so a mutation that kept both - a truncate shrinking chunk.Size, then a sparse extend back to the original length - passed both the size and fingerprint checks and served a stale view. Digest size, modification timestamp, cipher key, compression, manifest status, and SSE type as well.
This commit is contained in:
@@ -45,11 +45,15 @@ const (
|
||||
defaultFormatChunkSizeMB = 4
|
||||
)
|
||||
|
||||
// formatChunkIdentity digests the chunk list a layout was written against.
|
||||
// formatChunkIdentity digests the chunk list a layout was written against,
|
||||
// covering every field that changes what a read returns: a FUSE truncate, for
|
||||
// one, mutates Size while keeping the chunk's id.
|
||||
func formatChunkIdentity(chunks []*filer_pb.FileChunk) []byte {
|
||||
digest := md5.New()
|
||||
for _, chunk := range chunks {
|
||||
fmt.Fprintf(digest, "%d:%s;", chunk.Offset, chunk.GetFileIdString())
|
||||
fmt.Fprintf(digest, "%d:%s:%d:%d:%x:%t:%t:%d;",
|
||||
chunk.Offset, chunk.GetFileIdString(), chunk.Size, chunk.ModifiedTsNs,
|
||||
chunk.CipherKey, chunk.IsCompressed, chunk.IsChunkManifest, chunk.SseType)
|
||||
}
|
||||
return digest.Sum(nil)
|
||||
}
|
||||
|
||||
@@ -68,4 +68,26 @@ func TestFormatChunkIdentity(t *testing.T) {
|
||||
if bytes.Equal(identity, formatChunkIdentity(changedOffset)) {
|
||||
t.Fatalf("identity ignored an offset change")
|
||||
}
|
||||
// a truncate mutates Size while keeping the chunk id
|
||||
changedSize := []*filer_pb.FileChunk{
|
||||
{FileId: "1,ab", Offset: 0, Size: 10},
|
||||
{FileId: "2,cd", Offset: 10, Size: 15},
|
||||
}
|
||||
if bytes.Equal(identity, formatChunkIdentity(changedSize)) {
|
||||
t.Fatalf("identity ignored a size change")
|
||||
}
|
||||
changedMtime := []*filer_pb.FileChunk{
|
||||
{FileId: "1,ab", Offset: 0, Size: 10},
|
||||
{FileId: "2,cd", Offset: 10, Size: 20, ModifiedTsNs: 7},
|
||||
}
|
||||
if bytes.Equal(identity, formatChunkIdentity(changedMtime)) {
|
||||
t.Fatalf("identity ignored a modification timestamp change")
|
||||
}
|
||||
changedManifest := []*filer_pb.FileChunk{
|
||||
{FileId: "1,ab", Offset: 0, Size: 10},
|
||||
{FileId: "2,cd", Offset: 10, Size: 20, IsChunkManifest: true},
|
||||
}
|
||||
if bytes.Equal(identity, formatChunkIdentity(changedManifest)) {
|
||||
t.Fatalf("identity ignored a manifest flag change")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user