Your shopping cart is empty!
Basic file system architecture
The Linux file system architecture is an interesting example of abstracting complexity. Using a common set of API functions, a large variety of file systems can be supported on a large variety of storage devices. Take, for example, the readfunction call, which allows some number of bytes to be read from a given file descriptor. The readfunction is unaware of file system types, such as ext3 or NFS. It is also unaware of the particular storage medium upon which the file system is mounted, such as AT Attachment Packet Interface (ATAPI) disk, Serial-Attached SCSI (SAS) disk, or Serial Advanced Technology Attachment (SATA) disk. Yet, when the readfunction is called for an open file, the data is returned as expected. This article explores how this is done and investigates the major structures of the Linux file system layer.
A file system is an organization of data and metadata on a storage device. With a vague definition like that, you know that the code required to support this will be interesting. As I mentioned, there are many types of file systems and media. With all of this variation, you can expect that the Linux file system interface is implemented as a layered architecture, separating the user interface layer from the file system implementation from the drivers that manipulate the storage devices.
Associating a file system to a storage device in Linux is a process called mounting. The mountcommand is used to attach a file system to the current file system hierarchy (root). During a mount, you provide a file system type, a file system, and a mount point.
To illustrate the capabilities of the Linux file system layer (and the use of mount), create a file system in a file within the current file system. This is accomplished first by creating a file of a given size using dd(copy a file using /dev/zero as the source) -- in other words, a file initialized with zeros, as shown in Listing 1.
Listing 1. Creating an initialized file
$ dd if=/dev/zero of=file.img bs=1k count=10000
10000+0 records in
10000+0 records out
You now have a file called file.img that's 10MB. Use the losetupcommand to associate a loop device with the file (making it look like a block device instead of just a regular file within the file system):
$ losetup /dev/loop0 file.img
With the file now appearing as a block device (represented by /dev/loop0), create a file system on the device with mke2fs. This command creates a new second ext2 file system of the defined size, as shown in Listing 2.
Listing 2. Creating an ext2 file system with the loop device
$ mke2fs -c /dev/loop0 10000
mke2fs 1.35 (28-Feb-2004)
max_blocks 1024000, rsv_groups = 1250, rsv_gdb = 39
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
2512 inodes, 10000 blocks
500 blocks (5.00%) reserved for the super user
The file.img file, represented by the loop device (/dev/loop0), is now mounted to the mount point /mnt/point1 using the mountcommand. Note the specification of the file system as ext2. When mounted, you can treat this mount point as a new file system by doing using an lscommand, as shown in Listing 3.
Listing 3. Creating a mount point and mounting the file system through the loop device
$ mkdir /mnt/point1
$ mount -t ext2 /dev/loop0 /mnt/point1
$ ls /mnt/point1
As shown in Listing 4, you can continue this process by creating a new file within the new mounted file system, associating it with a loop device, and creating another file system on it.
Listing 4. Creating a new loop file system within a loop file system
$ dd if=/dev/zero of=/mnt/point1/file.img bs=1k count=1000
1000+0 records in
1000+0 records out
$ losetup /dev/loop1 /mnt/point1/file.img
$ mke2fs -c /dev/loop1 1000
mke2fs 1.35 (28-Feb-2004)
max_blocks 1024000, rsv_groups = 125, rsv_gdb = 3
$ mkdir /mnt/point2
$ mount -t ext2 /dev/loop1 /mnt/point2
$ ls /mnt/point2
$ ls /mnt/point1
From this simple demonstration, it's easy to see how powerful the Linux file system (and the loop device) can be. You can use this same approach to create encrypted file systems with the loop device on a file. This is useful to protect your data by transiently mounting your file using the loop device when needed.