These classnotes are depreciated. As of 2005, I no longer teach the classes. Notes will remain online for legacy purposes

UNIX02/Maintaining Filesystems

Classnotes | UNIX02 | RecentChanges | Preferences

What are filesystems?

A filesystem is the methods and data structures that an operating system uses to keep track of files on a disk or partition; that is, the way the files are organised on the disk. The word is also used to refer to a partition or disk that is used to store the files or the type of the filesystem. Thus, one might say "I have two filesystems meaning one has two partitions on which one stores files, or that one is using the "ext2 filesystem, meaning the type of the filesystem.

The difference between a disk or partition and the filesystem it contains is important. A few programs (including, reasonably enough, programs that create filesystems) operate directly on the raw sectors of a disk or partition; if there is an existing file system there it will be destroyed or seriously corrupted. Most programs operate on a filesystem, and therefore won't work on a partition that doesn't contain one (or that contains one of the wrong type).

Before a partition or disk can be used as a filesystem, it needs to be initialised, and the bookkeeping data structures need to be written to the disk. This process is called making a filesystem.

Most UNIX filesystem types have a similar general structure, although the exact details vary quite a bit. The central concepts are superblock, inode, data block, directory block, and indirection block. The superblock contains information about the filesystem as a whole, such as its size (the exact information here depends on the filesystem). An inode contains all information about a file, except its name. The name is stored in the directory, together with the number of the inode. A directory entry consists of a filename and the number of the inode which represents the file. The inode contains the numbers of several data blocks, which are used to store the data in the file. There is space only for a few data block numbers in the inode, however, and if more are needed, more space for pointers to the data blocks is allocated dynamically. These dynamically allocated blocks are indirect blocks; the name indicates that in order to find the data block, one has to find its number in the indirect block first.

Filesystems Linux can use

There are a large number of filesystems that Linux can presently support. Here is a small list of some of the more common ones (if you would like a more extensive list, then check the [Filesystems HOWTO]).

Native Filesystems

  • ext, ext2, ext3, reiserfs

Imported UNIX Filesystems

  • IBM's JFS, SGI's XFS, Minix, FFS

Other Filesystems

  • DOS FAT 12/16/32, VFAT (long filenames), HPFS (OS/2), HFS (MAC), NTFS (Win NT line), UDF, ISO 9660

Creating Filesystems

Filesystems are created, i.e., initialised, with the mkfs command. There is actually a separate program for each filesystem type. mkfs is just a front end that runs the appropriate program depending on the desired filesystem type. The type is selected with the -t fstype option.

Is you look inside your /sbin directory, you can see the mkfs commands for making filesystems on your machine:

 root@rygel:/home/sam# ls -la /sbin/mkfs*
 -rwxr-xr-x    1 root     root    4488 Jan 30  2003 /sbin/mkfs
 -rwxr-xr-x    1 root     root   31020 Feb 21 17:26 /sbin/mkfs.ext2
 -rwxr-xr-x    1 root     root   31020 Feb 21 17:26 /sbin/mkfs.ext3
 -rwxr-xr-x    1 root     root   51016 Oct  8  2002 /sbin/mkfs.jfs
 -rwxr-xr-x    1 root     root    14264 Jan 30  2003 /sbin/mkfs.minix
 lrwxrwxrwx    1 root     root       7 Apr  3 04:54 /sbin/mkfs.msdos
 -rwxr-xr-x    1 root     root  116776 Sep  8  2002 /sbin/mkfs.reiserfs
 lrwxrwxrwx    1 root     root        7 Apr  3 04:54 /sbin/mkfs.vfat
 -rwxr-xr-x    1 root     root   293044 Feb 17  2003 /sbin/mkfs.xfs

The programs called by mkfs have slightly different command line interfaces. The common and most important options are summarised below; see the manual pages for more.

-t fstype
Select the type of the filesystem.
Search for bad blocks and initialise the bad block list accordingly.
-l filename
Read the initial bad block list from the name file.

For example, if I wanted to make a reiserfs file system on the partion /dev/hda2, I would execute:

 # mkfs.reiserfs /dev/hda2

Badblocks Example: Formatting Floppies

To create an ext2 filesystem on a floppy, one would give the following commands:

 $ fdformat -n /dev/fd0H1440
 Double-sided, 80 tracks, 18 sec/track. Total capacity 
 1440 kB.
 Formatting ... done
 $ badblocks /dev/fd0H1440 1440 $>$ bad-blocks
 $ mkfs -t ext2 -l bad-blocks /dev/fd0H1440
 mke2fs 0.5a, 5-Apr-94 for EXT2 FS 0.5, 94/03/10
 360 inodes, 1440 blocks
 72 blocks (5.00%) reserved for the super user
 First data block=1
 Block size=1024 (log=0)
 Fragment size=1024 (log=0)
 1 block group
 8192 blocks per group, 8192 fragments per group
 360 inodes per group

 Writing inode tables: done
 Writing superblocks and filesystem accounting information: 

