mirror of
https://github.com/unraid/webgui.git
synced 2026-05-08 13:21:03 -05:00
Added: Cumulative parity check
This allows a parity check to be divided over multiple time windows.
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
: <input type="submit" name="#apply" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()"></td>
|
||||
</form>
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user