Skip to content

Commit cc0c8fc

Browse files
committed
wip: mount2: remove embedded vfs.Node objects
Signed-off-by: Anagh Kumar Baranwal <6824881+darthShadow@users.noreply.github.com>
1 parent 1d76593 commit cc0c8fc

File tree

3 files changed

+107
-68
lines changed

3 files changed

+107
-68
lines changed

cmd/mount2/fs.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/rclone/rclone/fs"
1515
"github.com/rclone/rclone/fs/fserrors"
1616
"github.com/rclone/rclone/fs/log"
17+
"github.com/rclone/rclone/lib/join"
1718
"github.com/rclone/rclone/vfs"
1819
)
1920

@@ -34,6 +35,16 @@ func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS {
3435
return fsys
3536
}
3637

38+
func (f *FS) path(node *Node, names ...string) string {
39+
rootNode := node.EmbeddedInode().Root()
40+
nodePath := node.Path(rootNode)
41+
nodePathElements := []string{"", nodePath}
42+
if len(names) == 0 {
43+
return join.FilePathJoin(nodePathElements...)
44+
}
45+
return join.FilePathJoin(append(nodePathElements, names...)...)
46+
}
47+
3748
// Root returns the root node
3849
func (f *FS) Root() (node *Node, err error) {
3950
defer log.Trace("", "")("node=%+v, err=%v", &node, &err)

cmd/mount2/node.go

Lines changed: 95 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@ import (
1616
"github.com/rclone/rclone/vfs"
1717
)
1818

19+
/**
20+
References:
21+
* https://github.com/octohelm/unifs/blob/main/pkg/fuse/node.go
22+
* https://github.com/rfjakob/gocryptfs/blob/master/internal/fusefrontend_reverse/node.go
23+
* https://github.com/seaweedfs/seaweedfs/tree/master/weed/mount
24+
*/
25+
1926
// Node represents a directory or file
2027
type Node struct {
21-
fusefs.Inode
22-
node vfs.Node
2328
fsys *FS
29+
fusefs.Inode
2430
}
2531

2632
// Node types must be InodeEmbedders
@@ -35,57 +41,66 @@ func newNode(fsys *FS, vfsNode vfs.Node) (node *Node) {
3541
return node
3642
}
3743
node = &Node{
38-
node: vfsNode,
3944
fsys: fsys,
4045
}
4146
// Cache the node for later
4247
vfsNode.SetSys(node)
4348
return node
4449
}
4550

51+
// Path returns the path of the node relative to the root
52+
func (n *Node) path(names ...string) string {
53+
return n.fsys.path(n, names...)
54+
}
55+
4656
// String used for pretty printing.
4757
func (n *Node) String() string {
48-
return n.node.Path()
58+
return n.path()
59+
}
60+
61+
// VFS returns the VFS that this node is part of
62+
func (n *Node) VFS() *vfs.VFS {
63+
return n.fsys.VFS
64+
}
65+
66+
// lookup a Node given a path
67+
func (n *Node) lookupNode(leaf string) (vfs.Node, syscall.Errno) {
68+
var (
69+
node vfs.Node
70+
err error
71+
)
72+
if leaf == "" {
73+
node, err = n.VFS().Stat(n.path())
74+
} else {
75+
node, err = n.VFS().Stat(n.path(leaf))
76+
}
77+
return node, translateError(err)
4978
}
5079

