Linux Filesystem
Filesystem
├── Reserved / Metadata Region
│ ├── Boot block (optional / reserved)
│ ├── Superblock
│ ├── Block bitmap
│ ├── Inode bitmap
│ └── Inode table
│
└── Allocatable Region
└── Data blocks
- inode calculation example??
Block
- aka logical blocks
- small fixed-size unit of storage used by the filesystem
- often 4KB
- Filesystem divides disk space into blocks
- They can store
- Superblock data
- Inode tables
- Bitmaps
- Data blocks
Superblock
- metadata about entire filesystem as a whole such as size
- Total blocks
- Free blocks
- Block size
- Total Inodes
- Free Inodes
- Filesystem type
- Filesystem state
# for ext4 formatted filesystems
dumpe2fs /dev/sda3
tune2fs -l /dev/sda3Inode
- Index node
- Stores metadata about a file, except its filename
- owner
- permissions
- timestamps
- file type
- link count
- pointers to data blocks
- See File metadata
# inode metadata
stat <file/directory>
# inode number of file
ls -i <file>
# inode number of directory
ls -id <directory>Directory
- A directory is a special type of file used to organize files and folders
- It contains multiple directory entries
- A directory inode points to the data blocks containing its directory entries
- Directory Entry
- maps a filename to an inode number
notes.txt --> inode 123
image.png --> inode 124
report.pdf --> inode 125
- Check directory contents along with inodes
ls -il <directory>Inode table
- A filesystem structure that stores all inodes
- Each inode occupies an entry in the inode table
- inode table is stored in the metadata region of filesystem along with inode bitmap
- Directory entries use inode numbers to locate the corresponding inode
Data block
- A block used specifically for storing actual file contents
- Inodes point to several data blocks which are used to store the data in the file
- inode —> block1, block2, block3
- Indirect block: Inode has limited space for block pointers
- If a file needs more data blocks than can be directly referenced by the inode, the inode can point to another block called an indirect block
- inode —> indirect block —> block101, block102, block103
- Indirect blocks store pointers/addresses, not actual file contents
- These extra pointer blocks are allocated dynamically when more block references are needed
- Data blocks can contain:
- File contents
- Directory contents
- Indirect block information (block addresses)
Bitmap
- A compact data structure used by the filesystem to track allocation status of resources
- Each bit represents whether a resource is free or in use
- Types:
- Block bitmap
- Tracks free/used data blocks
- Inode bitmap
- Tracks free/used inodes
- Block bitmap
Journaling
- A filesystem mechanism that records intended filesystem changes in a journal before applying them to the actual filesystem
- Helps maintain consistency and recover from crashes or power failures
- Flow
- Filesystem operation
- Write change to journal
- Apply filesystem changes
- Mark journal entry complete
File descriptors
- A file descriptor is an integer used to reference an opened file or I/O resource
- It can represent files, sockets, pipes, terminals, and other I/O resources
- Each process gets a File Descriptor Table (per-process, but lives in kernel memory)
- Programs run in user mode and never directly access the FDT
- The kernel maintains a separate FDT for each process inside its
task_struct(asfiles_struct) - When a syscall like
open()orread()is made, the CPU switches to kernel mode, the kernel looks up the FDT, and returns to user mode with just the result - Maps fd integer (index) —> pointer to open file description (
struct file) - Userspace only ever sees the fd integer; all actual pointers stay inside the kernel
- Standard File descriptor
0—>stdin1—>stdout2—>stderr
# List down file descriptors of a process
ls -l /proc/{pid}/fd
# See info of fd from open file description
cat /proc/{pid}/fdinfo/{fd}- There is a limit to number of file descriptors that can be opened by a process
# provides control over resources available to the shell and any child processes it creates
# check limit of open file descriptors
ulimit -n # Ubuntu
# 1048576
# see all limits
ulimit -aSystem-wide Open File Table
- A kernel-managed global table containing open file descriptions
- Shared across the entire operating system
- File descriptors from different processes may reference the same open file description
fork()— child inherits parent’s fds, both point to the same open file description (shared offset)- So, the parent and child share the exact same cursor/offset. If the child reads 10 bytes, the parent’s offset moves forward too.
- Two independent processes calling
open()on the same file get separate open file descriptions, each with their own offset- Each process maintains its own reading/writing cursor position, preventing them from accidentally overwriting each other’s progress.
- Even though they have separate entries in this table, both entries point to the exact same single entry in the Inode Table.
- Each open file description contains:
- File Offset: The exact byte location where the process is currently reading or writing
- Status Flags: File access mode and behavior
O_RDONLY,O_WRONLY,O_APPEND,O_NONBLOCK
- Reference Count: Tracks how many different processes are using this specific file description
- Inode Reference: Points to the corresponding inode
# list open files
lsof -p <pid>
# list open files based on internet address
lsof -i[TCP|UDP][@address][:port]File Descriptor Layers
- These tables are all in-memory structures managed by the kernel
- File Descriptor Table (per-process)
- maps:
fd integer --> open file description (Open File Table)
- maps:
- Open File Table (system-wide)
- maps:
open file descriptions --> inode (Inode Table)
- maps:
- Inode Table (system-wide/VFS layer)
- not to be confused with Disk Inode Table
- contains metadata and points to data blocks
Open File Flow
open("/path/to/notes.txt")system call- Filesystem searches directory
- Directory entry found
notes.txt --> inode 123
- Read inode 123 and get the Metadata
- Kernel creates an open file description
- Initializes file offset
- Stores status flags (read/write/append, etc.)
- References the inode
- Kernel creates an entry for
fdin the process file descriptor table - Return
fdto application
Read File Flow
read(fd, buffer, size)system call- Kernel locates inode
- Follow direct/indirect block pointers as needed
- Read data blocks
- Copy content to buffer
- Return bytes read
Delete File Flow
unlink("notes.txt")system call- Filesystem locates the directory entry
- Directory entry is removed
notes.txt --> inode 123mapping is deleted
- Inode (hard) link count is decreased
- Check whether link count becomes
0- If No:
- Other hard links still exist
- File remains alive
- If Yes
- Check whether the file is still open by a process
- If Yes:
- Keep inode and data blocks
- File remains alive until all open references are closed
- If No:
- Data blocks become free
- Inode becomes free
- Block/inode Bitmaps are updated
- If No:
Close File Flow
close(fd)system call- Kernel removes the file descriptor
- Open file references are decreased
- If hard link count =
0and open file references =0- Data blocks become free
- Inode becomes free
- Block/inode Bitmaps are updated
VFS (Virtual File System)
- aka Virtual Filesystem switch
- A kernel abstraction layer that provides a uniform interface between user space and different filesystem implementations
- User space programs call the same system calls (
open,read,write) regardless of the underlying filesystem - VFS translates these calls into filesystem-specific operations (
ext4,xfs,tmpfsetc.) - Enables mounting different filesystem types at different mount points simultaneously
flowchart TD A["User Space Applications (nano, ls, cp)"] B["VFS - Virtual File System"] C[ext4] D[exfat] E[tmpfs] F["Main Disk (HDD / SSD)"] G["USB Drive"] H["System RAM"] A -->|"System Calls <br> (open, read, write)"| B B --> C & D & E C --> F D --> G E --> H
VFS Core Objects
- VFS defines four core in-memory objects - each mirrors a concept already in the filesystem
- The dentry cache (dcache) is why repeated
lsoropencalls on the same path are fast- filename —> inode mapping is already in memory
- When a filesystem is mounted, it registers its own implementations of these objects with VFS
| VFS Object | Filesystem concept | Description |
|---|---|---|
| superblock | Superblock | Represents a mounted filesystem instance Holds metadata like block size, inode count |
| inode | Inode | In-memory representation of a file/directory Populated from disk inode on first access |
| dentry | Directory Entry | Maps a filename to an inode Cached in the dentry cache to avoid repeated disk lookups |
| file | Open File Description | Represents an open file for a process Holds offset, flags, pointer to dentry |
Filesystem and Partitions
- A filesystem is created inside a partition, not on the raw disk
/dev/sda= whole disk (contains partition table: MBR or GPT)/dev/sda1,/dev/sda2= partitions — each gets its own filesystem
- One partition = one filesystem (standard)
- All filesystem structures (superblock, inode table, bitmaps, data blocks) are scoped within the partition
# create ext4 filesystem on a partition
mkfs.ext4 /dev/sda1Common Linux Filesystems
- List of filesystems currently mounted:
/proc/mountsmountis legacy tool to view the same datafindmntgives a human-friendly tree view
Disk Filesystems
ext4(Fourth Extended Filesystem)- Default on Ubuntu, Debian, and most general-purpose distros
- Supports journaling, extents, large files
- Max file size: 16TB; max volume: 1EB
xfs- Default on RHEL, CentOS, Fedora
- High performance for large files and parallel I/O
- Supports journaling; cannot shrink a volume
btrfs(B-tree Filesystem)- Modern filesystem with advanced features
- Built-in snapshots, subvolumes, checksums, transparent compression
- Default on openSUSE; used by Fedora
vfat/exfat- Cross-platform (Windows/macOS/Linux)
vfat(FAT32)- max file size 4GB
- used for EFI boot partition (
/boot/efi)
exfat- removes the 4GB limit
- used on large USB drives and SD cards
Virtual / Pseudo Filesystems
- Exist entirely in RAM, No disk backing
- Contents are lost on reboot
- Exposed as a filesystem so userspace can use standard file tools (
cat,ls,echo) to interact with the kernel - Most files show size
0inls -l- content is generated on-demand at
read()time, so no size is known upfront - Exception:
tmpfsfiles have real sizes since tmpfs actually stores data in RAM
- content is generated on-demand at
| Filesystem | Mount point | Purpose |
|---|---|---|
tmpfs | /tmp, /run, /dev/shm | General temp storage in RAM |
devtmpfs | /dev | Device nodes, populated by kernel at boot |
devpts | /dev/pts | Pseudo-terminal slave devices |
procfs | /proc | Process info and kernel parameters |
sysfs | /sys | Kernel device/driver object tree |
securityfs | /sys/kernel/security | Linux Security Module (LSM) interfaces |
tracefs | /sys/kernel/tracing | Kernel tracing (ftrace) |
debugfs | /sys/kernel/debug | Kernel debugging interfaces |
configfs | /sys/kernel/config | Userspace-driven kernel object configuration |
cgroup2 | /sys/fs/cgroup | Control groups v2 (resource limiting) |
pstore | /sys/fs/pstore | Persistent storage for crash/panic logs |
bpf | /sys/fs/bpf | Pinned BPF maps and programs |
efivars | /sys/firmware/efi/efivars | Read/write UEFI firmware variables |
Swap
- Not a filesystem - no directory entries, inodes, or file operations
- Raw memory extension: kernel pages out cold memory to swap space, reclaims RAM
- Can be a dedicated partition (
/dev/sdaX) or a swap file