From 66f1035d933fe0923dd07ad9046bf0ab0deb7133 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 4 Mar 2015 23:59:06 +0100 Subject: [PATCH 1/4] simple nofuse build tag to allow freebsd compilation and maybe pave the way towards windows as well --- core/commands/mount_nofuse.go | 23 +++++++ core/commands/mount_unix.go | 2 +- fuse/ipns/ipns_test.go | 4 +- fuse/ipns/ipns_unix.go | 2 + fuse/ipns/link_unix.go | 2 + fuse/ipns/mount_unix.go | 2 +- fuse/ipns/nofuse.go | 38 +++++++++++ fuse/ipns/repub_unix.go | 2 + fuse/mount/fuse.go | 121 +++++++++++++++++++++++++++++++++ fuse/mount/mount.go | 111 ------------------------------ fuse/readonly/ipfs_test.go | 2 + fuse/readonly/mount_unix.go | 2 +- fuse/readonly/readonly_unix.go | 2 +- 13 files changed, 197 insertions(+), 116 deletions(-) create mode 100644 core/commands/mount_nofuse.go create mode 100644 fuse/ipns/nofuse.go create mode 100644 fuse/mount/fuse.go diff --git a/core/commands/mount_nofuse.go b/core/commands/mount_nofuse.go new file mode 100644 index 00000000000..9c3090bbb1c --- /dev/null +++ b/core/commands/mount_nofuse.go @@ -0,0 +1,23 @@ +// +build (linux darwin freebsd) and nofuse + +package commands + +import ( + "errors" + + cmds "github.com/jbenet/go-ipfs/commands" + "github.com/jbenet/go-ipfs/core" +) + +var MountCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Mounts IPFS to the filesystem (read-only) - !!Disabled!!", + ShortDescription: ` +Caution! Your version ipfs is compiled _without_ fuse support. +`, + }, +} + +func Mount(node *core.IpfsNode, fsdir, nsdir string) error { + return errors.New("not compiled in") +} diff --git a/core/commands/mount_unix.go b/core/commands/mount_unix.go index 5db9f815063..987cde5c49c 100644 --- a/core/commands/mount_unix.go +++ b/core/commands/mount_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd +// +build (linux darwin freebsd) and !nofuse package commands diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index 18984666910..83f175b3738 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -1,15 +1,17 @@ +// +build !nofuse + package ipns import ( "bytes" "crypto/rand" - context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" "io/ioutil" "os" "testing" "time" fstest "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil" + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" core "github.com/jbenet/go-ipfs/core" u "github.com/jbenet/go-ipfs/util" diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index edb126f6c41..d6c605520ba 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -1,3 +1,5 @@ +// +build !nofuse + // package fuse/ipns implements a fuse filesystem that interfaces // with ipns, the naming system for ipfs. package ipns diff --git a/fuse/ipns/link_unix.go b/fuse/ipns/link_unix.go index 2b3bd0065a0..5353296d813 100644 --- a/fuse/ipns/link_unix.go +++ b/fuse/ipns/link_unix.go @@ -1,3 +1,5 @@ +// +build !nofuse + package ipns import ( diff --git a/fuse/ipns/mount_unix.go b/fuse/ipns/mount_unix.go index ea3e499a41a..37eb8aa1077 100644 --- a/fuse/ipns/mount_unix.go +++ b/fuse/ipns/mount_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd +// +build (linux darwin freebsd) and !nofuse package ipns diff --git a/fuse/ipns/nofuse.go b/fuse/ipns/nofuse.go new file mode 100644 index 00000000000..d8e19d8c0d4 --- /dev/null +++ b/fuse/ipns/nofuse.go @@ -0,0 +1,38 @@ +// +build nofuse + +package ipns + +import ( + "errors" + + "github.com/jbenet/go-ipfs/core" + ci "github.com/jbenet/go-ipfs/p2p/crypto" +) + +// InitializeKeyspace sets the ipns record for the given key to +// point to an empty directory. +func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { + // emptyDir := &mdag.Node{Data: ft.FolderPBData()} + // nodek, err := n.DAG.Add(emptyDir) + // if err != nil { + // return err + // } + + // err = n.Pinning.Pin(emptyDir, false) + // if err != nil { + // return err + // } + + // err = n.Pinning.Flush() + // if err != nil { + // return err + // } + + // pub := nsys.NewRoutingPublisher(n.Routing) + // err = pub.Publish(n.Context(), key, nodek) + // if err != nil { + // return err + // } + + return errors.New("how is this fuse related?") +} diff --git a/fuse/ipns/repub_unix.go b/fuse/ipns/repub_unix.go index 4e807578d3a..9e3d7ac5beb 100644 --- a/fuse/ipns/repub_unix.go +++ b/fuse/ipns/repub_unix.go @@ -1,3 +1,5 @@ +// +build !nofuse + package ipns import "time" diff --git a/fuse/mount/fuse.go b/fuse/mount/fuse.go new file mode 100644 index 00000000000..e63ac8c4435 --- /dev/null +++ b/fuse/mount/fuse.go @@ -0,0 +1,121 @@ +// +build !nofuse + +package mount + +import ( + "fmt" + "time" + + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse" + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs" + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup" +) + +// mount implements go-ipfs/fuse/mount +type mount struct { + mpoint string + filesys fs.FS + fuseConn *fuse.Conn + // closeErr error + + cg ctxgroup.ContextGroup +} + +// 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 ctxgroup.ContextGroup, fsys fs.FS, mountpoint string) (Mount, error) { + conn, err := fuse.Mount(mountpoint) + if err != nil { + return nil, err + } + + m := &mount{ + mpoint: mountpoint, + fuseConn: conn, + filesys: fsys, + cg: ctxgroup.WithParent(p), // link it to parent. + } + m.cg.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() { + err := fs.Serve(m.fuseConn, m.filesys) + log.Debugf("Mounting %s -- fs.Serve returned (%s)", err) + errs <- err + close(errs) + }() + + // 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 + } + + 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 { + return nil + } + log.Debug("fuse unmount err: %s", err) + + // try closing the fuseConn + err = m.fuseConn.Close() + if err == nil { + return nil + } + if err != nil { + log.Debug("fuse conn error: %s", err) + } + + // try mount.ForceUnmountManyTimes + if err := ForceUnmountManyTimes(m, 10); err != nil { + return err + } + + log.Infof("Seemingly unmounted %s", m.MountPoint()) + return nil +} + +func (m *mount) CtxGroup() ctxgroup.ContextGroup { + return m.cg +} + +func (m *mount) MountPoint() string { + return m.mpoint +} + +func (m *mount) Unmount() error { + // call ContextCloser Close(), which calls unmount() exactly once. + return m.cg.Close() +} diff --git a/fuse/mount/mount.go b/fuse/mount/mount.go index 9e73a000f54..a114d180b9c 100644 --- a/fuse/mount/mount.go +++ b/fuse/mount/mount.go @@ -7,8 +7,6 @@ import ( "runtime" "time" - fuse "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse" - fs "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs" ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup" u "github.com/jbenet/go-ipfs/util" @@ -31,115 +29,6 @@ type Mount interface { CtxGroup() ctxgroup.ContextGroup } -// mount implements go-ipfs/fuse/mount -type mount struct { - mpoint string - filesys fs.FS - fuseConn *fuse.Conn - // closeErr error - - cg ctxgroup.ContextGroup -} - -// 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 ctxgroup.ContextGroup, fsys fs.FS, mountpoint string) (Mount, error) { - conn, err := fuse.Mount(mountpoint) - if err != nil { - return nil, err - } - - m := &mount{ - mpoint: mountpoint, - fuseConn: conn, - filesys: fsys, - cg: ctxgroup.WithParent(p), // link it to parent. - } - m.cg.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() { - err := fs.Serve(m.fuseConn, m.filesys) - log.Debugf("Mounting %s -- fs.Serve returned (%s)", err) - errs <- err - close(errs) - }() - - // 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 - } - - 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 { - return nil - } - log.Debug("fuse unmount err: %s", err) - - // try closing the fuseConn - err = m.fuseConn.Close() - if err == nil { - return nil - } - if err != nil { - log.Debug("fuse conn error: %s", err) - } - - // try mount.ForceUnmountManyTimes - if err := ForceUnmountManyTimes(m, 10); err != nil { - return err - } - - log.Infof("Seemingly unmounted %s", m.MountPoint()) - return nil -} - -func (m *mount) CtxGroup() ctxgroup.ContextGroup { - return m.cg -} - -func (m *mount) MountPoint() string { - return m.mpoint -} - -func (m *mount) Unmount() error { - // call ContextCloser Close(), which calls unmount() exactly once. - return m.cg.Close() -} - // ForceUnmount attempts to forcibly unmount a given mount. // It does so by calling diskutil or fusermount directly. func ForceUnmount(m Mount) error { diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go index ebdfac56ff7..9816b59c2a9 100644 --- a/fuse/readonly/ipfs_test.go +++ b/fuse/readonly/ipfs_test.go @@ -1,3 +1,5 @@ +// +build !nofuse + package readonly import ( diff --git a/fuse/readonly/mount_unix.go b/fuse/readonly/mount_unix.go index d81d51b9c63..54e2ae47a24 100644 --- a/fuse/readonly/mount_unix.go +++ b/fuse/readonly/mount_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd +// +build (linux darwin freebsd) and !nofuse package readonly diff --git a/fuse/readonly/readonly_unix.go b/fuse/readonly/readonly_unix.go index ed4b80f5d1d..159dd0718b4 100644 --- a/fuse/readonly/readonly_unix.go +++ b/fuse/readonly/readonly_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd +// +build (linux darwin freebsd) and !nofuse // package fuse/readonly implements a fuse filesystem to access files // stored inside of ipfs. From 293234ae636fabfcc5406a9aab6e68c4e7cb928d Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 5 Mar 2015 00:18:59 +0100 Subject: [PATCH 2/4] InitializeKeyspace doesnt care about fuse --- fuse/ipns/common.go | 37 +++++++++++++++++++++++++++++++++++++ fuse/ipns/ipns_unix.go | 29 ----------------------------- fuse/ipns/nofuse.go | 38 -------------------------------------- 3 files changed, 37 insertions(+), 67 deletions(-) create mode 100644 fuse/ipns/common.go delete mode 100644 fuse/ipns/nofuse.go diff --git a/fuse/ipns/common.go b/fuse/ipns/common.go new file mode 100644 index 00000000000..45c391d75c8 --- /dev/null +++ b/fuse/ipns/common.go @@ -0,0 +1,37 @@ +package ipns + +import ( + "github.com/jbenet/go-ipfs/core" + mdag "github.com/jbenet/go-ipfs/merkledag" + nsys "github.com/jbenet/go-ipfs/namesys" + ci "github.com/jbenet/go-ipfs/p2p/crypto" + ft "github.com/jbenet/go-ipfs/unixfs" +) + +// InitializeKeyspace sets the ipns record for the given key to +// point to an empty directory. +func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { + emptyDir := &mdag.Node{Data: ft.FolderPBData()} + nodek, err := n.DAG.Add(emptyDir) + if err != nil { + return err + } + + err = n.Pinning.Pin(emptyDir, false) + if err != nil { + return err + } + + err = n.Pinning.Flush() + if err != nil { + return err + } + + pub := nsys.NewRoutingPublisher(n.Routing) + err = pub.Publish(n.Context(), key, nodek) + if err != nil { + return err + } + + return nil +} diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index d6c605520ba..645b9ce2771 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -20,7 +20,6 @@ import ( core "github.com/jbenet/go-ipfs/core" chunk "github.com/jbenet/go-ipfs/importer/chunk" mdag "github.com/jbenet/go-ipfs/merkledag" - nsys "github.com/jbenet/go-ipfs/namesys" ci "github.com/jbenet/go-ipfs/p2p/crypto" path "github.com/jbenet/go-ipfs/path" ft "github.com/jbenet/go-ipfs/unixfs" @@ -39,34 +38,6 @@ var ( longRepublishTimeout = time.Millisecond * 500 ) -// InitializeKeyspace sets the ipns record for the given key to -// point to an empty directory. -func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { - emptyDir := &mdag.Node{Data: ft.FolderPBData()} - nodek, err := n.DAG.Add(emptyDir) - if err != nil { - return err - } - - err = n.Pinning.Pin(emptyDir, false) - if err != nil { - return err - } - - err = n.Pinning.Flush() - if err != nil { - return err - } - - pub := nsys.NewRoutingPublisher(n.Routing) - err = pub.Publish(n.Context(), key, nodek) - if err != nil { - return err - } - - return nil -} - // FileSystem is the readwrite IPNS Fuse Filesystem. type FileSystem struct { Ipfs *core.IpfsNode diff --git a/fuse/ipns/nofuse.go b/fuse/ipns/nofuse.go deleted file mode 100644 index d8e19d8c0d4..00000000000 --- a/fuse/ipns/nofuse.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build nofuse - -package ipns - -import ( - "errors" - - "github.com/jbenet/go-ipfs/core" - ci "github.com/jbenet/go-ipfs/p2p/crypto" -) - -// InitializeKeyspace sets the ipns record for the given key to -// point to an empty directory. -func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { - // emptyDir := &mdag.Node{Data: ft.FolderPBData()} - // nodek, err := n.DAG.Add(emptyDir) - // if err != nil { - // return err - // } - - // err = n.Pinning.Pin(emptyDir, false) - // if err != nil { - // return err - // } - - // err = n.Pinning.Flush() - // if err != nil { - // return err - // } - - // pub := nsys.NewRoutingPublisher(n.Routing) - // err = pub.Publish(n.Context(), key, nodek) - // if err != nil { - // return err - // } - - return errors.New("how is this fuse related?") -} From e55aaf3f832bb42e8b943470e6653b67f664dd3f Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 5 Mar 2015 00:45:38 +0100 Subject: [PATCH 3/4] nofuse: better help description for 'ipfs mount' --- core/commands/mount_nofuse.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/commands/mount_nofuse.go b/core/commands/mount_nofuse.go index 9c3090bbb1c..60c2b01017d 100644 --- a/core/commands/mount_nofuse.go +++ b/core/commands/mount_nofuse.go @@ -11,9 +11,14 @@ import ( var MountCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Mounts IPFS to the filesystem (read-only) - !!Disabled!!", + Tagline: "Mounts IPFS to the filesystem (disabled)", ShortDescription: ` -Caution! Your version ipfs is compiled _without_ fuse support. +This version of ipfs is compiled without fuse support, which is required +for mounting. If you'd like to be able to mount, please use a version of +ipfs compiled with fuse. + +For the latest instructions, please check the project's repository: + http://github.com/jbenet/go-ipfs `, }, } From 40e0a5a886f607200e312645c13ebea97047166d Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 5 Mar 2015 01:01:10 +0100 Subject: [PATCH 4/4] added nofuse make target --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 231c8442ffd..98712baf665 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ install: build: cd cmd/ipfs && go build -i +nofuse: + cd cmd/ipfs && go install -tags nofuse + ############################################################## # tests targets