forked from cerc-io/ipld-eth-server
Update vendor directory and make necessary code changes
Fixes for new geth version
This commit is contained in:
+162
@@ -0,0 +1,162 @@
|
||||
// +build !nofuse
|
||||
// +build !windows
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/jbenet/goprocess"
|
||||
)
|
||||
|
||||
var ErrNotMounted = errors.New("not mounted")
|
||||
|
||||
// mount implements go-ipfs/fuse/mount
|
||||
type mount struct {
|
||||
mpoint string
|
||||
filesys fs.FS
|
||||
fuseConn *fuse.Conn
|
||||
|
||||
active bool
|
||||
activeLock *sync.RWMutex
|
||||
|
||||
proc goprocess.Process
|
||||
}
|
||||
|
||||
// Mount mounts a fuse fs.FS at a given location, and returns a Mount instance.
|
||||
// parent is a ContextGroup to bind the mount's ContextGroup to.
|
||||
func NewMount(p goprocess.Process, fsys fs.FS, mountpoint string, allow_other bool) (Mount, error) {
|
||||
var conn *fuse.Conn
|
||||
var err error
|
||||
|
||||
if allow_other {
|
||||
conn, err = fuse.Mount(mountpoint, fuse.AllowOther())
|
||||
} else {
|
||||
conn, err = fuse.Mount(mountpoint)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := &mount{
|
||||
mpoint: mountpoint,
|
||||
fuseConn: conn,
|
||||
filesys: fsys,
|
||||
active: false,
|
||||
activeLock: &sync.RWMutex{},
|
||||
proc: goprocess.WithParent(p), // link it to parent.
|
||||
}
|
||||
m.proc.SetTeardown(m.unmount)
|
||||
|
||||
// launch the mounting process.
|
||||
if err := m.mount(); err != nil {
|
||||
_ = m.Unmount() // just in case.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *mount) mount() error {
|
||||
log.Infof("Mounting %s", m.MountPoint())
|
||||
|
||||
errs := make(chan error, 1)
|
||||
go func() {
|
||||
// fs.Serve blocks until the filesystem is unmounted.
|
||||
err := fs.Serve(m.fuseConn, m.filesys)
|
||||
log.Debugf("%s is unmounted", m.MountPoint())
|
||||
if err != nil {
|
||||
log.Debugf("fs.Serve returned (%s)", err)
|
||||
errs <- err
|
||||
}
|
||||
m.setActive(false)
|
||||
}()
|
||||
|
||||
// wait for the mount process to be done, or timed out.
|
||||
select {
|
||||
case <-time.After(MountTimeout):
|
||||
return fmt.Errorf("mounting %s timed out", m.MountPoint())
|
||||
case err := <-errs:
|
||||
return err
|
||||
case <-m.fuseConn.Ready:
|
||||
}
|
||||
|
||||
// check if the mount process has an error to report
|
||||
if err := m.fuseConn.MountError; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.setActive(true)
|
||||
|
||||
log.Infof("Mounted %s", m.MountPoint())
|
||||
return nil
|
||||
}
|
||||
|
||||
// umount is called exactly once to unmount this service.
|
||||
// note that closing the connection will not always unmount
|
||||
// properly. If that happens, we bring out the big guns
|
||||
// (mount.ForceUnmountManyTimes, exec unmount).
|
||||
func (m *mount) unmount() error {
|
||||
log.Infof("Unmounting %s", m.MountPoint())
|
||||
|
||||
// try unmounting with fuse lib
|
||||
err := fuse.Unmount(m.MountPoint())
|
||||
if err == nil {
|
||||
m.setActive(false)
|
||||
return nil
|
||||
}
|
||||
log.Warningf("fuse unmount err: %s", err)
|
||||
|
||||
// try closing the fuseConn
|
||||
err = m.fuseConn.Close()
|
||||
if err == nil {
|
||||
m.setActive(false)
|
||||
return nil
|
||||
}
|
||||
log.Warningf("fuse conn error: %s", err)
|
||||
|
||||
// try mount.ForceUnmountManyTimes
|
||||
if err := ForceUnmountManyTimes(m, 10); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Seemingly unmounted %s", m.MountPoint())
|
||||
m.setActive(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mount) Process() goprocess.Process {
|
||||
return m.proc
|
||||
}
|
||||
|
||||
func (m *mount) MountPoint() string {
|
||||
return m.mpoint
|
||||
}
|
||||
|
||||
func (m *mount) Unmount() error {
|
||||
if !m.IsActive() {
|
||||
return ErrNotMounted
|
||||
}
|
||||
|
||||
// call Process Close(), which calls unmount() exactly once.
|
||||
return m.proc.Close()
|
||||
}
|
||||
|
||||
func (m *mount) IsActive() bool {
|
||||
m.activeLock.RLock()
|
||||
defer m.activeLock.RUnlock()
|
||||
|
||||
return m.active
|
||||
}
|
||||
|
||||
func (m *mount) setActive(a bool) {
|
||||
m.activeLock.Lock()
|
||||
m.active = a
|
||||
m.activeLock.Unlock()
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// package mount provides a simple abstraction around a mount point
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
logging "github.com/ipfs/go-log"
|
||||
goprocess "github.com/jbenet/goprocess"
|
||||
)
|
||||
|
||||
var log = logging.Logger("mount")
|
||||
|
||||
var MountTimeout = time.Second * 5
|
||||
|
||||
// Mount represents a filesystem mount
|
||||
type Mount interface {
|
||||
// MountPoint is the path at which this mount is mounted
|
||||
MountPoint() string
|
||||
|
||||
// Unmounts the mount
|
||||
Unmount() error
|
||||
|
||||
// Checks if the mount is still active.
|
||||
IsActive() bool
|
||||
|
||||
// Process returns the mount's Process to be able to link it
|
||||
// to other processes. Unmount upon closing.
|
||||
Process() goprocess.Process
|
||||
}
|
||||
|
||||
// ForceUnmount attempts to forcibly unmount a given mount.
|
||||
// It does so by calling diskutil or fusermount directly.
|
||||
func ForceUnmount(m Mount) error {
|
||||
point := m.MountPoint()
|
||||
log.Warningf("Force-Unmounting %s...", point)
|
||||
|
||||
cmd, err := UnmountCmd(point)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errc := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(errc)
|
||||
|
||||
// try vanilla unmount first.
|
||||
if err := exec.Command("umount", point).Run(); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// retry to unmount with the fallback cmd
|
||||
errc <- cmd.Run()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(7 * time.Second):
|
||||
return fmt.Errorf("umount timeout")
|
||||
case err := <-errc:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// UnmountCmd creates an exec.Cmd that is GOOS-specific
|
||||
// for unmount a FUSE mount
|
||||
func UnmountCmd(point string) (*exec.Cmd, error) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
return exec.Command("diskutil", "umount", "force", point), nil
|
||||
case "linux":
|
||||
return exec.Command("fusermount", "-u", point), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unmount: unimplemented")
|
||||
}
|
||||
}
|
||||
|
||||
// ForceUnmountManyTimes attempts to forcibly unmount a given mount,
|
||||
// many times. It does so by calling diskutil or fusermount directly.
|
||||
// Attempts a given number of times.
|
||||
func ForceUnmountManyTimes(m Mount, attempts int) error {
|
||||
var err error
|
||||
for i := 0; i < attempts; i++ {
|
||||
err = ForceUnmount(m)
|
||||
if err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
<-time.After(time.Millisecond * 500)
|
||||
}
|
||||
return fmt.Errorf("unmount %s failed after 10 seconds of trying", m.MountPoint())
|
||||
}
|
||||
|
||||
type closer struct {
|
||||
M Mount
|
||||
}
|
||||
|
||||
func (c *closer) Close() error {
|
||||
log.Warning(" (c *closer) Close(),", c.M.MountPoint())
|
||||
return c.M.Unmount()
|
||||
}
|
||||
|
||||
func Closer(m Mount) io.Closer {
|
||||
return &closer{m}
|
||||
}
|
||||
Reference in New Issue
Block a user