A file system is just a librarian + card catalog for your disk. The disk is a giant warehouse of numbered shelves (blocks). You don't want to remember "my essay is in block 90412". So the OS gives you:
a human name ("essay.txt"),
a catalog card that records where the data blocks are and who owns them (the inode ),
a folder that maps names → catalog cards (the directory ),
an address to walk from the root to your file (the path ).
The deep idea: names and metadata are separated from data . That one design choice explains hard links, why renaming is cheap, and why ls -l shows what it shows.
A file is a named, ordered sequence of bytes plus metadata. To the OS the content is "just bytes"; structure (lines, JSON, JPEG) is interpreted by programs, not by the file system. A file is the OS's unit of persistent storage with a name.
Definition Directory (folder)
A directory is itself a special file whose content is a table of entries, each mapping a name → an inode number . So a folder doesn't "contain" files — it contains (name, inode#) pairs that point to files.
Definition Inode (index node)
An inode is the on-disk structure holding all metadata about a file except its name : size, owner UID/GID, permissions, timestamps, link count, and pointers to the data blocks . Each file has exactly one inode, identified by an inode number that is unique within a filesystem.
A path is the route used to locate a file by name. An absolute path starts at the root / (e.g. /home/ana/a.txt); a relative path starts at the current working directory (e.g. docs/a.txt). Each /-separated component is a directory lookup, ending at the final file.
Intuition The key separation
If the name lived inside the file's metadata, a file could only ever have one name . By putting the name in the directory and the metadata in the inode , multiple directory entries can point to the same inode number → this is a hard link . The inode's link count is exactly "how many names point to me", and the file's data is freed only when that count hits 0 and no process has it open.
directory "docs" inode 5012 data blocks
+-----------+--------+ +------------------+ +---------+
| name | inode# | | size, owner, | ---> | block 9 |
+-----------+--------+ | perms, times, | ---> | block 40|
| a.txt | 5012 |--------> | link_count = 2, | ---> | block 88|
| copy.txt | 5012 |--------> | block ptrs | +---------+
+-----------+--------+ +------------------+
Two names, one inode, one copy of data → a.txt and copy.txt are the same file .
To open /home/ana/a.txt, the kernel performs iterative directory lookup :
Start at the root inode (its inode number is fixed/known, e.g. inode 2 on ext-style FS).
Read root's directory data → find entry "home" → get its inode#.
Load that inode, read its directory data → find "ana" → get inode#.
Load that inode, read its directory data → find "a.txt" → get inode#.
Load that inode → now we have the metadata + block pointers → check permissions → return a file handle.
Intuition Why this design is fast yet flexible
Each step is a small lookup in a directory table, so cost ≈ (path depth) directory reads . Renaming a file = change one (name, inode#) entry — the inode and data never move. That's why mv is instant even for a 4 GB file (within one filesystem).
Intuition Why not just "start block + length"?
A simple file could store start, length — but files grow, shrink, and get fragmented. So inodes store an array of block pointers , plus indirect pointers to scale to large files without bloating every inode.
Worked example Classic ext2 numbers
B = 4096 B = 4096 B = 4096 , P = 4 P = 4 P = 4 bytes → k = 1024 k = 1024 k = 1024 . D = 12 D = 12 D = 12 direct.
Why these? ext2 uses 12 direct + 1 single + 1 double + 1 triple.
( 12 + 1024 + 1024 2 + 1024 3 ) ⋅ 4096 ≈ 4.4 × 10 12 bytes ≈ 4 TB . (12 + 1024 + 1024^2 + 1024^3)\cdot 4096 \approx 4.4\times10^{12}\text{ bytes} \approx 4\text{ TB}. ( 12 + 1024 + 102 4 2 + 102 4 3 ) ⋅ 4096 ≈ 4.4 × 1 0 12 bytes ≈ 4 TB .
Small files use only direct pointers (fast); huge files transparently use indirection.
Worked example 2 — Counting directory reads for
/a/b/c/d.txt
Components after root: a, b, c, d.txt → 4 lookups (root inode is already known).
Why this step? each / triggers one directory-table search to map name→inode.
stat file shows size but the directory shows the name
stat reads the inode (size, perms, times); the name isn't in stat because the name lives in the parent directory's table, not the inode. Why? metadata vs naming are separated by design.
Common mistake "The directory
contains the file's bytes."
Why it feels right: GUIs draw files inside folders, so it seems folders hold contents.
Fix: a directory only holds (name → inode#) entries. The bytes live in data blocks pointed to by the inode. The folder is an index , not a container.
Common mistake "A hard link is a copy."
Why it feels right: two names, both work — looks like duplication.
Fix: both names point to the same inode → one copy of data, shared changes. Only link_count differs from a fresh file. A copy (cp) makes a new inode + new blocks.
Common mistake "Inode stores the filename."
Why it feels right: the file "has" a name, so surely it's in the file's record.
Fix: the inode stores everything except the name. The name is in the parent directory — that's exactly what enables multiple names (hard links) and cheap renames.
Common mistake "Symlink = hard link."
Why it feels right: both let you reach a file by another name.
Fix: a symlink stores a path string (a pointer by name) in its own inode; if the target is deleted the symlink dangles . A hard link is another directory entry to the same inode# and never dangles while count > 0. Symlinks can cross filesystems and point at directories; hard links generally cannot.
Recall Feynman: explain to a 12-year-old
Imagine a school library. The book is your file (the actual pages = data). The catalog card is the inode: it doesn't have the story, but it says how big the book is, who can borrow it, and which shelf the pages are on. The folder/list of titles is the directory: it just maps "title → card number". A path is the directions: "go to floor 2, room Science, shelf 5". You can put the same card number under two different titles — now one book has two names! When the last title pointing to that card is erased and nobody is currently reading it, the librarian throws the pages away.
"DIP-N" = D irectory holds N ames, I node holds metadata + P ointers (not the Name).
And "Last name + last reader gone → bye" for when data is freed (link_count=0 ∧ open_count=0).
What is an inode? An on-disk structure storing all metadata about a file except its name (size, owner, perms, timestamps, link count, data-block pointers).
Where is a file's name stored? In its parent directory, as a (name → inode number) entry — not in the inode.
What is a directory, structurally? A special file whose contents are a table mapping names to inode numbers.
Absolute vs relative path? Absolute starts at root /; relative starts at the current working directory.
What is link_count in an inode? The number of directory entries (hard links) pointing to that inode.
When are a file's data blocks freed? When link_count = 0 AND no process has it open (open_count = 0).
Why is renaming a large file instant (same FS)? Only one (name, inode#) directory entry changes; inode and data blocks don't move.
Hard link vs symbolic link? Hard link = extra directory entry to the SAME inode#; symlink = a file storing a target PATH string, can dangle and cross filesystems.
Hard link vs copy? Hard link shares one inode and one copy of data; copy creates a new inode and new data blocks.
Max file size formula with direct + 3 levels of indirect? (D + k + k² + k³)·B, where k = block/pointer-size, B = block size, D = direct pointers.
How many directory lookups to resolve /a/b/c.txt? 3 (a, b, c.txt); root inode is already known.
What does stat read vs what shows the name? stat reads the inode (size/perms/times); the name comes from the parent directory.
Hard links vs Symbolic links
ext2-ext4 inode structure
Virtual File System (VFS) layer
Block allocation and fragmentation
File permissions and UID-GID
open() read() write() system calls
Mount points and multiple filesystems
many entries share one inode
data freed when count hits 0
Intuition Hinglish mein samjho
Dekho, file system ko ek library samjho. File matlab actual content (bytes) — jaise kisi book ke pages. Inode ek catalog card hai jo file ke baare mein sab kuch rakhta hai — size, owner, permissions, timestamps, aur sabse important: data blocks ke pointers — par filename store NAHI karta. Directory (folder) ek table hai jo simple mapping rakhta hai: naam → inode number. Aur path woh raasta hai (jaise /home/ana/a.txt) jisse OS root se chalkar file tak pahunchta hai, har / pe ek directory lookup karke.
Sabse bada concept yeh hai: naam aur data alag-alag rakhe jaate hain . Isi wajah se ek hi file ke do naam ho sakte hain — bas do directory entries same inode number ko point karein. Ise hard link kehte hain, aur inode ka link_count batata hai kitne naam point kar rahe hain. File ka data tabhi delete hota hai jab link_count = 0 ho AUR koi process use open na kiye baithi ho.
Yeh design itna powerful kyun hai? Kyunki rename ya move karna instant hota hai (same filesystem mein) — sirf ek (naam, inode#) entry badalti hai, data idhar-udhar nahi hota. Aur bade files ke liye inode mein direct pointers ke saath single/double/triple indirect pointers hote hain, jisse chhoti files fast rahein aur badi files bhi TB-scale tak ja sakein.
Exam aur real coding dono mein yeh kaam aata hai: ls -l, stat, ln, ln -s, rm ka behaviour samajhne ke liye yahi base hai. Yaad rakho mnemonic DIP-N : D irectory rakhta hai N ames, I node rakhta hai metadata + P ointers, par Name nahi.