talos/internal/pkg/mount/v2/unmount.go
Andrey Smirnov b453385bd9
feat: support volume configuration, provisioning, etc
This implements the first round of changes, replacing the volume backend
with the new implementation, while keeping most of the external
interfaces intact.

See #8367

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
2024-08-30 18:32:34 +04:00

77 lines
1.7 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package mount
import (
"context"
"fmt"
"time"
"golang.org/x/sys/unix"
)
func unmountLoop(ctx context.Context, printer func(string, ...any), target string, flags int, timeout time.Duration, extraMessage string) (bool, error) {
errCh := make(chan error, 1)
go func() {
errCh <- unix.Unmount(target, flags)
}()
start := time.Now()
progressTicker := time.NewTicker(timeout / 5)
defer progressTicker.Stop()
unmountLoop:
for {
select {
case <-ctx.Done():
return true, ctx.Err()
case err := <-errCh:
return true, err
case <-progressTicker.C:
timeLeft := timeout - time.Since(start)
if timeLeft <= 0 {
break unmountLoop
}
if printer != nil {
printer("unmounting %s%s is taking longer than expected, still waiting for %s", target, extraMessage, timeLeft)
}
}
}
return false, nil
}
// SafeUnmount unmounts the target path, first without force, then with force if the first attempt fails.
//
// It makes sure that unmounting has a finite operation timeout.
func SafeUnmount(ctx context.Context, printer func(string, ...any), target string) error {
const (
unmountTimeout = 90 * time.Second
unmountForceTimeout = 10 * time.Second
)
ok, err := unmountLoop(ctx, printer, target, 0, unmountTimeout, "")
if ok {
return err
}
if printer != nil {
printer("unmounting %s with force", target)
}
ok, err = unmountLoop(ctx, printer, target, unix.MNT_FORCE, unmountTimeout, " with force flag")
if ok {
return err
}
return fmt.Errorf("unmounting %s with force flag timed out", target)
}