summaryrefslogtreecommitdiffstats
path: root/perl-install/raid.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/raid.pm')
-rw-r--r--perl-install/raid.pm131
1 files changed, 120 insertions, 11 deletions
diff --git a/perl-install/raid.pm b/perl-install/raid.pm
index 11284a90a..480868547 100644
--- a/perl-install/raid.pm
+++ b/perl-install/raid.pm
@@ -1,4 +1,4 @@
-package raid; # $Id$
+package raid;
use diagnostics;
use strict;
@@ -13,10 +13,21 @@ use run_program;
use devices;
use modules;
-sub max_nb() { 31 }
+=head1 SYNOPSYS
+
+Manage regular soft RAID (MD=Multiple Drive).
+
+=head1 Functions
+
+=over
+
+=cut
+
+sub max_nb() { 131 }
sub check_prog {
- my ($in) = @_;
+ # perl_checker: require interactive
+ my ($in) = @_; # perl_checker: $in = interactive->new
$::prefix ? whereis_binary('mdadm') : $in->do_pkgs->ensure_binary_is_installed('mdadm', 'mdadm');
}
@@ -37,9 +48,15 @@ sub new {
$md_part;
}
+=item add()
+
+Add a partition to a RAID array
+
+=cut
+
sub add {
my ($md_part, $part) = @_;
- $md_part->{isMounted} and die N("Can not add a partition to _formatted_ RAID %s", $md_part->{device});
+ $md_part->{isMounted} and die N("Cannot add a partition to _formatted_ RAID %s", $md_part->{device});
inactivate_and_dirty($md_part);
set_isFormatted($part, 0);
$part->{raid} = $md_part->{device};
@@ -48,6 +65,12 @@ sub add {
update($md_part);
}
+=item delete()
+
+Remove a partition from a RAID array
+
+=cut
+
sub delete {
my ($raids, $md_part) = @_;
inactivate_and_dirty($md_part);
@@ -91,13 +114,26 @@ sub updateSize {
elsif (/1/) { min @l }
elsif (/4|5/) { min(@l) * (@l - 1) }
elsif (/6/) { min(@l) * (@l - 2) }
+ elsif (/10/) { min(@l) * (@l / 2) }
};
}
+=item allmodules()
+
+Return list of the RAID modules we support
+
+=cut
+
sub allmodules {
- [ 'raid0', 'raid1', 'raid10', 'raid456' ];
+ ('raid0', 'raid1', 'raid10', 'raid456');
}
+=item module($part)
+
+Return list of modules need by a md device (according to its RAID level)
+
+=cut
+
sub module {
my ($part) = @_;
my $level = $part->{level};
@@ -105,6 +141,8 @@ sub module {
if (member($level, 4, 5, 6)) {
'raid456';
+ } elsif (member($level, 10)) {
+ 'raid10';
} elsif ($level =~ /^\d+$/) {
"raid$level";
} else {
@@ -134,9 +172,11 @@ sub make {
run_program::run_or_die('mdadm', '--create', '--run', $dev,
if_($nb == 1, '--force'),
+ if_($nb == 2 && $part->{level} == 10, '--layout=f2'),
'--chunk=' . $part->{'chunk-size'},
"--level=$part->{level}",
"--raid-devices=$nb",
+ if_($part->{metadata}, "--metadata=$part->{metadata}"),
map { devices::make($_->{device}) } @{$part->{disks}});
if (my $raw_part = get_md_info($dev)) {
@@ -157,7 +197,7 @@ sub format_part {
sub verify {
my ($raids) = @_;
foreach (@$raids) {
- my $nb = $_->{level} =~ /6/ ? 4 : $_->{level} =~ /4|5/ ? 3 : 2;
+ my $nb = $_->{level} =~ /4|5|6/ ? 3 : 2;
@{$_->{disks}} >= $nb or die N("Not enough partitions for RAID level %d\n", $_->{level});
}
}
@@ -168,32 +208,77 @@ sub inactivate_and_dirty {
set_isFormatted($part, 0);
}
+=item active_mds()
+
+Return list of active MDs
+
+=cut
+
sub active_mds() {
map { if_(/^(md\S+)\s*:\s*active/, $1) } cat_("/proc/mdstat");
}
+
+=item inactive_mds()
+
+Return list of inactive MDs
+
+=cut
+
sub inactive_mds() {
map { if_(/^(md\S+)\s*:\s*inactive/, $1) } cat_("/proc/mdstat");
}
+=item free_mds()
+
+Return list of unused MD device nodes
+
+=cut
+
sub free_mds {
my ($raids) = @_;
difference2([ map { "md$_" } 0 .. max_nb() ], [ map { $_->{device} } @$raids ]);
}
+=item detect_durting_install()
+
+Load RAID modules.
+Stop RAIDS that might have been started too early by udev.
+Scan & starts RAID arrays, then stop any inactive md.
+
+=cut
+
sub detect_during_install {
my (@parts) = @_;
- foreach (@{allmodules()}) {
- eval { modules::load($_) };
- }
+ eval { modules::load($_) } foreach allmodules();
+
+ # udev may have started raids but failed due to not yet loaded modules and
+ # they remains inactive ("md: personality for level 1 is not loaded!")
+ stop_inactive_mds();
+
detect_during_install_once(@parts);
detect_during_install_once(@parts) if active_mds(); #- try again to detect RAID 10
+ stop_inactive_mds();
+}
+
+=item stop_inactive_mds()
+
+Stop any inactive md.
+=cut
+
+sub stop_inactive_mds() {
foreach (inactive_mds()) {
log::l("$_ is an inactive md, we stop it to ensure it doesn't busy devices");
run_program::run('mdadm', '--stop', devices::make($_));
}
}
+=item detect_during_install_once(@parts)
+
+Scan & starts RAID arrays, then stop any inactive md.
+
+=cut
+
sub detect_during_install_once {
my (@parts) = @_;
devices::make("md$_") foreach 0 .. max_nb();
@@ -210,7 +295,7 @@ sub get_existing {
foreach my $md (active_mds()) {
my $raw_part = get_md_info(devices::make($md)) or next;
- $raw_part->{level} =~ s/raid//; #- { linear | raid0 | raid1 | raid5 | raid6 } -> { linear | 0 | 1 | 5 | 6 }
+ $raw_part->{level} =~ s/raid//; #- { linear | raid0 | raid1 | raid5 | raid6 | raid10 } -> { linear | 0 | 1 | 5 | 6 | 10 }
my @mdparts =
map {
@@ -222,7 +307,14 @@ sub get_existing {
}
} split(',', $raw_part->{devices});
- my $md_part = new($raids, device => $md, UUID => $raw_part->{UUID}, level => $raw_part->{level}, disks => \@mdparts);
+ my ($info) = $md =~ m!([^/]*)$!;
+ my $md_part = new($raids,
+ device => $md,
+ UUID => $raw_part->{UUID},
+ level => $raw_part->{level},
+ metadata => $raw_part->{metadata},
+ info => $info . " (RAID$raw_part->{level})",
+ disks => \@mdparts);
my $type = fs::type::type_subpart_from_magic($md_part);
if ($type) {
@@ -238,11 +330,23 @@ sub get_existing {
$raids;
}
+=item is_active($dev)
+
+Is it an?active md
+
+=cut
+
sub is_active {
my ($dev) = @_;
member($dev, active_mds());
}
+=item write_conf()
+
+Write /etc/mdadm.conf
+
+=cut
+
sub write_conf {
my ($raids) = @_;
@@ -250,6 +354,7 @@ sub write_conf {
my @devices = uniq(map { devices::make($_->{device}) } map { @{$_->{disks}} } @$raids);
+ # $::isInstall test for draklive-install:
output($::isInstall ? "$::prefix/etc/mdadm.conf" : "/etc/mdadm.conf",
join(' ', 'DEVICE', @devices) . "\n",
map { "ARRAY " . devices::make($_->{device}) . " UUID=$_->{UUID} auto=yes\n" } @$raids);
@@ -282,4 +387,8 @@ sub parse_mdadm_conf {
\%conf;
}
+=back
+
+=cut
+
1;