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/.
15
"golang.org/x/sys/unix"
18
func unmountWithTimeout(target string, flags int, timeout time.Duration) error {
19
errCh := make(chan error, 1)
22
errCh <- unix.Unmount(target, flags)
25
timer := time.NewTimer(timeout)
30
return fmt.Errorf("unmounting %s timed out after %s", target, timeout)
36
// UnmountAll attempts to unmount all the mounted filesystems via "self" mountinfo.
37
func UnmountAll() error {
41
ticker := time.NewTicker(time.Second)
45
mounts, err := readMountInfo()
52
for _, mountInfo := range mounts {
53
if mountInfo.MountPoint == "" {
57
if strings.HasPrefix(mountInfo.MountSource, "/dev/") {
58
err = unmountWithTimeout(mountInfo.MountPoint, 0, time.Second)
61
log.Printf("unmounted %s (%s)", mountInfo.MountPoint, mountInfo.MountSource)
63
log.Printf("failed unmounting %s: %s", mountInfo.MountPoint, err)
70
if failedUnmounts == 0 {
74
log.Printf("retrying %d unmount operations...", failedUnmounts)
82
type mountInfo struct {
87
func readMountInfo() ([]mountInfo, error) {
88
f, err := os.Open("/proc/self/mountinfo")
93
defer f.Close() //nolint:errcheck
95
var mounts []mountInfo
97
scanner := bufio.NewScanner(f)
99
line := scanner.Text()
101
parts := strings.SplitN(line, " - ", 2)
107
var mntInfo mountInfo
109
pre := strings.Fields(parts[0])
110
post := strings.Fields(parts[1])
113
mntInfo.MountPoint = pre[4]
117
mntInfo.MountSource = post[1]
120
mounts = append(mounts, mntInfo)
123
return mounts, scanner.Err()