221 lines
8.3 KiB

// Copyright 2015 Google Inc. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package fuseops
import (
// A 64-bit number used to uniquely identify a file or directory in the file
// system. File systems may mint inode IDs with any value except for
// RootInodeID.
// This corresponds to struct inode::i_no in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
type InodeID uint64
// A distinguished inode ID that identifies the root of the file system, e.g.
// in an OpenDirOp or LookUpInodeOp. Unlike all other inode IDs, which are
// minted by the file system, the FUSE VFS layer may send a request for this ID
// without the file system ever having referenced it in a previous response.
const RootInodeID = 1
func init() {
// Make sure the constant above is correct. We do this at runtime rather than
// defining the constant in terms of fusekernel.RootID for two reasons:
// 1. Users can more clearly see that the root ID is low and can therefore
// be used as e.g. an array index, with space reserved up to the root.
// 2. The constant can be untyped and can therefore more easily be used as
// an array index.
if RootInodeID != fusekernel.RootID {
"Oops, RootInodeID is wrong: %v vs. %v",
// Attributes for a file or directory inode. Corresponds to struct inode (cf.
// http://goo.gl/tvYyQt).
type InodeAttributes struct {
Size uint64
// The number of incoming hard links to this inode.
Nlink uint64
// The mode of the inode. This is exposed to the user in e.g. the result of
// fstat(2).
// Note that in contrast to the defaults for FUSE, this package mounts file
// systems in a manner such that the kernel checks inode permissions in the
// standard posix way. This is implemented by setting the default_permissions
// mount option (cf. http://goo.gl/1LxOop and http://goo.gl/1pTjuk).
// For example, in the case of mkdir:
// * (http://goo.gl/JkdxDI) sys_mkdirat calls inode_permission.
// * (...) inode_permission eventually calls do_inode_permission.
// * (http://goo.gl/aGCsmZ) calls i_op->permission, which is
// fuse_permission (cf. http://goo.gl/VZ9beH).
// * (http://goo.gl/5kqUKO) fuse_permission doesn't do anything at all for
// several code paths if FUSE_DEFAULT_PERMISSIONS is unset. In contrast,
// if that flag *is* set, then it calls generic_permission.
Mode os.FileMode
// Time information. See `man 2 stat` for full details.
Atime time.Time // Time of last access
Mtime time.Time // Time of last modification
Ctime time.Time // Time of last modification to inode
Crtime time.Time // Time of creation (OS X only)
// Ownership information
Uid uint32
Gid uint32
func (a *InodeAttributes) DebugString() string {
return fmt.Sprintf(
"%d %d %v %d %d",
// A generation number for an inode. Irrelevant for file systems that won't be
// exported over NFS. For those that will and that reuse inode IDs when they
// become free, the generation number must change when an ID is reused.
// This corresponds to struct inode::i_generation in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
// Some related reading:
// http://fuse.sourceforge.net/doxygen/structfuse__entry__param.html
// http://stackoverflow.com/q/11071996/1505451
// http://goo.gl/CqvwyX
// http://julipedia.meroh.net/2005/09/nfs-file-handles.html
// http://goo.gl/wvo3MB
type GenerationNumber uint64
// An opaque 64-bit number used to identify a particular open handle to a file
// or directory.
// This corresponds to fuse_file_info::fh.
type HandleID uint64
// An offset into an open directory handle. This is opaque to FUSE, and can be
// used for whatever purpose the file system desires. See notes on
// ReadDirOp.Offset for details.
type DirOffset uint64
// Information about a child inode within its parent directory. Shared by
// LookUpInodeOp, MkDirOp, CreateFileOp, etc. Consumed by the kernel in order
// to set up a dcache entry.
type ChildInodeEntry struct {
// The ID of the child inode. The file system must ensure that the returned
// inode ID remains valid until a later ForgetInodeOp.
Child InodeID
// A generation number for this incarnation of the inode with the given ID.
// See comments on type GenerationNumber for more.
Generation GenerationNumber
// Current attributes for the child inode.
// When creating a new inode, the file system is responsible for initializing
// and recording (where supported) attributes like time information,
// ownership information, etc.
// Ownership information in particular must be set to something reasonable or
// by default root will own everything and unprivileged users won't be able
// to do anything useful. In traditional file systems in the kernel, the
// function inode_init_owner (http://goo.gl/5qavg8) contains the
// standards-compliant logic for this.
Attributes InodeAttributes
// The FUSE VFS layer in the kernel maintains a cache of file attributes,
// used whenever up to date information about size, mode, etc. is needed.
// For example, this is the abridged call chain for fstat(2):
// * (http://goo.gl/tKBH1p) fstat calls vfs_fstat.
// * (http://goo.gl/3HeITq) vfs_fstat eventuall calls vfs_getattr_nosec.
// * (http://goo.gl/DccFQr) vfs_getattr_nosec calls i_op->getattr.
// * (http://goo.gl/dpKkst) fuse_getattr calls fuse_update_attributes.
// * (http://goo.gl/yNlqPw) fuse_update_attributes uses the values in the
// struct inode if allowed, otherwise calling out to the user-space code.
// In addition to obvious cases like fstat, this is also used in more subtle
// cases like updating size information before seeking (http://goo.gl/2nnMFa)
// or reading (http://goo.gl/FQSWs8).
// Most 'real' file systems do not set inode_operations::getattr, and
// therefore vfs_getattr_nosec calls generic_fillattr which simply grabs the
// information from the inode struct. This makes sense because these file
// systems cannot spontaneously change; all modifications go through the
// kernel which can update the inode struct as appropriate.
// In contrast, a FUSE file system may have spontaneous changes, so it calls
// out to user space to fetch attributes. However this is expensive, so the
// FUSE layer in the kernel caches the attributes if requested.
// This field controls when the attributes returned in this response and
// stashed in the struct inode should be re-queried. Leave at the zero value
// to disable caching.
// More reading:
// http://stackoverflow.com/q/21540315/1505451
AttributesExpiration time.Time
// The time until which the kernel may maintain an entry for this name to
// inode mapping in its dentry cache. After this time, it will revalidate the
// dentry.
// As in the discussion of attribute caching above, unlike real file systems,
// FUSE file systems may spontaneously change their name -> inode mapping.
// Therefore the FUSE VFS layer uses dentry_operations::d_revalidate
// (http://goo.gl/dVea0h) to intercept lookups and revalidate by calling the
// user-space LookUpInode method. However the latter may be slow, so it
// caches the entries until the time defined by this field.
// Example code walk:
// * (http://goo.gl/M2G3tO) lookup_dcache calls d_revalidate if enabled.
// * (http://goo.gl/ef0Elu) fuse_dentry_revalidate just uses the dentry's
// inode if fuse_dentry_time(entry) hasn't passed. Otherwise it sends a
// lookup request.
// Leave at the zero value to disable caching.
// Beware: this value is ignored on OS X, where entry caching is disabled by
// default. See notes on MountConfig.EnableVnodeCaching for more.
EntryExpiration time.Time