diff options
Diffstat (limited to 'perl-install/fs/dmraid.pm')
| -rw-r--r-- | perl-install/fs/dmraid.pm | 203 |
1 files changed, 177 insertions, 26 deletions
diff --git a/perl-install/fs/dmraid.pm b/perl-install/fs/dmraid.pm index 7bc5d9162..7a279abc7 100644 --- a/perl-install/fs/dmraid.pm +++ b/perl-install/fs/dmraid.pm @@ -1,4 +1,4 @@ -package fs::dmraid; # $Id$ +package fs::dmraid; use diagnostics; use strict; @@ -14,25 +14,54 @@ use fs::wild_device; use run_program; -init() or log::l("dmraid::init failed"); +=head1 SYNOPSYS + +Manage fake RAIDs using dmraid + +=head1 Functions + +=over + +=item init() + +Load kernel modules, init device mapper then scan for fake RAIDs. + +=cut sub init() { whereis_binary('dmraid') or die "dmraid not installed"; - eval { modules::load('dm-mirror') }; + eval { modules::load('dm-mirror', 'dm-zero') }; devices::init_device_mapper(); if ($::isInstall) { - call_dmraid('-ay'); + foreach my $name (call_dmraid('-s', '-c', '-i')) { + chomp($name); + log::l("got: $name"); + call_dmraid('-ay', '-i', '--rm_partitions', '-p', $name); + run_program::run('/sbin/kpartx', '-u', '-a', '/dev/mapper/' . $name); + } } 1; } -#- call_dmraid is overloaded when debugging, see the end of this file +=item call_dmraid($option, @args) + +Runs dmraid with $option & @args. +It is overloaded when debugging, see the end of this file. + +=cut + sub call_dmraid { - my ($option) = @_; - run_program::get_stdout('dmraid', $option); + my ($option, @args) = @_; + run_program::get_stdout('dmraid', $option, @args); } +=item check($in) + +Ensures dmraid is installed. If yes, calls init(). + +=cut + sub check { my ($in) = @_; @@ -41,20 +70,46 @@ sub check { 1; } +=item _raid_devices_raw() + +Get the real VG names, needed for ddf1, and safer than begins_with for raid10 + +=cut + sub _raid_devices_raw() { + log::l("_raid_devices_raw"); + my %vgs; + my %pv2vg = map { + chomp(); + log::l("got: $_"); + my %l; @l{qw(name size stride level status subsets devs spares)} = split(':'); + $vgs{$l{name}} = 1 if defined $l{spares}; + if (/freeing device "(.*)", path "(.*)"/ && defined $vgs{$1}) { + log::l("$2 => $1"); + $2 => $1; + } + } call_dmraid(qw(-d -s -c -c)); + map { chomp; + log::l("got: $_"); my %l; @l{qw(pv format vg level status size)} = split(':'); - \%l; - } call_dmraid('-ccr'); + if (defined $l{size} && defined $l{vg} && defined $pv2vg{$l{pv}} && !defined $vgs{$l{vg}}) { + log::l("using $pv2vg{$l{pv}} instead of $l{vg}"); + $l{vg} = $pv2vg{$l{pv}}; + } + if_(defined $l{size}, \%l); + } call_dmraid(qw(-r -c -c)); } sub _raid_devices() { my @l = _raid_devices_raw(); my %vg2pv; push @{$vg2pv{$_->{vg}}}, delete $_->{pv} foreach @l; + my %vg2status; push @{$vg2status{$_->{vg}}}, delete $_->{status} foreach @l; map { delete $_->{size}; #- now irrelevant $_->{disks} = $vg2pv{$_->{vg}}; + $_->{status} = (every { $_ eq 'ok' } @{$vg2status{$_->{vg}}}) ? 'ok' : join(' ', @{$vg2status{$_->{vg}}}); $_; } uniq_ { $_->{vg} } @l; } @@ -62,9 +117,10 @@ sub _raid_devices() { sub _sets_raw() { map { chomp; + log::l("got: $_"); my %l; @l{qw(name size stride level status subsets devs spares)} = split(':'); - \%l; - } call_dmraid('-ccs'); + if_(defined $l{spares}, \%l); + } call_dmraid('-s', '-c', '-c'); } sub _sets() { @@ -73,10 +129,16 @@ sub _sets() { foreach (@sets) { my $name = $_->{name}; my @l = grep { begins_with($name, $_->{vg}) } @raid_devices; + log::l("ERROR: multiple match for set $name: " . join(' ', map { $_->{vg} } @l)) if @l > 1; + + @l = grep { begins_with($_->{vg}, $name) } @raid_devices if !@l; + if (@l) { - log::l("ERROR: multiple match for set $name: " . join(' ', map { $_->{vg} } @l)) if @l > 1; - my ($raid) = @l; - add2hash($_, $raid); + foreach my $raid (@l) { + push @{$_->{disks}}, @{$raid->{disks}}; + add2hash($_, $raid); + $_->{status} = $raid->{status} if $_->{status} eq 'ok' && $::isInstall; + } } else { log::l("ERROR: no matching raid devices for set $name"); } @@ -84,19 +146,69 @@ sub _sets() { @sets; } +=item vgs() + +Returns the list of VGs corresponding to dmraid + +=cut + sub vgs() { map { my $dev = "mapper/$_->{name}"; my $vg = fs::wild_device::to_subpart("/dev/$dev"); - add2hash($vg, { media_type => 'hd', prefix => $dev, bus => "dmraid_$_->{format}", disks => $_->{disks} }); + add2hash($vg, { media_type => 'hd', bus => "dmraid_$_->{format}", disks => $_->{disks} }); #- device should exist, created by dmraid(8) using libdevmapper #- if it doesn't, we suppose it's not in use - if_(-e "/dev/$dev", $vg); + if (-e "/dev/$dev") { + $vg; + } else { + log::l("ignoring $dev as /dev/$dev doesn't exist"); + (); + } + + } grep { + if ($_->{status} eq 'ok') { + 1; + } else { + call_dmraid('-an', $_->{vg}) if $::isInstall; #- for things like bad_sil below, deactivating half activated dmraid + 0; + } + } _sets(); +} + +=item migrate_device_names ($vg) - } grep { $_->{status} eq 'ok' } _sets(); +Handles migration from /dev/mapper/xxx1 to /dev/mapper/xxxp1, as used by initrd/nash. +dmraid has been patched to follow xxxp1 device names. +So until the box has rebooted on new initrd/dmraid, we must cope with /dev/mapper/xxx1 device names +(cf mdk#44182) + +=cut + +sub migrate_device_names { + my ($vg) = @_; + + my $dev_name = basename($vg->{device}); + foreach (all('/dev/mapper')) { + my ($nb) = /^\Q$dev_name\E(\d+)$/ or next; + my $new = $dev_name . 'p' . $nb; + if (! -e "/dev/mapper/$new") { + log::l("migrating to $new, creating a compat symlink $_"); + rename "/dev/mapper/$_", "/dev/mapper/$new"; + symlink $new, "/dev/mapper/$_"; + } + } } +=back + +=head1 Debugging + +If $ENV{DRAKX_DEBUG_DMRAID} is set, debugging dmraid is done. +The C<call_dmraid()> function is overloaded and will spit out warnings. +=cut + if ($ENV{DRAKX_DEBUG_DMRAID}) { eval(<<'EOF'); my %debug_data = ( @@ -115,14 +227,14 @@ if ($ENV{DRAKX_DEBUG_DMRAID}) { # devs : 2 # spares : 0 - '-ccs' => "isw_ffafgbdhi_toto:234441216:256:mirror:ok:0:2:0\n", + '-s' => "isw_ffafgbdhi_toto:234441216:256:mirror:ok:0:2:0\n", # dmraid -r #################### #/dev/sda: isw, "isw_ffafgbdhi", GROUP, ok, 488397166 sectors, data@ 0 #/dev/sdb: isw, "isw_ffafgbdhi", GROUP, ok, 234441646 sectors, data@ 0 - '-ccr' => "/dev/sda:isw:isw_ffafgbdhi:GROUP:ok:488397166:0\n" . - "/dev/sdb:isw:isw_ffafgbdhi:GROUP:ok:234441646:0\n", + '-r' => "/dev/sda:isw:isw_ffafgbdhi:GROUP:ok:488397166:0\n" . + "/dev/sdb:isw:isw_ffafgbdhi:GROUP:ok:234441646:0\n", }, pdc => { @@ -137,24 +249,63 @@ if ($ENV{DRAKX_DEBUG_DMRAID}) { # devs : 2 # spares : 0 - '-ccs' => "pdc_bcefbiigfg:80043200:128:mirror:ok:0:2:0\n", + '-s' => "pdc_bcefbiigfg:80043200:128:mirror:ok:0:2:0\n", # dmraid -r #################### # /dev/sda: pdc, "pdc_bcefbiigfg", mirror, ok, 80043200 sectors, data@ 0 # /dev/sdb: pdc, "pdc_bcefbiigfg", mirror, ok, 80043200 sectors, data@ 0 - '-ccr' => "/dev/sda:pdc:pdc_bcefbiigfg:mirror:ok:80043200:0\n" . + '-r' => "/dev/sda:pdc:pdc_bcefbiigfg:mirror:ok:80043200:0\n" . "/dev/sdb:pdc:pdc_bcefbiigfg:mirror:ok:80043200:0\n", - }, + }, + bad_sil => { + '-s' => "sil_aeacdidecbcb:234439600:0:mirror:ok:0:1:0\n", + # ERROR: sil: only 3/4 metadata areas found on /dev/sdb, electing... + + '-r' => "/dev/sdb:sil:sil_aeacdidecbcb:mirror:broken:234439600:0\n", + # ERROR: sil: only 3/4 metadata areas found on /dev/sdb, electing... + }, + + weird_nvidia => { + '-s' => <<'EO', +/dev/sda: "sil" and "nvidia" formats discovered (using nvidia)! +/dev/sdb: "sil" and "nvidia" formats discovered (using nvidia)! +nvidia_bcjdbjfa:586114702:128:mirror:ok:0:2:0 +EO + '-r' => <<'EO', +/dev/sda: "sil" and "nvidia" formats discovered (using nvidia)! +/dev/sdb: "sil" and "nvidia" formats discovered (using nvidia)! +/dev/sda:nvidia:nvidia_bcjdbjfa:mirror:ok:586114702:0 +/dev/sdb:nvidia:nvidia_bcjdbjfa:mirror:ok:586114702:0 +EO + # ERROR: multiple match for set nvidia_bcjdbjfa: nvidia_bcjdbjfa + }, + + nvidia_with_subsets => { + '-s' => <<'EO', +nvidia_bfcciffh:625163520:128:raid10:ok:2:4:0 +EO + '-r' => <<'EO', +/dev/sda:nvidia:nvidia_bfcciffh-0:stripe:ok:312581806:0 +/dev/sdb:nvidia:nvidia_bfcciffh-0:stripe:ok:312581806:0 +/dev/sdc:nvidia:nvidia_bfcciffh-1:stripe:ok:312581806:0 +/dev/sdd:nvidia:nvidia_bfcciffh-1:stripe:ok:312581806:0 +EO + # ERROR: multiple match for set nvidia_bcjdbjfa: nvidia_bcjdbjfa + }, ); *call_dmraid = sub { - my ($option) = @_; - my $s = $debug_data{$ENV{DRAKX_DEBUG_DMRAID}}{$option} or return; - split("\n", $s); + my ($option, @args) = @_; + if (my $s = $debug_data{$ENV{DRAKX_DEBUG_DMRAID}}{$option}) { + split("\n", $s); + } else { + warn "dmraid $option @args\n"; + } }; EOF + $@ and die; } 1; |
