
Many file system types and device types can coexist on the same system. How can we unify them all under one uniform interface? Let’s consider three levels of the storage schematic presented above:
This is the API that userspace programs use to interact with files. Recall file
I/O syscalls from L03-file-io: open(), close(), read(), etc. Userspace
programs receive file descriptor from the kernel and uses syscalls to interact
with the file.
Prefer to give userspace programs a simple and unified interface instead of exposing implementation details! As such, delegate fs-specific details to the kernel.
We’ve learned about several file systems at this point: FFS, ext2, ext3, lfs, reiserfs, etc. We can format (or partition) a storage device (HDD/SSD/etc.) with a file system.
There are even distributed file systems where data is not stored locally, but on some remote server!
However, we don’t want to burden userspace programs with fs-specific details. We need to hook into the kernel so that userspace programs can simply use the unified syscall API!
An FS abstraction layer that transparently and uniformly supports multiple file systems. VFS specifies an interface that a given FS implements to hook into the kernel
struct sched_class from HW6VFS carries out file I/O operations from userspace by dispatching operations to the FS implementation of the VFS interface
dir->inode_op->mkdir()Four high-level VFS data structures: struct file, struct dentry, struct inode, struct super_block.
struct fileRecall from L03-file-io/HW4: struct file represents an instance of an open
file.
dup())struct path f_path (which refers to inode)VFS interface: struct file_operations *f_op
struct dentryBasically a “hard link”: contains name of link and inode number.
Break up an absolute path into dentries, one per component. For example:
/home/hans/foo:
/homehansfooPath resolution is expensive! To open /home/hans/foo you need to:
/ to find the root inodehomehome to find the inodehanshans to find the inodefoofoo to find the inodeLinux employs some cool caching to help improve performance… more on this later.
VFS interface: const struct dentry_operations *d_op
struct inodeUnique descriptor of a file or directory
i_ino: inode # unique per mounted filesystem
Can refer to fs-specific data via i_private (will be used for HW8)
VFS interface: const struct inode_operations *i_op
struct super_blockDescriptor of a mounted filesystem.
VFS interface: const struct super_operations *s_op
Linux kernel makes path resolution efficient by employing a dentry cache (dcache).
(simplified version from this online book)
ext2 at /home
s_root field of super_block refers to root dentry of the mount"/home/hans/foo" for reading
"/home/hans/foo" for writing
struct file because P2 is an independent process"/home/hans/bar"
/home/hans/ path resolution cached in dcachehans/ directory data block to find dentry for barfoobar and foo are hard links to the same inode!Last updated: 2023-04-18