| .. SPDX-License-Identifier: GPL-2.0 | |
| ========================================= | |
| Overview of the Linux Virtual File System | |
| ========================================= | |
| Original author: Richard Gooch <rgooch@atnf.csiro.au> | |
| - Copyright (C) 1999 Richard Gooch | |
| - Copyright (C) 2005 Pekka Enberg | |
| Introduction | |
| ============ | |
| The Virtual File System (also known as the Virtual Filesystem Switch) is | |
| the software layer in the kernel that provides the filesystem interface | |
| to userspace programs. It also provides an abstraction within the | |
| kernel which allows different filesystem implementations to coexist. | |
| VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so on | |
| are called from a process context. Filesystem locking is described in | |
| the document Documentation/filesystems/locking.rst. | |
| Directory Entry Cache (dcache) | |
| ------------------------------ | |
| The VFS implements the open(2), stat(2), chmod(2), and similar system | |
| calls. The pathname argument that is passed to them is used by the VFS | |
| to search through the directory entry cache (also known as the dentry | |
| cache or dcache). This provides a very fast look-up mechanism to | |
| translate a pathname (filename) into a specific dentry. Dentries live | |
| in RAM and are never saved to disc: they exist only for performance. | |
| The dentry cache is meant to be a view into your entire filespace. As | |
| most computers cannot fit all dentries in the RAM at the same time, some | |
| bits of the cache are missing. In order to resolve your pathname into a | |
| dentry, the VFS may have to resort to creating dentries along the way, | |
| and then loading the inode. This is done by looking up the inode. | |
| The Inode Object | |
| ---------------- | |
| An individual dentry usually has a pointer to an inode. Inodes are | |
| filesystem objects such as regular files, directories, FIFOs and other | |
| beasts. They live either on the disc (for block device filesystems) or | |
| in the memory (for pseudo filesystems). Inodes that live on the disc | |
| are copied into the memory when required and changes to the inode are | |
| written back to disc. A single inode can be pointed to by multiple | |
| dentries (hard links, for example, do this). | |
| To look up an inode requires that the VFS calls the lookup() method of | |
| the parent directory inode. This method is installed by the specific | |
| filesystem implementation that the inode lives in. Once the VFS has the | |
| required dentry (and hence the inode), we can do all those boring things | |
| like open(2) the file, or stat(2) it to peek at the inode data. The | |
| stat(2) operation is fairly simple: once the VFS has the dentry, it | |
| peeks at the inode data and passes some of it back to userspace. | |
| The File Object | |
| --------------- | |
| Opening a file requires another operation: allocation of a file | |
| structure (this is the kernel-side implementation of file descriptors). | |
| The freshly allocated file structure is initialized with a pointer to | |
| the dentry and a set of file operation member functions. These are | |
| taken from the inode data. The open() file method is then called so the | |
| specific filesystem implementation can do its work. You can see that | |
| this is another switch performed by the VFS. The file structure is | |
| placed into the file descriptor table for the process. | |
| Reading, writing and closing files (and other assorted VFS operations) | |
| is done by using the userspace file descriptor to grab the appropriate | |
| file structure, and then calling the required file structure method to | |
| do whatever is required. For as long as the file is open, it keeps the | |
| dentry in use, which in turn means that the VFS inode is still in use. | |
| Registering and Mounting a Filesystem | |
| ===================================== | |
| To register and unregister a filesystem, use the following API | |
| functions: | |
| .. code-block:: c | |
| #include <linux/fs.h> | |
| extern int register_filesystem(struct file_system_type *); | |
| extern int unregister_filesystem(struct file_system_type *); | |
| The passed struct file_system_type describes your filesystem. When a | |
| request is made to mount a filesystem onto a directory in your | |
| namespace, the VFS will call the appropriate get_tree() method for the | |
| specific filesystem. See Documentation/filesystems/mount_api.rst | |
| for more details. | |
| You can see all filesystems that are registered to the kernel in the | |
| file /proc/filesystems. | |
| struct file_system_type | |
| ----------------------- | |
| This describes the filesystem. The following | |
| members are defined: | |
| .. code-block:: c | |
| struct file_system_type { | |
| const char *name; | |
| int fs_flags; | |
| int (*init_fs_context)(struct fs_context *); | |
| const struct fs_parameter_spec *parameters; | |
| void (*kill_sb) (struct super_block *); | |
| struct module *owner; | |
| struct file_system_type * next; | |
| struct hlist_head fs_supers; | |
| struct lock_class_key s_lock_key; | |
| struct lock_class_key s_umount_key; | |
| struct lock_class_key s_vfs_rename_key; | |
| struct lock_class_key s_writers_key[SB_FREEZE_LEVELS]; | |
| struct lock_class_key i_lock_key; | |
| struct lock_class_key i_mutex_key; | |
| struct lock_class_key invalidate_lock_key; | |
| struct lock_class_key i_mutex_dir_key; | |
| }; | |
| ``name`` | |
| the name of the filesystem type, such as "ext2", "iso9660", | |
| "msdos" and so on | |
| ``fs_flags`` | |
| various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) | |
| ``init_fs_context`` | |
| Initializes 'struct fs_context' ->ops and ->fs_private fields with | |
| filesystem-specific data. | |
| ``parameters`` | |
| Pointer to the array of filesystem parameters descriptors | |
| 'struct fs_parameter_spec'. | |
| More info in Documentation/filesystems/mount_api.rst. | |
| ``kill_sb`` | |
| the method to call when an instance of this filesystem should be | |
| shut down | |
| ``owner`` | |
| for internal VFS use: you should initialize this to THIS_MODULE | |
| in most cases. | |
| ``next`` | |
| for internal VFS use: you should initialize this to NULL | |
| ``fs_supers`` | |
| for internal VFS use: hlist of filesystem instances (superblocks) | |
| s_lock_key, s_umount_key, s_vfs_rename_key, s_writers_key, | |
| i_lock_key, i_mutex_key, invalidate_lock_key, i_mutex_dir_key: lockdep-specific | |
| The Superblock Object | |
| ===================== | |
| A superblock object represents a mounted filesystem. | |
| struct super_operations | |
| ----------------------- | |
| This describes how the VFS can manipulate the superblock of your | |
| filesystem. The following members are defined: | |
| .. code-block:: c | |
| struct super_operations { | |
| struct inode *(*alloc_inode)(struct super_block *sb); | |
| void (*destroy_inode)(struct inode *); | |
| void (*free_inode)(struct inode *); | |
| void (*dirty_inode) (struct inode *, int flags); | |
| int (*write_inode) (struct inode *, struct writeback_control *wbc); | |
| int (*drop_inode) (struct inode *); | |
| void (*evict_inode) (struct inode *); | |
| void (*put_super) (struct super_block *); | |
| int (*sync_fs)(struct super_block *sb, int wait); | |
| int (*freeze_super) (struct super_block *sb, | |
| enum freeze_holder who); | |
| int (*freeze_fs) (struct super_block *); | |
| int (*thaw_super) (struct super_block *sb, | |
| enum freeze_wholder who); | |
| int (*unfreeze_fs) (struct super_block *); | |
| int (*statfs) (struct dentry *, struct kstatfs *); | |
| void (*umount_begin) (struct super_block *); | |
| int (*show_options)(struct seq_file *, struct dentry *); | |
| int (*show_devname)(struct seq_file *, struct dentry *); | |
| int (*show_path)(struct seq_file *, struct dentry *); | |
| int (*show_stats)(struct seq_file *, struct dentry *); | |
| ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); | |
| ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); | |
| struct dquot **(*get_dquots)(struct inode *); | |
| long (*nr_cached_objects)(struct super_block *, | |
| struct shrink_control *); | |
| long (*free_cached_objects)(struct super_block *, | |
| struct shrink_control *); | |
| }; | |
| All methods are called without any locks being held, unless otherwise | |
| noted. This means that most methods can block safely. All methods are | |
| only called from a process context (i.e. not from an interrupt handler | |
| or bottom half). | |
| ``alloc_inode`` | |
| this method is called by alloc_inode() to allocate memory for | |
| struct inode and initialize it. If this function is not | |
| defined, a simple 'struct inode' is allocated. Normally | |
| alloc_inode will be used to allocate a larger structure which | |
| contains a 'struct inode' embedded within it. | |
| ``destroy_inode`` | |
| this method is called by destroy_inode() to release resources | |
| allocated for struct inode. It is only required if | |
| ->alloc_inode was defined and simply undoes anything done by | |
| ->alloc_inode. | |
| ``free_inode`` | |
| this method is called from RCU callback. If you use call_rcu() | |
| in ->destroy_inode to free 'struct inode' memory, then it's | |
| better to release memory in this method. | |
| ``dirty_inode`` | |
| this method is called by the VFS when an inode is marked dirty. | |
| This is specifically for the inode itself being marked dirty, | |
| not its data. If the update needs to be persisted by fdatasync(), | |
| then I_DIRTY_DATASYNC will be set in the flags argument. | |
| I_DIRTY_TIME will be set in the flags in case lazytime is enabled | |
| and struct inode has times updated since the last ->dirty_inode | |
| call. | |
| ``write_inode`` | |
| this method is called when the VFS needs to write an inode to | |
| disc. The second parameter indicates whether the write should | |
| be synchronous or not, not all filesystems check this flag. | |
| ``drop_inode`` | |
| called when the last access to the inode is dropped, with the | |
| inode->i_lock spinlock held. | |
| This method should be either NULL (normal UNIX filesystem | |
| semantics) or "inode_just_drop" (for filesystems that do | |
| not want to cache inodes - causing "delete_inode" to always be | |
| called regardless of the value of i_nlink) | |
| The "inode_just_drop()" behavior is equivalent to the old | |
| practice of using "force_delete" in the put_inode() case, but | |
| does not have the races that the "force_delete()" approach had. | |
| ``evict_inode`` | |
| called when the VFS wants to evict an inode. Caller does | |
| *not* evict the pagecache or inode-associated metadata buffers; | |
| the method has to use truncate_inode_pages_final() to get rid | |
| of those. Caller makes sure async writeback cannot be running for | |
| the inode while (or after) ->evict_inode() is called. Optional. | |
| ``put_super`` | |
| called when the VFS wishes to free the superblock | |
| (i.e. unmount). This is called with the superblock lock held | |
| ``sync_fs`` | |
| called when VFS is writing out all dirty data associated with a | |
| superblock. The second parameter indicates whether the method | |
| should wait until the write out has been completed. Optional. | |
| ``freeze_super`` | |
| Called instead of ->freeze_fs callback if provided. | |
| Main difference is that ->freeze_super is called without taking | |
| down_write(&sb->s_umount). If filesystem implements it and wants | |
| ->freeze_fs to be called too, then it has to call ->freeze_fs | |
| explicitly from this callback. Optional. | |
| ``freeze_fs`` | |
| called when VFS is locking a filesystem and forcing it into a | |
| consistent state. This method is currently used by the Logical | |
| Volume Manager (LVM) and ioctl(FIFREEZE). Optional. | |
| ``thaw_super`` | |
| called when VFS is unlocking a filesystem and making it writable | |
| again after ->freeze_super. Optional. | |
| ``unfreeze_fs`` | |
| called when VFS is unlocking a filesystem and making it writable | |
| again after ->freeze_fs. Optional. | |
| ``statfs`` | |
| called when the VFS needs to get filesystem statistics. | |
| ``umount_begin`` | |
| called when the VFS is unmounting a filesystem. | |
| ``show_options`` | |
| called by the VFS to show mount options for /proc/<pid>/mounts | |
| and /proc/<pid>/mountinfo. | |
| (see "Mount Options" section) | |
| ``show_devname`` | |
| Optional. Called by the VFS to show device name for | |
| /proc/<pid>/{mounts,mountinfo,mountstats}. If not provided then | |
| '(struct mount).mnt_devname' will be used. | |
| ``show_path`` | |
| Optional. Called by the VFS (for /proc/<pid>/mountinfo) to show | |
| the mount root dentry path relative to the filesystem root. | |
| ``show_stats`` | |
| Optional. Called by the VFS (for /proc/<pid>/mountstats) to show | |
| filesystem-specific mount statistics. | |
| ``quota_read`` | |
| called by the VFS to read from filesystem quota file. | |
| ``quota_write`` | |
| called by the VFS to write to filesystem quota file. | |
| ``get_dquots`` | |
| called by quota to get 'struct dquot' array for a particular inode. | |
| Optional. | |
| ``nr_cached_objects`` | |
| called by the sb cache shrinking function for the filesystem to | |
| return the number of freeable cached objects it contains. | |
| Optional. | |
| ``free_cache_objects`` | |
| called by the sb cache shrinking function for the filesystem to | |
| scan the number of objects indicated to try to free them. | |
| Optional, but any filesystem implementing this method needs to | |
| also implement ->nr_cached_objects for it to be called | |
| correctly. | |
| We can't do anything with any errors that the filesystem might | |
| encountered, hence the void return type. This will never be | |
| called if the VM is trying to reclaim under GFP_NOFS conditions, | |
| hence this method does not need to handle that situation itself. | |
| Implementations must include conditional reschedule calls inside | |
| any scanning loop that is done. This allows the VFS to | |
| determine appropriate scan batch sizes without having to worry | |
| about whether implementations will cause holdoff problems due to | |
| large scan batch sizes. | |
| Whoever sets up the inode is responsible for filling in the "i_op" | |
| field. This is a pointer to a "struct inode_operations" which describes | |
| the methods that can be performed on individual inodes. | |
| struct xattr_handler | |
| --------------------- | |
| On filesystems that support extended attributes (xattrs), the s_xattr | |
| superblock field points to a NULL-terminated array of xattr handlers. | |
| Extended attributes are name:value pairs. | |
| ``name`` | |
| Indicates that the handler matches attributes with the specified | |
| name (such as "system.posix_acl_access"); the prefix field must | |
| be NULL. | |
| ``prefix`` | |
| Indicates that the handler matches all attributes with the | |
| specified name prefix (such as "user."); the name field must be | |
| NULL. | |
| ``list`` | |
| Determine if attributes matching this xattr handler should be | |
| listed for a particular dentry. Used by some listxattr | |
| implementations like generic_listxattr. | |
| ``get`` | |
| Called by the VFS to get the value of a particular extended | |
| attribute. This method is called by the getxattr(2) system | |
| call. | |
| ``set`` | |
| Called by the VFS to set the value of a particular extended | |
| attribute. When the new value is NULL, called to remove a | |
| particular extended attribute. This method is called by the | |
| setxattr(2) and removexattr(2) system calls. | |
| When none of the xattr handlers of a filesystem match the specified | |
| attribute name or when a filesystem doesn't support extended attributes, | |
| the various ``*xattr(2)`` system calls return -EOPNOTSUPP. | |
| The Inode Object | |
| ================ | |
| An inode object represents an object within the filesystem. | |
| struct inode_operations | |
| ----------------------- | |
| This describes how the VFS can manipulate an inode in your filesystem. | |
| As of kernel 2.6.22, the following members are defined: | |
| .. code-block:: c | |
| struct inode_operations { | |
| int (*create) (struct mnt_idmap *, struct inode *,struct dentry *, umode_t, bool); | |
| struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); | |
| int (*link) (struct dentry *,struct inode *,struct dentry *); | |
| int (*unlink) (struct inode *,struct dentry *); | |
| int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,const char *); | |
| struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t); | |
| int (*rmdir) (struct inode *,struct dentry *); | |
| int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t,dev_t); | |
| int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *, | |
| struct inode *, struct dentry *, unsigned int); | |
| int (*readlink) (struct dentry *, char __user *,int); | |
| const char *(*get_link) (struct dentry *, struct inode *, | |
| struct delayed_call *); | |
| int (*permission) (struct mnt_idmap *, struct inode *, int); | |
| struct posix_acl * (*get_inode_acl)(struct inode *, int, bool); | |
| int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *); | |
| int (*getattr) (struct mnt_idmap *, const struct path *, struct kstat *, u32, unsigned int); | |
| ssize_t (*listxattr) (struct dentry *, char *, size_t); | |
| void (*update_time)(struct inode *inode, enum fs_update_time type, | |
| int flags); | |
| void (*sync_lazytime)(struct inode *inode); | |
| int (*atomic_open)(struct inode *, struct dentry *, struct file *, | |
| unsigned open_flag, umode_t create_mode); | |
| int (*tmpfile) (struct mnt_idmap *, struct inode *, struct file *, umode_t); | |
| struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int); | |
| int (*set_acl)(struct mnt_idmap *, struct dentry *, struct posix_acl *, int); | |
| int (*fileattr_set)(struct mnt_idmap *idmap, | |
| struct dentry *dentry, struct file_kattr *fa); | |
| int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa); | |
| struct offset_ctx *(*get_offset_ctx)(struct inode *inode); | |
| }; | |
| Again, all methods are called without any locks being held, unless | |
| otherwise noted. | |
| ``create`` | |
| called by the open(2) and creat(2) system calls. Only required | |
| if you want to support regular files. The dentry you get should | |
| not have an inode (i.e. it should be a negative dentry). Here | |
| you will probably call d_instantiate() with the dentry and the | |
| newly created inode | |
| ``lookup`` | |
| called when the VFS needs to look up an inode in a parent | |
| directory. The name to look for is found in the dentry. This | |
| method must call d_add() to insert the found inode into the | |
| dentry. The "i_count" field in the inode structure should be | |
| incremented. If the named inode does not exist a NULL inode | |
| should be inserted into the dentry (this is called a negative | |
| dentry). Returning an error code from this routine must only be | |
| done on a real error, otherwise creating inodes with system | |
| calls like create(2), mknod(2), mkdir(2) and so on will fail. | |
| If you wish to overload the dentry methods then you should | |
| initialise the "d_dop" field in the dentry; this is a pointer to | |
| a struct "dentry_operations". This method is called with the | |
| directory inode semaphore held | |
| ``link`` | |
| called by the link(2) system call. Only required if you want to | |
| support hard links. You will probably need to call | |
| d_instantiate() just as you would in the create() method | |
| ``unlink`` | |
| called by the unlink(2) system call. Only required if you want | |
| to support deleting inodes | |
| ``symlink`` | |
| called by the symlink(2) system call. Only required if you want | |
| to support symlinks. You will probably need to call | |
| d_instantiate() just as you would in the create() method | |
| ``mkdir`` | |
| called by the mkdir(2) system call. Only required if you want | |
| to support creating subdirectories. You will probably need to | |
| call d_instantiate_new() just as you would in the create() method. | |
| If d_instantiate_new() is not used and if the fh_to_dentry() | |
| export operation is provided, or if the storage might be | |
| accessible by another path (e.g. with a network filesystem) | |
| then more care may be needed. Importantly d_instantate() | |
| should not be used with an inode that is no longer I_NEW if there | |
| any chance that the inode could already be attached to a dentry. | |
| This is because of a hard rule in the VFS that a directory must | |
| only ever have one dentry. | |
| For example, if an NFS filesystem is mounted twice the new directory | |
| could be visible on the other mount before it is on the original | |
| mount, and a pair of name_to_handle_at(), open_by_handle_at() | |
| calls could instantiate the directory inode with an IS_ROOT() | |
| dentry before the first mkdir returns. | |
| If there is any chance this could happen, then the new inode | |
| should be d_drop()ed and attached with d_splice_alias(). The | |
| returned dentry (if any) should be returned by ->mkdir(). | |
| ``rmdir`` | |
| called by the rmdir(2) system call. Only required if you want | |
| to support deleting subdirectories | |
| ``mknod`` | |
| called by the mknod(2) system call to create a device (char, | |
| block) inode or a named pipe (FIFO) or socket. Only required if | |
| you want to support creating these types of inodes. You will | |
| probably need to call d_instantiate() just as you would in the | |
| create() method | |
| ``rename`` | |
| called by the rename(2) system call to rename the object to have | |
| the parent and name given by the second inode and dentry. | |
| The filesystem must return -EINVAL for any unsupported or | |
| unknown flags. Currently the following flags are implemented: | |
| (1) RENAME_NOREPLACE: this flag indicates that if the target of | |
| the rename exists the rename should fail with -EEXIST instead of | |
| replacing the target. The VFS already checks for existence, so | |
| for local filesystems the RENAME_NOREPLACE implementation is | |
| equivalent to plain rename. | |
| (2) RENAME_EXCHANGE: exchange source and target. Both must | |
| exist; this is checked by the VFS. Unlike plain rename, source | |
| and target may be of different type. | |
| ``get_link`` | |
| called by the VFS to follow a symbolic link to the inode it | |
| points to. Only required if you want to support symbolic links. | |
| This method returns the symlink body to traverse (and possibly | |
| resets the current position with nd_jump_link()). If the body | |
| won't go away until the inode is gone, nothing else is needed; | |
| if it needs to be otherwise pinned, arrange for its release by | |
| having get_link(..., ..., done) do set_delayed_call(done, | |
| destructor, argument). In that case destructor(argument) will | |
| be called once VFS is done with the body you've returned. May | |
| be called in RCU mode; that is indicated by NULL dentry | |
| argument. If request can't be handled without leaving RCU mode, | |
| have it return ERR_PTR(-ECHILD). | |
| If the filesystem stores the symlink target in ->i_link, the | |
| VFS may use it directly without calling ->get_link(); however, | |
| ->get_link() must still be provided. ->i_link must not be | |
| freed until after an RCU grace period. Writing to ->i_link | |
| post-iget() time requires a 'release' memory barrier. | |
| ``readlink`` | |
| this is now just an override for use by readlink(2) for the | |
| cases when ->get_link uses nd_jump_link() or object is not in | |
| fact a symlink. Normally filesystems should only implement | |
| ->get_link for symlinks and readlink(2) will automatically use | |
| that. | |
| ``permission`` | |
| called by the VFS to check for access rights on a POSIX-like | |
| filesystem. | |
| May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in | |
| rcu-walk mode, the filesystem must check the permission without | |
| blocking or storing to the inode. | |
| If a situation is encountered that rcu-walk cannot handle, | |
| return | |
| -ECHILD and it will be called again in ref-walk mode. | |
| ``setattr`` | |
| called by the VFS to set attributes for a file. This method is | |
| called by chmod(2) and related system calls. | |
| ``getattr`` | |
| called by the VFS to get attributes of a file. This method is | |
| called by stat(2) and related system calls. | |
| ``listxattr`` | |
| called by the VFS to list all extended attributes for a given | |
| file. This method is called by the listxattr(2) system call. | |
| ``update_time`` | |
| called by the VFS to update a specific time or the i_version of | |
| an inode. If this is not defined the VFS will update the inode | |
| itself and call mark_inode_dirty_sync. | |
| ``sync_lazytime``: | |
| called by the writeback code to update the lazy time stamps to | |
| regular time stamp updates that get syncing into the on-disk | |
| inode. | |
| ``atomic_open`` | |
| called on the last component of an open. Using this optional | |
| method the filesystem can look up, possibly create and open the | |
| file in one atomic operation. If it wants to leave actual | |
| opening to the caller (e.g. if the file turned out to be a | |
| symlink, device, or just something filesystem won't do atomic | |
| open for), it may signal this by returning finish_no_open(file, | |
| dentry). This method is only called if the last component is | |
| negative or needs lookup. Cached positive dentries are still | |
| handled by f_op->open(). If the file was created, FMODE_CREATED | |
| flag should be set in file->f_mode. In case of O_EXCL the | |
| method must only succeed if the file didn't exist and hence | |
| FMODE_CREATED shall always be set on success. | |
| ``tmpfile`` | |
| called in the end of O_TMPFILE open(). Optional, equivalent to | |
| atomically creating, opening and unlinking a file in given | |
| directory. On success needs to return with the file already | |
| open; this can be done by calling finish_open_simple() right at | |
| the end. | |
| ``fileattr_get`` | |
| called on ioctl(FS_IOC_GETFLAGS) and ioctl(FS_IOC_FSGETXATTR) to | |
| retrieve miscellaneous file flags and attributes. Also called | |
| before the relevant SET operation to check what is being changed | |
| (in this case with i_rwsem locked exclusive). If unset, then | |
| fall back to f_op->ioctl(). | |
| ``fileattr_set`` | |
| called on ioctl(FS_IOC_SETFLAGS) and ioctl(FS_IOC_FSSETXATTR) to | |
| change miscellaneous file flags and attributes. Callers hold | |
| i_rwsem exclusive. If unset, then fall back to f_op->ioctl(). | |
| ``get_offset_ctx`` | |
| called to get the offset context for a directory inode. A | |
| filesystem must define this operation to use | |
| simple_offset_dir_operations. | |
| The Address Space Object | |
| ======================== | |
| The address space object is used to group and manage pages in the page | |
| cache. It can be used to keep track of the pages in a file (or anything | |
| else) and also track the mapping of sections of the file into process | |
| address spaces. | |
| There are a number of distinct yet related services that an | |
| address-space can provide. These include communicating memory pressure, | |
| page lookup by address, and keeping track of pages tagged as Dirty or | |
| Writeback. | |
| The first can be used independently to the others. The VM can try to | |
| release clean pages in order to reuse them. To do this it can call | |
| ->release_folio on clean folios with the private | |
| flag set. Clean pages without PagePrivate and with no external references | |
| will be released without notice being given to the address_space. | |
| To achieve this functionality, pages need to be placed on an LRU with | |
| lru_cache_add and mark_page_active needs to be called whenever the page | |
| is used. | |
| Pages are normally kept in a radix tree index by ->index. This tree | |
| maintains information about the PG_Dirty and PG_Writeback status of each | |
| page, so that pages with either of these flags can be found quickly. | |
| The Dirty tag is primarily used by mpage_writepages - the default | |
| ->writepages method. It uses the tag to find dirty pages to | |
| write back. If mpage_writepages is not used (i.e. the address | |
| provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is almost | |
| unused. write_inode_now and sync_inode do use it (through | |
| __sync_single_inode) to check if ->writepages has been successful in | |
| writing out the whole address_space. | |
| The Writeback tag is used by filemap*wait* and sync_page* functions, via | |
| filemap_fdatawait_range, to wait for all writeback to complete. | |
| An address_space handler may attach extra information to a page, | |
| typically using the 'private' field in the 'struct page'. If such | |
| information is attached, the PG_Private flag should be set. This will | |
| cause various VM routines to make extra calls into the address_space | |
| handler to deal with that data. | |
| An address space acts as an intermediate between storage and | |
| application. Data is read into the address space a whole page at a | |
| time, and provided to the application either by copying of the page, or | |
| by memory-mapping the page. Data is written into the address space by | |
| the application, and then written-back to storage typically in whole | |
| pages, however the address_space has finer control of write sizes. | |
| The read process essentially only requires 'read_folio'. The write | |
| process is more complicated and uses write_begin/write_end or | |
| dirty_folio to write data into the address_space, and | |
| writepages to writeback data to storage. | |
| Removing pages from an address_space requires holding the inode's i_rwsem | |
| exclusively, while adding pages to the address_space requires holding the | |
| inode's i_mapping->invalidate_lock exclusively. | |
| When data is written to a page, the PG_Dirty flag should be set. It | |
| typically remains set until writepages asks for it to be written. This | |
| should clear PG_Dirty and set PG_Writeback. It can be actually written | |
| at any point after PG_Dirty is clear. Once it is known to be safe, | |
| PG_Writeback is cleared. | |
| Writeback makes use of a writeback_control structure to direct the | |
| operations. This gives the writepages operation some | |
| information about the nature of and reason for the writeback request, | |
| and the constraints under which it is being done. It is also used to | |
| return information back to the caller about the result of a | |
| writepages request. | |
| Handling errors during writeback | |
| -------------------------------- | |
| Most applications that do buffered I/O will periodically call a file | |
| synchronization call (fsync, fdatasync, msync or sync_file_range) to | |
| ensure that data written has made it to the backing store. When there | |
| is an error during writeback, they expect that error to be reported when | |
| a file sync request is made. After an error has been reported on one | |
| request, subsequent requests on the same file descriptor should return | |
| 0, unless further writeback errors have occurred since the previous file | |
| synchronization. | |
| Ideally, the kernel would report errors only on file descriptions on | |
| which writes were done that subsequently failed to be written back. The | |
| generic pagecache infrastructure does not track the file descriptions | |
| that have dirtied each individual page however, so determining which | |
| file descriptors should get back an error is not possible. | |
| Instead, the generic writeback error tracking infrastructure in the | |
| kernel settles for reporting errors to fsync on all file descriptions | |
| that were open at the time that the error occurred. In a situation with | |
| multiple writers, all of them will get back an error on a subsequent | |
| fsync, even if all of the writes done through that particular file | |
| descriptor succeeded (or even if there were no writes on that file | |
| descriptor at all). | |
| Filesystems that wish to use this infrastructure should call | |
| mapping_set_error to record the error in the address_space when it | |
| occurs. Then, after writing back data from the pagecache in their | |
| file->fsync operation, they should call file_check_and_advance_wb_err to | |
| ensure that the struct file's error cursor has advanced to the correct | |
| point in the stream of errors emitted by the backing device(s). | |
| struct address_space_operations | |
| ------------------------------- | |
| This describes how the VFS can manipulate mapping of a file to page | |
| cache in your filesystem. The following members are defined: | |
| .. code-block:: c | |
| struct address_space_operations { | |
| int (*read_folio)(struct file *, struct folio *); | |
| int (*writepages)(struct address_space *, struct writeback_control *); | |
| bool (*dirty_folio)(struct address_space *, struct folio *); | |
| void (*readahead)(struct readahead_control *); | |
| int (*write_begin)(const struct kiocb *, struct address_space *mapping, | |
| loff_t pos, unsigned len, | |
| struct page **pagep, void **fsdata); | |
| int (*write_end)(const struct kiocb *, struct address_space *mapping, | |
| loff_t pos, unsigned len, unsigned copied, | |
| struct folio *folio, void *fsdata); | |
| sector_t (*bmap)(struct address_space *, sector_t); | |
| void (*invalidate_folio) (struct folio *, size_t start, size_t len); | |
| bool (*release_folio)(struct folio *, gfp_t); | |
| void (*free_folio)(struct folio *); | |
| ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter); | |
| int (*migrate_folio)(struct mapping *, struct folio *dst, | |
| struct folio *src, enum migrate_mode); | |
| int (*launder_folio) (struct folio *); | |
| bool (*is_partially_uptodate) (struct folio *, size_t from, | |
| size_t count); | |
| void (*is_dirty_writeback)(struct folio *, bool *, bool *); | |
| int (*error_remove_folio)(struct mapping *mapping, struct folio *); | |
| int (*swap_activate)(struct swap_info_struct *sis, struct file *f, sector_t *span) | |
| int (*swap_deactivate)(struct file *); | |
| int (*swap_rw)(struct kiocb *iocb, struct iov_iter *iter); | |
| }; | |
| ``read_folio`` | |
| Called by the page cache to read a folio from the backing store. | |
| The 'file' argument supplies authentication information to network | |
| filesystems, and is generally not used by block based filesystems. | |
| It may be NULL if the caller does not have an open file (eg if | |
| the kernel is performing a read for itself rather than on behalf | |
| of a userspace process with an open file). | |
| If the mapping does not support large folios, the folio will | |
| contain a single page. The folio will be locked when read_folio | |
| is called. If the read completes successfully, the folio should | |
| be marked uptodate. The filesystem should unlock the folio | |
| once the read has completed, whether it was successful or not. | |
| The filesystem does not need to modify the refcount on the folio; | |
| the page cache holds a reference count and that will not be | |
| released until the folio is unlocked. | |
| Filesystems may implement ->read_folio() synchronously. | |
| In normal operation, folios are read through the ->readahead() | |
| method. Only if this fails, or if the caller needs to wait for | |
| the read to complete will the page cache call ->read_folio(). | |
| Filesystems should not attempt to perform their own readahead | |
| in the ->read_folio() operation. | |
| If the filesystem cannot perform the read at this time, it can | |
| unlock the folio, do whatever action it needs to ensure that the | |
| read will succeed in the future and return AOP_TRUNCATED_PAGE. | |
| In this case, the caller should look up the folio, lock it, | |
| and call ->read_folio again. | |
| Callers may invoke the ->read_folio() method directly, but using | |
| read_mapping_folio() will take care of locking, waiting for the | |
| read to complete and handle cases such as AOP_TRUNCATED_PAGE. | |
| ``writepages`` | |
| called by the VM to write out pages associated with the | |
| address_space object. If wbc->sync_mode is WB_SYNC_ALL, then | |
| the writeback_control will specify a range of pages that must be | |
| written out. If it is WB_SYNC_NONE, then a nr_to_write is | |
| given and that many pages should be written if possible. If no | |
| ->writepages is given, then mpage_writepages is used instead. | |
| This will choose pages from the address space that are tagged as | |
| DIRTY and will write them back. | |
| ``dirty_folio`` | |
| called by the VM to mark a folio as dirty. This is particularly | |
| needed if an address space attaches private data to a folio, and | |
| that data needs to be updated when a folio is dirtied. This is | |
| called, for example, when a memory mapped page gets modified. | |
| If defined, it should set the folio dirty flag, and the | |
| PAGECACHE_TAG_DIRTY search mark in i_pages. | |
| ``readahead`` | |
| Called by the VM to read pages associated with the address_space | |
| object. The pages are consecutive in the page cache and are | |
| locked. The implementation should decrement the page refcount | |
| after starting I/O on each page. Usually the page will be | |
| unlocked by the I/O completion handler. The set of pages are | |
| divided into some sync pages followed by some async pages, | |
| rac->ra->async_size gives the number of async pages. The | |
| filesystem should attempt to read all sync pages but may decide | |
| to stop once it reaches the async pages. If it does decide to | |
| stop attempting I/O, it can simply return. The caller will | |
| remove the remaining pages from the address space, unlock them | |
| and decrement the page refcount. Set PageUptodate if the I/O | |
| completes successfully. | |
| ``write_begin`` | |
| Called by the generic buffered write code to ask the filesystem | |
| to prepare to write len bytes at the given offset in the file. | |
| The address_space should check that the write will be able to | |
| complete, by allocating space if necessary and doing any other | |
| internal housekeeping. If the write will update parts of any | |
| basic-blocks on storage, then those blocks should be pre-read | |
| (if they haven't been read already) so that the updated blocks | |
| can be written out properly. | |
| The filesystem must return the locked pagecache folio for the | |
| specified offset, in ``*foliop``, for the caller to write into. | |
| It must be able to cope with short writes (where the length | |
| passed to write_begin is greater than the number of bytes copied | |
| into the folio). | |
| A void * may be returned in fsdata, which then gets passed into | |
| write_end. | |
| Returns 0 on success; < 0 on failure (which is the error code), | |
| in which case write_end is not called. | |
| ``write_end`` | |
| After a successful write_begin, and data copy, write_end must be | |
| called. len is the original len passed to write_begin, and | |
| copied is the amount that was able to be copied. | |
| The filesystem must take care of unlocking the folio, | |
| decrementing its refcount, and updating i_size. | |
| Returns < 0 on failure, otherwise the number of bytes (<= | |
| 'copied') that were able to be copied into pagecache. | |
| ``bmap`` | |
| called by the VFS to map a logical block offset within object to | |
| physical block number. This method is used by the FIBMAP ioctl | |
| and for working with swap-files. To be able to swap to a file, | |
| the file must have a stable mapping to a block device. The swap | |
| system does not go through the filesystem but instead uses bmap | |
| to find out where the blocks in the file are and uses those | |
| addresses directly. | |
| ``invalidate_folio`` | |
| If a folio has private data, then invalidate_folio will be | |
| called when part or all of the folio is to be removed from the | |
| address space. This generally corresponds to either a | |
| truncation, punch hole or a complete invalidation of the address | |
| space (in the latter case 'offset' will always be 0 and 'length' | |
| will be folio_size()). Any private data associated with the folio | |
| should be updated to reflect this truncation. If offset is 0 | |
| and length is folio_size(), then the private data should be | |
| released, because the folio must be able to be completely | |
| discarded. This may be done by calling the ->release_folio | |
| function, but in this case the release MUST succeed. | |
| ``release_folio`` | |
| release_folio is called on folios with private data to tell the | |
| filesystem that the folio is about to be freed. ->release_folio | |
| should remove any private data from the folio and clear the | |
| private flag. If release_folio() fails, it should return false. | |
| release_folio() is used in two distinct though related cases. | |
| The first is when the VM wants to free a clean folio with no | |
| active users. If ->release_folio succeeds, the folio will be | |
| removed from the address_space and be freed. | |
| The second case is when a request has been made to invalidate | |
| some or all folios in an address_space. This can happen | |
| through the fadvise(POSIX_FADV_DONTNEED) system call or by the | |
| filesystem explicitly requesting it as nfs and 9p do (when they | |
| believe the cache may be out of date with storage) by calling | |
| invalidate_inode_pages2(). If the filesystem makes such a call, | |
| and needs to be certain that all folios are invalidated, then | |
| its release_folio will need to ensure this. Possibly it can | |
| clear the uptodate flag if it cannot free private data yet. | |
| ``free_folio`` | |
| free_folio is called once the folio is no longer visible in the | |
| page cache in order to allow the cleanup of any private data. | |
| Since it may be called by the memory reclaimer, it should not | |
| assume that the original address_space mapping still exists, and | |
| it should not block. | |
| ``direct_IO`` | |
| called by the generic read/write routines to perform direct_IO - | |
| that is IO requests which bypass the page cache and transfer | |
| data directly between the storage and the application's address | |
| space. | |
| ``migrate_folio`` | |
| This is used to compact the physical memory usage. If the VM | |
| wants to relocate a folio (maybe from a memory device that is | |
| signalling imminent failure) it will pass a new folio and an old | |
| folio to this function. migrate_folio should transfer any private | |
| data across and update any references that it has to the folio. | |
| ``launder_folio`` | |
| Called before freeing a folio - it writes back the dirty folio. | |
| To prevent redirtying the folio, it is kept locked during the | |
| whole operation. | |
| ``is_partially_uptodate`` | |
| Called by the VM when reading a file through the pagecache when | |
| the underlying blocksize is smaller than the size of the folio. | |
| If the required block is up to date then the read can complete | |
| without needing I/O to bring the whole page up to date. | |
| ``is_dirty_writeback`` | |
| Called by the VM when attempting to reclaim a folio. The VM uses | |
| dirty and writeback information to determine if it needs to | |
| stall to allow flushers a chance to complete some IO. | |
| Ordinarily it can use folio_test_dirty and folio_test_writeback but | |
| some filesystems have more complex state (unstable folios in NFS | |
| prevent reclaim) or do not set those flags due to locking | |
| problems. This callback allows a filesystem to indicate to the | |
| VM if a folio should be treated as dirty or writeback for the | |
| purposes of stalling. | |
| ``error_remove_folio`` | |
| normally set to generic_error_remove_folio if truncation is ok | |
| for this address space. Used for memory failure handling. | |
| Setting this implies you deal with pages going away under you, | |
| unless you have them locked or reference counts increased. | |
| ``swap_activate`` | |
| Called to prepare the given file for swap. It should perform | |
| any validation and preparation necessary to ensure that writes | |
| can be performed with minimal memory allocation. It should call | |
| add_swap_extent(), or the helper iomap_swapfile_activate(), and | |
| return the number of extents added. If IO should be submitted | |
| through ->swap_rw(), it should set SWP_FS_OPS, otherwise IO will | |
| be submitted directly to the block device ``sis->bdev``. | |
| ``swap_deactivate`` | |
| Called during swapoff on files where swap_activate was | |
| successful. | |
| ``swap_rw`` | |
| Called to read or write swap pages when SWP_FS_OPS is set. | |
| The File Object | |
| =============== | |
| A file object represents a file opened by a process. This is also known | |
| as an "open file description" in POSIX parlance. | |
| struct file_operations | |
| ---------------------- | |
| This describes how the VFS can manipulate an open file. As of kernel | |
| 4.18, the following members are defined: | |
| .. code-block:: c | |
| struct file_operations { | |
| struct module *owner; | |
| fop_flags_t fop_flags; | |
| loff_t (*llseek) (struct file *, loff_t, int); | |
| ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); | |
| ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); | |
| ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); | |
| ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); | |
| int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, | |
| unsigned int flags); | |
| int (*iterate_shared) (struct file *, struct dir_context *); | |
| __poll_t (*poll) (struct file *, struct poll_table_struct *); | |
| long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | |
| long (*compat_ioctl) (struct file *, unsigned int, unsigned long); | |
| int (*mmap) (struct file *, struct vm_area_struct *); | |
| int (*open) (struct inode *, struct file *); | |
| int (*flush) (struct file *, fl_owner_t id); | |
| int (*release) (struct inode *, struct file *); | |
| int (*fsync) (struct file *, loff_t, loff_t, int datasync); | |
| int (*fasync) (int, struct file *, int); | |
| int (*lock) (struct file *, int, struct file_lock *); | |
| unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | |
| int (*check_flags)(int); | |
| int (*flock) (struct file *, int, struct file_lock *); | |
| ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); | |
| ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); | |
| void (*splice_eof)(struct file *file); | |
| int (*setlease)(struct file *, int, struct file_lease **, void **); | |
| long (*fallocate)(struct file *file, int mode, loff_t offset, | |
| loff_t len); | |
| void (*show_fdinfo)(struct seq_file *m, struct file *f); | |
| #ifndef CONFIG_MMU | |
| unsigned (*mmap_capabilities)(struct file *); | |
| #endif | |
| ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, | |
| loff_t, size_t, unsigned int); | |
| loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in, | |
| struct file *file_out, loff_t pos_out, | |
| loff_t len, unsigned int remap_flags); | |
| int (*fadvise)(struct file *, loff_t, loff_t, int); | |
| int (*uring_cmd)(struct io_uring_cmd *ioucmd, unsigned int issue_flags); | |
| int (*uring_cmd_iopoll)(struct io_uring_cmd *, struct io_comp_batch *, | |
| unsigned int poll_flags); | |
| int (*mmap_prepare)(struct vm_area_desc *); | |
| }; | |
| Again, all methods are called without any locks being held, unless | |
| otherwise noted. | |
| ``llseek`` | |
| called when the VFS needs to move the file position index | |
| ``read`` | |
| called by read(2) and related system calls | |
| ``read_iter`` | |
| possibly asynchronous read with iov_iter as destination | |
| ``write`` | |
| called by write(2) and related system calls | |
| ``write_iter`` | |
| possibly asynchronous write with iov_iter as source | |
| ``iopoll`` | |
| called when aio wants to poll for completions on HIPRI iocbs | |
| ``iterate_shared`` | |
| called when the VFS needs to read the directory contents | |
| ``poll`` | |
| called by the VFS when a process wants to check if there is | |
| activity on this file and (optionally) go to sleep until there | |
| is activity. Called by the select(2) and poll(2) system calls | |
| ``unlocked_ioctl`` | |
| called by the ioctl(2) system call. | |
| ``compat_ioctl`` | |
| called by the ioctl(2) system call when 32 bit system calls are | |
| used on 64 bit kernels. | |
| ``mmap`` | |
| called by the mmap(2) system call. Deprecated in favour of | |
| ``mmap_prepare``. | |
| ``open`` | |
| called by the VFS when an inode should be opened. When the VFS | |
| opens a file, it creates a new "struct file". It then calls the | |
| open method for the newly allocated file structure. You might | |
| think that the open method really belongs in "struct | |
| inode_operations", and you may be right. I think it's done the | |
| way it is because it makes filesystems simpler to implement. | |
| The open() method is a good place to initialize the | |
| "private_data" member in the file structure if you want to point | |
| to a device structure | |
| ``flush`` | |
| called by the close(2) system call to flush a file | |
| ``release`` | |
| called when the last reference to an open file is closed | |
| ``fsync`` | |
| called by the fsync(2) system call. Also see the section above | |
| entitled "Handling errors during writeback". | |
| ``fasync`` | |
| called by the fcntl(2) system call when asynchronous | |
| (non-blocking) mode is enabled for a file | |
| ``lock`` | |
| called by the fcntl(2) system call for F_GETLK, F_SETLK, and | |
| F_SETLKW commands | |
| ``get_unmapped_area`` | |
| called by the mmap(2) system call | |
| ``check_flags`` | |
| called by the fcntl(2) system call for F_SETFL command | |
| ``flock`` | |
| called by the flock(2) system call | |
| ``splice_write`` | |
| called by the VFS to splice data from a pipe to a file. This | |
| method is used by the splice(2) system call | |
| ``splice_read`` | |
| called by the VFS to splice data from file to a pipe. This | |
| method is used by the splice(2) system call | |
| ``setlease`` | |
| called by the VFS to set or release a file lock lease. Local | |
| filesystems that wish to use the kernel-internal lease implementation | |
| should set this to generic_setlease(). Other setlease implementations | |
| should call generic_setlease() to record or remove the lease in the inode | |
| after setting it. When set to NULL, attempts to set or remove a lease will | |
| return -EINVAL. | |
| ``fallocate`` | |
| called by the VFS to preallocate blocks or punch a hole. | |
| ``copy_file_range`` | |
| called by the copy_file_range(2) system call. | |
| ``remap_file_range`` | |
| called by the ioctl(2) system call for FICLONERANGE and FICLONE | |
| and FIDEDUPERANGE commands to remap file ranges. An | |
| implementation should remap len bytes at pos_in of the source | |
| file into the dest file at pos_out. Implementations must handle | |
| callers passing in len == 0; this means "remap to the end of the | |
| source file". The return value should the number of bytes | |
| remapped, or the usual negative error code if errors occurred | |
| before any bytes were remapped. The remap_flags parameter | |
| accepts REMAP_FILE_* flags. If REMAP_FILE_DEDUP is set then the | |
| implementation must only remap if the requested file ranges have | |
| identical contents. If REMAP_FILE_CAN_SHORTEN is set, the caller is | |
| ok with the implementation shortening the request length to | |
| satisfy alignment or EOF requirements (or any other reason). | |
| ``fadvise`` | |
| possibly called by the fadvise64() system call. | |
| ``mmap_prepare`` | |
| Called by the mmap(2) system call. Allows a VFS to set up a | |
| file-backed memory mapping, most notably establishing relevant | |
| private state and VMA callbacks. | |
| If further action such as pre-population of page tables is required, | |
| this can be specified by the vm_area_desc->action field and related | |
| parameters. | |
| Note that the file operations are implemented by the specific | |
| filesystem in which the inode resides. When opening a device node | |
| (character or block special) most filesystems will call special | |
| support routines in the VFS which will locate the required device | |
| driver information. These support routines replace the filesystem file | |
| operations with those for the device driver, and then proceed to call | |
| the new open() method for the file. This is how opening a device file | |
| in the filesystem eventually ends up calling the device driver open() | |
| method. | |
| Directory Entry Cache (dcache) | |
| ============================== | |
| struct dentry_operations | |
| ------------------------ | |
| This describes how a filesystem can overload the standard dentry | |
| operations. Dentries and the dcache are the domain of the VFS and the | |
| individual filesystem implementations. Device drivers have no business | |
| here. These methods may be set to NULL, as they are either optional or | |
| the VFS uses a default. As of kernel 2.6.22, the following members are | |
| defined: | |
| .. code-block:: c | |
| struct dentry_operations { | |
| int (*d_revalidate)(struct inode *, const struct qstr *, | |
| struct dentry *, unsigned int); | |
| int (*d_weak_revalidate)(struct dentry *, unsigned int); | |
| int (*d_hash)(const struct dentry *, struct qstr *); | |
| int (*d_compare)(const struct dentry *, | |
| unsigned int, const char *, const struct qstr *); | |
| int (*d_delete)(const struct dentry *); | |
| int (*d_init)(struct dentry *); | |
| void (*d_release)(struct dentry *); | |
| void (*d_iput)(struct dentry *, struct inode *); | |
| char *(*d_dname)(struct dentry *, char *, int); | |
| struct vfsmount *(*d_automount)(struct path *); | |
| int (*d_manage)(const struct path *, bool); | |
| struct dentry *(*d_real)(struct dentry *, enum d_real_type type); | |
| bool (*d_unalias_trylock)(const struct dentry *); | |
| void (*d_unalias_unlock)(const struct dentry *); | |
| }; | |
| ``d_revalidate`` | |
| called when the VFS needs to revalidate a dentry. This is | |
| called whenever a name look-up finds a dentry in the dcache. | |
| Most local filesystems leave this as NULL, because all their | |
| dentries in the dcache are valid. Network filesystems are | |
| different since things can change on the server without the | |
| client necessarily being aware of it. | |
| This function should return a positive value if the dentry is | |
| still valid, and zero or a negative error code if it isn't. | |
| d_revalidate may be called in rcu-walk mode (flags & | |
| LOOKUP_RCU). If in rcu-walk mode, the filesystem must | |
| revalidate the dentry without blocking or storing to the dentry, | |
| d_parent and d_inode should not be used without care (because | |
| they can change and, in d_inode case, even become NULL under | |
| us). | |
| If a situation is encountered that rcu-walk cannot handle, | |
| return | |
| -ECHILD and it will be called again in ref-walk mode. | |
| ``d_weak_revalidate`` | |
| called when the VFS needs to revalidate a "jumped" dentry. This | |
| is called when a path-walk ends at dentry that was not acquired | |
| by doing a lookup in the parent directory. This includes "/", | |
| "." and "..", as well as procfs-style symlinks and mountpoint | |
| traversal. | |
| In this case, we are less concerned with whether the dentry is | |
| still fully correct, but rather that the inode is still valid. | |
| As with d_revalidate, most local filesystems will set this to | |
| NULL since their dcache entries are always valid. | |
| This function has the same return code semantics as | |
| d_revalidate. | |
| d_weak_revalidate is only called after leaving rcu-walk mode. | |
| ``d_hash`` | |
| called when the VFS adds a dentry to the hash table. The first | |
| dentry passed to d_hash is the parent directory that the name is | |
| to be hashed into. | |
| Same locking and synchronisation rules as d_compare regarding | |
| what is safe to dereference etc. | |
| ``d_compare`` | |
| called to compare a dentry name with a given name. The first | |
| dentry is the parent of the dentry to be compared, the second is | |
| the child dentry. len and name string are properties of the | |
| dentry to be compared. qstr is the name to compare it with. | |
| Must be constant and idempotent, and should not take locks if | |
| possible, and should not or store into the dentry. Should not | |
| dereference pointers outside the dentry without lots of care | |
| (eg. d_parent, d_inode, d_name should not be used). | |
| However, our vfsmount is pinned, and RCU held, so the dentries | |
| and inodes won't disappear, neither will our sb or filesystem | |
| module. ->d_sb may be used. | |
| It is a tricky calling convention because it needs to be called | |
| under "rcu-walk", ie. without any locks or references on things. | |
| ``d_delete`` | |
| called when the last reference to a dentry is dropped and the | |
| dcache is deciding whether or not to cache it. Return 1 to | |
| delete immediately, or 0 to cache the dentry. Default is NULL | |
| which means to always cache a reachable dentry. d_delete must | |
| be constant and idempotent. | |
| ``d_init`` | |
| called when a dentry is allocated | |
| ``d_release`` | |
| called when a dentry is really deallocated | |
| ``d_iput`` | |
| called when a dentry loses its inode (just prior to its being | |
| deallocated). The default when this is NULL is that the VFS | |
| calls iput(). If you define this method, you must call iput() | |
| yourself | |
| ``d_dname`` | |
| called when the pathname of a dentry should be generated. | |
| Useful for some pseudo filesystems (sockfs, pipefs, ...) to | |
| delay pathname generation. (Instead of doing it when dentry is | |
| created, it's done only when the path is needed.). Real | |
| filesystems probably dont want to use it, because their dentries | |
| are present in global dcache hash, so their hash should be an | |
| invariant. As no lock is held, d_dname() should not try to | |
| modify the dentry itself, unless appropriate SMP safety is used. | |
| CAUTION : d_path() logic is quite tricky. The correct way to | |
| return for example "Hello" is to put it at the end of the | |
| buffer, and returns a pointer to the first char. | |
| dynamic_dname() helper function is provided to take care of | |
| this. | |
| Example : | |
| .. code-block:: c | |
| static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) | |
| { | |
| return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", | |
| dentry->d_inode->i_ino); | |
| } | |
| ``d_automount`` | |
| called when an automount dentry is to be traversed (optional). | |
| This should create a new VFS mount record and return the record | |
| to the caller. The caller is supplied with a path parameter | |
| giving the automount directory to describe the automount target | |
| and the parent VFS mount record to provide inheritable mount | |
| parameters. NULL should be returned if someone else managed to | |
| make the automount first. If the vfsmount creation failed, then | |
| an error code should be returned. If -EISDIR is returned, then | |
| the directory will be treated as an ordinary directory and | |
| returned to pathwalk to continue walking. | |
| If a vfsmount is returned, the caller will attempt to mount it | |
| on the mountpoint and will remove the vfsmount from its | |
| expiration list in the case of failure. | |
| This function is only used if DCACHE_NEED_AUTOMOUNT is set on | |
| the dentry. This is set by __d_instantiate() if S_AUTOMOUNT is | |
| set on the inode being added. | |
| ``d_manage`` | |
| called to allow the filesystem to manage the transition from a | |
| dentry (optional). This allows autofs, for example, to hold up | |
| clients waiting to explore behind a 'mountpoint' while letting | |
| the daemon go past and construct the subtree there. 0 should be | |
| returned to let the calling process continue. -EISDIR can be | |
| returned to tell pathwalk to use this directory as an ordinary | |
| directory and to ignore anything mounted on it and not to check | |
| the automount flag. Any other error code will abort pathwalk | |
| completely. | |
| If the 'rcu_walk' parameter is true, then the caller is doing a | |
| pathwalk in RCU-walk mode. Sleeping is not permitted in this | |
| mode, and the caller can be asked to leave it and call again by | |
| returning -ECHILD. -EISDIR may also be returned to tell | |
| pathwalk to ignore d_automount or any mounts. | |
| This function is only used if DCACHE_MANAGE_TRANSIT is set on | |
| the dentry being transited from. | |
| ``d_real`` | |
| overlay/union type filesystems implement this method to return one | |
| of the underlying dentries of a regular file hidden by the overlay. | |
| The 'type' argument takes the values D_REAL_DATA or D_REAL_METADATA | |
| for returning the real underlying dentry that refers to the inode | |
| hosting the file's data or metadata respectively. | |
| For non-regular files, the 'dentry' argument is returned. | |
| ``d_unalias_trylock`` | |
| if present, will be called by d_splice_alias() before moving a | |
| preexisting attached alias. Returning false prevents __d_move(), | |
| making d_splice_alias() fail with -ESTALE. | |
| Rationale: setting FS_RENAME_DOES_D_MOVE will prevent d_move() | |
| and d_exchange() calls from the outside of filesystem methods; | |
| however, it does not guarantee that attached dentries won't | |
| be renamed or moved by d_splice_alias() finding a preexisting | |
| alias for a directory inode. Normally we would not care; | |
| however, something that wants to stabilize the entire path to | |
| root over a blocking operation might need that. See 9p for one | |
| (and hopefully only) example. | |
| ``d_unalias_unlock`` | |
| should be paired with ``d_unalias_trylock``; that one is called after | |
| __d_move() call in __d_unalias(). | |
| Each dentry has a pointer to its parent dentry, as well as a hash list | |
| of child dentries. Child dentries are basically like files in a | |
| directory. | |
| Directory Entry Cache API | |
| -------------------------- | |
| There are a number of functions defined which permit a filesystem to | |
| manipulate dentries: | |
| ``dget`` | |
| open a new handle for an existing dentry (this just increments | |
| the usage count) | |
| ``dput`` | |
| close a handle for a dentry (decrements the usage count). If | |
| the usage count drops to 0, and the dentry is still in its | |
| parent's hash, the "d_delete" method is called to check whether | |
| it should be cached. If it should not be cached, or if the | |
| dentry is not hashed, it is deleted. Otherwise cached dentries | |
| are put into an LRU list to be reclaimed on memory shortage. | |
| ``d_drop`` | |
| this unhashes a dentry from its parents hash list. A subsequent | |
| call to dput() will deallocate the dentry if its usage count | |
| drops to 0 | |
| ``d_delete`` | |
| delete a dentry. If there are no other open references to the | |
| dentry then the dentry is turned into a negative dentry (the | |
| d_iput() method is called). If there are other references, then | |
| d_drop() is called instead | |
| ``d_add`` | |
| add a dentry to its parents hash list and then calls | |
| d_instantiate() | |
| ``d_instantiate`` | |
| add a dentry to the alias hash list for the inode and updates | |
| the "d_inode" member. The "i_count" member in the inode | |
| structure should be set/incremented. If the inode pointer is | |
| NULL, the dentry is called a "negative dentry". This function | |
| is commonly called when an inode is created for an existing | |
| negative dentry | |
| ``d_lookup`` | |
| look up a dentry given its parent and path name component It | |
| looks up the child of that given name from the dcache hash | |
| table. If it is found, the reference count is incremented and | |
| the dentry is returned. The caller must use dput() to free the | |
| dentry when it finishes using it. | |
| Mount Options | |
| ============= | |
| Parsing options | |
| --------------- | |
| On mount and remount the filesystem is passed a string containing a | |
| comma separated list of mount options. The options can have either of | |
| these forms: | |
| option | |
| option=value | |
| The <linux/parser.h> header defines an API that helps parse these | |
| options. There are plenty of examples on how to use it in existing | |
| filesystems. | |
| Showing options | |
| --------------- | |
| If a filesystem accepts mount options, it must define show_options() to | |
| show all the currently active options. The rules are: | |
| - options MUST be shown which are not default or their values differ | |
| from the default | |
| - options MAY be shown which are enabled by default or have their | |
| default value | |
| Options used only internally between a mount helper and the kernel (such | |
| as file descriptors), or which only have an effect during the mounting | |
| (such as ones controlling the creation of a journal) are exempt from the | |
| above rules. | |
| The underlying reason for the above rules is to make sure, that a mount | |
| can be accurately replicated (e.g. umounting and mounting again) based | |
| on the information found in /proc/mounts. | |
| Resources | |
| ========= | |
| (Note some of these resources are not up-to-date with the latest kernel | |
| version.) | |
| Creating Linux virtual filesystems. 2002 | |
| <https://lwn.net/Articles/13325/> | |
| The Linux Virtual File-system Layer by Neil Brown. 1999 | |
| <http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html> | |
| A tour of the Linux VFS by Michael K. Johnson. 1996 | |
| <https://www.tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html> | |
| A small trail through the Linux kernel by Andries Brouwer. 2001 | |
| <https://www.win.tue.nl/~aeb/linux/vfs/trail.html> |