Skip to content

Commit 2b87d45

Browse files
committed
Add retries when deleting a devmapper device
Signed-off-by: Maksym Pavlenko <[email protected]>
1 parent 1e624fa commit 2b87d45

1 file changed

Lines changed: 41 additions & 30 deletions

File tree

snapshots/devmapper/pool_device.go

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,33 @@ func NewPoolDevice(ctx context.Context, config *Config) (*PoolDevice, error) {
7575
return poolDevice, nil
7676
}
7777

78+
func retry(ctx context.Context, f func() error) error {
79+
var (
80+
maxRetries = 100
81+
retryDelay = 100 * time.Millisecond
82+
retryErr error
83+
)
84+
85+
for attempt := 1; attempt <= maxRetries; attempt++ {
86+
retryErr = f()
87+
if retryErr == nil {
88+
return nil
89+
} else if retryErr != unix.EBUSY {
90+
return retryErr
91+
}
92+
93+
// Don't spam logs
94+
if attempt%10 == 0 {
95+
log.G(ctx).WithError(retryErr).Warnf("retrying... (%d of %d)", attempt, maxRetries)
96+
}
97+
98+
// Devmapper device is busy, give it a bit of time and retry removal
99+
time.Sleep(retryDelay)
100+
}
101+
102+
return retryErr
103+
}
104+
78105
// ensureDeviceStates updates devices to their real state:
79106
// - marks devices with incomplete states (after crash) as 'Faulty'
80107
// - activates devices if they are marked as 'Activated' but the dm
@@ -393,30 +420,13 @@ func (p *PoolDevice) DeactivateDevice(ctx context.Context, deviceName string, de
393420
}
394421

395422
if err := p.transition(ctx, deviceName, Deactivating, Deactivated, func() error {
396-
var (
397-
maxRetries = 100
398-
retryDelay = 100 * time.Millisecond
399-
retryErr error
400-
)
401-
402-
for attempt := 1; attempt <= maxRetries; attempt++ {
403-
retryErr = dmsetup.RemoveDevice(deviceName, opts...)
404-
if retryErr == nil {
405-
return nil
406-
} else if retryErr != unix.EBUSY {
407-
return retryErr
408-
}
409-
410-
// Don't spam logs
411-
if attempt%10 == 0 {
412-
log.G(ctx).WithError(retryErr).Warnf("failed to deactivate device, retrying... (%d of %d)", attempt, maxRetries)
423+
return retry(ctx, func() error {
424+
if err := dmsetup.RemoveDevice(deviceName, opts...); err != nil {
425+
return errors.Wrap(err, "failed to deactivate device")
413426
}
414427

415-
// Devmapper device is busy, give it a bit of time and retry removal
416-
time.Sleep(retryDelay)
417-
}
418-
419-
return retryErr
428+
return nil
429+
})
420430
}); err != nil {
421431
return errors.Wrapf(err, "failed to deactivate device %q", deviceName)
422432
}
@@ -493,14 +503,15 @@ func (p *PoolDevice) RemoveDevice(ctx context.Context, deviceName string) error
493503

494504
func (p *PoolDevice) deleteDevice(ctx context.Context, info *DeviceInfo) error {
495505
if err := p.transition(ctx, info.Name, Removing, Removed, func() error {
496-
// Send 'delete' message to thin-pool
497-
e := dmsetup.DeleteDevice(p.poolName, info.DeviceID)
498-
499-
// Ignores the error if the device has been deleted already.
500-
if e != nil && !errors.Is(e, unix.ENODATA) {
501-
return e
502-
}
503-
return nil
506+
return retry(ctx, func() error {
507+
// Send 'delete' message to thin-pool
508+
e := dmsetup.DeleteDevice(p.poolName, info.DeviceID)
509+
// Ignores the error if the device has been deleted already.
510+
if e != nil && !errors.Is(e, unix.ENODATA) {
511+
return e
512+
}
513+
return nil
514+
})
504515
}); err != nil {
505516
return errors.Wrapf(err, "failed to delete device %q (dev id: %d)", info.Name, info.DeviceID)
506517
}

0 commit comments

Comments
 (0)