diff --git a/raid/lang/en b/raid/lang/en
index b7665ea93..29f5b9424 100644
--- a/raid/lang/en
+++ b/raid/lang/en
@@ -101,6 +101,8 @@ view_remove=Remove partition:
view_removedesc=Select a partition that is part of the RAID device and click this button to remove it. This may cause data to be lost!
view_remove_det=Remove detached
view_remove_detdesc=Remove partitions that are already physically detached from the system.
+view_replace=Replace partition:
+view_replacedesc=Select a partition that should be replaced. (Hot Replace)
view_grow=Grow RAID:
view_growdesc=Grow array (convert hot spares to active members)
view_convert_to_raid6=Convert to RAID6
@@ -133,6 +135,7 @@ emdadmcreate=mdadm in --create mode failed : $1
emdadmadd=mdadm in --manage --add mode failed : $1
emdadmgrow=mdadm in --grow mode failed : $1
emdadmremove=mdadm in --manage --remove mode failed : $1
+emdadmreplace=mdadm in --manage --replace mode failed : $1
emdadmfail=mdadm in --manage --fail mode failed : $1
log_create=Created $1 RAID device $2
@@ -142,6 +145,7 @@ log_delete=Deleted RAID device $1
log_mkfs=Created $1 filesystem on $2
log_add=Added partition $2 to RAID device $1
log_remove=Removed partition $2 from RAID device $1
+log_replace=Hot replaced partition $2 in RAID device $1 with a spare partition
log_grow=Grown RAID device $1 to a total of $2 disks
log_convert_to_raid6=Converted RAID5 device $1 to a RAID6 device
log_convert_to_raid5=Converted RAID6 device $1 to a RAID5 device
diff --git a/raid/log_parser.pl b/raid/log_parser.pl
index 8ece806d2..d07897684 100755
--- a/raid/log_parser.pl
+++ b/raid/log_parser.pl
@@ -30,6 +30,9 @@ elsif ($action eq 'add') {
elsif ($action eq 'remove') {
return &text('log_remove', "$object", "$p->{'disk'}");
}
+elsif ($action eq 'replace') {
+ return &text('log_replace', "$object", "$p->{'disk'}");
+ }
elsif ($action eq 'grow') {
return &text('log_grow', "$object", "$p->{'disk'}");
}
diff --git a/raid/raid-lib.pl b/raid/raid-lib.pl
index d786d370e..cb708d230 100755
--- a/raid/raid-lib.pl
+++ b/raid/raid-lib.pl
@@ -521,10 +521,10 @@ if ($raid_mode eq "mdadm") {
# Call mdadm commands to fail and remove
local $out = &backquote_logged(
"mdadm --manage $_[0]->{'value'} --fail $_[1] 2>&1");
- &error(&text('emdadfail', "$out")) if ($?);
+ &error(&text('emdadmfail', "$out")) if ($?);
local $out = &backquote_logged(
"mdadm --manage $_[0]->{'value'} --remove $_[1] 2>&1");
- &error(&text('emdadremove', "$out")) if ($?);
+ &error(&text('emdadmremove', "$out")) if ($?);
# Remove device from mdadm.conf
local $lref = &read_file_lines($config{'mdadm'});
@@ -558,10 +558,22 @@ if ($raid_mode eq "mdadm") {
# Call mdadm commands to remove
local $out = &backquote_logged(
"mdadm --manage $_[0]->{'value'} --remove detached 2>&1");
- &error(&text('emdadremove', "$out")) if ($?);
+ &error(&text('emdadmremove', "$out")) if ($?);
}
}
+# replace_partition(&raid, device)
+# Hot replaces a partition with a spare
+sub replace_partition
+{
+if ($raid_mode eq "mdadm") {
+ # Call mdadm commands to replace
+ local $out = &backquote_logged(
+ "mdadm --replace $_[0]->{'value'} $_[1] 2>&1");
+ &error(&text('emdadmreplace', "$out")) if ($?);
+ }
+}
+
# directive_lines(&directive, indent)
sub directive_lines
{
@@ -798,5 +810,13 @@ local $ver = $out =~ /\s+v([0-9\.]+)/ ? $1 : undef;
return wantarray ? ( $ver, $out ) : $ver;
}
+# supports_replace()
+# Only kernels with version 3.3 and above support the hot replace feature
+sub supports_replace
+{
+my $out = &backquote_command("uname -r 2>/dev/null = 3;
+}
+
1;
diff --git a/raid/save_raid.cgi b/raid/save_raid.cgi
index feb884c83..d23309792 100755
--- a/raid/save_raid.cgi
+++ b/raid/save_raid.cgi
@@ -113,6 +113,14 @@ elsif ($in{'remove_det'}) {
&unlock_raid_files();
&redirect("");
}
+elsif ($in{'replace'}) {
+ # Hot replace a member disk with a spare
+ &lock_raid_files();
+ &replace_partition($old, $in{'replacedisk'});
+ &unlock_raid_files();
+ &webmin_log("replace", undef, $old->{'value'}, { 'disk' => $in{'replacedisk'} } );
+ &redirect("");
+ }
elsif ($in{'convert_to_raid6'}) {
# Convert RAID level to RAID6
&lock_raid_files();
diff --git a/raid/view_raid.cgi b/raid/view_raid.cgi
index 1a5028658..02e8d357c 100755
--- a/raid/view_raid.cgi
+++ b/raid/view_raid.cgi
@@ -163,6 +163,12 @@ if ($raid_mode eq "mdadm") {
push(@grid, &ui_submit($text{'view_remove_det'}, "remove_det"),
$text{'view_remove_detdesc'});
}
+ if ($sparescnt > 0 && &get_mdadm_version() >= 3.3 && &supports_replace()) {
+ @rdisks = sort { $a->[0] cmp $b->[0] } @rdisks;
+ push(@grid, &ui_submit($text{'view_replace'}, "replace")." ".
+ &ui_select("replacedisk", undef, \@rdisks),
+ $text{'view_replacedesc'});
+ }
if ($sparescnt > 0 && $lvl != 10) {
@spares = sort { $a->[0] cmp $b->[0] } @spares;
push(@grid, &ui_submit($text{'view_grow'}, "grow")." ".