Understanding the Linux Kernel: The VFS

valyala1 pts0 comments

The VFS | Internals for InternsπŸ“š<br>Understanding the Linux Kernel (5 of 6)<br>β–Ό1.<br>The Linux Kernel Startup<br>2.<br>System Calls<br>3.<br>Memory Manager<br>4.<br>The Scheduler<br>5.<br>The VFS<br>You are here<br>6.<br>The Block Layer

In the previous article<br>we saw how the scheduler decides which task gets the CPU β€” so at this point we know how programs get to run. But running isn&rsquo;t enough: for a program to be useful, it almost always needs to read and store data β€” its config from /etc, a shared library from /usr/lib, the rows of a database file, the document you&rsquo;re saving. So the natural next question is: what actually happens when a program opens a file?<br>The answer starts with something quietly strange that&rsquo;s easy to never notice: file operations work identically on an ext4 file (the disk filesystem most Linux distributions use by default), a file in /proc that exists only as kernel memory, and a file on an NFS share on another machine. Same calls, same file descriptor semantics, same close() at the end. Somebody has to be translating &ldquo;read from whatever this is&rdquo; into the right concrete operation, and that somebody is the VFS β€” the Virtual File System , the kernel layer that sits between the syscall interface and every actual filesystem.<br>πŸ“Œ A note on scope<br>Everything here is against Linux 7.1 . The VFS lives mostly in fs/, with its public contract in include/linux/fs.h, include/linux/fs/super_types.h and include/linux/dcache.h. And as usual, this is a deliberate simplification to keep the core ideas clear. This article also stays deliberately above the concrete filesystems: how ext4, Btrfs, XFS and friends actually organize bytes on disk is a whole story of its own, and it&rsquo;s the one my filesystems series<br>tells.

So, how does one kernel speak to dozens of wildly different filesystems without special-casing a single one? With a very old trick.<br>One Interface, Many Filesystems<br>If you&rsquo;ve done object-oriented programming, you already know the trick the VFS uses, because it&rsquo;s the oldest one in the book: program against an interface, not an implementation (in C, an &ldquo;interface&rdquo; is a struct of pointers to functions). The syscall layer never calls ext4. It calls abstract operations on abstract objects β€” &ldquo;look up this name in this directory,&rdquo; &ldquo;read from this open file&rdquo; β€” and each filesystem provides its own implementation of those operations.<br>The whole model is built on four object types β€” the superblock , the inode , the dentry , and the file β€” and each of them carries a pointer to its own operations table; &ldquo;implementing&rdquo; the interface just means filling in those tables with your own functions. Everything else β€” path resolution, the caches, the file descriptor tables, the page cache plumbing β€” is generic code the VFS provides once, for everybody. A filesystem&rsquo;s job is just to fill in the tables. So let&rsquo;s meet the objects.<br>The Four Objects<br>Let&rsquo;s meet them one by one β€” who each object is and what role it plays. We&rsquo;ll go from the bottom up: from the object that stands for a whole filesystem to the one your file descriptor actually points at.<br>At the bottom sits the superblock (struct super_block, include/linux/fs/super_types.h:132): the object that says &ldquo;here is one mounted filesystem&rdquo; β€” mount two different partitions and you get two superblocks. Think of it as the filesystem&rsquo;s identity card: what kind of filesystem it is, where its root directory is, where its data lives. Its super_operations (super_types.h:83) are the housekeeping conversation between the two layers β€” allocate me an inode, write this one back, sync everything: the VFS decides when , the filesystem decides how .<br>Inside that filesystem live the inodes (struct inode, include/linux/fs.h:767). An inode is one thing in the filesystem β€” a file, a directory, a symlink β€” together with everything the kernel knows about it: who owns it, how big it is, when it last changed. Every filesystem stores its own flavor of inode on disk, in its own format, but they all project themselves into this one common in-memory shape. Its inode_operations (fs.h:2001) answer questions about names and structure: look something up, create it, delete it, rename it.<br>Now, here&rsquo;s a subtlety that trips everyone up at first: an inode doesn&rsquo;t know its own name . Names live in directories, and one inode can have several names (hard links) β€” so the kernel gives &ldquo;a name&rdquo; its own object, the dentry (directory entry, struct dentry, include/linux/dcache.h:93), which simply says &ldquo;in this directory, this name means that inode.&rdquo; Dentries exist to make things fast: the names the kernel resolves are remembered in the dcache (dentry cache), so resolving a path usually never touches the disk β€” and the kernel even remembers names that don&rsquo;t exist (negative dentries ), because programs ask for missing files all the time.<br>And finally, the object your program...

rsquo file filesystem linux kernel ldquo

Related Articles