From: Martin Wilck Date: Thu, 25 Sep 2025 21:09:07 +0000 (+0200) Subject: mdcheck: restore backward-compatible behavior without arguments X-Git-Tag: mdadm-4.5~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e61a08bebd8473b2be2ba9b5f03d89222b8244f5;p=thirdparty%2Fmdadm.git mdcheck: restore backward-compatible behavior without arguments The previous patch changed the behavior of mdcheck when invoked without --continue or --restart. Previously it would have started a new check from zero on all arrays. After the previous patch, it acted like --continue on arrays where a check had been started already, and started a new check only for arrays where no Checked_* marker was present. Introduce a new run mode --start for the latter behavior. --start is the mode which will be called by mdcheck_continue.service now. For backward compatibility reasons, when mdcheck is called without a mode argument (--continue, --start, or --restart), it starts a new check from position zero on all MD arrays detected on the system. Signed-off-by: Martin Wilck --- diff --git a/misc/mdcheck b/misc/mdcheck index d133fea0..13d4a11a 100644 --- a/misc/mdcheck +++ b/misc/mdcheck @@ -23,19 +23,26 @@ # will be checkpointed when that time has expired. # A subsequent invocation will allow the 'check' to continue. # +# Arrays are identified by UUID and the 'sync_completed' value is stored +# in /var/lib/mdcheck/MD_UUID_$UUID. When the script has finished checking +# an array, it creates a file /var/lib/mdcheck/Checked_$UUID. +# +# Modes are: +# --continue Don't start new checks, only continue previously started +# ones for which MD_UUID_$UUID already exists. +# --start Like --continue, but also start new checks for arrays +# for which the file Checked_$UUID does not exist. +# --restart: Enable restarting checks that were previously finished +# (remove all Checked_* files) and exit immediately. +# This mode doesn't start any array checks. +# +# With none of these options given, a new check from 0 will be started on +# all arrays, even those that hadn't finished before. +# # Options are: -# --continue Don't start new checks, only continue previously started ones. -# --restart: Enable restarting the array checks # --duration This is passed to "date --date=$duration" to find out # when to finish -# -# Arrays are identified by UUID and the 'sync_completed' value is stored -# in /var/lib/mdcheck/MD_UUID_$UUID. If this file exists on startup of -# the script, the check will continue where the previous check left off. -# After the check completes, /var/lib/mdcheck/Checked_$UUID will be created. -# Another full check will be started after this file is removed. -# Use "mdcheck --restart" to remove these markers and re-enable checking -# all arrays. + # If the script is run from systemd, simply write to the journal on stderr. # Otherwise, use logger. @@ -56,27 +63,52 @@ devname() { echo -n "/dev/$dev" } -args=$(getopt -o "" -l help,continue,restart,duration: -n mdcheck -- "$@") +usage() { + echo >&2 'Usage: mdcheck [mode] [options] + +Mode: + --help print this help + --continue only continue previously started checks + --start continue, and start check on arrays that have not been checked + --restart re-enable checking previously finished arrays + start check from position 0 on all arrays +Options: + --duration + set the amount of time to run the checks for + ( must be understood by "date --date")' +} + +set_mode() { + [[ "$MODE" ]] && { + echo >&2 'ERROR: only one of --continue, --start, or --restart may be set +' + usage + exit 1 + } + MODE=$1 +} + +args=$(getopt -o "" -l help,continue,start,restart,duration: -n mdcheck -- "$@") rv=$? -if [ $rv -ne 0 ]; then exit $rv; fi +if [ $rv -ne 0 ]; then + usage + exit $rv +fi eval set -- $args -cont= -restart= +MODE= endtime= while [ " $1" != " --" ] do case $1 in --help ) - echo >&2 'Usage: mdcheck [--restart|--continue] [--duration time-offset]' - echo >&2 ' time-offset must be understood by "date --date"' + usage exit 0 ;; - --continue ) - cont=yes ;; - --restart ) - restart=yes ;; + --continue|--start|--restart) + set_mode "$1" + ;; --duration ) shift; dur=$1 endtime=$(date --date "$dur" "+%s") @@ -86,16 +118,22 @@ do done shift -if [ "$cont" = yes ]; then - if [ "$restart" = yes ]; then - echo 'ERROR: --restart and --continue cannot be combined' >&2 - exit 1 - fi -elif [ "$restart" = yes ]; then - log 'Re-enabling array checks for all arrays' - rm -f /var/lib/mdcheck/Checked_* - exit $? -fi +[[ $# -eq 0 ]] || { + usage + exit 1 +} + +case $MODE in + --restart) + log 'Re-enabling array checks for previously finished arrays' + rm -f /var/lib/mdcheck/Checked_* + exit 0 + ;; + "") + log 'Starting new check from 0 on all MD RAID arrays' + rm -f /var/lib/mdcheck/Checked_* /var/lib/mdcheck/MD_UUID_* + ;; +esac # We need a temp file occasionally... tmp=/var/lib/mdcheck/.md-check-$$ @@ -154,7 +192,7 @@ do log "WARNING: $checked exists, continuing anyway" } start=`cat "$fl"` - elif [[ ! -f "$checked" && -z "$cont" ]]; then + elif [[ ! -f "$checked" && "$MODE" != --continue ]]; then start=0 else # nothing to do continue diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service index 8eb97cfd..6ea2bc1e 100644 --- a/systemd/mdcheck_continue.service +++ b/systemd/mdcheck_continue.service @@ -12,7 +12,6 @@ Documentation=man:mdadm(8) [Service] Type=simple Environment="MDADM_CHECK_DURATION=6 hours" -# Note that we're not calling "mdcheck --continue" here. -# We want previously started checks to be continued, and new ones -# to be started. -ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION} +# mdcheck --start will continues previously started checks, and starts from +# zero for arrays without a "Checked_$UUID" marker in /var/lib/mdcheck +ExecStart=/usr/share/mdadm/mdcheck --start --duration ${MDADM_CHECK_DURATION}