github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/fuse/mount/mount.go (about) 1 // package mount provides a simple abstraction around a mount point 2 package mount 3 4 import ( 5 "fmt" 6 "io" 7 "os/exec" 8 "runtime" 9 "time" 10 11 goprocess "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess" 12 13 u "github.com/ipfs/go-ipfs/util" 14 ) 15 16 var log = u.Logger("mount") 17 18 var MountTimeout = time.Second * 5 19 20 // Mount represents a filesystem mount 21 type Mount interface { 22 // MountPoint is the path at which this mount is mounted 23 MountPoint() string 24 25 // Unmounts the mount 26 Unmount() error 27 28 // Process returns the mount's Process to be able to link it 29 // to other processes. Unmount upon closing. 30 Process() goprocess.Process 31 } 32 33 // ForceUnmount attempts to forcibly unmount a given mount. 34 // It does so by calling diskutil or fusermount directly. 35 func ForceUnmount(m Mount) error { 36 point := m.MountPoint() 37 log.Warningf("Force-Unmounting %s...", point) 38 39 var cmd *exec.Cmd 40 switch runtime.GOOS { 41 case "darwin": 42 cmd = exec.Command("diskutil", "umount", "force", point) 43 case "linux": 44 cmd = exec.Command("fusermount", "-u", point) 45 default: 46 return fmt.Errorf("unmount: unimplemented") 47 } 48 49 errc := make(chan error, 1) 50 go func() { 51 defer close(errc) 52 53 // try vanilla unmount first. 54 if err := exec.Command("umount", point).Run(); err == nil { 55 return 56 } 57 58 // retry to unmount with the fallback cmd 59 errc <- cmd.Run() 60 }() 61 62 select { 63 case <-time.After(7 * time.Second): 64 return fmt.Errorf("umount timeout") 65 case err := <-errc: 66 return err 67 } 68 } 69 70 // ForceUnmountManyTimes attempts to forcibly unmount a given mount, 71 // many times. It does so by calling diskutil or fusermount directly. 72 // Attempts a given number of times. 73 func ForceUnmountManyTimes(m Mount, attempts int) error { 74 var err error 75 for i := 0; i < attempts; i++ { 76 err = ForceUnmount(m) 77 if err == nil { 78 return err 79 } 80 81 <-time.After(time.Millisecond * 500) 82 } 83 return fmt.Errorf("Unmount %s failed after 10 seconds of trying.", m.MountPoint()) 84 } 85 86 type closer struct { 87 M Mount 88 } 89 90 func (c *closer) Close() error { 91 log.Error(" (c *closer) Close(),", c.M.MountPoint()) 92 return c.M.Unmount() 93 } 94 95 func Closer(m Mount) io.Closer { 96 return &closer{m} 97 }