github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/daemon/graphdriver/aufs/mount.go (about) 1 //go:build linux 2 // +build linux 3 4 package aufs // import "github.com/docker/docker/daemon/graphdriver/aufs" 5 6 import ( 7 "os/exec" 8 "syscall" 9 "time" 10 11 "github.com/moby/sys/mount" 12 "github.com/pkg/errors" 13 "golang.org/x/sys/unix" 14 ) 15 16 // Unmount the target specified. 17 func Unmount(target string) error { 18 const retries = 5 19 20 // auplink flush 21 for i := 0; ; i++ { 22 out, err := exec.Command("auplink", target, "flush").CombinedOutput() 23 if err == nil { 24 break 25 } 26 rc := 0 27 if exiterr, ok := err.(*exec.ExitError); ok { 28 if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { 29 rc = status.ExitStatus() 30 } 31 } 32 if i >= retries || rc != int(unix.EINVAL) { 33 logger.WithError(err).WithField("method", "Unmount").Warnf("auplink flush failed: %s", out) 34 break 35 } 36 // auplink failed to find target in /proc/self/mounts because 37 // kernel can't guarantee continuity while reading from it 38 // while mounts table is being changed 39 logger.Debugf("auplink flush error (retrying %d/%d): %s", i+1, retries, out) 40 } 41 42 // unmount 43 var err error 44 for i := 0; i < retries; i++ { 45 err = mount.Unmount(target) 46 if err != nil && errors.Is(err, unix.EBUSY) { 47 logger.Debugf("aufs unmount %s failed with EBUSY (retrying %d/%d)", target, i+1, retries) 48 time.Sleep(100 * time.Millisecond) 49 continue // try again 50 } 51 break 52 } 53 54 // either no error occurred, or another error 55 return err 56 }