Merge pull request #3740 from MichaelEischer/fix-restore-size-stats
Fix restore size calculation for multiple snapshots
This commit is contained in:
commit
ab49c14621
2 changed files with 13 additions and 9 deletions
8
changelog/unreleased/issue-3736
Normal file
8
changelog/unreleased/issue-3736
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Bugfix: `stats` fix restore size calculation for multiple snapshots
|
||||||
|
|
||||||
|
Since restic 0.10.0 the restore size calculated by the `stats` command for
|
||||||
|
multiple snapshots was too low. The hardlink detection was accidentally applied
|
||||||
|
across multiple snapshots and thus ignored many files. This has been fixed.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/3736
|
||||||
|
https://github.com/restic/restic/pull/3740
|
|
@ -111,7 +111,6 @@ func runStats(gopts GlobalOptions, args []string) error {
|
||||||
// create a container for the stats (and other needed state)
|
// create a container for the stats (and other needed state)
|
||||||
stats := &statsContainer{
|
stats := &statsContainer{
|
||||||
uniqueFiles: make(map[fileID]struct{}),
|
uniqueFiles: make(map[fileID]struct{}),
|
||||||
uniqueInodes: make(map[uint64]struct{}),
|
|
||||||
fileBlobs: make(map[string]restic.IDSet),
|
fileBlobs: make(map[string]restic.IDSet),
|
||||||
blobs: restic.NewBlobSet(),
|
blobs: restic.NewBlobSet(),
|
||||||
snapshotsCount: 0,
|
snapshotsCount: 0,
|
||||||
|
@ -175,7 +174,8 @@ func statsWalkSnapshot(ctx context.Context, snapshot *restic.Snapshot, repo rest
|
||||||
return restic.FindUsedBlobs(ctx, repo, restic.IDs{*snapshot.Tree}, stats.blobs, nil)
|
return restic.FindUsedBlobs(ctx, repo, restic.IDs{*snapshot.Tree}, stats.blobs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := walker.Walk(ctx, repo, *snapshot.Tree, restic.NewIDSet(), statsWalkTree(repo, stats))
|
uniqueInodes := make(map[uint64]struct{})
|
||||||
|
err := walker.Walk(ctx, repo, *snapshot.Tree, restic.NewIDSet(), statsWalkTree(repo, stats, uniqueInodes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("walking tree %s: %v", *snapshot.Tree, err)
|
return fmt.Errorf("walking tree %s: %v", *snapshot.Tree, err)
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ func statsWalkSnapshot(ctx context.Context, snapshot *restic.Snapshot, repo rest
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func statsWalkTree(repo restic.Repository, stats *statsContainer) walker.WalkFunc {
|
func statsWalkTree(repo restic.Repository, stats *statsContainer, uniqueInodes map[uint64]struct{}) walker.WalkFunc {
|
||||||
return func(parentTreeID restic.ID, npath string, node *restic.Node, nodeErr error) (bool, error) {
|
return func(parentTreeID restic.ID, npath string, node *restic.Node, nodeErr error) (bool, error) {
|
||||||
if nodeErr != nil {
|
if nodeErr != nil {
|
||||||
return true, nodeErr
|
return true, nodeErr
|
||||||
|
@ -242,8 +242,8 @@ func statsWalkTree(repo restic.Repository, stats *statsContainer) walker.WalkFun
|
||||||
|
|
||||||
// if inodes are present, only count each inode once
|
// if inodes are present, only count each inode once
|
||||||
// (hard links do not increase restore size)
|
// (hard links do not increase restore size)
|
||||||
if _, ok := stats.uniqueInodes[node.Inode]; !ok || node.Inode == 0 {
|
if _, ok := uniqueInodes[node.Inode]; !ok || node.Inode == 0 {
|
||||||
stats.uniqueInodes[node.Inode] = struct{}{}
|
uniqueInodes[node.Inode] = struct{}{}
|
||||||
stats.TotalSize += node.Size
|
stats.TotalSize += node.Size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,10 +290,6 @@ type statsContainer struct {
|
||||||
// contents (hashed sequence of content blob IDs)
|
// contents (hashed sequence of content blob IDs)
|
||||||
uniqueFiles map[fileID]struct{}
|
uniqueFiles map[fileID]struct{}
|
||||||
|
|
||||||
// uniqueInodes marks visited files according to their
|
|
||||||
// inode # (hashed sequence of inode numbers)
|
|
||||||
uniqueInodes map[uint64]struct{}
|
|
||||||
|
|
||||||
// fileBlobs maps a file name (path) to the set of
|
// fileBlobs maps a file name (path) to the set of
|
||||||
// blobs that have been seen as a part of the file
|
// blobs that have been seen as a part of the file
|
||||||
fileBlobs map[string]restic.IDSet
|
fileBlobs map[string]restic.IDSet
|
||||||
|
|
Loading…
Reference in a new issue