Added FUSE support #55
10
fuse.go
@ -12,7 +12,15 @@ import (
|
|||||||
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, err := fusefs.BuildRootNode(dev)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Building root node failed").
|
||||||
|
Err(err).
|
||||||
|
Send()
|
||||||
|
return err
|
||||||
|
return err
|
||||||
yannickulrich marked this conversation as resolved
Outdated
Elara6331
commented
`err` is returned twice here
yannickulrich
commented
Oh, sorry, fixed now Oh, sorry, fixed now
|
|||||||
|
}
|
||||||
|
|
||||||
server, err := fs.Mount(k.String("fuse.mountpoint"), root, &fs.Options{
|
server, err := fs.Mount(k.String("fuse.mountpoint"), root, &fs.Options{
|
||||||
MountOptions: fuse.MountOptions{
|
MountOptions: fuse.MountOptions{
|
||||||
// Set to true to see how the file system works.
|
// Set to true to see how the file system works.
|
||||||
|
@ -39,11 +39,16 @@ type ITNode struct {
|
|||||||
var myfs *blefs.FS = nil
|
var myfs *blefs.FS = nil
|
||||||
var inodemap map[string]uint64 = 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, error) {
|
||||||
|
var err error
|
||||||
inodemap = make(map[string]uint64)
|
inodemap = make(map[string]uint64)
|
||||||
myfs, _ = dev.FS()
|
myfs, err = dev.FS()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("FUSE failed to get filesystem").Err(err).Send()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &ITNode{kind: 0}
|
return &ITNode{kind: 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var properties = make([]ITProperty, 6)
|
var properties = make([]ITProperty, 6)
|
||||||
@ -118,12 +123,21 @@ func (n *ITNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// on device
|
// on device
|
||||||
files, _ := myfs.ReadDir(n.path)
|
files, err := myfs.ReadDir(n.path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("ReadDir failed").Str("path", n.path).Err(err).Send()
|
||||||
|
return nil, syscall.ENOENT
|
||||||
Elara6331 marked this conversation as resolved
Outdated
yannickulrich
commented
How would you recommend doing this? I suppose it could fail for all sorts of reasons such as
In other places such as when we open a file, we could have
Again, I'm sorry but I'm not a Go expert and don't really now how to do this properly.. especially when dealing with How would you recommend doing this? I suppose it could fail for all sorts of reasons such as
* no such file or directory `ENOENT`
* generic input/output error `EIO`
* invalid argument `EINVAL`
* connection aborted `ECONNABORTED`
* connection refused `ECONNREFUSED`
* connection reset `ECONNRESET`
* is actually a file `EISNAM`
In other places such as when we open a file, we could have
* is actually a folder `EISDIR`
* file exists `EEXIST`
Again, I'm sorry but I'm not a Go expert and don't really now how to do this properly.. especially when dealing with `FSError`
Elara6331
commented
The In this case, I'd use a Go type switch to check which error type actually occurred and then check the code or do whatever else needs to be done. Maybe there could be a function like If you don't feel comfortable doing that, I can merge this and then implement it myself and send you the commit so you can see how I did it, or you can just try it yourself, whatever you feel would be better. The `err` can be several different kinds of errors, and `FSError` is just one of them. It's actually a type I made. You can see it here: https://gitea.arsenm.dev/Arsen6331/infinitime/src/commit/512d48bc2469/blefs/error.go#L20. It contains an error code you can check to see what went wrong, and you can scroll down to see the meaning of each code.
In this case, I'd use a Go type switch to check which error type actually occurred and then check the code or do whatever else needs to be done. Maybe there could be a function like `syscallErr()` that takes an `error` and returns the proper syscall error?
If you don't feel comfortable doing that, I can merge this and then implement it myself and send you the commit so you can see how I did it, or you can just try it yourself, whatever you feel would be better.
yannickulrich
commented
Something like in 4c59561a99? There are a few Something like in 4c59561a99? There are a few `TODO` where I'm not sure what the correct POSIX error would be and improvised. If you have a better idea, feel free to change them though
Elara6331
commented
That looks good, thanks That looks good, thanks
|
|||||||
|
}
|
||||||
|
|
||||||
log.Info("readdir").Str("path", n.path).Int("objects", len(files)).Send()
|
log.Info("readdir").Str("path", n.path).Int("objects", len(files)).Send()
|
||||||
r := make([]fuse.DirEntry, len(files))
|
r := make([]fuse.DirEntry, len(files))
|
||||||
n.lst = make([]DirEntry, len(files))
|
n.lst = make([]DirEntry, len(files))
|
||||||
for ind, entry := range files {
|
for ind, entry := range files {
|
||||||
info, _ := entry.Info()
|
info, err := entry.Info()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Info failed").Str("path", n.path).Err(err).Send()
|
||||||
|
return nil, syscall.ENOENT
|
||||||
|
}
|
||||||
name := info.Name()
|
name := info.Name()
|
||||||
|
|
||||||
file := DirEntry{
|
file := DirEntry{
|
||||||
|
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