Raid 0 + 1

Kevin Thompson antiduh at csh.rit.edu
Mon Oct 29 13:28:32 PDT 2007


> Hi Folks,
>
> I talked with my customer, and we decided to implement a 0 + 1 RAID,
> with 4 disks of 250Gb each.
>
> Here is how my RAID is working now:

I have some rough instructions I wrote up about doing a bootable 0+1 Geom
RAID, in wiki format. I don't have a public place to post them, so I've
just copied them below. Feedback is welcome.

Once you get it setup, I would highly recommend that you experiment with
the setup before relying on it - make sure you know how to handle failed
disk replacements, etc. VMWare/camcontrol/atacontrol is very handy in this
regard.

--Kevin Thompson




==Introduction==

This article describes one method to build a RAID 0+1 array with 4 logical
disks using the FreeBSD GEOM framework, and being able to boot off of such
an array.

Building a GEOM mirror and being able to directly boot off of it is a
relatively simple task - this is due to the fact that when mirroring is
done, all FreeBSD slices maintain their disk-level structure - GEOM stores
its metadata at the end of the disk/partition/etc. Most importantly, in
such a configuration the MBR and boot file system is untouched.

The latter is not the case in RAID 0, RAID 0+1, or RAID 1+0 setups.

In striping configurations, the boot filesystem is interleaved between the
various disks (usually two), and as such, the filesystem appears to be
corrupt if read from only one disk.

Since the MBR program on the boot disk is incapable of understanding this
physical block layout, it is unable to find the kernel in order to start
FreeBSD.

However, should the MBR program be able to read the boot filesystem, it
can then load the kernel and related kernel modules, which would then
allow the system to 'boot' from the raidset.

Technically speaking, the only file system that has to remain untouched is
the /boot file system. root (/), /usr, /var, /tmp, et cetera may all then
be mounted from a raidset.

In this example, for simplicity's sake, I protect all of the typical root
file system,  not just /boot. A more enterprising user may want to modify
their approach.

==Instructions==
Boot with a FreeBSD install disk, then start the fixit console. Next
you'll need to clean up the environment (the fixit console needs a little
updating)
 ln -s /dist/boot/kernel /boot/kernel
 ln -s /dist/lib /lib
 EDITOR=/mnt2/usr/bin/vi; export EDITOR
 PATH=$PATH':'/mnt2/sbin':'/mnt2/usr/bin':'/mnt2/usr/sbin
 export PATH


Now load the kernel modules for the geom modules we're going to be using.
 glabel load
 gstripe load
 gmirror load

Next, we're going to label each of the drives. The 'da0' drive name is
typically assigned by the bios on boot, by way of some sort of metric such
as chain location. The geom label module writes a fixed label to each
drive, so that no matter where each drive goes, or if new devices are
inserted and the numbering is reordered, the raid set will always work the
same.
 glabel label geom0 da0
 glabel label geom1 da1
 glabel label geom2 da2
 glabel label geom3 da3

Now install a mbr and basic partioning on each drive. This will create a
single partition taking the entire drive for each drive.
 fdisk -vBI /dev/label/geom0
 fdisk -vBI /dev/label/geom1
 fdisk -vBI /dev/label/geom2
 fdisk -vBI /dev/label/geom3

On the first disk slice of the first drive, install a simple disk label
and bootstrap code.
 bsdlabel -wB /dev/label/geom0s1

Now edit the generic label on that disk, setting it as you please. 'a' is
commonly root, 'b' the swap partition and 'd' the rest. Don't create any
more partitions other than a, b and d (d will be used as the provider for
a future geom consumer).

 slave(/u9/antiduh) # bsdlabel -e /dev/label/geom0s1
 #  size   offset    fstype   [fsize bsize bps/cpg]
 a: 500M   16 	     4.2BSD
 b: 500M   *         swap
 c:                         # leave as is
 d: *      *         4.2BSD

The '*' for size means use whatever is left, and the '*' for offset means
use the next logical offset.

Once you're finished labeling the first drive, write the label for the
drive out to a file, then use it to initialize the other three disks:
 bsdlabel /dev/label/geom0s1 > /file
 bsdlabel -R /dev/label/geom1s1 /file
 bsdlabel -R /dev/label/geom2s1 /file
 bsdlabel -R /dev/label/geom3s1 /file


Now, create a GEOM mirror out of the 'a' partition of each drive. This
will eventually be the root partition. The new device will be called
'''boot''', and will enumerate in FreeBSD as '''/dev/mirror/boot'''
 gmirror label -vh boot /dev/label/geom0s1a /dev/label/geom1s1a
/dev/label/geom2s1a /dev/label/geom3s1a

Now we're going to pull together the d partion on each drive, create
pairwise stripes, then mirror the new stripes together.
 gstripe label -vh -s 131072 st0 /dev/label/geom0s1d /dev/geom1s1d
 gstripe label -vh -s 131072 st1 /dev/label/geom2s1d /dev/geom3s1d

