From 5df6bf80b1495c140e2d038038bf002197287313 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 30 Nov 2024 16:07:18 +0100 Subject: [PATCH] fs: retry vss creation on VSS_E_SNAPSHOT_SET_IN_PROGRESS error Depending on the change packages, the VSS tests from ./cmd/restic and the fs package may overlap in time. This causes the snapshot creation to fail. Add retries in that case. --- internal/fs/vss_windows.go | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/fs/vss_windows.go b/internal/fs/vss_windows.go index 7281e0210..840e97107 100644 --- a/internal/fs/vss_windows.go +++ b/internal/fs/vss_windows.go @@ -171,6 +171,11 @@ func (h HRESULT) Str() string { return "UNKNOWN" } +// Error implements the error interface +func (h HRESULT) Error() string { + return h.Str() +} + // VssError encapsulates errors returned from calling VSS api. type vssError struct { text string @@ -195,6 +200,11 @@ func (e *vssError) Error() string { return fmt.Sprintf("VSS error: %s: %s (%#x)", e.text, e.hresult.Str(), e.hresult) } +// Unwrap returns the underlying HRESULT error +func (e *vssError) Unwrap() error { + return e.hresult +} + // vssTextError encapsulates errors returned from calling VSS api. type vssTextError struct { text string @@ -943,10 +953,23 @@ func NewVssSnapshot(provider string, "%s", volume)) } - snapshotSetID, err := iVssBackupComponents.StartSnapshotSet() - if err != nil { - iVssBackupComponents.Release() - return VssSnapshot{}, err + const retryStartSnapshotSetSleep = 5 * time.Second + var snapshotSetID ole.GUID + for { + var err error + snapshotSetID, err = iVssBackupComponents.StartSnapshotSet() + if errors.Is(err, VSS_E_SNAPSHOT_SET_IN_PROGRESS) && time.Now().Add(-retryStartSnapshotSetSleep).Before(deadline) { + // retry snapshot set creation while deadline is not reached + time.Sleep(retryStartSnapshotSetSleep) + continue + } + + if err != nil { + iVssBackupComponents.Release() + return VssSnapshot{}, err + } else { + break + } } if err := iVssBackupComponents.AddToSnapshotSet(volume, providerID, &snapshotSetID); err != nil {