4.2.33 · D4Operating Systems

Exercises — Directory structure — tree, DAG (hard links, symbolic links)

1,999 words9 min readBack to topic

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.txt and b.txt share inode 42, so they are the same file (a hard-link pair). Their link count is 2, confirming exactly two names point at inode 42.
  • s.txt has its own inode 99 and type char l — 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: rm calls unlink, remove a name → . Final link count = 2 (names a.txt and c.txt remain). 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.txt stays at .
  • Two inodes now exist: inode for a.txt, and a separate inode for s.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.

Figure — Directory structure — tree, DAG (hard links, symbolic links)

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 child sub contributes a .. pointing at d, 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