Michael W. Lucas
"Disklabel" is a term many people brush off on those occasions when they hear it. Once you have a running system, you don't need to worry about disklabels. Most BSD operating systems gloss over the details of disklabels during the install process, making a new user's life slightly easier. (OpenBSD actually brings a user into fairly intimate contact with the disk, but it's the exception.) One day when things go wrong, however, you'll wish you understood disklabels.
On modern i386 computer systems, you'll stumble across two different sorts of partitions. One is the Microsoft-style partition; the other is the BSD-style partition. The Microsoft-style partition is used by FAT, NTFS, and their variants. The FreeBSD folks call that sort of partition a slice, and have their own partitions within that Microsoft-style partition. OpenBSD puts its partitions directly on the disk, in effect using the whole disk as a single slice. Other BSDs use some variant of these techniques.
First, what is a disklabel? A disklabel is a file at the beginning of the disk (or slice) that indicates where each BSD-style partition begins and how many disk sectors it occupies.
On any BSD, you can read the disklabel with disklabel(8). Just run disklabel, and give the device a name. By default it names the disklabel of the first legitimate disk on your hard drive.
$ disklabel ad4 # /dev/ad4s1c: type: ESDI disk: ad4s1 label: flags: bytes/sector: 512 sectors/track: 63 tracks/cylinder: 255 sectors/cylinder: 16065 cylinders: 4864 sectors/unit: 78156162 rpm: 3600 interleave: 1 trackskew: 0 cylinderskew: 0 headswitch: 0 # milliseconds track-to-track seek: 0 # milliseconds drivedata: 0 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 204800 0 4.2BSD 1024 8192 16 # (Cyl. 0 - 12*) b: 2104592 204800 swap # (Cyl. 12*- 143*) c: 78156162 0 unused 0 0 # (Cyl. 0 - 4864*) e: 4194304 2309392 4.2BSD 1024 8192 16 # (Cyl. 143*- 404*) f: 71652466 6503696 4.2BSD 1024 8192 16 # (Cyl. 404*- 4864*) #
Much of the information in the code above is fairly obvious. A sector is a minimal chunk of disk. Each sector on this disk holds 512 bytes, or half a kilobyte. We can see how many tracks per cylinder, how many sectors per cylinder, how many cylinders, and so on. We also see the disk's speed in RPM, which is nice but certainly not vital. The real meat of the disklabel is the last chunk, which lists the various partitions and their characteristics.
First we see the number of partitions the disk can support. While this particular disk has five partitions, the disklabel shows that it could support eight.
The important things in this last section are the initial letter, the size, the offset, and the fstype. Everything else is ignored on a modern, fast filesystem with soft updates. (You are using soft updates, right?)
Each letter represents a partition. The 'a' is the traditional root partition. The 'c' partition represents the whole disk. Each partition letter is assigned to a certain partition type and this varies between BSDs:
a = root b = swap c = whole disk d = obselete whole disk e-h = everything else
Each partition takes up sectors on the disk. The "size" is the number of sectors a partition occupies, while the offset is the number of sectors that precede the current partition. Finally, the fstype indicates what sort of filesystem this partition uses. Most UFS (Unix File System) partitions have an fstype of 4.2BSD.
For example, partition 'a' in the above snippet is at an offset of 0. This is what you would expect for the first partition in the disk. This partition fills 204800 sectors. Since we're in the computer world here, and start numbering at zero, the last sector in partition 'a' is number 204799. Again, it's a UFS partition, so has a type of 4.2BSD.
Partition 'b' starts at an offset of 204800, and takes up 2104592 sectors. This seems pretty simple, no? You might expect partition 'c' to start at sector 2309392, as 204800+2104592=2309392. Instead, partition 'c' throws you for a loop.
'c' begins at an offset of zero, and it has a size of 78156162. This looks utterly nonsensical! You might think that overlapping partitions are bad, and you'd be correct--for anything except partition 'c'. Remember, 'c' is a special partition that represents the whole disk. The disk begins at offset zero, so partition 'c' begins there. Similarly, the whole disk has 78156162 sectors, so partition 'c' is that size. Partition 'c' is useful for double-checking how many sectors you have free, but you can just about ignore it when figuring out how to divide your disk.
Partition 'e' and 'f' in our example follow the pattern established by a and b.
So, this is all very nice, but how can we use it in the real world?
My FreeBSD laptop's hard drive has four slices. One slice is basically unused, but broken up into partitions. The example above is from that slice. I'd like to convert that slice, /dev/ad0s2, into a single, large partition. On FreeBSD I could use sysinstall(8) to do this. On other operating systems, even other BSD ones, sysinstall isn't an option. Besides, using the command line is much more macho, don't you think?
Before you even consider starting, back up your system and any important data you have. Nobody but you is responsible if your efforts to change the disk cause data loss. We will certainly eliminate any data on partitions you rearrange!
First, make sure that you won't annoy the system later. Remove any entries for partitions that you're going to edit in that slice from /etc/fstab.
A closer look at the disklabel shows something that I'd forgotten. Partition b is the system's swap space! While this particular system doesn't page often, I still want a bit of swap space. This makes things only slightly more difficult. I need a swap partition, and a UFS partition.
Before touching anything, plan the changes you want. In this case I want a 350MB swap 'b' partition, and everything else should be a single data partition, 'e'.
We could go calculating 512-byte sectors and figure out our 350MB swap partition that way, but disklabel recognizes the K, M, and G abbreviations. It also recognizes an *, which means "everything that's left", or a %, which means the percent of space left after assigning fixed-size partitions. Combining this, we want a new disklabel that looks like this. Since our 'c' partition represents the entire slice, we want to leave that untouched.
# size offset fstype [fsize bsize bps/cpg] b: 350M 0 swap c: 78156162 0 unused 0 0 e: * * 4.2BSD 1024 8192 16 #
Once you unmount a slice, you can edit it with disklabel's -e flag. To be careful, drop to single-user mode when you're editing your disklabel. Be sure to double-check your backups before you change anything!
In single-user mode, I just run:
# disklabel -e ad0s2
It brings up a text editor with the complete disklabel in it, and I
make the necessary changes to the bottom. I can now
/dev/ad0s2e, and create the new filesystem. Finally, I edit
/etc/fstab to tell the system about the new swap space and filesystem,
and boot into multiuser mode.
With just a few edits, I'm able to change the partitions as I want. No matter how scary disklabels may look, they're fairly straightforward once you understand them.
Read more Big Scary Daemons columns.
Return to the BSD DevCenter.