diff --git a/weed/mount/content_flush_condition_test.go b/weed/mount/content_flush_condition_test.go index ba9d588651..3cf80501b6 100644 --- a/weed/mount/content_flush_condition_test.go +++ b/weed/mount/content_flush_condition_test.go @@ -316,6 +316,13 @@ func TestMergeContentEntry(t *testing.T) { t.Fatalf("truncate then write kept %v, size %d", got, merged.Attributes.FileSize) } + // Shortening a manifest reference leaves its members whole. + peerManifest := proto.Clone(base).(*filer_pb.Entry) + peerManifest.Chunks = append(peerManifest.Chunks, &filer_pb.FileChunk{Fid: &filer_pb.FileId{VolumeId: 1, FileKey: 5, Cookie: 1}, Offset: 0, Size: 10, IsChunkManifest: true}) + if _, ok := mergeContentEntry(peerManifest, base, regrown, regrown, 1, false); ok { + t.Fatal("merged a peer manifest across the truncate") + } + // A peer truncate stands when the handle only overwrote inside it. peerTruncated := proto.Clone(base).(*filer_pb.Entry) peerTruncated.Chunks, peerTruncated.Attributes.FileSize = peerTruncated.Chunks[:1], 1 diff --git a/weed/mount/weedfs_file_sync.go b/weed/mount/weedfs_file_sync.go index 533d4f1034..adc95e0707 100644 --- a/weed/mount/weedfs_file_sync.go +++ b/weed/mount/weedfs_file_sync.go @@ -379,7 +379,8 @@ const maxContentFlushMerges = 3 // (truncatedTo, or -1); otherwise the stored size stands unless the handle // changed its size or wrote past it. // A different file at the path, inline content changed on both sides, -// inline content next to chunks (reads stop at the inline bytes), or a local +// inline content next to chunks (reads stop at the inline bytes), a manifest +// across the truncate (its members keep their sizes), or a local // whole-file rewrite (rewrote) over a peer's chunk change cannot be merged: // the rewrite carries the handle's stale view. func mergeContentEntry(stored, base, local, sent *filer_pb.Entry, truncatedTo int64, rewrote bool) (*filer_pb.Entry, bool) { @@ -417,6 +418,9 @@ func mergeContentEntry(stored, base, local, sent *filer_pb.Entry, truncatedTo in } c = proto.Clone(c).(*filer_pb.FileChunk) if truncatedTo >= 0 && c.Offset+int64(c.Size) > truncatedTo { + if c.IsChunkManifest { + return nil, false + } c.Size = uint64(truncatedTo - c.Offset) } merged.Chunks = append(merged.Chunks, c)