archiver: Fix race condition resulting in files containing null IDs
In some rare cases files could be created which contain null IDs (all zero) in their content list. This was caused by a race condition between growing the `Content` slice and inserting the blob IDs into it. In some cases the blob ID was written to the old slice, which a short time afterwards was replaced with a larger copy, that did not yet contain the blob ID.
This commit is contained in:
parent
5f9ac2b165
commit
5756c96c9f
2 changed files with 8 additions and 0 deletions
|
@ -48,14 +48,19 @@ func TestBlobSaver(t *testing.T) {
|
||||||
|
|
||||||
var wait sync.WaitGroup
|
var wait sync.WaitGroup
|
||||||
var results []SaveBlobResponse
|
var results []SaveBlobResponse
|
||||||
|
var lock sync.Mutex
|
||||||
|
|
||||||
wait.Add(20)
|
wait.Add(20)
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
buf := &Buffer{Data: []byte(fmt.Sprintf("foo%d", i))}
|
buf := &Buffer{Data: []byte(fmt.Sprintf("foo%d", i))}
|
||||||
idx := i
|
idx := i
|
||||||
|
lock.Lock()
|
||||||
results = append(results, SaveBlobResponse{})
|
results = append(results, SaveBlobResponse{})
|
||||||
|
lock.Unlock()
|
||||||
b.Save(ctx, restic.DataBlob, buf, func(res SaveBlobResponse) {
|
b.Save(ctx, restic.DataBlob, buf, func(res SaveBlobResponse) {
|
||||||
|
lock.Lock()
|
||||||
results[idx] = res
|
results[idx] = res
|
||||||
|
lock.Unlock()
|
||||||
wait.Done()
|
wait.Done()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,10 @@ func (s *FileSaver) saveFile(ctx context.Context, chnker *chunker.Chunker, snPat
|
||||||
|
|
||||||
// add a place to store the saveBlob result
|
// add a place to store the saveBlob result
|
||||||
pos := idx
|
pos := idx
|
||||||
|
|
||||||
|
lock.Lock()
|
||||||
node.Content = append(node.Content, restic.ID{})
|
node.Content = append(node.Content, restic.ID{})
|
||||||
|
lock.Unlock()
|
||||||
|
|
||||||
s.saveBlob(ctx, restic.DataBlob, buf, func(sbr SaveBlobResponse) {
|
s.saveBlob(ctx, restic.DataBlob, buf, func(sbr SaveBlobResponse) {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
|
|
Loading…
Reference in a new issue