Easy Mirroring Without RAID: the Poor Man’s Disk Array

This howto explain how to use rsync to build a data mirroring mechanism on a local machine, with two hard drives, ala RAID 1, but without RAID 1 (!).

I had the project to setup a RAID 5 array using 3*120 Gb hard drives in USB enclosures. Unfortunately my project stalled due to instability in early 2.6.x kernels (I heard that 2.6.12 and upper are now useable for “RAID over USB”).

Because of the urgency of reliable storage (and because I don’t want to waste time compiling and fine-tuning kernels), I decided to do it using traditionnal IDE host. So I plugged two 120Gb HDD on my machine as master device, one on each IDE channel.

Open Brick NG and RAID-1-like setup

Then I made a big XFS partition on each, and update my /etc/fstab:

/dev/sda1 /                auto  noatime   1 1
/dev/hda1 /mnt/hd1         xfs   defaults  1 2
/dev/hdc1 /mnt/hd1_mirror  xfs   defaults  1 2

At that moment I have to explain you that my machine is an OpenBrick NG, with a USB 2.0 512 Mb thumb drive (/dev/sda1 in the fstab) on which all my linux system is installed. That explain why my two IDE channels are free for use.

The idea is now to use /mnt/hd1 to store and manipulate my datas, then rsync that drive with his alter-ego (/mnt/hd1_mirror) every night. To do that, I’ve just added the following command in a cron entry:

rsync -a --delete --delete-excluded --delete-after /mnt/hd1/ /mnt/hd1_mirror/

And voilà !

As you guess, this solution is far from perfect, and has major inconvenients regarding RAID 1:

  • No immediate backup : the backuped datas are 1-day old;
  • Seek time is not reduce by half;
  • Transfer rate is not doubled.

Oh, and by the way, be careful to not write files on /mnt/hd1_mirror/ because they will be deleted each night during the mirroring process.

How-to Compile and Use xvidcap

Compile gvidcap !

Get the last stable source code archive on xvidcap Sourceforge project page or download it from the CVS:

cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/xvidcap co -P xvidcap

Install required dependencies:

urpmi gcc automake libgtk+2-devel ffmpeg-devel liblame0-devel

Dirty compile:

make distclean [optional]
CPPFLAGS=-I/usr/include/ffmpeg LDFLAGS=-L/usr/bin/ffmpeg
./configure --with-gtk2 --with-forced-embedded-ffmpeg && make gvidcap
make gvidcap
make install [optional]

Quick test:

./src/gvidcap &

Use gvidcap !

Raw capture:

gvidcap --gui no -v --file ~/img_%04d.xwd --frames 0 --fps 10 --cap_geometry 1024x768+0+0

The following can be used but it slow down the machine (png compression require too cpu):

gvidcap --gui no -v --compress 9 --file ~/img_%04d.png --frames 0 --fps 10 --cap_geometry 1024x728+0+0

Convert .xwd images to .png images because mplayer only support .png, .jpg, .tga and .sgi image file format:

convert img_*.xwd img_%04d.png && rm -rf ./*.xwd

Preview the video:

mplayer "mf://*.png" -mf fps=10

Make a video from successive screenshots:

mencoder "mf://*.png" -mf fps=10 -ovc lavc -o ./video.avi

Documentation:

Qemu: How-To Share Network Access with the Ghest OS

Qemu Network Sharing

Create a file /etc/qemu-ifup that contain:

#!/bin/sh
sudo modprobe tun
sudo /sbin/ifconfig $1 up 10.0.2.2 netmask 255.255.255.0 broadcast 10.0.2.255

# IP masquerade
sudo echo "1" > /proc/sys/net/ipv4/ip_forward
sudo /sbin/iptables -N nat
sudo /sbin/iptables -t nat -F
sudo /sbin/iptables -t nat -A POSTROUTING -s 10.0.2.15 -j MASQUERADE
sudo /sbin/iptables -t nat -A POSTROUTING -d 10.0.2.15 -o $1

Don’t forget to give it execution permissions:

chmod 755 /etc/qemu-ifup

Start qemu with the following parameters:

qemu /home/kevin/qemu-mdk10.1.img -n /etc/qemu-ifup

Setup the network in your ghest OS in qemu:

ifconfig eth0 10.0.2.15
route add default gw 10.0.2.2

Test the visibility of the guest OS from the host OS:

[root@localhost kevin]# ping 10.0.2.15
PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.
64 bytes from 10.0.2.15: icmp_seq=1 ttl=64 time=2.96 ms
64 bytes from 10.0.2.15: icmp_seq=2 ttl=64 time=0.295 ms
64 bytes from 10.0.2.15: icmp_seq=3 ttl=64 time=0.296 ms

--- 10.0.2.15 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.295/1.185/2.965/1.258 ms

Test the visibility of the host from the guest:

[root@localhost root]# ping 10.0.2.2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=1.08 ms
64 bytes from 10.0.2.2: icmp_seq=2 ttl=64 time=0.433 ms
64 bytes from 10.0.2.2: icmp_seq=3 ttl=64 time=0.383 ms

--- 10.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.383/0.634/1.087/0.321 ms

Qemu commands

Some useful command to help running and setup qemu…

  • Create an empty compressed 10 Go disk image (in qcow2 format):

    qemu-img create -f qcow2 /home/kevin/qemu-disk-image.qcow 10G
    
  • Boot on your machine’s CD-Rom in qemu with previous disk image as primary HDD:
    qemu -cdrom /dev/cdrom -hda /home/kevin/qemu-disk-image.qcow -boot d
    
  • Same as above but with a CD-Rom iso image:
    qemu -cdrom /home/kevin/ubuntu.iso -hda /home/kevin/qemu-disk-image.qcow -boot d
    
  • Boot the previously created disk image:
    qemu /home/kevin/qemu-disk-image.qcow
    
  • Convert qcow image to a raw image:
    qemu-img convert /home/kevin/qemu-disk-image.qcow -O raw /home/kevin/qemu-disk-image.raw
    
  • Mount a RAW disk image:
    mount -o loop,offset=32256 /home/kevin/qemu-disk-image.raw /media/qemu/
    
  • Mount a qcow2 disk image via the nbd protocol (don’t forget to install the nbd-client package):
    modprobe nbd max_part=63
    qemu-nbd -c /dev/nbd0 /home/kevin/qemu-disk-image.qcow2
    mount /dev/nbd0p1 /media/qemu
    
  • To run a x86_64 guest system on a 32-bit host, simply use qemu-system-x86_64 binary command instead of qemu.

How-To Mount a File System Binary Image

Obtain a binary image

We have a USB key with a file system on it, and we want to save its content. We do a binary image using:

dd if=/dev/sda1 of=/home/kevin/usb_key.img

Mount the image file

Get informations about the file system of the image file using:

fdisk -l -u /home/kevin/usb_key.img

This show you something like that:

Disque usb_key.img: 0 Mo, 0 octets
9 têtes, 56 secteurs/piste, 0 cylindres, total 0 sectors
Unités = secteurs de 1 * 512 = 512 octets

Périphérique Boot   Start   End      Blocks   Id   System
usb_key.img1        56      511559   255752   83   Linux

Get the sector number where the partition start (56) and the size of sectors (512). Multiply the two values:

56 * 512 = 28672

Then setup a loopback block device based on the image:

losetup -o 28672 /dev/loop0 /home/kevin/usb_key.img

Now you can mount your USB key:

mount /dev/loop0 /mnt/usb_key/