From 798a88363f6d223eb0e0b25d72c04b7c9901a8c8 Mon Sep 17 00:00:00 2001 From: Sandy Xu Date: Mon, 27 May 2024 17:26:36 +0800 Subject: [PATCH 1/2] meta: fix protection check for compaction --- pkg/meta/base.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/meta/base.go b/pkg/meta/base.go index f0461d048c57..bf0b5a571e03 100644 --- a/pkg/meta/base.go +++ b/pkg/meta/base.go @@ -2043,17 +2043,19 @@ func (m *baseMeta) compactChunk(inode Ino, indx uint32, once, force bool) { ss = ss[:maxCompactSlices] } skipped := skipSome(ss) - var first, last *slice - if skipped > 0 { - first, last = ss[0], ss[skipped-1] - } compacted := ss[skipped:] pos, size, slices := compactChunk(compacted) if len(compacted) < 2 || size == 0 { return } - if first != nil && last != nil && pos+size > first.pos && last.pos+last.len > pos { - panic(fmt.Sprintf("invalid compaction: skipped slices [%+v, %+v], pos %d, size %d", *first, *last, pos, size)) + for _, s := range ss[:skipped] { + if pos+size > s.pos && s.pos+s.len > pos { + var sstring string + for _, s := range ss { + sstring += fmt.Sprintf("\n%+v", *s) + } + panic(fmt.Sprintf("invalid compaction skipped %d, pos %d, size %d; slices: %s", skipped, pos, size, sstring)) + } } var id uint64 From 7e2f552ab2c137d01c7295c931236ecae9477f11 Mon Sep 17 00:00:00 2001 From: Sandy Xu Date: Mon, 27 May 2024 20:28:30 +0800 Subject: [PATCH 2/2] add unit test --- pkg/meta/base_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pkg/meta/base_test.go b/pkg/meta/base_test.go index c47e764237fe..d389f538915e 100644 --- a/pkg/meta/base_test.go +++ b/pkg/meta/base_test.go @@ -1551,6 +1551,26 @@ func testCompaction(t *testing.T, m Meta, trash bool) { if len(slices) != 1 || slices[0].Len != 3<<20 { t.Fatalf("inode %d should be compacted, but have %d slices, size %d", inode, len(slices), slices[0].Len) } + + m.NewSlice(ctx, &sliceId) + _ = m.Write(ctx, inode, 2, 0, Slice{Id: sliceId, Size: 2338508, Len: 2338508}, time.Now()) + m.NewSlice(ctx, &sliceId) + _ = m.Write(ctx, inode, 2, 8829056, Slice{Id: sliceId, Size: 1074933, Len: 1074933}, time.Now()) + m.NewSlice(ctx, &sliceId) + _ = m.Write(ctx, inode, 2, 7663608, Slice{Id: sliceId, Size: 41480, Len: 4148}, time.Now()) + _ = m.Fallocate(ctx, inode, fallocZeroRange, 2*ChunkSize+4515328, 3152428, nil) + _ = m.Fallocate(ctx, inode, fallocZeroRange, 2*ChunkSize+4515328, 2607724, nil) + if c, ok := m.(compactor); ok { + c.compactChunk(inode, 2, false, true) + } + if st := m.Read(ctx, inode, 2, &slices); st != 0 { + t.Fatalf("read 1: %s", st) + } + // compact twice: 4515328+2607724-2338508 = 4784544; 8829056+1074933-2338508-4784544=2780937 + if len(slices) != 3 || slices[0].Len != 2338508 || slices[1].Len != 4784544 || slices[2].Len != 2780937 { + t.Fatalf("inode %d should be compacted, but have %d slices, size %d,%d,%d", + inode, len(slices), slices[0].Len, slices[1].Len, slices[2].Len) + } } func testConcurrentWrite(t *testing.T, m Meta) {