We should now have two new devices '''/dev/stripe/st0''' and
'''/dev/stripe/st1'''. Now mirror those two devices to create our final
device that will next be used for the rest of our filesystems:
 gmirror label -vh gm0 /dev/stripe/st0 /dev/stripe/st1

We now have our final device '''/dev/mirror/gm0''' that is going to serve
as the base for our regular filesystems.

Create a basic slicing of the new disk, then edit to taste. Note that we
don't fdisk the raw gm0 device - we create slices directly on the raw
device.
 slave(/u9/antiduh) # bsdlabel -wB /dev/mirror/gm0
 slave(/u9/antiduh) # bsdlabel -e /dev/mirror/gm0
 #        size   offset    fstype   [fsize bsize bps/cpg]
 a: 1		16	unused	# that is just a bare '1', not '1M'. This is to get
around a bug in bsdlabel
 c: #-- leave as is --
 e: 1000M 	*	4.2BSD	# /var
 f: 500M	*	4.2BSD  # /tmp
 d: *		*	4.2BSD  # /usr, which just gets the rest

Now create our filesystems on associated slices (the -U option enables
soft updates)
 newfs /dev/mirror/boot
 newfs -U /dev/mirror/gm0d
 newfs -U /dev/mirror/gm0e
 newfs -U /dev/mirror/gm0f

Now we finally get down to mounting the disks, installing the OS on it,
setting up the OS to boot, and finally booting.

Mount the root disk as /mnt
 mount /dev/mirror/boot /mnt

Create mount points for our other file systems, then mount them:
 mkdir /mnt/usr
 mkdir /mnt/var
 mkdir /mnt/tmp

 mount /dev/mirror/gm0d /mnt/usr
 mount /dev/mirror/gm0e /mnt/var
 mount /dev/mirror/gm0f /mnt/tmp

Now we're going to do a install the fun way:
 DESTDIR=/mnt
 export DESTDIR
 cd /dist/6.2-RELEASE/base; ./install.sh
 cd ../ports; ./install.sh
 cd ../manpages; ./install.sh
 cd ../kernels; ./install.sh GENERIC
 mv /mnt/boot/GENERIC/* /mnt/boot/kernel


You now have a basic, blank, sorta bootable unconfigured FreeBSD install
on the machine.

Setup the boot loader to load the needed kernel modules, so that we can
mount root from the mirror.
 echo 'geom_label_load="YES"'  >> /mnt/boot/loader.conf
 echo 'geom_stripe_load="YES"' >> /mnt/boot/loader.conf
 echo 'geom_mirror_load="YES"' >> /mnt/boot/loader.conf

Set a kernel option to use more memory but make the stripe layer faster,
otherwise stripes are unbearably slow.
 echo 'kern.geom.stripe.fast=1"' >> /mnt/boot/loader.conf

Now setup our initial fstab file:
 echo '/dev/label/geom0s1b	none	swap	sw	0	0' >> /mnt/etc/fstab
 echo '/dev/label/geom1s1b	none	swap	sw	0	0' >> /mnt/etc/fstab
 echo '/dev/label/geom2s1b	none	swap	sw	0	0' >> /mnt/etc/fstab
 echo '/dev/label/geom3s1b	none	swap	sw	0	0' >> /mnt/etc/fstab
 echo '/dev/mirror/boot		/	ufs	rw	1 	1' >> /mnt/etc/fstab
 echo '/dev/mirror/gm0d		/usr	ufs	rw	2 	2' >> /mnt/etc/fstab
 echo '/dev/mirror/gm0e		/var	ufs	rw	2 	2' >> /mnt/etc/fstab
 echo '/dev/mirror/gm0f		/tmp	ufs	rw	2 	2' >> /mnt/etc/fstab

Reboot and the machine should start the raid sets automatically and mount
off of the raid array automatically. Keep that install CD handy in case
you messed up.

Login, change the root password, setup rc.conf (hostname, interfaces, ssh,
linux binary compat... ), start installing stuff, etc.

Enjoy.

==Block Diagram==
<code>
 da0 --label-->geom0
 da1 --label-->geom1
 da2 --label-->geom2
 da3 --label-->geom3

 label/geom0s1a --|--mirror-->/dev/mirror/boot
 label/geom1s1a --|
 label/geom2s1a --|
 label/geom3s1a --|

 label/geom0s1d --|--stripe-->/dev/stripe/st0 --|--mirror-->/dev/mirror/gm0
 label/geom1s1d --|                             |
                                                |
 label/geom2s1d --|--stripe-->/dev/stripe/st1 --|
 label/geom3s1d --|

 mirror/boot   --> /

 mirror/gm0s1d --> /usr
 mirror/gm0s1e --> /var
 mirror/gm0s1f --> /tmp

 label/geom0s1b --> swap
 label/geom1s1b --> swap
 label/geom2s1b --> swap
 label/geom3s1b --> swap
</code>






More information about the freebsd-geom mailing list