Understanding Filesystem Inodes
03/07/2001We've spent the last few articles looking at partition tables and file systems. We've discovered that your PC finds your FreeBSD slice by reading the BIOS partition table. That FreeBSD slice has a Unix partition table that contains the "disk packing label," which describes the layout of the filesystems on that slice. This week, we can finally take a look at inodes: what they are and what information about them is available to you on your FreeBSD system.
Let's start by taking another look at the output of the "disklabel" command from one of my FreeBSD systems; I've snipped the output to just show the layout of the partitions:
disklabel ad0
<snip>
8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 102400 0 4.2BSD 0 0 0 # (Cyl. 0 - 6*)
b: 270976 102400 swap # (Cyl. 6*- 23*)
c: 6538455 0 unused 0 0 # (Cyl. 0 - 406)
e: 40960 373376 4.2BSD 0 0 0 # (Cyl. 23*- 25*)
f: 6124119 414336 4.2BSD 0 0 0 # (Cyl. 25*- 406*)
Notice that partitions "a", "e", and "f" are to be formatted with the filesystem type 4.2BSD, meaning the Berkeley fast file system (FFS). What is interesting to note is that each partition has been defined by its cylinders. That is, partition "a" uses cylinders 0-6, partition "e" uses cylinders 23-25, and partition "f" uses cylinders 25-406. The "*" means that the partition didn't begin or end exactly on a cylinder boundary.
What exactly is a cylinder? If you're a bit rusty on how hard drives work, you may find this article and its figures useful.
|
Also in FreeBSD Basics: |
Basically, a hard drive is composed of a number of circular disks called platters. Each platter has been divided into circular tracks; a cylinder is the same track on all the platters. If you could separate all the cylinders on your hard drive, you would end up with a series of increasingly smaller sized rings with each ring being the thickness of your hard drive.
A partition is simply a cylinder group, or a group of adjacent cylinders logically joined into a wider, doughnut-shaped ring. If a partition is formatted with a filesystem, that filesystem will maintain one inode table to keep track of any data placed on that cylinder group. To summarize:
- A filesystem is responsible for one cylinder group.
- A cylinder group has one inode table.
Each partition that has been formatted with a filesystem has three distinct areas:
- an area known as the superblock
- an area that contains the inode entries
- the remaining area, which is used to store files
The superblock describes the parameters of the filesystem, such as the
number of blocks, the size of the blocks, the size of the fragments, and the
number of inodes. (If you're curious as to what else is defined in the
superblock, you'll find all the parameters in man 5 fs.) These
parameters were determined by the newfs command and any switches you may have passed to that command when you created the filesystem. This means
that if at a later date you discover that you will run out of inodes before
you run out of disk blocks, you will have to recreate the filesystem in
order to change these parameters. You'll need to back up your data and
test your backup first, as recreating the filesystem with the newfs utility will destroy all of the existing data on that cylinder group.
After the superblock area is the area that contains all of the inode entries.
Each inode entry is 128 bytes in size and contains information about the file
that it represents; this information is known as the file's "metadata." You can
find out for yourself what this metadata is by reading the file /usr/include/ufs/ufs/dinode.h; even though this is a C file, it is well commented and not too hard to figure out. I've summarized its contents by
listing the metadata that an inode keeps track of:
- the permissions of the file
- the file link count
- old user and group ids
- the inode number
- the size of the file in bytes
- the last time the file was accessed (atime)
- the last time the file was modified (mtime)
- the last inode change time for the file (ctime)
- direct disk blocks
- indirect disk blocks
- status flags (chflags)
- blocks actually held
- file generation number
- the owner of the file
- the primary group of the owner of the file
Notice that the name of the file is not part of the inode's metadata. The filesystem doesn't care what the name of the file is; it only needs to know what inode number is associated with that file.
Much of a file's metadata can be viewed by doing a long directory
listing. Let's take a look at the long listing for the root directory by
using the ls command with the l switch here.
We've been given seven columns of output that represent each file's:
permissionslink countownergroupsize in bytesmtimepathnameYou should be able to recognize the first six as part of the metadata contained in each file's inode.
You can also find out the inode number of each file by adding the
i switch to the ls command (view sample output here).
Notice that this output added an extra column to the long listing; the
number in the first column is the inode number for that file. Inode number
"2" has been mentioned four times; once for proc, tmp, usr, and var. Inode 2 is always the first inode of a filesystem and represents the root or starting point of that filesystem. We can use the df command to see which filesystems have been mounted on this system:
df
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/ad0s2a 49583 27729 17888 61% /
/dev/ad0s2f 2967289 737169 1992737 27% /usr
/dev/ad0s2e 19815 3647 14583 20% /var
procfs 4 4 0 100% /proc
mfs:27 131231 1 120732 0% /tmp
Not surprisingly, usr, var, proc and tmp show up as mounted filesystems. Don't forget that each filesystem maintains its own inode table; that is, inode 2 for usr is a different inode entry in a completely different inode table than the inode 2 entry for "var." The only thing these inode entries share in common is the number 2, as they are both the root entry for their respective filesystems.
The df or disk free utility has a switch that will tell you how many inodes are on each filesystem. Let's run the df utility again with the i switch. View the output here
It's a good idea to run this command on a regular basis to ensure that your filesystems are not running out of either disk storage blocks or inode entries. Unless you are creating a large number of very small files, you will probably run out of disk blocks long before you run out of inodes. Knowing whether or not you've created enough inodes while leaving enough storage blocks is a matter of experience, as it depends upon what your FreeBSD system is used for and what types of files are created by your users. If you run this command often, you'll get an idea of what is normal for your system; you'll also learn if the defaults are not appropriate for your system.
The last thing I'd like you to notice about an inode is that it keeps track of three different times: the file's mtime, atime, and ctime.
A file's "mtime" is its last modification time; that is, when the actual
contents of the file were last changed. For example, if you open a file
with your favourite text editor and add or delete some text, you have
modified the contents of that file. When you save your changes, the inode
will update the "mtime" of that file. Remember that ls -l will show
the mtime of the file.
A file's "atime" is the last time that file was accessed. For example, if
you read a file using a pager, you will access the file and the inode will
update the "atime" for that file. You can view a directory listing by
atime instead of the default mtime by using the switches lut as shown here.
The "ctime" is updated whenever the inode itself is changed. For example,
if you change the permissions, owner, or group of a file you are actually
making changes to that file's inode, so the "ctime" will also be
updated. To see a listing by ctime, use the switches lc with the
ls utility, as shown here.
If you take a close look at those last three ls listings, you'll note that the times are indeed different and reflect the three types of times
recorded by each file's inode.
Next week, I'd like to start taking a closer look at IP packets and headers so you'll have the grounding necessary to understand packet filters and firewalls.
Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.
Read more FreeBSD Basics columns.
Discuss this article in the Operating Systems Forum.
Return to the BSD DevCenter.