Have you ever needed a software RAID solution for a low-end server install? Perhaps you've wanted your workstation to take advantage of the redundancy provided by a disk mirror without investing in a hardware RAID controller. Has a prior painful configuration experience turned you off software RAID altogether on Unix systems?
Since 5.3-Release, FreeBSD comes with
gmirror(8), which allows you to easily configure a software RAID 1 solution. While tutorials on
gmirror exist, I found them to require either manual calculations of partition sizes with
bsdlabel or the use of a fix-it floppy on an existing system.
It made more sense to me to configure RAID during the install of the operating system. I also wanted a procedure that was easy to follow and didn't introduce human error in the form of a math miscalculation. After cobbling together the available documentation and experimenting my way through various configurations, I came across a procedure that has worked well for me on several different systems. I also received valuable feedback from Pawel Jakub Dawidek, the author of
gmirror, who gave some insight into some of the not yet documented features of
Before demonstrating the configuration, it is useful to understand a bit about GEOM. GEOM is the modular disk framework introduced in FreeBSD 5.0. This modularity allows the creation of programs to manipulate disks. The best examples are the software RAID programs introduced with FreeBSD 5.3:
gstripe(8)provides a stripe set or RAID 0
gmirror(8)provides a mirror/duplex or RAID 1
graid3(8)provides a stripe with parity or RAID 3
The initial g indicates that each of these programs takes advantage of GEOM.
Note: if you're totally new to RAID, Webopedia has a good definition of each RAID level.
man 4 geom describes the terms it uses to refer to disks, some of which you'll see when setting up
gmirror. These terms include the following:
If you're going to use RAID 1, make your life easy and purchase two identical disks (of the same model and size). You can complicate things by insisting on different disks with different sizes, but in the end you just end up with a harder configuration that wastes the extra disk space on the larger disk. Cable the identical drives so that one is the primary master and the other is the secondary master. Before installing the operating system, double-check that your CMOS recognizes both disks.
Using your favorite installation method, start a FreeBSD install of any version (5.3 or higher). When you get to the Select Drives menu, it should show ad0 and ad2. Select ad0, as you will be installing the operating system on the primary master.
fdisk utility, remove any existing partitions and then select "Use entire disk." When asked about the boot menu, choose "Standard MBR."
In the disklabel editor, set up the partitions on ad0 according to your requirements. If in doubt, choose
a for automatic. Then choose your install sets and your install media, and let the operating system install as usual.
When finished, go through the postinstall configurations and set your time zone, create a user account, set the root password, and so on.
However, don't reboot when you end up back at the
sysinstall main menu. Instead, press Alt-F4, which will take you to a command prompt. The first command I type is
csh so I can get a shell with history (the default shell is Bourne).
Creating a mirror/duplex is as simple as typing:
# gmirror label -v -b round-robin gm0 /dev/ad0
gmirror label creates the mirror;
-v enables verbose mode;
-b round-robin chooses a balance algorithm (at the moment, round-robin is the algorithm with the best performance);
gm0 is the name of mirror/duplex (this name represents the first GEOM mirror); and
/dev/ad0 represents the disk containing the data to mirror.
However, you'll be disappointed if you try the command now:
# gmirror label -v -b round-robin gm0 /dev/ad0 Can't store metadata on /dev/ad0: Operation not permitted
This is a security feature that indicates that the disk is currently mounted for writing and therefore is unavailable. However, you can get around this chicken-and-egg problem and temporarily force
gmirror to bypass this measure in order to create the mirror/duplex by setting a
# sysctl kern.geom.debugflags=16 kern.geom.debugflags: 0 -> 16
Don't worry; this MIB will return to 0 when you reboot (which I'll have you do in just a few minutes). Try again:
# gmirror label -v -b round-robin gm0 /dev/ad0 Metadata value stored on /dev/ad0
That's it; you now have a RAID 1 system.
It is, however, useful to tell the operating system to load it whenever you boot. This requires edits to two files. The first one is currently empty, so just
echo over the required line:
# echo geom_mirror_load="YES" > /boot/loader.conf
However, /etc/fstab is not empty, so I recommend making a backup copy before editing it:
# cp /etc/fstab /etc/fstab.orig # vi /etc/fstab
ad to a
gm, and insert a
/dev. For example,
/dev/mirror/gm0s1a. Unless you've made extra partitions, you'll have
ad0s1 devices ending in
f and will need to edit each of those lines.
When finished, triple-check your changes to both /etc/fstab and /boot/loader.conf. While it is fixable, it sucks not being able to boot into a new system because of a typo.
Note: some tutorials indicate you also need to add a
swapoff option to /etc/rc.conf. This is no longer necessary, and neither is using
shutdown -r now instead of
Once you're sure you don't have any typos, return to Alt-F1 and exit the installation menu after removing your installation media.
If you watch your boot-up messages, you should see this in bold white text right after the disks are probed:
GEOM_MIRROR: Device gm0 created (id=2125638583). GEOM_MIRROR: Device gm0: provider ad0 detected. GEOM_MIRROR: Device gm0: provider ad0 activated. GEOM_MIRROR: Device gm0: provider mirror/gm0 launched. GEOM_MIRROR: Device gm0 already configured. Mounting root from ufs:/dev/mirror/gm0s1a
and the system will continue to boot. However, if you have a typo in /etc/fstab, the boot will stop at this point and wait for you to type something meaningful. In this example, I forgot to insert
mirror when I edited /etc/fstab, meaning
/dev/gm0s1a should have been
/dev/mirror/gm0s1a so that FreeBSD could find my root filesystem:
Mounting root from ufs:/dev/gm0s1a setrootbyname failed ffs_mountroot: can't find rootvp Root mount failed: 6 Manual root filesystem specification: <fstype>:<device> Mount <device> using filesystem <fstype> e.g. ufs:da0s1a ? List valid disk boot devices <empty line> Abort manual input mountroot>
Fortunately, that's not as scary as it looks. Start by listing your valid disk boot devices:
mountroot> ? List of GEOM managed disk devices: mirror/gm0s1f mirror/gm0s1e mirror/gm0s1d mirror/gm0s1c mirror/gm0s1b mirror/gm0s1a mirror/gm0s1 ad2s1 mirror/gm0 ad0s1 ad2 acd0 ad0 fd0
If you type in the correct location of the / filesystem, the system will continue to reboot:
mountroot> ufs:/dev/mirror/gm0s1a Mounting root from /dev/mirror/gm0s1a
After logging in, be sure to edit the offending line in /etc/fstab and try rebooting again. When you can boot up and log in successfully, verify that each partition on the mirror mounted successfully with:
% df -h Filesystem Size Used Avail Capacity Mounted on /dev/mirror/gm0s1a 248M 35M 193M 15% / devfs 1.0K 1.0K 0B 100% /dev /dev/mirror/gm0s1e 248M 12K 228M 0% /tmp /dev/mirror/gm0s1f 7.3G 99M 6.7G 1% /usr /dev/mirror/gm0s1d 248M 196K 228M 0% /var
df won't show your swap partition; you can verify it with:
% swapinfo Device 1K-blocks Used Avail Capacity /dev/mirror/gm0s1b 629544 0 629544 0%
The only thing left to do is to synchronize the data on both hard drives. This will happen automatically as soon as you issue the command to insert the second drive into the mirror:
# gmirror insert gm0 /dev/ad2 GEOM_MIRROR: Device gm0: provider ad2 detected. GEOM_MIRROR: Device gm0: rebuilding provider ad2.
To see what's happening:
# gmirror list | more Geom name: gm0 State: DEGRADED Components: 2 Balance: round-robin Slice: 4096 Flags: NONE GenID: 0 SyncID: 1 ID: 2125638583 Providers: 1. Name: mirror/gm0 Mediasize: 10262568448 (9.6G) Sectorsize: 512 Mode: r6w5e2 Consumers: 1. Name: ad0 Mediasize: 10262568448 (9.6G) Sectorsize: 512 Mode: r1w1e1 State: ACTIVE Priority: 0 Flags: DIRTY GenID: 0 SyncID: 1 ID: 3986018406 2. Name: ad2 Mediasize: 10262568448 (9.6G) Sectorsize: 512 Mode: r1w1e1 State: SYNCHRONIZING Priority: 0 Flags: DIRTY, SYNCHRONIZING GenID: 0 SyncID: 1 Synchronized: 1% ID: 1946262342
SYNCHRONIZING on the
Flags line. It will take a while for these two drives to synchronize, as it is currently at 1 percent. I've seen times ranging from about 30 minutes for a 10GB drive to about two and a half hours for a 75GB drive. If you're curious, check the progress with:
# gmirror status Name Status Components mirror/gm0 DEGRADED ad0 ad2 (2%)
You'll see a status message in bold white text when the synchronization finishes:
GEOM_MIRROR: Device gm0: rebuilding provider ad2 finished. GEOM_MIRROR: Device gm0: provider ad2 activated.
If you repeat
gmirror list, you'll note that the
State has changed from
COMPLETE and the
Synchronized line is now gone. Don't worry if you see
DIRTY on the
Flags line, as it simply indicates that the system has written new data to the disk but hasn't mirrored it yet. If you were to wait a few seconds on a quiet disk, you would see the
Flags line change to
For the final test,
reboot the system.
This time your startup messages should include:
GEOM_MIRROR: Device gm0 created (id=2125638583). GEOM_MIRROR: Device gm0: provider ad0 detected. GEOM_MIRROR: Device gm0: provider ad2 detected. GEOM_MIRROR: Device gm0: provider ad0 activated. GEOM_MIRROR: Device gm0: provider ad2 activated. GEOM_MIRROR: Device gm0: provider mirror/gm0 launched. Mounting root from ufs:/dev/mirror/gm0s1a
GEOM utilities are works in progress, and the developers constantly add new features and updates to the man pages. It's well worth your while to keep your favorite version of FreeBSD up-to-date using
cvsup or to choose a newer release when deciding which version of FreeBSD to install.
If you wish to gather performance statistics on your mirror/duplex, try
gstat(8). A good read through
gmirror(8) is also in order, especially if you want an overview of the procedure for replacing a failed disk.
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.
Return to theBSD DevCenter
Copyright © 2009 O'Reilly Media, Inc.