What happens after mounting filesystem from file?
Example:
I have rootfs.ext2 file which is located in data directory and mounted under /mnt directory
mount rootfs.ext2 /mnt
After removing rootfs.ext2 I still can use files under /mnt directory, cat file, run binaries, etc.
rm -f rootfs.ext2
I was thinking that rootfs.ext2 file still exists in data directory however it was deleted. I filled whole data directory for test purposes with new data by filling file from /dev/urandom (for rewritting actual data that was before in data directory)
cat /dev/urandom > /data/Filling
Even after filling whole space in data directory I still can access /mnt and run binaries.
The question is what happens with file after mounting it and why I still can moderate throw it? Can I delete rootfs.ext2 (if it's mounted under /) file without undefined behavior of system(binaries are running, full access to filesystem, etc)
Links to documentation are appreciated.
Linux (and Unix) filesystems have several features that allow that.
Inodes
Data (the thing you get when you run
cat) and metadata (what you get fromstatandls) is stored in inodes ("indexed nodes") which are like a key-value type storage. Inodes are indexed in the sense that an inode is referred to by its ID, the inode number.That means that the data in
rootfs.ext2is stored in an inode.Hard Links
Files inside directories are represented as directory entries. A directory entry is a pair of name and inode number.
You can think of directories as hashtables, where the key is the name, and the value is the inode number.
The full path that a directory entry represents is called a hard link to that inode.
That means that multiple directory entries, in different directories or even in the same directory, can point to the same inode number.
You can create that by running:
ln, by default, creates a hard link.ls -iprints the inode number, and you can see that in the above example,x1andx2have the same inode number, and are therefore both hard links to that inode.You can also see that the first
lsprints1before root - that's the number of hard links that inode 1956 has. You see it increasing to 2 afterx2is created.What this means is that
rootfs.ext2is a hard link that points to the inode that actually holds the filesystem.Reference Count
Every inode has a reference count.
When nothing is loaded, the inode's reference count is equal to its hard link count.
But if the file is opened, the open file is another reference.
For example:
Because this is reference counting, a file can has 0 hard links, but still have references. Continuing the above example, with the file still open:
The hard links that point to the inode are gone, but the open file still points to the inode, so the inode is not deleted.
(BTW if you check, you'll see that /proc/self/fd/8 is actually not another hard link to that inode, but rather a symbolic link. However, the fact that you can still read the inode's data indicates that the inode wasn't deleted)
Internally Open Files
Opening a file from userspace, like we did above with
exec 8<>x2, is just one way to open files. Many things in the Linux kernel internally open files. For example:Loop Mounts
When you run
mount rootfs.ext2 /mnt, what actually happens is thatmountcreates a block device, e.g./dev/loop9, then opensrootfs.ext2, and configures/dev/loop9, as a loop device backed by the open file descriptor forrootfs.ext2.As noted above, that means that as long as the block device is configured as a loop device for that file descriptor, that
rootfs.ext2inode remains open, and therefore with a reference count > 0, and therefore not deleted.In fact, even if you deleted the loop device itself, the data would still be available, because that block device is also internally open, meaning both the backing regular file (
rootfs.ext2) and the block device (/dev/loop9) are kept open:Extra Credit: Open Directories
Inodes contain whatever data and/or metadata is needed. Regular files, like
rootfs.ext2, are represented as inodes. But directories are also inodes, as well as block devices, pipes, sockets, etc.This means that directories have reference counts too, and that they too are opened. Famously via
opendir(), but also internally:open(/etc/passwd), the inode of the root directory (/) is briefly opened to look upetc, and the inode for/etcis briefly opened to loop uppasswd.lsin it. However, it will not be able to create new files in it.You can unmount a mount point that is still in use, because every such "use" is counted as a reference: