Commit 1b3f7953 authored by Jakob Unterwurzacher's avatar Jakob Unterwurzacher

nodefs: do not overwrite the "out.Ino" inode number

...if it has already been set by the filesystem.

"out.Ino" is the user-facing inode number that is displayed by "ls -li".

This change allows loopback filesystems to expose the inode number of
the underlying filesystem.
As a "real" inode number, this one is stable for the lifetime of the file,
even across remounts.

libfuse has the `use_ino` option that allows the inode numbers to be set
arbitrarily as well. This has been used by EncFS for years.

The Linux kernel stores the inode number in `orig_ino`. Grepping in
`fs/fuse` shows that it is only read once in `fuse_update_attributes`,
and only if the `stat` argument is not NULL. There is only one caller
that passes that argument: `fuse_getattr`.

In short, the kernel does not use the inode number for anything but
reporting it via `stat()`, hence setting the inode number is safe.

This functionality will be used for improving log output in gocryptfs,
where file names cannot be used because they are encrypted.
parent 228db4e1
...@@ -89,7 +89,9 @@ func (c *rawBridge) childLookup(out *fuse.EntryOut, n *Inode, context *fuse.Cont ...@@ -89,7 +89,9 @@ func (c *rawBridge) childLookup(out *fuse.EntryOut, n *Inode, context *fuse.Cont
n.Node().GetAttr((*fuse.Attr)(&out.Attr), nil, context) n.Node().GetAttr((*fuse.Attr)(&out.Attr), nil, context)
n.mount.fillEntry(out) n.mount.fillEntry(out)
out.NodeId, out.Generation = c.fsConn().lookupUpdate(n) out.NodeId, out.Generation = c.fsConn().lookupUpdate(n)
if out.Ino == 0 {
out.Ino = out.NodeId out.Ino = out.NodeId
}
if out.Nlink == 0 { if out.Nlink == 0 {
// With Nlink == 0, newer kernels will refuse link // With Nlink == 0, newer kernels will refuse link
// operations. // operations.
......
...@@ -70,7 +70,9 @@ func (m *fileSystemMount) fillEntry(out *fuse.EntryOut) { ...@@ -70,7 +70,9 @@ func (m *fileSystemMount) fillEntry(out *fuse.EntryOut) {
func (m *fileSystemMount) fillAttr(out *fuse.AttrOut, nodeId uint64) { func (m *fileSystemMount) fillAttr(out *fuse.AttrOut, nodeId uint64) {
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
m.setOwner(&out.Attr) m.setOwner(&out.Attr)
if out.Ino == 0 {
out.Ino = nodeId out.Ino = nodeId
}
} }
func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile { func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile {
......
...@@ -99,7 +99,9 @@ func (c *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu ...@@ -99,7 +99,9 @@ func (c *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu
child.mount.fillEntry(out) child.mount.fillEntry(out)
out.NodeId, out.Generation = c.fsConn().lookupUpdate(child) out.NodeId, out.Generation = c.fsConn().lookupUpdate(child)
if out.Ino == 0 {
out.Ino = out.NodeId out.Ino = out.NodeId
}
return fuse.OK return fuse.OK
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment