talm

Форк
0
124 строки · 2.2 Кб
1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4

5
package mount
6

7
import (
8
	"bufio"
9
	"fmt"
10
	"log"
11
	"os"
12
	"strings"
13
	"time"
14

15
	"golang.org/x/sys/unix"
16
)
17

18
func unmountWithTimeout(target string, flags int, timeout time.Duration) error {
19
	errCh := make(chan error, 1)
20

21
	go func() {
22
		errCh <- unix.Unmount(target, flags)
23
	}()
24

25
	timer := time.NewTimer(timeout)
26
	defer timer.Stop()
27

28
	select {
29
	case <-timer.C:
30
		return fmt.Errorf("unmounting %s timed out after %s", target, timeout)
31
	case err := <-errCh:
32
		return err
33
	}
34
}
35

36
// UnmountAll attempts to unmount all the mounted filesystems via "self" mountinfo.
37
func UnmountAll() error {
38
	// timeout in seconds
39
	const timeout = 10
40

41
	ticker := time.NewTicker(time.Second)
42
	defer ticker.Stop()
43

44
	for range timeout {
45
		mounts, err := readMountInfo()
46
		if err != nil {
47
			return err
48
		}
49

50
		failedUnmounts := 0
51

52
		for _, mountInfo := range mounts {
53
			if mountInfo.MountPoint == "" {
54
				continue
55
			}
56

57
			if strings.HasPrefix(mountInfo.MountSource, "/dev/") {
58
				err = unmountWithTimeout(mountInfo.MountPoint, 0, time.Second)
59

60
				if err == nil {
61
					log.Printf("unmounted %s (%s)", mountInfo.MountPoint, mountInfo.MountSource)
62
				} else {
63
					log.Printf("failed unmounting %s: %s", mountInfo.MountPoint, err)
64

65
					failedUnmounts++
66
				}
67
			}
68
		}
69

70
		if failedUnmounts == 0 {
71
			break
72
		}
73

74
		log.Printf("retrying %d unmount operations...", failedUnmounts)
75

76
		<-ticker.C
77
	}
78

79
	return nil
80
}
81

82
type mountInfo struct {
83
	MountPoint  string
84
	MountSource string
85
}
86

87
func readMountInfo() ([]mountInfo, error) {
88
	f, err := os.Open("/proc/self/mountinfo")
89
	if err != nil {
90
		return nil, err
91
	}
92

93
	defer f.Close() //nolint:errcheck
94

95
	var mounts []mountInfo
96

97
	scanner := bufio.NewScanner(f)
98
	for scanner.Scan() {
99
		line := scanner.Text()
100

101
		parts := strings.SplitN(line, " - ", 2)
102

103
		if len(parts) < 2 {
104
			continue
105
		}
106

107
		var mntInfo mountInfo
108

109
		pre := strings.Fields(parts[0])
110
		post := strings.Fields(parts[1])
111

112
		if len(pre) >= 5 {
113
			mntInfo.MountPoint = pre[4]
114
		}
115

116
		if len(post) >= 1 {
117
			mntInfo.MountSource = post[1]
118
		}
119

120
		mounts = append(mounts, mntInfo)
121
	}
122

123
	return mounts, scanner.Err()
124
}
125

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.