First, the floppy was formatted (the -n option prevents validation, i.e., bad block checking). Then bad blocks were searched with badblocks, with the output redirected to a file, bad-blocks. Finally, the filesystem was created, with the bad block list initialised by whatever badblocks found.

The -c option could have been used with mkfs instead of badblocks and a separate file. The example below does that.

 $ mkfs -t ext2 -c /dev/fd0H1440
 mke2fs 0.5a, 5-Apr-94 for EXT2 FS 0.5, 94/03/10
 360 inodes, 1440 blocks
 72 blocks (5.00%) reserved for the super user
 First data block=1
 Block size=1024 (log=0)
 Fragment size=1024 (log=0)
 1 block group
 8192 blocks per group, 8192 fragments per group
 360 inodes per group

 Checking for bad blocks (read-only test): done
 Writing inode tables: done
 Writing superblocks and filesystem accounting information: 

The -c option is more convenient than a separate use of badblocks, but badblocks is necessary for checking after the filesystem has been created.

The process to prepare filesystems on hard disks or partitions is the same as for floppies, except that the formatting isn't needed.

Mounting and unmounting

Before one can use a filesystem, it has to be mounted. The operating system then does various bookkeeping things to make sure that everything works. Since all files in UNIX are in a single directory tree, the mount operation will make it look like the contents of the new filesystem are the contents of an existing subdirectory in some already mounted filesystem.

The command to use is mount, and it's usage is:

 mount [options] [filesystem] [mount_point]

For example, if I wanted to have the filesystems /dev/hda2 mounted as /home and /dev/hda3 mounted as /usr, I would issue the following commands:

 # mount /dev/hda2 /home
 # mount /dev/hda3 /usr

Here, the mount command takes two arguments. The first one is the device file corresponding to the disk or partition containing the filesystem. The second one is the directory below which it will be mounted. After these commands the contents of the two filesystems look just like the contents of the /home and /usr directories, respectively. One would then say that "/dev/hda2 is mounted on /home'', and similarly for /usr. To look at either filesystem, one would look at the contents of the directory on which it has been mounted, just as if it were any other directory. Note the difference between the device file, /dev/hda2, and the mounted-on directory, /home. The device file gives access to the raw contents of the disk, the mounted-on directory gives access to the files on the disk. The mounted-on directory is called the mount point.

Linux supports many filesystem types. mount tries to guess the type of the filesystem. You can also use the -t fstype option to specify the type directly; this is sometimes necessary, since the heuristics mount uses do not always work. For example, to mount an MS-DOS floppy, you could use the following command:

 $ mount -t msdos /dev/fd0 /mnt/floppy

The mounted-on directory need not be empty, although it must exist. Any files in it, however, will be inaccessible by name while the filesystem is mounted. (Any files that have already been opened will still be accessible. Files that have hard links from other directories can be accessed using those names.) There is no harm done with this, and it can even be useful. For instance, some people like to have /tmp and /var/tmp synonymous, and make /tmp be a symbolic link to /var/tmp. When the system is booted, before the /var filesystem is mounted, a /var/tmp directory residing on the root filesystem is used instead. When /var is mounted, it will make the /var/tmp directory on the root filesystem inaccessible. If /var/tmp didn't exist on the root filesystem, it would be impossible to use temporary files before mounting /var.

If you don't intend to write anything to the filesystem, use the -r switch for mount to do a read-only mount. This will make the kernel stop any attempts at writing to the filesystem, and will also stop the kernel from updating file access times in the inodes. Read-only mounts are necessary for unwritable media, e.g., CD-ROMs. They are also useful if you have a filesystem with some sort of degrading condition which you need to salvage data of from, or from a system which you are actively performing maintenance on.

The alert reader has already noticed a slight logistical problem. How is the first filesystem (called the root filesystem, because it contains the root directory) mounted, since it obviously can't be mounted on another filesystem? Well, the answer is that it is done by magic. The root filesystem is magically mounted at boot time, and one can rely on it to always be mounted. If the root filesystem can't be mounted, the system does not boot. The name of the filesystem that is magically mounted as root is either compiled into the kernel, or set using a boot loader.

The root filesystem is usually first mounted read-only. The startup scripts will then run fsck to verify its validity, and if there are no problems, they will re-mount it so that writes will also be allowed. fsck must not be run on a mounted filesystem, since any changes to the filesystem while fsck is running will cause trouble. Since the root filesystem is mounted read-only while it is being checked, fsck can fix any problems without worry, since the remount operation will flush any metadata that the filesystem keeps in memory.

