Added: Cumulative parity check

This allows a parity check to be divided over multiple time windows.
This commit is contained in:
bergware
2021-12-16 00:33:14 +01:00
parent e55aeb733f
commit 2694cf9747
5 changed files with 141 additions and 21 deletions
+23 -12
View File
@@ -198,16 +198,18 @@ function stopParity(form,text) {
<?endif;?>
}
function pauseParity(form) {
parityStatus.stop();
$.post('/webGui/include/ParityControl.php',{action:'pause'},function(){
$('#pauseButton').val("_(Resume)_").prop('disabled',true).prop('onclick',null).off('click').click(function(){resumeParity(form);});
$(form).append('<input type="hidden" name="cmdNoCheck" value="Pause">');
$('#pauseButton').val("_(Resume)_").prop('onclick',null).off('click').click(function(){resumeParity(form);});
form.submit();
});
}
function resumeParity(form) {
parityStatus.stop();
$.post('/webGui/include/ParityControl.php',{action:'resume'},function(){
$('#pauseButton').val("_(Pause)_").prop('disabled',true).prop('onclick',null).off('click').click(function(){pauseParity(form);});
$(form).append('<input type="hidden" name="cmdCheck" value="Resume">');
$('#pauseButton').val("_(Pause)_").prop('onclick',null).off('click').click(function(){pauseParity(form);});
form.submit();
});
}
@@ -255,7 +257,7 @@ reload_page();
$('.tooltip_diskio').tooltipster({delay:100,trigger:'custom',triggerOpen:{mouseenter:true},triggerClose:{click:false,scroll:true,mouseleave:true}});
toggle_diskio(true);
<?
$parity = $var['mdResync'] ? "<br><small>_(Disabled)_ -- _(Parity operation is running)_</small>" : "";
$parity = $var['mdResyncPos'] ? "<br><small>_(Disabled)_ -- _(Parity operation is running)_</small>" : "";
$mover = file_exists('/var/run/mover.pid') ? "<br><small>_(Disabled)_ -- _(Mover is running)_</small>" : "";
$btrfs = exec('pgrep -cf /sbin/btrfs') ? "<br><small>_(Disabled)_ -- _(BTRFS operation is running)_</small>" : "";
?>
@@ -277,17 +279,26 @@ devices.on('connect', function(e) {
<?endif;?>
var parityStatus = new NchanSubscriber('/sub/parity');
parityStatus.on('message', function(data) {
parityStatus.on('message', function(data){
$.each(data.split(';'),function(k,v) {if ($('#line'+k).length>0) $('#line'+k).html(v);});
if (!data && $('#cancelButton').length>0 && $('#cancelButton').val()=="_(Cancel)_") {
$('#cancelButton').val("_(Done)_").prop('onclick',null).off('click').click(function(){refresh();});
$('#pauseButton').prop('disabled',true);
$('#cancelText').html('');
$('#line4').html("_(completed)_");
} else if ($('#pauseButton').length>0 && $('#pauseButton').prop('disabled')==false) {
var form = document.arrayOps;
if ($('#pauseButton').val()=="_(Pause)_" && data.search("_(paused)_")!=-1) {
$('#pauseButton').val("_(Resume)_").prop('onclick',null).off('click').click(function(){resumeParity(form);});
} else if ($('#pauseButton').val()=="_(Resume)_" && data.search("_(paused)_")==-1) {
$('#pauseButton').val("_(Pause)_").prop('onclick',null).off('click').click(function(){pauseParity(form);});
}
}
});
devices.start();
<?if ($var['mdResyncPos']):?>
setTimeout(function(){$('#pauseButton').prop('disabled',false);$('#cancelButton').prop('disabled',false);},250);
parityStatus.start();
<?endif;?>
$(function(){
@@ -373,24 +384,24 @@ function formatWarning(val) {
else:
if ($var['mdResyncAction']=="check"):?>
<tr><td>_(Read-Check in progress)_.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Read-Check')"></td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?> disabled>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Read-Check')" disabled></td>
<td id="cancelText"><?if ($var['mdResync']):?>**_(Pause)_** _(will pause the Read-Check)_.<?else:?>**_(Resume)_** _(will resume the paused Read-Check)_.<?endif;?><br>**_(Cancel)_** _(will stop the Read-Check)_.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"check")):?>
<tr><td>_(Parity-Check in progress)_.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Parity-Check')"></td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?> disabled>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Parity-Check')" disabled></td>
<td id="cancelText"><?if ($var['mdResync']):?>**_(Pause)_** _(will pause the Parity-Check)_.<?else:?>**_(Resume)_** _(will resume the paused Parity-Check)_.<?endif;?><br>**_(Cancel)_** _(will stop the Parity-Check)_.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"recon")):?>
<tr><td>_(Parity-Sync/Data-Rebuild in progress)_.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Parity-Sync/Data-Rebuild')"></td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?> disabled>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Parity-Sync/Data-Rebuild')" disabled></td>
<td id="cancelText"><?if ($var['mdResync']):?>**_(Pause)_** _(will pause the Parity-Sync/Data-Rebuild)_.<?else:?>**_(Resume)_** _(will resume the paused Parity-Sync/Data-Rebuild)_.<?endif;?><br>**_(Cancel)_** _(will stop Parity-Sync/Data-Rebuild)_.
<br>_(WARNING: canceling may leave the array unprotected)_!</td></tr>
<? elseif (strstr($var['mdResyncAction'],"clear")):?>
<tr><td>_(Clearing in progress)_.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Clearing')"></td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="_(Pause)_" onclick="pauseParity(this.form)"<?else:?> value="_(Resume)_" onclick="resumeParity(this.form)"<?endif;?> disabled>
<input type="button" id="cancelButton" value="_(Cancel)_" onclick="stopParity(this.form,'Clearing')" disabled></td>
<td id="cancelText"><?if ($var['mdResync']):?>**_(Pause)_** _(will pause the Clearing)_.<?else:?>**_(Resume)_** _(will resume the paused Clearing)_.<?endif;?><br>**_(Cancel)_** _(will stop Clearing)_.</td></tr>
<? endif;?>
<tr><td></td><td><input type="button" value="_(History)_" onclick="openBox('/webGui/include/ParityHistory.php','<?=_('Parity/Read-Check History')?>',600,900,false)"></td>
+30
View File
@@ -23,6 +23,7 @@ $mode = ['Disabled','Daily','Weekly','Monthly','Yearly','Custom'];
$days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
$months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
$memory = '/tmp/memory.tmp';
if (file_exists($memory)) {
parse_str(file_get_contents($memory), $parity);
if (empty($parity['hour'])) $parity['hour'] = "";
@@ -31,6 +32,8 @@ if (file_exists($memory)) {
if (empty($parity['month'])) $parity['month'] = "";
if (empty($parity['write'])) $parity['write'] = "";
}
if ($parity['mode']<2) $parity['cumulative'] = '';
if ($parity['mode']==2) $parity['frequency'] = '1';
?>
<script>
<?if ($parity['mode']==5):?>
@@ -84,6 +87,12 @@ function presetParity(form) {
form.month.disabled = mode<4;
form.write.disabled = mode==0;
}
function showCumulative(val,pace) {
if (val=='') $('#cumulative').hide(pace); else $('#cumulative').show(pace);
}
$(function(){
showCumulative($('select[name="cumulative"]').val());
});
</script>
<form markdown="1" name="parity_settings" method="POST" action="/update.php" target="progressFrame" onsubmit="prepareParity(this)">
<input type="hidden" name="#file" value="dynamix/dynamix.cfg"/>
@@ -188,6 +197,27 @@ _(Write corrections to parity disk)_:
:parity_write_corrections_help:
_(Cumulative parity check)_:
: <select name="cumulative" onchange="showCumulative(this.value,'slow')" <?=$parity['mode']>1?'':'disabled'?>>
<?=mk_option($parity['cumulative'], "", _("No"))?>
<?=mk_option($parity['cumulative'], "1", _("Yes"))?>
</select>
<div markdown="1" id="cumulative" style="display:none">
_(Accumulation frequency)_:
: <select name="frequency">
<?=mk_option($parity['frequency'], "1", _("Daily"))?>
<?=mk_option($parity['frequency'], "7", _("Weekly"),$parity['mode']==2 ? 'disabled' : '')?>
</select>
_(Accumulation duration)_:
: <select name="duration">
<?for ($h=1; $h<24; $h++):?>
<?=mk_option($parity['duration'], $h, $h.' '._('hour'.($h==1?'':'s')))?>
<?endfor;?>
</select>
</div>
&nbsp;
: <input type="submit" name="#apply" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()"></td>
</form>
+1 -2
View File
@@ -11,8 +11,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$stamps = '/var/tmp/stamps.ini';
$stamps = '/var/tmp/stamps.ini';
switch ($_POST['action']) {
case 'pause':
+56 -7
View File
@@ -15,43 +15,92 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/webGui/include/Wrappers.php";
$memory = '/tmp/memory.tmp';
$mdcmd = '/usr/local/sbin/mdcmd';
$ctrl = '/usr/local/emhttp/webGui/scripts/parity_control';
function month($m) {
return array_filter(explode(',',$m),function($x){return $x>=date('m');})[0];
}
if (isset($_POST['#apply'])) {
$cron = "";
$cron = [];
if ($_POST['mode']>0) {
$time = $_POST['hour'] ?? '* *';
$dotm = $_POST['dotm'] ?? '*';
$month = $_POST['month'] ?? '*';
$day = $_POST['day'] ?? '*';
$write = $_POST['write'] ?? '';
$term = '';
$term = $end = '';
switch ($dotm) {
case '28-31':
case '28-31':
$term = '[[ $(date +%e -d +1day) -eq 1 ]] && ';
$end = ' || :';
break;
case 'W1' :
$dotm = '*';
$term = '[[ $(date +%e) -le 7 ]] && ';
$end = ' || :';
break;
case 'W2' :
$dotm = '*';
$term = '[[ $(date +%e -d -7days) -le 7 ]] && ';
$end = ' || :';
break;
case 'W3' :
$dotm = '*';
$term = '[[ $(date +%e -d -14days) -le 7 ]] && ';
$end = ' || :';
break;
case 'W4' :
case 'W4' :
$dotm = '*';
$term = '[[ $(date +%e -d -21days) -le 7 ]] && ';
$end = ' || :';
break;
case 'WL' :
case 'WL' :
$dotm = '*';
$term = '[[ $(date +%e -d +7days) -le 7 ]] && ';
$end = ' || :';
break;
}
$cron = "# Generated parity check schedule:\n$time $dotm $month $day $term/usr/local/sbin/mdcmd check $write &> /dev/null || :\n\n";
$cron[] = "# Generated parity check schedule:";
if ($_POST['cumulative']==1) {
$freq = $_POST['frequency'];
$span = $_POST['duration'];
[$m, $h] = explode(' ',$time);
$H = ($h + $span) % 24;
switch ($freq) {
case 1: // daily
$M1 = $M2 = $D = '*';
break;
case 7: // weekly
if ($day != '*') {
$M1 = $M2 = '*';
$D = strtok($day,',');
if ($H < $h) $D = ($D + 1) % 7;
} elseif ($dotm != '*') {
$D = '*';
$M = $month=='*' ? date('m') : month($month);
$M = exec("date +%e -d '$M/1+1month-1day'");
$s0 = strpos($dotm,'-')===false ? $dotm : $M;
$s1 = $s2 = [];
$x1 = $s0 + ($H < $h ? 1 : 0); if ($x1 > $M) $x1 -= $M;
$x2 = $s0;
for ($n=0; $n<5; $n++) {
$s1[] = $x1; $s2[] = $x2;
$x1 += 7; if ($x1 > $M) $x1 -= $M;
$x2 += 7; if ($x2 > $M) $x2 -= $M;
}
$M1 = implode(',',$s1);
$M2 = implode(',',$s2);
}
break;
}
$cron[] = "$m $H $M1 * $D $ctrl pause &> /dev/null";
$cron[] = "$m $h $M2 * $D $ctrl resume &> /dev/null";
}
$cron[] = "$time $dotm $month $day {$term}{$mdcmd} check $write &> /dev/null$end";
}
parse_cron_cfg("dynamix", "parity-check", $cron);
parse_cron_cfg("dynamix", "parity-check", implode("\n",$cron)."\n");
@unlink($memory);
} else {
file_put_contents($memory, http_build_query($_POST));
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/php -q
<?PHP
/* Copyright 2005-2021, Lime Technology
* Copyright 2012-2021, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$stamps = '/var/tmp/stamps.ini';
$mdcmd = '/usr/local/sbin/mdcmd';
if (exec("grep -Po '^mdResyncPos=\K\d+' /proc/mdstat")>0) {
switch ($argv[1]) {
case 'pause':
if (!file_exists($stamps)) file_put_contents($stamps,parse_ini_file('/var/local/emhttp/var.ini')['sbSynced']);
file_put_contents($stamps,','.time(),FILE_APPEND);
exec("$mdcmd nocheck pause");
break;
case 'resume':
file_put_contents($stamps,','.time(),FILE_APPEND);
exec("$mdcmd check resume");
break;
}
}
?>