mirror of
https://github.com/restic/restic.git
synced 2026-06-01 14:49:44 +00:00
check: consider split pack index entries as repository damage
This commit is contained in:
@@ -261,8 +261,15 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts global.Options, args
|
||||
}
|
||||
|
||||
errorsFound := false
|
||||
salvagePacks := restic.NewIDSet()
|
||||
|
||||
for _, hint := range hints {
|
||||
switch hint.(type) {
|
||||
switch hint := hint.(type) {
|
||||
case *repository.ErrIncompletePackEntry:
|
||||
printer.E("%s", hint.Error())
|
||||
salvagePacks.Insert(hint.PackID)
|
||||
errorsFound = true
|
||||
summary.NumErrors++
|
||||
case *repository.ErrDuplicatePacks:
|
||||
printer.S("%s", hint.Error())
|
||||
summary.HintRepairIndex = true
|
||||
@@ -295,7 +302,6 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts global.Options, args
|
||||
|
||||
orphanedPacks := 0
|
||||
errChan := make(chan error)
|
||||
salvagePacks := restic.NewIDSet()
|
||||
|
||||
printer.P("check all packs\n")
|
||||
go chkr.Packs(ctx, errChan)
|
||||
|
||||
@@ -17,6 +17,16 @@ import (
|
||||
|
||||
const maxStreamBufferSize = 4 * 1024 * 1024
|
||||
|
||||
// ErrIncompletePackEntry is returned when indexes contain different data for a pack.
|
||||
type ErrIncompletePackEntry struct {
|
||||
PackID restic.ID
|
||||
Indexes restic.IDSet
|
||||
}
|
||||
|
||||
func (e *ErrIncompletePackEntry) Error() string {
|
||||
return fmt.Sprintf("pack %v has different data in indexes: %v", e.PackID, e.Indexes)
|
||||
}
|
||||
|
||||
// ErrDuplicatePacks is returned when a pack is found in more than one index.
|
||||
type ErrDuplicatePacks struct {
|
||||
PackID restic.ID
|
||||
@@ -79,6 +89,9 @@ func computePackTypes(ctx context.Context, idx restic.ListBlobser) (map[restic.I
|
||||
func (c *Checker) LoadIndex(ctx context.Context, p restic.TerminalCounterFactory) (hints []error, errs []error) {
|
||||
debug.Log("Start")
|
||||
packToIndex := make(map[restic.ID]restic.IDSet)
|
||||
// in restic < 0.10.0, the blobs of a pack could be split over multiple indexes.
|
||||
// by now this is considered as repository damage.
|
||||
packToPackBlobHash := make(map[restic.ID]restic.IDSet)
|
||||
|
||||
// Use the repository's internal loadIndexWithCallback to handle per-index errors
|
||||
err := c.repo.loadIndexWithCallback(ctx, p, func(id restic.ID, idx *index.Index, err error) error {
|
||||
@@ -104,6 +117,14 @@ func (c *Checker) LoadIndex(ctx context.Context, p restic.TerminalCounterFactory
|
||||
packToIndex[blob.PackID].Insert(id)
|
||||
}
|
||||
|
||||
for pbs := range idx.EachByPack(ctx, restic.NewIDSet()) {
|
||||
packBlobHash := index.PackBlobsHash(pbs)
|
||||
if _, ok := packToPackBlobHash[pbs.PackID]; !ok {
|
||||
packToPackBlobHash[pbs.PackID] = restic.NewIDSet()
|
||||
}
|
||||
packToPackBlobHash[pbs.PackID].Insert(packBlobHash)
|
||||
}
|
||||
|
||||
debug.Log("%d blobs processed", cnt)
|
||||
return nil
|
||||
})
|
||||
@@ -120,7 +141,12 @@ func (c *Checker) LoadIndex(ctx context.Context, p restic.TerminalCounterFactory
|
||||
debug.Log("checking for duplicate packs")
|
||||
for packID := range packTypes {
|
||||
debug.Log(" check pack %v: contained in %d indexes", packID, len(packToIndex[packID]))
|
||||
if len(packToIndex[packID]) > 1 {
|
||||
if len(packToPackBlobHash[packID]) > 1 {
|
||||
hints = append(hints, &ErrIncompletePackEntry{
|
||||
PackID: packID,
|
||||
Indexes: packToIndex[packID],
|
||||
})
|
||||
} else if len(packToIndex[packID]) > 1 {
|
||||
hints = append(hints, &ErrDuplicatePacks{
|
||||
PackID: packID,
|
||||
Indexes: packToIndex[packID],
|
||||
|
||||
Reference in New Issue
Block a user