Permute array.pl
From Linux Raid Wiki
(Difference between revisions)
DavidGreaves (Talk | contribs) (Initial raid5 permutation script) |
DavidGreaves (Talk | contribs) m (quietened down and shows possible solutions) |
||
Line 13: | Line 13: | ||
return "syntax: permute_array --md <md_device> --mount <mountpoint> [--opts <mdadm options>] [--for_real] <all devices>\n"; | return "syntax: permute_array --md <md_device> --mount <mountpoint> [--opts <mdadm options>] [--for_real] <all devices>\n"; | ||
} | } | ||
+ | |||
+ | my $MD_DEVICE; | ||
+ | my $MOUNTPOINT; | ||
+ | my $MDADM_OPTS=""; | ||
+ | my $REAL; | ||
################################################################ | ################################################################ | ||
Line 24: | Line 29: | ||
# This may need a --force... <gulp> | # This may need a --force... <gulp> | ||
− | my $create = "mdadm --create $MD_DEVICE -- | + | my $create = "yes | mdadm --create $MD_DEVICE --raid-devices=$num_devices --level=5 $MDADM_OPTS @device_list 2>/dev/null\n"; |
# Don't forget to mount read-only | # Don't forget to mount read-only | ||
− | my $mount = "mount -oro $MD_DEVICE $MOUNTPOINT"; | + | my $mount = "mount -oro $MD_DEVICE $MOUNTPOINT 2>/dev/null"; |
+ | my $umount = "umount $MOUNTPOINT 2>/dev/null"; | ||
# and stop the array... | # and stop the array... | ||
− | my $stop = "mdadm --stop $MD_DEVICE"; | + | my $stop = "mdadm --stop $MD_DEVICE 2>/dev/null"; |
# REAL == --for_real option | # REAL == --for_real option | ||
Line 40: | Line 46: | ||
system $mount; | system $mount; | ||
if (!(my $err = $?>>8)) { | if (!(my $err = $?>>8)) { | ||
− | + | print "Success. possible command : \n $create\n"; | |
+ | system $umount; | ||
} | } | ||
# we expect this to succeed | # we expect this to succeed | ||
Line 58: | Line 65: | ||
# Execution starts here... | # Execution starts here... | ||
# | # | ||
− | |||
− | |||
− | |||
− | |||
sub factorial($); | sub factorial($); | ||
Latest revision as of 13:39, 13 July 2007
#!/usr/bin/perl -w # If you forgot how you built an array and need to try various # permutations then this is for you... # based on Mark-Jason Dominus' mjd_permute: permute each word of input use strict; use Getopt::Long; sub usage { return "syntax: permute_array --md <md_device> --mount <mountpoint> [--opts <mdadm options>] [--for_real] <all devices>\n"; } my $MD_DEVICE; my $MOUNTPOINT; my $MDADM_OPTS=""; my $REAL; ################################################################ # This function is passed each permutation of component devices. # This includes a 'missing' device. # This is the place to hack command variations etc... sub try_array { # @_ looks like: ("/dev/sda1", "missing", "/dev/sdb1") my @device_list = @_; my $num_devices = scalar @_; # This may need a --force... <gulp> my $create = "yes | mdadm --create $MD_DEVICE --raid-devices=$num_devices --level=5 $MDADM_OPTS @device_list 2>/dev/null\n"; # Don't forget to mount read-only my $mount = "mount -oro $MD_DEVICE $MOUNTPOINT 2>/dev/null"; my $umount = "umount $MOUNTPOINT 2>/dev/null"; # and stop the array... my $stop = "mdadm --stop $MD_DEVICE 2>/dev/null"; # REAL == --for_real option if ($REAL) { # we expect this to succeed system $create; if (my $err = $?>>8) { die "command : $create\n exited with status $err\n\n"; } # we expect this to fail and are happy if it succeeds system $mount; if (!(my $err = $?>>8)) { print "Success. possible command : \n $create\n"; system $umount; } # we expect this to succeed system $stop; if (my $err = $?>>8) { die "command : $stop\n exited with status $err\n\n"; } } else { # Just show the create/mount/stop commands # If you want more control you could use this to write a script print "$create\n$mount\n$stop\n"; } } ################################################################ # Execution starts here... # sub factorial($); GetOptions ('md=s' => \$MD_DEVICE, "mount=s" => \$MOUNTPOINT, "opts=s" => \$MDADM_OPTS, "for_real" => \$REAL); if (!defined($MD_DEVICE) or !defined($MOUNTPOINT)) { die &usage; } print "using device $MD_DEVICE and mounting on $MOUNTPOINT\n"; # we *always* assume a 'missing' device - not doing so will destroy # the array... my @devices = @ARGV; # how many devices? my $num_devices = scalar @devices; if ($num_devices < 2) { die "$0 needs at least two component devices\n"; } # how many base permutations... my $num_permutations = factorial(scalar @devices); # try all permutations, substituting 'missing' for each device in # turn... for (my $d=0; $d < $num_devices; $d++) { my $skip_device = $devices[$d]; $devices[$d] = "missing"; print "skipping $skip_device\n\n"; for (my $i=0; $i < $num_permutations; $i++) { my @permutation = @devices[n2perm($i, $#devices)]; try_array(@permutation); } $devices[$d] = $skip_device; } ################################################################ # permutation code # n2pat($N, $len) : produce the $N-th pattern of length $len sub n2pat { my $i = 1; my $N = shift; my $len = shift; my @pat; while ($i <= $len + 1) { # Should really be just while ($N) { ... push @pat, $N % $i; $N = int($N/$i); $i++; } return @pat; } # pat2perm(@pat) : turn pattern returned by n2pat() into # permutation of integers. XXX: splice is already O(N) sub pat2perm { my @pat = @_; my @source = (0 .. $#pat); my @perm; push @perm, splice(@source, (pop @pat), 1) while @pat; return @perm; } # n2perm($N, $len) : generate the Nth permutation of $len objects sub n2perm { pat2perm(n2pat(@_)); } # Utility function: factorial with memoizing BEGIN { my @fact = (1); sub factorial($) { my $n = shift; return $fact[$n] if defined $fact[$n]; $fact[$n] = $n * factorial($n - 1); } }