TT Lab
Get started
Learn Learning paths Courses

Operating Systems

Delete the Name, the File Lives On

Continue in TT Lab

Goal

In the reading, you read that "the name and the substance are separate". Here you confirm by hand what behaviors that separation actually produces.

After the eight steps, you will be able to answer questions like these. Why do writes fail when df says there is free space, why does the space not come back after I delete a log, and how should I swap in a configuration file so that a reader never sees a half-written file.

Working directory

mkdir -p /root/fs && cd /root/fs

Create every output here.

Tools you will use

stat -c '%i %h %d %n' 파일   # 아이노드, 링크 수, 장치 번호, 이름
ls -i                        # 아이노드 번호를 함께 보기
ls -l /proc/<PID>/fd         # 그 프로세스가 열어 둔 파일들

With stat, %i is the substance's identity card. If the %i of two names is the same, they are the same file. This is different from having the same size and contents.

How grading works

For three of the steps, the grader runs the scripts you wrote directly.

hold.py      채점기가 만든 파일을 넘겨 주고, 이름을 뗀 뒤에도
             읽어 내는지 봅니다
findleak.sh  채점기가 직접 유출을 만들어 놓고, 그것을 찾아내는지
             봅니다. 유출이 없어진 뒤에도 계속 보고하면 실패입니다
swap.sh      채점기가 대상 파일을 열어 둔 채로 여러분의 교체를
             시킵니다. 열어 둔 디스크립터로 새 내용이 보이면
             대상에 직접 쓴 것이므로 실패입니다

Explanations in words are not graded. Only what works is checked.

How do you know whether it is the same file

Create orig.txt, then create a second name hard.txt that points to the same substance and a copy copy.txt that only has the same contents. Check the inode numbers of the three and write them in identity.txt.

A hard link is ln 원본 새이름, and a copy is cp 원본 새이름 (original file, new name).

To check, run stat -c '%i %h %n' orig.txt hard.txt copy.txt.

Having the same contents is different from being the same file. According to diff, all three look the same. Only the inode number tells you whether there is one substance or two.

What does the link count count

Create a third name third.txt that points to the same substance. Write what the link count of orig.txt becomes, and what that value has to reach for the blocks to be reclaimed, in nlink.txt.

stat -c %h orig.txt gives the link count. With three names it is 3.

rm is not a command that deletes a file but a command that detaches a name. This is why the system call is named unlink. The blocks are reclaimed only when no name is left and no process has the file open.

Read a deleted file

Create hold.py. It first opens the file it receives as an argument, then detaches the name, then reads the contents through that descriptor and prints them. It should also print what that descriptor is still holding on to.

In Python, detaching a name is os.unlink(경로), where the argument is the file path. The order is everything: open, detach, read.

You can see what the descriptor is holding with os.readlink('/proc/self/fd/%d' % f.fileno()). For a file whose name has been detached, the kernel appends (deleted) to it.

Reading the whole contents and then deleting is different. That is just a copy, and what you are trying to see here is the fact that the substance stays alive even without a name.

Find the culprit holding the space

Create findleak.sh. It finds every file on this system that has lost its name but is still open, and prints the process holding it and its path. Give it execute permission.

/proc/<PID>/fd shows the files a process has open as symbolic links. Those whose names have been detached have (deleted) appended.

Start from ls -l /proc/[0-9]*/fd 2>/dev/null | grep deleted. You cannot read processes you lack permission for, so discard the errors.

You must not hard-code the result. The grader checks whether you keep reporting after it creates a leak and then removes it.

What breaks when you move the original

Create base.txt, then create a hard link keep.txt and a symbolic link soft.txt to it. Then move base.txt to moved.txt. Write in links.txt which one broke and why. (Leave the files you created in steps 1 and 2 as they are.)

A symbolic link is ln -s, and a hard link is made without -s, using plain ln.

After moving, run cat soft.txt and cat keep.txt separately. Also look at what it points to with ls -l soft.txt.

A hard link holds an inode, and a symbolic link holds a path string. A symbolic link follows that path anew each time it is accessed.

Swap in a configuration file safely

Create swap.sh <새내용파일> <대상파일> (the first argument is the file with the new contents, the second is the target file). It swaps the target so that a reader of the target never sees a half-written file. Give it execute permission, and do not leave temporary files behind.

You must not write to the target directly. Write the new contents to a temporary file in the same directory, and swap the name with mv.

Within the same filesystem, mv modifies only one directory entry, so it is atomic. A reader sees either the old substance or the new substance, and there is no in-between.

The grader runs your script while it has the target file open. If you swapped the name, that descriptor should keep showing the old contents.

Where swapping a name stops working

Check the device numbers of the working directory and of /dev/shm. Try it yourself to see what error occurs when you attempt to swap a name across that boundary, and write down what mv actually does in that case in exdev.txt.

The device number is stat -c %d 경로, where the last argument is the path. If the values differ, they are different filesystems.

To try it, run python3 -c "import os; os.rename('a.txt', '/dev/shm/a.txt')". When mv meets this error, it quietly copies and deletes the original, so to see the failure you have to call rename directly.

This is why a safe swap must be done within the same filesystem. Copying takes time, and if it is interrupted midway, a half-written file is left.

When df seems to be lying

Write a diagnosis in report.md. It covers the two cases in which writes fail even though df says there is free space, the command to confirm each, how to get the space back, and where this incident mostly originates.

Both cases were already covered in earlier steps. One is the case where something other than blocks ran out (df -i), and the other is the one you found yourself in step 4.

If you stop at finding the cause, the incident continues. Write separately how to get the space back right now and how to keep it from happening again.

The goal is a document that the next person can read and follow as it is.