#! /usr/bin/perl -w # AJ Lewis # Copyright (C) Red Hat, Inc 2004 All rights reserved # # Build up an n-way persistant mirror and verify it works # ########################################################################## use strict; use warnings; my $name = "foo"; my $log = "log"; # array of arrays - [device, size, stamp] my $raiddevs = [["/dev/sda2", 1024000, 89], ["/dev/sda7", 1024000, 90], ["/dev/sda8", 1024000, 91]]; my $mirstamp = 88; my $mirstamp2 = 87; # [device, size] my $logdev = ["/dev/sda6", 10240]; my $hashdd = "/usr/src/joestests/hashdd/hashdd"; my $dmdir = "/dev/mapper"; # Actually create the mapped device with dmsetup sub create_dm { my ($table, $name) = @_; print "* creating $name: $table\n"; system("echo $table | dmsetup create $name"); return ($? >> 8); } # Reload teh mapped device with dmsetup sub reload_dm { my ($table, $name) = @_; print "* reloading $name: $table\n"; system("echo $table | dmsetup load $name"); if (($? >> 8) != 0) { return 1; } system("dmsetup resume $name"); return ($? >> 8); } # build a linear target table sub build_linear { my ($devref) = @_; my @devs = @$devref; my $count = $#devs + 1; my $table = ""; my $dev; foreach $dev (@devs) { $table = $table . "0 @$dev[1] linear @$dev[0] 8"; } return $table; } # build a raid1 target table sub build_raid1 { my ($devref, $logname) = @_; my @devs = @$devref; my $count = $#devs + 1; my $minsize = 999999999999; my $dev; # Use the smallest device size for the mirror size foreach $dev (@devs) { if (@$dev[1] < $minsize) { $minsize = @$dev[1]; } } my $table = "0 $minsize mirror disk 2 $dmdir/$logname 1024 $count "; foreach $dev (@devs) { $table = $table . "@$dev[0] 8 "; } return $table; } sub del_dm { my ($name) = @_; print "* removing $name\n"; system("dmsetup remove $name"); return ($? >> 8); } sub wait_dm { my ($name) = @_; print "* waiting on $name\n"; system("dmsetup wait $name"); return ($? >> 8); } sub init_log { my ($dev, $name) = @_; my $tab = build_linear [$dev]; if (create_dm $tab, $name) { return 1; } print "* clearing log: $name\n"; system("dd if=/dev/zero of=$dmdir/$log"); return 0; } sub stamp { my ($name, $num) = @_; print "* stamping $name with $num\n"; system("$hashdd seed=$num of=$dmdir/$name"); return ($? >> 8); } sub verify { my ($name, $num) = @_; print "* checking stamp on $name with $num\n"; system("$hashdd seed=$num if=$dmdir/$name"); return ($? >> 8); } # # # Start of real work # # # # Clear any old cruft del_dm $name; del_dm $log; my $tab; my $v; print "** SETUP\n"; my $first = 1; # Build up the individual devices with different stamps foreach $v (@$raiddevs) { $tab = build_linear [$v]; if($first) { die "Can't create $tab" if create_dm($tab, $name); $first = 0; } else { die "Can't reload $tab" if reload_dm($tab, $name); } stamp "$name", $$v[2]; } # create the persistant log device die "Can't initialize log" if init_log $logdev, $log; print "** Build RAID1\n"; # build a raid1 with all devices $tab = build_raid1 $raiddevs, $log; die "Can't reload $tab" if reload_dm $tab, $name; wait_dm $name; print "** Verify RAID1\n"; # verify all devices match the first $first = 1; foreach $v (@$raiddevs) { if ($first != 1) { $tab = build_linear [$v]; die "Can't reload $tab" if reload_dm $tab, $name; die "Can't verify $tab" if verify $name, $$raiddevs[0][2]; } $first = 0; } print "** Rebuild RAID1 from log\n"; # rebuild the raid1 and attempt to write to it $tab = build_raid1 $raiddevs, $log; die "Can't reload $tab" if reload_dm $tab, $name; print "Writing 512 bytes to mirror"; system("dd if=/dev/zero of=$dmdir/$name bs=512 count=1"); print "** Verify writing to RAID1\n"; stamp "$name", $mirstamp; die "Can't verify $name" if verify $name, $mirstamp; # verify all devices match the mirror foreach $v (@$raiddevs) { $tab = build_linear [$v]; die "Can't reload $tab" if reload_dm $tab, $name; die "Can't verify $tab" if verify $name, $mirstamp; } del_dm $name; del_dm $log; print "** Rebuild RAID1 and verify writes work while resyncing\n"; # create the persistant log device die "Can't initialize log" if init_log $logdev, $log; # build a raid1 with all devices $tab = build_raid1 $raiddevs, $log; die "Can't create $tab" if create_dm $tab, $name; stamp "$name", $mirstamp2; die "Can't verify $name" if verify $name, $mirstamp2; wait_dm $name; # verify all devices match the mirror foreach $v (@$raiddevs) { $tab = build_linear [$v]; die "Can't reload $tab" if reload_dm $tab, $name; die "Can't verify $tab" if verify $name, $mirstamp2; } del_dm $name; del_dm $log;