3 # Copyright (C) 2014-2017 Neil Brown <neilb@suse.de>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
17 # Email: <neilb@suse.com>
19 # This script should be run periodically to automatically
20 # perform a 'check' on any md arrays.
22 # It supports a 'time budget' such that any incomplete 'check'
23 # will be checkpointed when that time has expired.
24 # A subsequent invocation can allow the 'check' to continue.
27 # --continue Don't start new checks, only continue old ones.
28 # --duration This is passed to "date --date=$duration" to find out
31 # To support '--continue', arrays are identified by UUID and the 'sync_completed'
32 # value is stored in /var/lib/mdcheck/$UUID
34 # convert a /dev/md name into /sys/.../md equivalent
39 readlink
-f /sys
/dev
/block
/$maj:$min
42 args
=$
(getopt
-o hcd
: -l help,continue,duration
: -n mdcheck
-- "$@")
44 if [ $rv -ne 0 ]; then exit $rv; fi
50 while [ " $1" != " --" ]
54 echo >&2 'Usage: mdcheck [--continue] [--duration time-offset]'
55 echo >&2 ' time-offset must be understood by "date --date"'
58 --continue ) cont
=yes ;;
59 --duration ) shift; dur
=$1
60 endtime
=$
(date --date "$dur" "+%s")
67 # We need a temp file occasionally...
68 tmp
=/var
/lib
/mdcheck
/.md-check-$$
69 trap 'rm -f "$tmp"' 0 2 3 15
72 # firstly, clean out really old state files
73 mkdir
-p /var
/lib
/mdcheck
74 find /var
/lib
/mdcheck
-name "MD_UUID*" -type f
-mtime +180 -exec rm {} \
;
76 # Now look at each md device.
80 [ -e "$dev" ] ||
continue
82 if [ ! -f "$sys/md/sync_action" ]
83 then # cannot check this array
86 if [ "`cat $sys/md/sync_action`" != 'idle' ]
87 then # This array is busy
91 mdadm
--detail --export "$dev" |
grep '^MD_UUID=' > $tmp ||
continue
93 fl
="/var/lib/mdcheck/MD_UUID_$MD_UUID"
97 logger
-p daemon.info mdcheck start checking
$dev
98 elif [ -z "$MD_UUID" -o ! -f "$fl" ]
100 # Nothing to continue here
104 logger
-p daemon.info mdcheck
continue checking
$dev from
$start
108 eval MD_
${cnt}_fl
=\
$fl
109 eval MD_
${cnt}_sys
=\
$sys
110 eval MD_
${cnt}_dev
=\
$dev
112 echo $start > $sys/md
/sync_min
113 echo check
> $sys/md
/sync_action
121 while [ `date +%s` -lt $endtime ]
124 for i
in `eval echo {1..$cnt}`
127 eval sys
=\
$MD_${i}_sys
129 if [ -z "$fl" ]; then continue; fi
131 if [ "`cat $sys/md/sync_action`" != 'check' ]
137 read a rest
< $sys/md
/sync_completed
141 if [ -z "$any" ]; then exit 0; fi
145 # We've waited, and there are still checks running.
147 for i
in `eval echo {1..$cnt}`
150 eval sys
=\
$MD_${i}_sys
151 eval dev
=\
$MD_${i}_dev
153 if [ -z "$fl" ]; then continue; fi
155 if [ "`cat $sys/md/sync_action`" != 'check' ]
161 echo idle
> $sys/md
/sync_action
162 cat $sys/md
/sync_min
> $fl
163 logger
-p daemon.info pause checking
$dev at `cat $fl`