-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NFS host and guest support #40
base: master
Are you sure you want to change the base?
Conversation
Looking briefly at the client you linked I think that's right - the client is only coded to support 1 call occurring / outstanding at a time. |
8c7cbcc
to
4402e35
Compare
Had some time to look at this. Still a few things left to do but the server and client seem to work. At least well enough for a smoke test. |
try updating to the latest v0.0.2 of go-nfs and you may see the stale handle issue you ran into in the video go away. This is very cool! |
Did a quick test and it seems like it did fix that. :^] However, willscott/go-nfs#121 broke some stuff on my end.
Thanks! Extra technical details on the breakage: On the server side, within mountpoint.go:Mount(...), I'm basically taking an extended The To remedy this I can just implement Footnotes
|
Added symbolic link support to the IPFS Other link related changes were made in other parts of the code too (filesystem interface pkg + FUSE host). When I get a chance I'm going to clean up some remaining TODOS, and do some testing with IPFS link nodes. |
happy to do a review pass when you're ready for it |
The rationale for this is that editors / LSP picks up the const comment and applies it to all members of the block. The root and error constants are not "permission bits" like the values above them.
ae840b4
to
200d0d7
Compare
This is probably good enough for a first pass. Some context on various packages:
Its subpkg
All the other changes could be ignored, but you're welcome to look at them too if you want. The general idea for There will still be a need to keep "mountpoint" data serializable, but I think it can be done better than it currently is. |
HC mountCmdHost[HT, HM], | ||
HM marshaller, | ||
HT any, | ||
](host filesystem.Host, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you need the linebreak here after the return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be gofumpt
rules being enabled in my LSP settings.
If I remove it, it just inserts it again.
I like most of the decisions of gofumpt
, but it usually does weird stuff with function signatures...
I'll leave this alone for now and hope the entire function gets blown away in a future refactor.
"github.com/multiformats/go-multiaddr" | ||
) | ||
|
||
type ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the generics and the combination of host and guest mount in this file make the logic a bit hard to follow - i wonder if some of the generics could be normalized to have a bit more repetition but be more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
There are some benefits to having these generic command constructors, but even as the author I get tripped up on it. Especially with some of the bad constraint names, and huge signatures.
I've been considering alternate ways to deal with it but have been struggling to come up with something that is both good and compiler legal.
Thinking about trying to do a large refactor after this PR that splits a lot of this up, but I'm worried about creating some kind of dependency cycle somewhere. We'll see how it goes.
@@ -63,6 +64,7 @@ func NewIPNS(core coreiface.CoreAPI, ipfs fs.FS, options ...IPNSOption) (*IPNS, | |||
readAll | executeAll, | |||
}, | |||
nodeTimeout: 1 * time.Minute, | |||
linkLimit: 40, // Arbitrary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise to constant somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For sure. This is part of a larger problem as well, detailed below but can be ignored.
The way I handle mountpoint data (the parameters required to instantiate a file system) is currently weird.
And I was thinking about better ways to handle them.
The ipfs
pkg has constructors for the IPFS fs.FS
systems, but in /command/mount
we create a struct containing values for that constructor.
(The mount command is just a client that sends that struct + other data to the fs
daemon process, which translates that portion back into parameters for the fs.FS
constructor which is calls in its own process space).
I'm putting thought into how to better deal with this, but I'm not sure yet.
One thing I was considering was just changing the constructors to accepting a settings struct, and exposing that. This way the constructor parameter is itself an exposed serializable type/format.
The other was going to be to keep them as-is, but expose all the default values in exported consts DefaultLinkLimit = 40
, so that external packages could come up with their own serializable format if they need to, irrelevant of how the Go API is.
Or some other nonsense.
The main reason the constructor options need to be serializable, is so that we can implement something similar to Unix's fstab
. We can just dump the current mountpoints to disk, and load them again at startup.
(This currently works, but there's no command to automate it. I want to fix this up first before doing that.)
return closerFn, nil | ||
} | ||
|
||
func (*Guest) GuestID() filesystem.ID { return GuestID } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this means you're only able to have one mount of this at a time because it'll always have the same global filesystem ID?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah. It's just the name of the file system.
That interface method is probably poorly name. It used to be FSID
iirc. Maybe it should be .Type
or something else?
I forget all the places it's used, but I think the mount table uses it. The mount commands might use it, but I think not for "reasons".
Check this out, if we start the daemon with an exposed socket, it acts as a 9P server.
We can then instantiate a bunch of mount points, then as a 9P client, see what the actual mount table looks like.
Which shows those names being used in both the paths and mountpoint tags.
Windows:
fs daemon -api-server /ip4/192.168.1.40/tcp/564
fs mount nfs keyfs -api-server /ip4/192.168.1.40/tcp/564 /ip4/192.168.1.40/tcp/2050
fs mount nfs pinfs -api-server /ip4/192.168.1.40/tcp/564 /ip4/192.168.1.40/tcp/2051
fs mount nfs pinfs -api-server /ip4/192.168.1.40/tcp/564 /ip4/192.168.1.40/tcp/2049
fs.exe mount fuse nfs -api-server /ip4/192.168.1.40/tcp/564 -nfs-server /ip4/192.168.1.40/tcp/2049 I:
Linux:
mount -t 9p 192.168.1.40 /mnt/9 -o trans=tcp,port=564
tree /mnt/9
Co-authored-by: Will <willscott@gmail.com>
I'm planning to look over these changes again when I get a chance, and afterwards will probably merge this in. Will, thanks for the help on this. I appreciate you going beyond just the NFS parts too. I'm in no rush to get this merged, so if you're still looking at the code, or plan on running some interactive tests against it, just let me know and I'll hold off on pressing the button. |
I wasn't planning to look at this again in the short term. Thanks for proving it out though, I'm excited it exists! |
Sorry for the silence on this. I did end up doing a rather large refactor of the code base, but I'm not actually sure if it's an improvement. Afterwards, I'm planning on recording a lengthy video orientation, with each section explaining each package of the code base, along with rationale for why it was done the way it is. Personal note: I have to be gone for a few days but I'll act on this when I get back. Edit (2024.03.19): I did port the FUSE host and the IPFS guests over to a newer style on that branch. And most of the command line flag stuff was redone as well. Intended to have that finished this week, but got interrupted with something IRL again. Hopefully next week. |
This was originally quoted to see if the CI was permuting the flags correctly, but was never changed from a string into a process call. This amends that.
Indirectly requested from ipfs/roadmap#83
Creating a draft before the bot locks the thread.
This is still a WIP but basic functionality seems to work for both hosting and attaching.
However, initial testing shows it is not reliable.
Looking at the logs, there seems to be some kind of continuity problem in the NFS server or client where 2 lookup requests back to back will be processed in the wrong order. (Likely some kind of race condition.)
The error stems from this section of the client.
and I noticed the server is handling sends on the socket within a goroutine (see references to this struct member).
The issue could lie within the NFS libraries or my own implementations, so I'll have to investigate that when I get the chance.
Example server/host invocation:
fs mount nfs pinfs /ip4/192.168.1.40/tcp/2049
I.e.
fs mount nfs $guestAPI $nfsServerMaddr
(Assuming an IPFS node is running on this machine with default settings. Otherwise pass
-pinfs-api $ipfsAPIMaddr
before the final multiaddr argument.)Example guest/client invocation:
fs mount fuse nfs -nfs-server /ip4/192.168.1.40/tcp/2049 I:
I.e.
fs mount $host nfs $nfsServerMaddr $mountPoint
CC: @willscott
We spoke about utilizing this library for this purpose a very long time ago but I never got around to it until now.
Letting you know about its existence.
I'm planning on looking into the above error myself sometime, but you're more than welcome to hack around too. ;^]