Skip to content
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

Initial mount draft/WIP #6036

Closed
wants to merge 2 commits into from
Closed

Initial mount draft/WIP #6036

wants to merge 2 commits into from

Conversation

djdv
Copy link
Contributor

@djdv djdv commented Mar 1, 2019

Reference issue: #5003
Originally intended to be a read-only, Windows-only, variant, we now have an alternate implementation of ipfs mount that builds and runs on multiple platforms, and abstracts various APIs to expose an IPFS node as a virtual mutable filesystem.
A demo of this is here: https://youtu.be/hh0epHWyt4I

In this document I'll outline the expectations as well as the current faults of the implementation that need to be resolved before final.

The daemon will expose a "mount-root" which will be referenced by name or / hereafter.
The mount-root is a virtual filesystem that wraps IPFS APIs and exposes them via the fuse filesystem API.
The APIs will be referenced as a "subsystem", while individual subsystems will be refereed to as "root"s.
Paths beneath subsystems will be referenced generically as "node"s.

At current, we expose the following subsystems at the following endpoints: /ipfs, /ipns, /files

The ipfs-root wraps the pin api, to expose pins of the node as files.
i.e. Readdir("/ipfs") would expose the following entries on stock node
QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv, QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn

ipfs-nodes beneath the ipfs-root map to various CoreAPI requests, exposing the ipfs-nodes as native file types with which read-only file system operations can be performed on.
i.e.
Opendir("/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv")
Open("/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/about")
etc.
ipfs-nodes do not have to be pins nor do they have to exist locally on the node's instance. If valid, the mount logic will attempt to fetch them from the network.

The files-root wraps the MFS API and shares the same root as the ipfs files command.
Exposing the same contents as ipfs files ls / and providing generic file system operations for its nodes as above, but also allowing for mutable operations as well.
i.e.
Mknod("/files/sub-file")
Mkdir("/files/sub-dir")
etc.

The ipns-root wraps the same systems as the previous roots, as well as the key and name api's specifically.
Exposing the node's keys ipfs key list as native file system types. As well as providing key management.
i.e.
Mknod("/ipns/key-pointing-to-file")
Mkidir("/ipns/key-pointing-to-directory")
Rename("/ipns/key-old-name", "/ipns/key-new-name")
Unlink("/ipns/key-name")
etc.

ipns-nodes may be referenced via a named path or a CID path. Both of which are valid, but carry different operation access. Paths referenced via key's are resolved locally, and allow for mutable operations.
i.e.
both /ipns/self and /ipns/QmTjr6BNmV6v3h7df3gbrNpsQLC5Y91csHWUE3QSYki2QK are valid ipns-nodes but carry different bejhaviour.


Draft / Implementation notes:

Currently, most operations can be performed on most types, but the instance is somewhat fragile and not everything is functioning properly all the time.
Effort is being put into simplifying the codebase and generalizing operation functions.
Currently, paths are being passed in as strings and parsed via a lookup function LookupPath() into generic "fusePath" interface objects. Underneath, each node is hard typed, dependent on its path.
These objects implement the CoreAPI Path type and are passed around to various operation functions.
For example, you can derive a fuse compatible IO interface/object from a fusePath, or pass it to the CoreAPI if it's a valid global path.

The current goal is to take the various procedural functions in the codebase and translate them into methods on the objects themselves. This should be a large reduction and more sensible in terms of object life-time/correctness. At current, the common patterns are a procedural and OO mix which should be made more consistent.
Type switches are used extensively but it makes much more sense to just have path.Read() than read(ipfs-path) { switch fusePath.(type) { ipfsRead(ipfs-path) }
It also makes more sense for the IO interface to live on the path, rather than just be associated with it through other means.

There are a number of bad behaviours currently, but non are worth listing in particular.
With the coupling of the nodes, the source of the existing issues should become more apparent or be fixed inherently. A particular example will be ASYNC IO. Currently nodes are very much independent, but the idea is to change how nodes are initialized, locked, and considerations about their lifetime. Simplifying things like this should inadvertently expose and/or fix issues around other operations.

Very little of the config is wired up, things are mostly hard coded or placeholder. The worst offender being all call contexts sharing the context of the daemon, so doing something like calling read on a hash that has no providers will hang indefinitely (or until the OS kills it). Simply defining a sensible timeout context should remedy this.

I have a pretty good understanding of what's wrong with this draft and what still needs to be done but criticism and listing problems are welcomed.

License: MIT
Signed-off-by: Dominic Della Valle <[email protected]>
License: MIT
Signed-off-by: Dominic Della Valle <[email protected]>
@bam80
Copy link

bam80 commented Mar 28, 2021

Was this work continued by somebody else?
Is there a new issue to track?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants