From e597b99b55d0f00a23340f5b09961cdc269623e6 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 23 Apr 2022 11:28:18 +0200 Subject: [PATCH] repository: Reduce repack workers to prevent deadlock As repack streams packs these occupy one backend connection. Uploading a new pack also requires a backend connection. To prevent a deadlock during repack when reaching the backend connections limit, simply limit the repackWorker count to always leave one connection for uploading. --- internal/repository/repack.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/repository/repack.go b/internal/repository/repack.go index 14fef3f20..4d0ca8236 100644 --- a/internal/repository/repack.go +++ b/internal/repository/repack.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/restic/restic/internal/debug" + "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/ui/progress" @@ -23,6 +24,10 @@ const numRepackWorkers = 8 func Repack(ctx context.Context, repo restic.Repository, dstRepo restic.Repository, packs restic.IDSet, keepBlobs restic.BlobSet, p *progress.Counter) (obsoletePacks restic.IDSet, err error) { debug.Log("repacking %d packs while keeping %d blobs", len(packs), len(keepBlobs)) + if repo == dstRepo && dstRepo.Backend().Connections() < 2 { + return nil, errors.Fatal("repack step requires a backend connection limit of at least two") + } + var keepMutex sync.Mutex wg, wgCtx := errgroup.WithContext(ctx) @@ -86,7 +91,11 @@ func Repack(ctx context.Context, repo restic.Repository, dstRepo restic.Reposito return nil } - for i := 0; i < numRepackWorkers; i++ { + connectionLimit := dstRepo.Backend().Connections() - 1 + if connectionLimit > numRepackWorkers { + connectionLimit = numRepackWorkers + } + for i := 0; i < int(connectionLimit); i++ { wg.Go(worker) }