Today's Outline
- filesystem and disk access layers
- the Virtual File System (VFS) layer
- VFS objects: superblocks, inodes, dentries, file objects, open file tables
Implementation layers for disk and file access
- disks serve a number of purposes, including
implementing file systems and swap (and memory mapping a file combines
the two)
- implementers find it convenient to think in terms of abstractions
- low-level abstractions, e.g. "read disk block n", are used to
implement higher-level abstractions, e.g. "read bytes a through b of
file x".
- in an OS, the highest-level abstraction implements the system
calls, the lowest-level abstraction controls the hardware
- the following is the layering for the Linux disk and file
access system (note that this picture is not in the book):
The Virtual File System layer (VFS)
- The Virtual File System layer (VFS) supports file system
operations across a variety of file systems, including
- native file systems such as ext2 and ext3
- foreign file systems such as FAT
- distributed file systems such as NFS, Coda, and Andrew
- in-memory filesystems such ramfs
- the VFS is unix-oriented, in that it expects (for example)
that each file will be represented by an inode and that a directory
will be stored in a file
- if a file system does not have inodes (for example, the file
metadata is stored in the file itself, rather than in a separate block),
the inode object in memory is built by the file system code to reflect
the information in the file itself
VFS objects
- the superblock object describes
a mounted filesystem. There is one per mounted filesystem
- the inode object describes a file. There is one per file
being accessed, and inodes may be cached while files are not accessed
- the dentry object is a cached file name, with a pointer to the
corresponding inode
- the file object represents an open file. It includes a pointer to
a dentry which has a pointer to the inode
- each process has a files_struct (open file table)
object which represents
all files opened by that process (p. 232 in the 2nd edition)
This includes an array of file descriptors, the index into which is the
fd returned by an open call
- each process also has an fs object that records the root and current
directories, and a namespace object which allows each process to
have a different set of mounted devices
struct files_struct {
/*
* read mostly part
*/
atomic_t count;
struct fdtable *fdt;
struct fdtable fdtab;
/*
* written part on a separate cache line in SMP
*/
spinlock_t file_lock ____cacheline_aligned_in_smp;
int next_fd;
struct embedded_fd_set close_on_exec_init;
struct embedded_fd_set open_fds_init;
struct file * fd_array[NR_OPEN_DEFAULT];
};