Exercises — Directory structure — tree, DAG (hard links, symbolic links)
A quick reminder of the two objects everything hinges on, so no symbol is used before it is defined:
Level 1 — Recognition
Exercise 1.1
Given this ls -li output, state the inode number of each entry and say which two entries are the same file:
42 -rw-r--r-- 2 root root 3 a.txt
42 -rw-r--r-- 2 root root 3 b.txt
99 lrwxrwxrwx 1 root root 5 s.txt -> a.txt
Recall Solution
WHAT the columns mean: the first number is the inode; the number after permissions (2, 2, 1) is the link count.
a.txt→ inode 42,b.txt→ inode 42,s.txt→ inode 99.a.txtandb.txtshare inode 42, so they are the same file (a hard-link pair). Their link count is2, confirming exactly two names point at inode 42.s.txthas its own inode 99 and type charl— it is a symlink, a different file whose data is the text"a.txt".
Exercise 1.2
For each row above, give the ls -l type character and what it tells you.
Recall Solution
a.txt,b.txt: type char-→ a regular file.s.txt: type char ==l== → a symbolic link. The type char is the very first character of the permission string.
Level 2 — Application
Exercise 2.1
Start with echo hi > a.txt (fresh inode, count 1). Run in order:
ln a.txt b.txt
ln a.txt c.txt
rm b.txt
What is the link count of the inode after each command?
Recall Solution
ln a.txt b.txt: add a name → .ln a.txt c.txt: add a name → .rm b.txt:rmcallsunlink, remove a name → . Final link count = 2 (namesa.txtandc.txtremain). The data is fully intact.
Exercise 2.2
Same fresh a.txt (count 1). Run:
ln -s a.txt s.txt
What is a.txt's link count now, and how many inodes exist?
Recall Solution
- A symlink does not bump the target's count:
a.txtstays at . - Two inodes now exist: inode for
a.txt, and a separate inode fors.txt(its data = the string"a.txt"). Contrast with a hard link, which would have made count and created no new inode.
Level 3 — Analysis
Exercise 3.1
A file has inode 42 with link count : names a.txt and b.txt. A process opens a.txt (holds an open file descriptor), then someone runs rm a.txt and rm b.txt. Trace , the "open" count, and say exactly when the data blocks are freed.
Recall Solution
The full free condition from the parent note is: free when AND open.
| Step | open fds | data alive? | |
|---|---|---|---|
| start | 2 | 1 | yes |
rm a.txt |
1 | 1 | yes (still a name) |
rm b.txt |
0 | 1 | yes — but a process still holds it open |
| process closes fd | 0 | 0 | freed now |
So the blocks are freed only when the process closes its descriptor, not at rm b.txt. This is why a running program can keep reading a "deleted" log file. |
Exercise 3.2
Draw / describe the namespace graph after:
mkdir d ; echo hi > d/x ; ln d/x d/y
Is it a tree or a DAG? Identify the node with in-degree .
Recall Solution
See the figure below. Directory d has two entries x and y, both pointing at the same inode (call it 42). That inode therefore has in-degree 2 (two incoming edges).
A tree requires every node to have exactly one parent/incoming edge, so this is not a tree — it is a DAG. No cycle exists (edges only go parent→child), so it is acyclic.

Level 4 — Synthesis
Exercise 4.1
You need ~/film to point at /mnt/usb/movie.mp4, which lives on a different filesystem. A colleague tries ln /mnt/usb/movie.mp4 ~/film and gets Invalid cross-device link. Explain the error and give the correct one-line command.
Recall Solution
WHY it fails: a hard link is a (name, inode_number) entry, and inode numbers are only meaningful within one filesystem. ~ and /mnt/usb are different filesystems, so inode 42 on the USB has no meaning in the home filesystem — hence Invalid cross-device link (EXDEV).
Fix: use a symlink, which stores a path string, not an inode number, and so crosses filesystems freely:
ln -s /mnt/usb/movie.mp4 ~/film
Exercise 4.2
Design a scenario where creating links accidentally causes an infinite traversal, and explain how the kernel stops it. Which link type is capable of this?
Recall Solution
Symlinks can do it:
ln -s loop b # b -> loop
ln -s b loop # loop -> b
cat loop # resolves loop->b->loop->b->...
Each resolution jumps to another path, and the two paths point at each other, so name resolution never terminates on its own.
How the kernel stops it: it caps the symlink chain depth (commonly ~40 hops) and returns ==ELOOP== ("Too many levels of symbolic links").
Why hard links can't cause this: directory hard links are forbidden for users, so hard links can only add names to file inodes — no cycle among directories is possible, keeping the directory graph a DAG.
Level 5 — Mastery
Exercise 5.1
A directory d is created fresh and is empty. What is its link count, and why is it not 1? Then you run mkdir d/sub. What is d's link count now? Derive the formula for a directory's link count in terms of the number of subdirectories it contains.
Recall Solution
A directory's incoming references are: (1) its name in its parent, plus (2) its own . entry (which points at itself), plus (3) one .. entry from each child subdirectory (each child's .. points back at this directory).
- Empty
d: name (1) +.(1) + zero children = . - After
mkdir d/sub: the new childsubcontributes a..pointing atd, so . - General formula, with = number of immediate subdirectories:
WHY the "2": the constant 2 is the directory's own name plus its
.self-link — present even when empty. Each subdirectory then adds exactly one via its...
Exercise 5.2
Using , a directory shows link count 5 in ls -ld. How many immediate subdirectories does it have? Does this count include regular (non-directory) files inside it?
Recall Solution
Solve immediate subdirectories.
Regular files do not affect this count: a regular file's name is its own inode's link count, not the directory's. Only subdirectories add a .. back-reference, so the directory's link count reveals its number of child directories — a neat forensic trick used by tools like find.
Recall One-line self-test reveals
Hard link changes target's count by ::: +1 (creation) or −1 (unlink)
Symlink changes target's count by ::: 0 (it stores text, not an inode reference)
Data freed exactly when ::: link count AND no process has it open
Empty directory link count ::: 2 (its name + its own .)
Directory link count formula ::: , where = number of subdirectories
Cross-filesystem link must be a ::: symlink (hard links can't cross filesystems)
Kernel error stopping symlink cycles ::: ELOOP
Connections
- Inodes and File Metadata
- Reference Counting and Garbage Collection
- Path Resolution and the namei() routine
- Unix system calls — link, unlink, symlink, stat
- Graphs — Trees vs DAGs
- Mount points and Virtual File System (VFS)
- File System Implementation — Block Allocation