Added FUSE support #55
2
fuse.go
@ -9,7 +9,7 @@ import (
|
|||||||
"go.arsenm.dev/infinitime"
|
"go.arsenm.dev/infinitime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func startFuse(ctx context.Context, dev *infinitime.Device) error {
|
func startFUSE(ctx context.Context, dev *infinitime.Device) error {
|
||||||
yannickulrich marked this conversation as resolved
Outdated
|
|||||||
// This is where we'll mount the FS
|
// This is where we'll mount the FS
|
||||||
os.Mkdir(k.String("fuse.mountpoint"), 0755)
|
os.Mkdir(k.String("fuse.mountpoint"), 0755)
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
Use Use `os.MkdirAll` here instead so that it creates parent directories, and handle the error (just return it).
yannickulrich
commented
This is actually a bit more complicated than that. If the mountpoint already exists, fuse will crash. We also can't delete the mountpoint beforehand ( This is actually a bit more complicated than that. If the mountpoint already exists, fuse will crash. We also can't delete the mountpoint beforehand (`rm: cannot remove '/tmp/itd/mnt': Transport endpoint is not connected`). The best way to solve this should be calling the [unmount function](https://pkg.go.dev/github.com/hanwen/go-fuse/v2@v2.2.0/fuse#Server.Unmount). How would you suggest going about doing this?
Elara6331
commented
Yeah, this one is going to be a bit more complicated. The FUSE library does have a different unmount function that you could call before trying to mount the fs, but it's not exported, so we'll need to do a small hack to get access to it anyway. In the
|
|||||||
root := fusefs.BuildRootNode(dev)
|
root := fusefs.BuildRootNode(dev)
|
||||||
|
@ -36,6 +36,9 @@ type ITNode struct {
|
|||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var myfs *blefs.FS = nil
|
||||||
|
var inodemap map[string]uint64 = nil
|
||||||
|
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
This error needs to be handled, you can just return it in this case and update the code that calls this function to do the actual handling This error needs to be handled, you can just return it in this case and update the code that calls this function to do the actual handling
yannickulrich
commented
Done in Done in a54ca7a
|
|||||||
func BuildRootNode(dev *infinitime.Device) *ITNode {
|
func BuildRootNode(dev *infinitime.Device) *ITNode {
|
||||||
inodemap = make(map[string]uint64)
|
inodemap = make(map[string]uint64)
|
||||||
myfs, _ = dev.FS()
|
myfs, _ = dev.FS()
|
||||||
@ -80,10 +83,6 @@ func BuildProperties(dev *infinitime.Device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
These variables should go above These variables should go above `BuildRootNode` because it's using them and it would be more readable that way. Also, Go doesn't require semicolons, you can remove those.
yannickulrich
commented
Done in Done in 673383f
|
|||||||
|
|
||||||
|
|
||||||
var myfs *blefs.FS = nil;
|
|
||||||
var inodemap map[string]uint64 = nil;
|
|
||||||
|
|
||||||
var _ = (fs.NodeReaddirer)((*ITNode)(nil))
|
var _ = (fs.NodeReaddirer)((*ITNode)(nil))
|
||||||
|
|
||||||
// Readdir is part of the NodeReaddirer interface
|
// Readdir is part of the NodeReaddirer interface
|
||||||
@ -206,7 +205,7 @@ func (n *ITNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*
|
|||||||
|
|
||||||
for _, file := range n.lst {
|
for _, file := range n.lst {
|
||||||
if file.path != n.path + "/" + name {
|
if file.path != n.path + "/" + name {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
log.Info("LookUp successful").Str("path", file.path).Send()
|
log.Info("LookUp successful").Str("path", file.path).Send()
|
||||||
|
|
||||||
@ -230,7 +229,7 @@ func (n *ITNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*
|
|||||||
child := n.NewInode(ctx, operations, stable)
|
child := n.NewInode(ctx, operations, stable)
|
||||||
return child, 0
|
return child, 0
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
log.Warn("LookUp failed").Str("path", n.path + "/" + name).Send()
|
log.Warn("LookUp failed").Str("path", n.path + "/" + name).Send()
|
||||||
}
|
}
|
||||||
@ -298,7 +297,7 @@ func (fh *bytesFileWriteHandle) Flush(ctx context.Context) (errno syscall.Errno)
|
|||||||
go func() {
|
go func() {
|
||||||
// For every progress event
|
// For every progress event
|
||||||
for sent := range fp.Progress() {
|
for sent := range fp.Progress() {
|
||||||
log.Info("Progress").Int("bytes", int(sent)).Int("of", len(fh.content)).Send();
|
log.Info("Progress").Int("bytes", int(sent)).Int("of", len(fh.content)).Send()
|
||||||
}
|
}
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
```diff
- log.Info("Progress").Int("bytes", int(sent)).Int("of", len(fh.content)).Send()
+ log.Info("FUSE Write Progress").Int("bytes", int(sent)).Int("total", len(fh.content)).Send()
yannickulrich
commented
Done in Done in b5328ec
|
|||||||
}()
|
}()
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
This is not correct. If no content has been written, you should still create the file because the user might want to create an empty file using a command like This is not correct. If no content has been written, you should still create the file because the user might want to create an empty file using a command like `touch`.
yannickulrich
commented
Oh, good point, thank you. Should be fixed now. Oh, good point, thank you. Should be fixed now.
|
|||||||
|
|
||||||
@ -330,7 +329,7 @@ func (fh *bytesFileWriteHandle) Fsync(ctx context.Context, flags uint32) (errno
|
|||||||
|
|
||||||
var _ = (fs.NodeGetattrer)((*ITNode)(nil))
|
var _ = (fs.NodeGetattrer)((*ITNode)(nil))
|
||||||
func (bn *ITNode) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
func (bn *ITNode) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||||
log.Info("getattr").Str("path", bn.path).Send();
|
log.Info("getattr").Str("path", bn.path).Send()
|
||||||
out.Ino = bn.Ino
|
out.Ino = bn.Ino
|
||||||
yannickulrich marked this conversation as resolved
Elara6331
commented
These should be debug logs rather than info logs. Also, the message should be a bit more specific, something like "FUSE getattr". Same for all the similar logs. These should be debug logs rather than info logs. Also, the message should be a bit more specific, something like "FUSE getattr". Same for all the similar logs.
yannickulrich
commented
Done in Done in b5328ec
|
|||||||
out.Mtime = bn.self.modtime
|
out.Mtime = bn.self.modtime
|
||||||
out.Ctime = bn.self.modtime
|
out.Ctime = bn.self.modtime
|
||||||
@ -342,8 +341,8 @@ func (bn *ITNode) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOu
|
|||||||
var _ = (fs.NodeSetattrer)((*ITNode)(nil))
|
var _ = (fs.NodeSetattrer)((*ITNode)(nil))
|
||||||
func (bn *ITNode) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
|
func (bn *ITNode) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
|
||||||
log.Info("setattr").Str("path", bn.path).Send()
|
log.Info("setattr").Str("path", bn.path).Send()
|
||||||
out.Size = 0;
|
out.Size = 0
|
||||||
out.Mtime = 0;
|
out.Mtime = 0
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,10 +364,10 @@ func (f *ITNode) Open(ctx context.Context, openFlags uint32) (fh fs.FileHandle,
|
|||||||
}
|
}
|
||||||
return fh, fuse.FOPEN_DIRECT_IO, 0
|
return fh, fuse.FOPEN_DIRECT_IO, 0
|
||||||
} else {
|
} else {
|
||||||
log.Info("Opening file: read").Str("path", f.path).Send();
|
log.Info("Opening file: read").Str("path", f.path).Send()
|
||||||
fp, err := myfs.Open(f.path)
|
fp, err := myfs.Open(f.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Opening file failed").Str("path", f.path).Err(err).Send();
|
log.Error("Opening file failed").Str("path", f.path).Err(err).Send()
|
||||||
return nil, 0, syscall.EROFS
|
return nil, 0, syscall.EROFS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +378,7 @@ func (f *ITNode) Open(ctx context.Context, openFlags uint32) (fh fs.FileHandle,
|
|||||||
go func() {
|
go func() {
|
||||||
// For every progress event
|
// For every progress event
|
||||||
for sent := range fp.Progress() {
|
for sent := range fp.Progress() {
|
||||||
log.Info("Progress").Int("bytes", int(sent)).Int("of", int(f.self.size)).Send();
|
log.Info("Progress").Int("bytes", int(sent)).Int("of", int(f.self.size)).Send()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
2
main.go
@ -188,7 +188,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
// Start fuse socket
|
// Start fuse socket
|
||||||
if k.Bool("fuse.enabled") {
|
if k.Bool("fuse.enabled") {
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
FUSE should be started before the socket (socket should always be last) FUSE should be started before the socket (socket should always be last)
yannickulrich
commented
Done in Done in 3b96901
|
|||||||
err = startFuse(ctx, dev)
|
err = startFUSE(ctx, dev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error starting fuse socket").Err(err).Send()
|
log.Error("Error starting fuse socket").Err(err).Send()
|
||||||
}
|
}
|
||||||
|
This function should be called
startFUSE
instead to adhere to Go naming conventionsThanks, I'm relatively new to Go, sorry for these issues
Done in
673383f