Search Knowledge

© 2026 LIBREUNI PROJECT

File Systems

File Systems

A disk drive is essentially a massive array of addressable blocks (traditionally 512 bytes or 4 KB each). To a human, this raw data is useless. The File System is the component of the operating system that provides the abstraction we know and love: organized files and nested directories.

The File Abstraction

A “File” is a named collection of related information that is recorded on secondary storage. To the user, a file is a single object. To the OS, a file is a collection of logical blocks mapped to physical disk sectors.

File Metadata

Every file has metadata, which is “data about data.” This includes:

  • Name and extension.
  • Size.
  • Creation, modification, and access timestamps.
  • Permissions (Who can read/write/execute?).
  • Location (Where on the disk do the blocks start?).

Applications retrieve this metadata via system calls. For example, using the POSIX stat system call in C to extract metadata attributes:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

void print_file_metadata(const char *filename) {
    struct stat sb;
    if (stat(filename, &sb) == 0) {
        printf("Size: %lld bytes\n", (long long)sb.st_size);
        printf("Owner UID: %d\n", sb.st_uid);
        printf("Permissions (Octal): %o\n", sb.st_mode & 0777);
    }
}

How Files are Stored: Allocation Methods

How does the OS keep track of which blocks belong to “vacation-photo.jpg”?

1. Contiguous Allocation

The file is stored in a single, unbroken sequence of blocks.

  • Pro: Extremely fast for sequential reading.
  • Con: External fragmentation. If you delete a middle file, the “hole” left behind might be too small for a new, larger file.

2. Linked Allocation

Each block contains a “pointer” to the next block in the file (like a linked list).

  • Pro: No fragmentation; every block can be used.
  • Con: Slow for random access. To read the last block of a 1GB file, you have to read every single block before it to find the pointers.

3. Indexed Allocation (The UNIX approach)

The OS creates an Index Block (called an inode in Unix) that contains a list of all the block addresses for that file.

  • Pro: Fast random access and no fragmentation.
  • Con: The index block itself takes up space.
Code
object "Inode (File Index)" as inode {
Owner: User1
Permissions: RW-
Size: 12KB
Block 0 -> 102
Block 1 -> 405
Block 2 -> 11
Indirect Pointer -> [Table of more blocks]
}
object "Disk Block 102" as b1
object "Disk Block 405" as b2
object "Disk Block 11" as b3

inode ..> b1
inode ..> b2
inode ..> b3
Inode (File Index)Owner: User1Permissions: RW-Size: 12KBBlock 0 -> 102Block 1 -> 405Block 2 -> 11Indirect Pointer -> [Table ofmore blocks]Disk Block 102Disk Block 405Disk Block 11

An example of a simplified UNIX-like inode structure defined in C, supporting direct and indirect indexing:

// Structure representing a Unix-style index node (inode)
struct inode {
    uint16_t i_mode;       // File type and access permissions
    uint32_t i_size;       // Size of file in bytes
    uint32_t i_blocks;     // Total number of blocks allocated to the file
    uint32_t i_block[15];  // Pointers to data blocks:
                           // i_block[0..11]: Direct block pointers
                           // i_block[12]: Singly indirect block pointer
                           // i_block[13]: Doubly indirect block pointer
                           // i_block[14]: Triply indirect block pointer
};

Directories: Just Special Files

A directory (folder) is actually just a special type of file. Instead of containing user data, it contains a list of filenames and their corresponding inode numbers. When you type cd Documents, the OS reads the “Documents” directory file, looks for the entry you want, and finds its inode.

A directory entry struct in C demonstrates how names map to physical inodes on disk:

// Simplified representation of a directory entry record
struct directory_entry {
    uint32_t inode_number;      // Inode number mapping to this file
    uint16_t record_length;     // Offset to the next entry record
    uint8_t  name_length;       // Length of the filename string
    char     name[255];         // Null-terminated filename string
};

Data Integrity: Journaling

What happens if the power goes out while the OS is in the middle of writing a large file? In older systems, this would lead to “corrupted” disks where the directory list said a file existed, but the blocks themselves contained garbage.

Modern file systems use Journaling (e.g., NTFS, Ext4, APFS).

  1. The Log: Before making any changes, the OS writes a small “log” or “journal” entry saying: “I am about to move Block A to Location B.”
  2. The Write: The OS performs the actual write.
  3. The Commit: The OS marks the journal entry as completed.

Below is an execution example showing a typical journaling transaction lifecycle:

[Transaction 512: Start]
  - Target: Inode 10842 (modify file size to 8192 bytes)
  - Action: Write Data Block 405 (contents: "New file content")
  - Action: Update Inode block mapping (Block 2 -> Block 405)
[Transaction 512: Logged to Journal]
[Write Data Block 405 to Physical Disk Sector] -> Crash here is safe (reverts to state before Transaction 512)
[Write Inode 10842 metadata to Physical Disk Sector]
[Transaction 512: Commit logged] -> Changes are permanent

If the system crashes, upon reboot, the OS checks the journal. If it finds a “Fixing” entry that wasn’t “Committed,” it can either complete the task or safely undo it, ensuring the disk is never in an inconsistent state.

Comparison of Major File Systems

The choosing of a file system dictates system properties. For example, a user can format a storage partition using different filesystem tools:

# Formats partition /dev/sdb1 with the Ext4 journaling file system
sudo mkfs.ext4 /dev/sdb1

# Formats partition /dev/sdb2 with the FAT32 file system (VFAT)
sudo mkfs.vfat -F 32 /dev/sdb2
NamePrimary OSKey Features
FAT32Windows/LegacyUniversal compatibility, but no security and 4GB file size limit.
NTFSWindowsJournaling, compression, encryption, and granular permissions.
Ext4LinuxExtremely stable, handles massive files, very performant.
APFSmacOS/iOSDesigned for SSDs, features “snapshots” and fast directory sizing.
ZFSBSD/Solaris”The God File System”: protects against data rot (silent corruption).

The Virtual File System (VFS)

In many OSs, there is a layer called the VFS. This allows the OS to support many different types of file systems simultaneously. An application just tells the VFS “open file X,” and the VFS figures out whether that file is on a USB drive (FAT32), a Linux partition (Ext4), or even a network drive (NFS/SMB).

An example of the VFS file operations interface in the Linux kernel exposes how filesystem-specific handlers are abstracted:

// Linux kernel VFS file_operations interface snippet
struct file_operations {
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, loff_t, loff_t, int);
};

Interactive Practice: File System Mechanisms

Test your knowledge of file allocation techniques and metadata mapping.

Which file allocation method provides the fastest random access speed while preventing external fragmentation?

References & Further Reading

  • File system (Wikipedia, CC-BY-SA 4.0)
  • File system structure (Wikipedia, CC-BY-SA 4.0)
  • Silberschatz, A., Galvin, P. B., & Gagne, G. (2018). Operating System Concepts (10th ed.). John Wiley & Sons.
  • Tanenbaum, A. S., & Bos, H. (2015). Modern Operating Systems (4th ed.). Pearson.
Previous Module Memory Management