Skip to content

Commit

Permalink
cmd/gc: fix the issue that pending delete objects are misclassified a…
Browse files Browse the repository at this point in the history
…s leaked (#5198)
  • Loading branch information
SandyXSD committed Sep 27, 2024
1 parent 730a347 commit 014a68d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 17 deletions.
2 changes: 1 addition & 1 deletion cmd/fsck.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func fsck(ctx *cli.Context) error {
// List all slices in metadata engine
sliceCSpin := progress.AddCountSpinner("Listed slices")
slices := make(map[meta.Ino][]meta.Slice)
r := m.ListSlices(c, slices, false, sliceCSpin.Increment)
r := m.ListSlices(c, slices, false, false, sliceCSpin.Increment)
if r != 0 {
logger.Fatalf("list all slices: %s", r)
}
Expand Down
27 changes: 21 additions & 6 deletions cmd/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func gc(ctx *cli.Context) error {

// List all slices in metadata engine
slices := make(map[meta.Ino][]meta.Slice)
r := m.ListSlices(c, slices, delete, sliceCSpin.Increment)
r := m.ListSlices(c, slices, true, delete, sliceCSpin.Increment)
if r != 0 {
logger.Fatalf("list all slices: %s", r)
}
Expand Down Expand Up @@ -247,9 +247,16 @@ func gc(ctx *cli.Context) error {
logger.Fatalf("list all blocks: %s", err)
}
vkeys := make(map[uint64]uint32)
pkeys := make(map[uint64]uint32)
ckeys := make(map[uint64]uint32)
var total int64
var totalBytes uint64
for _, s := range slices[0] {
pkeys[s.Id] = s.Size
total += int64(int(s.Size-1)/chunkConf.BlockSize) + 1
totalBytes += uint64(s.Size)
}
slices[0] = nil
for _, s := range slices[1] {
ckeys[s.Id] = s.Size
total += int64(int(s.Size-1)/chunkConf.BlockSize) + 1
Expand All @@ -269,6 +276,7 @@ func gc(ctx *cli.Context) error {

bar := progress.AddCountBar("Scanned objects", total)
valid := progress.AddDoubleSpinnerTwo("Valid objects", "Valid data")
pending := progress.AddDoubleSpinnerTwo("Pending delete objects", "Pending delete data")
compacted := progress.AddDoubleSpinnerTwo("Compacted objects", "Compacted data")
leaked := progress.AddDoubleSpinnerTwo("Leaked objects", "Leaked data")
skipped := progress.AddDoubleSpinnerTwo("Skipped objects", "Skipped data")
Expand Down Expand Up @@ -321,10 +329,12 @@ func gc(ctx *cli.Context) error {
bar.Increment()
cid, _ := strconv.Atoi(parts[0])
size := vkeys[uint64(cid)]
var cobj bool
var pobj, cobj bool
if size == 0 {
size, pobj = pkeys[uint64(cid)]
}
if size == 0 {
size = ckeys[uint64(cid)]
cobj = true
size, cobj = ckeys[uint64(cid)]
}
if size == 0 {
logger.Debugf("find leaked object: %s, size: %d", obj.Key(), obj.Size())
Expand All @@ -337,6 +347,8 @@ func gc(ctx *cli.Context) error {
if (indx+1)*csize > int(size) {
logger.Warnf("size of slice %d is larger than expected: %d > %d", cid, indx*chunkConf.BlockSize+csize, size)
foundLeaked(obj)
} else if pobj {
pending.IncrInt64(obj.Size())
} else if cobj {
compacted.IncrInt64(obj.Size())
} else {
Expand All @@ -346,6 +358,8 @@ func gc(ctx *cli.Context) error {
if indx*chunkConf.BlockSize+csize != int(size) {
logger.Warnf("size of slice %d is %d, but expect %d", cid, indx*chunkConf.BlockSize+csize, size)
foundLeaked(obj)
} else if pobj {
pending.IncrInt64(obj.Size())
} else if cobj {
compacted.IncrInt64(obj.Size())
} else {
Expand All @@ -371,13 +385,14 @@ func gc(ctx *cli.Context) error {
progress.Done()

vc, _ := valid.Current()
pc, pb := pending.Current()
cc, cb := compacted.Current()
lc, lb := leaked.Current()
sc, sb := skipped.Current()
dsc, dsb := cleanedSliceSpin.Current()
fc, fb := cleanedFileSpin.Current()
logger.Infof("scanned %d objects, %d valid, %d compacted (%d bytes), %d leaked (%d bytes), %d delslices (%d bytes), %d delfiles (%d bytes), %d skipped (%d bytes)",
bar.Current(), vc, cc, cb, lc, lb, dsc, dsb, fc, fb, sc, sb)
logger.Infof("scanned %d objects, %d valid, %d pending delete (%d bytes), %d compacted (%d bytes), %d leaked (%d bytes), %d delslices (%d bytes), %d delfiles (%d bytes), %d skipped (%d bytes)",
bar.Current(), vc, pc, pb, cc, cb, lc, lb, dsc, dsb, fc, fb, sc, sb)
if lc > 0 && !delete {
logger.Infof("Please add `--delete` to clean leaked objects")
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@ func testCompaction(t *testing.T, m Meta, trash bool) {
}
p.Done()
sliceMap := make(map[Ino][]Slice)
if st := m.ListSlices(ctx, sliceMap, false, nil); st != 0 {
if st := m.ListSlices(ctx, sliceMap, false, false, nil); st != 0 {
t.Fatalf("list all slices: %s", st)
}

Expand Down Expand Up @@ -1694,7 +1694,7 @@ func testTruncateAndDelete(t *testing.T, m Meta) {
}
var total int64
slices := make(map[Ino][]Slice)
m.ListSlices(ctx, slices, false, func() { total++ })
m.ListSlices(ctx, slices, false, false, func() { total++ })
var totalSlices int
for _, ss := range slices {
totalSlices += len(ss)
Expand All @@ -1709,7 +1709,7 @@ func testTruncateAndDelete(t *testing.T, m Meta) {

time.Sleep(time.Millisecond * 100)
slices = make(map[Ino][]Slice)
m.ListSlices(ctx, slices, false, nil)
m.ListSlices(ctx, slices, false, false, nil)
totalSlices = 0
for _, ss := range slices {
totalSlices += len(ss)
Expand Down
2 changes: 1 addition & 1 deletion pkg/meta/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ type Meta interface {
Compact(ctx Context, inode Ino, concurrency int, preFunc, postFunc func()) syscall.Errno

// ListSlices returns all slices used by all files.
ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, showProgress func()) syscall.Errno
ListSlices(ctx Context, slices map[Ino][]Slice, scanPending, delete bool, showProgress func()) syscall.Errno
// Remove all files and directories recursively.
// count represents the number of attempted deletions of entries (even if failed).
Remove(ctx Context, parent Ino, name string, count *uint64) syscall.Errno
Expand Down
27 changes: 25 additions & 2 deletions pkg/meta/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3041,7 +3041,7 @@ func (m *redisMeta) hscan(ctx context.Context, key string, f func([]string) erro
return nil
}

func (m *redisMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, showProgress func()) syscall.Errno {
func (m *redisMeta) ListSlices(ctx Context, slices map[Ino][]Slice, scanPending, delete bool, showProgress func()) syscall.Errno {
m.cleanupLeakedInodes(delete)
m.cleanupLeakedChunks(delete)
m.cleanupOldSliceRefs(delete)
Expand Down Expand Up @@ -3083,10 +3083,33 @@ func (m *redisMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool,
}
return nil
})
if err != nil || m.getFormat().TrashDays == 0 {
if err != nil {
logger.Warnf("scan chunks: %s", err)
return errno(err)
}

if scanPending {
_ = m.hscan(Background, m.sliceRefs(), func(keys []string) error {
for i := 0; i < len(keys); i += 2 {
key, val := keys[i], keys[i+1]
if strings.HasPrefix(val, "-") { // < 0
ps := strings.Split(key, "_")
if len(ps) == 2 {
id, _ := strconv.ParseUint(ps[0][1:], 10, 64)
size, _ := strconv.ParseUint(ps[1], 10, 32)
if id > 0 && size > 0 {
slices[0] = append(slices[0], Slice{Id: id, Size: uint32(size)})
}
}
}
}
return nil
})
}

if m.getFormat().TrashDays == 0 {
return 0
}
return errno(m.scanTrashSlices(ctx, func(ss []Slice, _ int64) (bool, error) {
slices[1] = append(slices[1], ss...)
if showProgress != nil {
Expand Down
18 changes: 16 additions & 2 deletions pkg/meta/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -2851,7 +2851,7 @@ func (m *dbMeta) scanAllChunks(ctx Context, ch chan<- cchunk, bar *utils.Bar) er
})
}

func (m *dbMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, showProgress func()) syscall.Errno {
func (m *dbMeta) ListSlices(ctx Context, slices map[Ino][]Slice, scanPending, delete bool, showProgress func()) syscall.Errno {
if delete {
m.doCleanupSlices()
}
Expand Down Expand Up @@ -2881,10 +2881,24 @@ func (m *dbMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, sh
if err != nil {
return errno(err)
}

if scanPending {
_ = m.roTxn(func(s *xorm.Session) error {
var cks []sliceRef
err := s.Where("refs <= 0").Find(&cks)
if err != nil {
return err
}
for _, ck := range cks {
slices[0] = append(slices[0], Slice{Id: ck.Id, Size: ck.Size})
}
return nil
})
}

if m.getFormat().TrashDays == 0 {
return 0
}

return errno(m.scanTrashSlices(ctx, func(ss []Slice, _ int64) (bool, error) {
slices[1] = append(slices[1], ss...)
if showProgress != nil {
Expand Down
16 changes: 14 additions & 2 deletions pkg/meta/tkv.go
Original file line number Diff line number Diff line change
Expand Up @@ -2392,7 +2392,7 @@ func (m *kvMeta) scanAllChunks(ctx Context, ch chan<- cchunk, bar *utils.Bar) er
})
}

func (m *kvMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, showProgress func()) syscall.Errno {
func (m *kvMeta) ListSlices(ctx Context, slices map[Ino][]Slice, scanPending, delete bool, showProgress func()) syscall.Errno {
if delete {
m.doCleanupSlices()
}
Expand Down Expand Up @@ -2421,10 +2421,22 @@ func (m *kvMeta) ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, sh
}
}
}

if scanPending {
// slice refs: Kccccccccnnnn
klen = 1 + 8 + 4
result, _ = m.scanValues(m.fmtKey("K"), -1, func(k, v []byte) bool {
return len(k) == klen && len(v) == 8 && parseCounter(v) < 0
})
for k := range result {
rb := utils.FromBuffer([]byte(k)[1:])
slices[0] = append(slices[0], Slice{Id: rb.Get64(), Size: rb.Get32()})
}
}

if m.getFormat().TrashDays == 0 {
return 0
}

return errno(m.scanTrashSlices(ctx, func(ss []Slice, _ int64) (bool, error) {
slices[1] = append(slices[1], ss...)
if showProgress != nil {
Expand Down

0 comments on commit 014a68d

Please sign in to comment.