When a filesystem no longer needs to be mounted, it can be unmounted with umount. umount takes one argument: either the device file or the mount point. For example, to unmount the directories of the previous example, one could use the commands

 $ umount /dev/hda2 (or umount /home)
 $ umount /usr (or umount /dev/hda3)

See the man page for further instructions on how to use the command. It is imperative that you always unmount a mounted floppy. Don't just pop the floppy out of the drive! Because of disk caching, the data is not necessarily written to the floppy until you unmount it, so removing the floppy from the drive too early might cause the contents to become garbled. If you only read from the floppy, this is not very likely, but if you write, even accidentally, the result may be catastrophic.

Mounting and unmounting filesystems are operations that require special privileges under most UNIXes. So how can you allow normal (non-root) users access to these operations for removable media (CDs, DVDs, Floppies)? The answers are diverse and vary from UNIX to UNIX and from Linux to Linux. Under Red Hat, SuSE, Mandrake, and other "newbie" oriented Linux distributions this is done through various "automounting" tools. However, on most non-"newbie" oriented systems (and many UNIX systems) there exists a special user group known as "wheel" which controls the mounting and unmounting of removable media. For a user to have access to this functionality, they must be a member of that group.

Checking filesystem integrity with fsck

Filesystems are complex creatures, and as such, they tend to be somewhat error-prone. A filesystem's correctness and validity can be checked using the fsck command. It can be instructed to repair any minor problems it finds, and to alert the user if there any unrepairable problems. Fortunately, the code to implement filesystems is debugged quite effectively, so there are seldom any problems at all, and they are usually caused by power failures, failing hardware, or operator errors; for example, by not shutting down the system properly.

Most systems are setup to run fsck automatically at boot time, so that any errors are detected (and hopefully corrected) before the system is used. Use of a corrupted filesystem tends to make things worse: if the data structures are messed up, using the filesystem will probably mess them up even more, resulting in more data loss.

Modern journalling filesystems do not need extensive filesystem checking, as their journals keep them in check. However, fsck can take a while to run on big non-journalling filesystems (eg ext2), and since errors almost never occur if the system has been shut down properly, a couple of tricks are used to avoid doing the checks in such cases. The first is that if the file /etc/fastboot exists, no checks are made. The second is that the ext2 filesystem has a special marker in its superblock that tells whether the filesystem was unmounted properly after the previous mount. This allows e2fsck (the version of fsck for the ext2 filesystem) to avoid checking the filesystem if the flag indicates that the unmount was done (the assumption being that a proper unmount indicates no problems). Whether the /etc/fastboot trick works on your system depends on your startup scripts, but the ext2 trick works every time you use e2fsck. It has to be explicitly bypassed with an option to e2fsck to be avoided. (See the e2fsck man page for details on how.)

The automatic checking only works for the filesystems that are mounted automatically at boot time. Use fsck manually to check other filesystems, e.g., floppies.

If fsck finds unrepairable problems, you need either in-depth knowledge of how filesystems work in general, and the type of the corrupt filesystem in particular, or good backups. The latter is easy (although sometimes tedious) to arrange, the former can sometimes be arranged via a friend, the Linux newsgroups and mailing lists, or some other source of support, if you don't have the know-how yourself.

fsck must only be run on unmounted filesystems, never on mounted filesystems (with the exception of the read-only root during startup). This is because it accesses the raw disk, and can therefore modify the filesystem without the operating system realizing it. There will be trouble, if the operating system is confused.

Checking for disk errors with badblocks

It can be a good idea to periodically check for bad blocks. This is done with the badblocks command. It outputs a list of the numbers of all bad blocks it can find. This list can be fed to fsck to be recorded in the filesystem data structures so that the operating system won't try to use the bad blocks for storing data. The following example will show how this could be done with a floppy which is using ext2.

 $ badblocks /dev/fd0H1440 1440 > bad-blocks
 $ fsck -t ext2 -l bad-blocks /dev/fd0H1440
 Parallelising fsck version 0.5a (5-Apr-94)
 e2fsck 0.5a, 5-Apr-94 for EXT2 FS 0.5, 94/03/10
 Pass 1: Checking inodes, blocks, and sizes
 Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity
 Pass 4: Check reference counts.
 Pass 5: Checking group summary information.

 /dev/fd0H1440: ***** FILE SYSTEM WAS MODIFIED *****
 /dev/fd0H1440: 11/360 files, 63/1440 blocks

If badblocks reports a block that was already used, e2fsck will try to move the block to another place. If the block was really bad, not just marginal, the contents of the file may be corrupted.

Classnotes | UNIX02 | RecentChanges | Preferences
This page is read-only | View other revisions
Last edited August 23, 2003 8:00 pm (diff)
(C) Copyright 2003 Samuel Hart
Creative Commons License
This work is licensed under a Creative Commons License.