51-
// lookup a Node in a directory
52-
func (n *Node) lookupVfsNodeInDir(leaf string) (vfsNode vfs.Node, errno syscall.Errno) {
53-
dir, ok := n.node.(*vfs.Dir)
80+
// lookup a Dir given a path
81+
func (n *Node) lookupDir(leaf string) (*vfs.Dir, syscall.Errno) {
82+
vfsNode, errno := n.lookupNode(leaf)
83+
if errno != 0 {
84+
return nil, errno
85+
}
86+
if !vfsNode.IsDir() {
87+
return nil, syscall.ENOTDIR
88+
}
89+
dir, ok := vfsNode.(*vfs.Dir)
5490
if !ok {
5591
return nil, syscall.ENOTDIR
5692
}
57-
vfsNode, err := dir.Stat(leaf)
58-
return vfsNode, translateError(err)
93+
return dir, 0
5994
}
6095

61-
// // lookup a Dir given a path
62-
// func (n *Node) lookupDir(path string) (dir *vfs.Dir, code fuse.Status) {
63-
// node, code := fsys.lookupVfsNodeInDir(path)
64-
// if !code.Ok() {
65-
// return nil, code
66-
// }
67-
// dir, ok := n.(*vfs.Dir)
68-
// if !ok {
69-
// return nil, fuse.ENOTDIR
70-
// }
71-
// return dir, fuse.OK
72-
// }
73-
74-
// // lookup a parent Dir given a path returning the dir and the leaf
75-
// func (n *Node) lookupParentDir(filePath string) (leaf string, dir *vfs.Dir, code fuse.Status) {
76-
// parentDir, leaf := path.Split(filePath)
77-
// dir, code = fsys.lookupDir(parentDir)
78-
// return leaf, dir, code
79-
// }
80-
8196
// Statfs implements statistics for the filesystem that holds this
8297
// Inode. If not defined, the `out` argument will zeroed with an OK
8398
// result. This is because OSX filesystems must Statfs, or the mount
8499
// will not work.
85100
func (n *Node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
86101
defer log.Trace(n, "")("out=%+v", &out)
87102
const blockSize = 4096
88-
total, _, free := n.fsys.VFS.Statfs()
103+
total, _, free := n.VFS().Statfs()
89104
out.Blocks = uint64(total) / blockSize // Total data blocks in file system.
90105
out.Bfree = uint64(free) / blockSize // Free blocks in file system.
91106
out.Bavail = out.Bfree // Free blocks in file system if you're not root.
@@ -110,7 +125,11 @@ var _ = (fusefs.NodeStatfser)((*Node)(nil))
110125
// with the Options.NullPermissions setting. If blksize is unset, 4096
111126
// is assumed, and the 'blocks' field is set accordingly.
112127
func (n *Node) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
113-
n.fsys.setAttrOut(n.node, out)
128+
vfsNode, errno := n.lookupNode("")
129+
if errno != 0 {
130+
return errno
131+
}
132+
n.fsys.setAttrOut(vfsNode, out)
114133
return 0
115134
}
116135

@@ -120,18 +139,22 @@ var _ = (fusefs.NodeGetattrer)((*Node)(nil))
120139
func (n *Node) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) {
121140
defer log.Trace(n, "in=%v", in)("out=%#v, errno=%v", &out, &errno)
122141
var err error
123-
n.fsys.setAttrOut(n.node, out)
142+
vfsNode, errno := n.lookupNode("")
143+
if errno != 0 {
144+
return errno
145+
}
146+
n.fsys.setAttrOut(vfsNode, out)
124147
size, ok := in.GetSize()
125148
if ok {
126-
err = n.node.Truncate(int64(size))
149+
err = vfsNode.Truncate(int64(size))
127150
if err != nil {
128151
return translateError(err)
129152
}
130153
out.Attr.Size = size
131154
}
132155
mtime, ok := in.GetMTime()
133156
if ok {
134-
err = n.node.SetModTime(mtime)
157+
err = vfsNode.SetModTime(mtime)
135158
if err != nil {
136159
return translateError(err)
137160
}
@@ -149,12 +172,16 @@ func (n *Node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fu
149172
defer log.Trace(n, "flags=%#o", flags)("errno=%v", &errno)
150173
// fuse flags are based off syscall flags as are os flags, so
151174
// should be compatible
152-
handle, err := n.node.Open(int(flags))
175+
vfsNode, errno := n.lookupNode("")
176+
if errno != 0 {
177+
return nil, 0, errno
178+
}
179+
handle, err := vfsNode.Open(int(flags))
153180
if err != nil {
154181
return nil, 0, translateError(err)
155182
}
156183
// If size unknown then use direct io to read
157-
if entry := n.node.DirEntry(); entry != nil && entry.Size() < 0 {
184+
if entry := vfsNode.DirEntry(); entry != nil && entry.Size() < 0 {
158185
fuseFlags |= fuse.FOPEN_DIRECT_IO
159186
}
160187
if n.fsys.opt.DirectIO {
@@ -190,17 +217,15 @@ var _ = (fusefs.NodeOpener)((*Node)(nil))
190217
// populate their fuse.EntryOut arguments.
191218
func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
192219
defer log.Trace(n, "name=%q", name)("inode=%v, attr=%v, errno=%v", &inode, &out, &errno)
193-
vfsNode, errno := n.lookupVfsNodeInDir(name)
220+
vfsNode, errno := n.lookupNode(name)
194221
if errno != 0 {
195222
return nil, errno
196223
}
197-
newNode := newNode(n.fsys, vfsNode)
198224

199-
// FIXME
200-
// out.SetEntryTimeout(dt time.Duration)
201-
// out.SetAttrTimeout(dt time.Duration)
202225
n.fsys.setEntryOut(vfsNode, out)
203226

227+
newNode := newNode(n.fsys, vfsNode)
228+
204229
return n.NewInode(ctx, newNode, fusefs.StableAttr{Mode: out.Attr.Mode}), 0
205230
}
206231

@@ -211,8 +236,9 @@ var _ = (fusefs.NodeLookuper)((*Node)(nil))
211236
// this method is just for performing sanity/permission
212237
// checks. The default is to return success.
213238
func (n *Node) Opendir(ctx context.Context) syscall.Errno {
214-
if !n.node.IsDir() {
215-
return syscall.ENOTDIR
239+
_, errno := n.lookupDir("")
240+
if errno != 0 {
241+
return errno
216242
}
217243
return 0
218244
}
@@ -286,10 +312,11 @@ var _ fusefs.DirStream = (*dirStream)(nil)
286312
// static in-memory file systems need not implement NodeReaddirer.
287313
func (n *Node) Readdir(ctx context.Context) (ds fusefs.DirStream, errno syscall.Errno) {
288314
defer log.Trace(n, "")("ds=%v, errno=%v", &ds, &errno)
289-
if !n.node.IsDir() {
290-
return nil, syscall.ENOTDIR
315+
vfsDir, errno := n.lookupDir("")
316+
if errno != 0 {
317+
return nil, errno
291318
}
292-
fh, err := n.node.Open(os.O_RDONLY)
319+
fh, err := vfsDir.Open(os.O_RDONLY)
293320
if err != nil {
294321
return nil, translateError(err)
295322
}
@@ -314,16 +341,16 @@ var _ = (fusefs.NodeReaddirer)((*Node)(nil))
314341
// Default is to return EROFS.
315342
func (n *Node) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
316343
defer log.Trace(name, "mode=0%o", mode)("inode=%v, errno=%v", &inode, &errno)
317-
dir, ok := n.node.(*vfs.Dir)
318-
if !ok {
319-
return nil, syscall.ENOTDIR
344+
vfsDir, errno := n.lookupDir("")
345+
if errno != 0 {
346+
return nil, errno
320347
}
321-
newDir, err := dir.Mkdir(name)
348+
newDir, err := vfsDir.Mkdir(name)
322349
if err != nil {
323350
return nil, translateError(err)
324351
}
325352
newNode := newNode(n.fsys, newDir)
326-
n.fsys.setEntryOut(newNode.node, out)
353+
n.fsys.setEntryOut(newDir, out)
327354
newInode := n.NewInode(ctx, newNode, fusefs.StableAttr{Mode: out.Attr.Mode})
328355
return newInode, 0
329356
}
@@ -336,13 +363,13 @@ var _ = (fusefs.NodeMkdirer)((*Node)(nil))
336363
// Default is to return EROFS.
337364
func (n *Node) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (node *fusefs.Inode, fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
338365
defer log.Trace(n, "name=%q, flags=%#o, mode=%#o", name, flags, mode)("node=%v, fh=%v, flags=%#o, errno=%v", &node, &fh, &fuseFlags, &errno)
339-
dir, ok := n.node.(*vfs.Dir)
340-
if !ok {
341-
return nil, nil, 0, syscall.ENOTDIR
366+
vfsDir, errno := n.lookupDir("")
367+
if errno != 0 {
368+
return nil, nil, 0, errno
342369
}
343370
// translate the fuse flags to os flags
344371
osFlags := int(flags) | os.O_CREATE
345-
file, err := dir.Create(name, osFlags)
372+
file, err := vfsDir.Create(name, osFlags)
346373
if err != nil {
347374
return nil, nil, 0, translateError(err)
348375
}
@@ -359,7 +386,7 @@ func (n *Node) Create(ctx context.Context, name string, flags uint32, mode uint3
359386
// }
360387

361388
// Find the created node
362-
vfsNode, errno := n.lookupVfsNodeInDir(name)
389+
vfsNode, errno := n.lookupNode(name)
363390
if errno != 0 {
364391
return nil, nil, 0, errno
365392
}
@@ -377,7 +404,7 @@ var _ = (fusefs.NodeCreater)((*Node)(nil))
377404
// FS tree automatically. Default is to return EROFS.
378405
func (n *Node) Unlink(ctx context.Context, name string) (errno syscall.Errno) {
379406
defer log.Trace(n, "name=%q", name)("errno=%v", &errno)
380-
vfsNode, errno := n.lookupVfsNodeInDir(name)
407+
vfsNode, errno := n.lookupNode(name)
381408
if errno != 0 {
382409
return errno
383410
}
@@ -390,7 +417,7 @@ var _ = (fusefs.NodeUnlinker)((*Node)(nil))
390417
// Default is to return EROFS.
391418
func (n *Node) Rmdir(ctx context.Context, name string) (errno syscall.Errno) {
392419
defer log.Trace(n, "name=%q", name)("errno=%v", &errno)
393-
vfsNode, errno := n.lookupVfsNodeInDir(name)
420+
vfsNode, errno := n.lookupNode(name)
394421
if errno != 0 {
395422
return errno
396423
}
@@ -404,20 +431,20 @@ var _ = (fusefs.NodeRmdirer)((*Node)(nil))
404431
// OK. Default is to return EROFS.
405432
func (n *Node) Rename(ctx context.Context, oldName string, newParent fusefs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) {
406433
defer log.Trace(n, "oldName=%q, newParent=%v, newName=%q", oldName, newParent, newName)("errno=%v", &errno)
407-
oldDir, ok := n.node.(*vfs.Dir)
408-
if !ok {
409-
return syscall.ENOTDIR
434+
vfsDir, errno := n.lookupDir("")
435+
if errno != 0 {
436+
return errno
410437
}
411438
newParentNode, ok := newParent.(*Node)
412439
if !ok {
413440
fs.Errorf(n, "newParent was not a *Node")
414441
return syscall.EIO
415442
}
416-
newDir, ok := newParentNode.node.(*vfs.Dir)
417-
if !ok {
443+
newDir, errno := newParentNode.lookupDir("")
444+
if errno != 0 {
418445
return syscall.ENOTDIR
419446
}
420-
return translateError(oldDir.Rename(oldName, newName, newDir))
447+
return translateError(vfsDir.Rename(oldName, newName, newDir))
421448
}
422449

423450
var _ = (fusefs.NodeRenamer)((*Node)(nil))
@@ -464,8 +491,8 @@ var _ fusefs.NodeReadlinker = (*Node)(nil)
464491
// Readlink read symbolic link target.
465492
func (n *Node) Readlink(ctx context.Context) (ret []byte, err syscall.Errno) {
466493
defer log.Trace(n, "")("ret=%v, err=%v", &ret, &err)
467-
path := n.node.Path()
468-
s, serr := n.node.VFS().Readlink(path)
494+
nodePath := n.path()
495+
s, serr := n.VFS().Readlink(nodePath)
469496
return []byte(s), translateError(serr)
470497
}
471498

@@ -474,8 +501,8 @@ var _ fusefs.NodeSymlinker = (*Node)(nil)
474501
// Symlink create symbolic link.
475502
func (n *Node) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *fusefs.Inode, err syscall.Errno) {
476503
defer log.Trace(n, "name=%v, target=%v", name, target)("node=%v, err=%v", &node, &err)
477-
fullPath := path.Join(n.node.Path(), name)
478-
vfsNode, serr := n.node.VFS().CreateSymlink(target, fullPath)
504+
fullPath := path.Join(n.path(), name)
505+
vfsNode, serr := n.VFS().CreateSymlink(target, fullPath)
479506
if serr != nil {
480507
return nil, translateError(serr)
481508
}

vfs/dir.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,7 @@ func (d *Dir) readDir() error {
857857
func (d *Dir) stat(leaf string) (Node, error) {
858858
d.mu.Lock()
859859
defer d.mu.Unlock()
860+
// TODO: Define & Use the Stat-er interface to avoid reading the entire directory
860861
err := d._readDir()
861862
if err != nil {
862863
return nil, err

0 commit comments

Comments
 (0)