· 7 years ago · Dec 10, 2018, 12:16 PM
1#!/bin/bash
2# Version .1 - initial attempt at preclear. Joe L.
3# Version .5 - fixed hard-coded device name.
4# Version .6 - added verification test of bytes cleared in first 512 byte block.
5# Version .7 - fixed sfdsisk vs blockdev mismatch on size.
6# Version .8 - replaced sfdisk partitioning with awk script, re-did
7# progress display, added disk pre/post read. Joe L.
8# Version .9 - added -t option to test for pre-cleared signature
9# Version .9.1 - modified "read" loop to not abort on read failure
10# Version .9.2 - Added support for send staus through e-mail. Needs mail configured correctly
11# Version .9.3 - Added sub-shell for background read of disk, to work around 4096 "wait" bug in bash.
12# Version .9.4 - Enable SMART monitoring, just in case it is disabled on a drive.
13# Version .9.5 - Added disk temperature display and disk read speed display.
14# Version .9.6 - Enhanced the mail reporting to include some statistics (time, MB/s temp .. ect)
15# - Fixed a bug with using zero.txt and concurrent tests. Each test will use it's own file.
16# - Changed read block size to be bigger than 1,000,000 if smaller, to improve read/write speed
17# Version .9.7 - Added verify of zeros read from entire disk in postread phase.
18# Version .9.8 - Added ability to set read and write block sizes with -w and -r options.
19# - Added ability to set number of blocks to read at a time with -b option.
20# Version .9.9 - Changes to not perform pre-read in multi-cycles of use immediately after post-read
21# - added "-l" option to list device names of disks not in the array.
22# - modifications to final output report for easier interpetation
23# - modification to name the temp files after the disks being cleared.
24# - Added ability to start partition at sector 64 with -A option.
25# Version .9.9a - improvements to analysis report
26# Version .9.9b - more improvements to analysis report
27# - fixed bug when parsing config/disk.cfg for existing assigned disks.
28# Version .9.9c - fixed bug where date format change in 5.0 unRAID changed and
29# caused "-l" option to not work as expected.
30# - more improvements to analysis report
31# Version .9.9d - more improvements to analysis report
32# Version 1.1 - added -C 64 and -C 63 options to convert precleared drives from
33# sector 63 start to sector 64 start.
34# - added display of command line arguments to initial confirmation screen
35# - added -W option to skip pre-read phase and start with "write" phase.
36# - added -V option to skip pre-read and "clear" and only
37# perform the post-read verify.
38# Version 1.2 - fixed "-l" option to not exclude disks with only a "scsi-" entry in /dev/disk/by-id
39# Version 1.3 - Added logic to read desired "default" Partition Type from /boot/config.
40# - Added logic to save dated copies of the final preclear and SMART reports to a
41# "preclear_reports" subdirectory on the flash drive.
42# - Added "-R" option to suppress the copy of final reports to a "preclear_reports"
43# directory on the flash drive. (they are always in /tmp until you reboot)
44# Version 1.4 - Added "-D" option to suppress use of "-d ata" on smartctl commands
45# Added "-d device_type" to allow use of alternate device_types as arguments to smartctl.
46# Added "-z" option to zero the MBR and do nothing else. (remainder of the drive will not
47# be cleared)
48# Version 1.5 - Added Model/Serial number of disk to output report.
49# Fixed default argument to smartctl when "-d" and "-D" options not given.
50# Added intermediate report of sectors pending re-allocation.
51# Version 1.6 - Fixed logic to prevent use on disk assigned to array
52# Version 1.7 - Again fixed logic to deal with change in disk.cfg format.
53# Version 1.8 - Changes to range of random blocks read to not read past last block on disk.
54# Version 1.9 - fixed parse of default partition type from config
55# fixed parse of assigned disks
56# Version 1.10 - create preclear_stat_sdX files (read by myMain) - bjp999
57# Version 1.11 - Change name of saved reports files to include serial number instead of device name.
58# added -S option if previous behaviour is desired instead (report name includes linux device)
59# Version 1.12 - Do not use "-d ata" if smartctl works without it.
60# Create correct preclear-signature for disks over 0xFFFFFFFF blocks in size.
61# Version 1.13 - 1.12beta was correct, 1.12 was not (I accidentally uploaded an older version)
62# 1.13 has the fixes and should work properly for GPT partitions and proper recognition of
63# default in the absence of "-A" or "-a" option.
64ver="1.13"
65
66progname=$0
67options=$*
68
69usage() {
70 cat <<EOF
71
72Usage: $progname [-t] [-n] [-N] [-W] [-R] [-m e-mail-addr] [-M 1|2|3|4] [-c count] [-A|-a] /dev/???
73
74To test if a drive is cleared:
75 $progname -t /dev/???
76
77To covert an already pre-cleared drive from using a start sector of 63 to a start sector of 64.
78 $progname -C 64 /dev/???
79
80To covert an already pre-cleared drive from using a start sector of 64 to a start sector of 63.
81 $progname -C 63 /dev/???
82
83To zero only the MBR of a disk (first 512 bytes)
84 $progname -z /dev/???
85
86To run the post-read-verify only on a drive.
87 $progname -V [-A|-a] /dev/???
88
89To run only the writing of zeros and post-read-verify phases (skipping the pre--read)
90 $progname -W [-A|-a] /dev/???
91
92To list device names of drives not assigned to the unRAID array:
93 $progname -l
94
95 where ??? = hda, hdb, sda, sdb, etc...
96
97 -n = Do NOT perform preread and postread of entire disk that would allow
98 SMART firmware to identify bad blocks.
99
100 -N = Do not perform read validation during postread. (skip this step)
101 (basic test to check if values read are all zero as expected.
102 Skipping this test will save a few miniutes, but possibly not detect
103 a drive that returns non-zero values when zeros were expected as bad.)
104
105 -c count = perform count preread/clear/postread cycles
106 where count is a number from 1 through 20
107 If not specified, default is 1 cycle. For large disks, 1 cycle
108 can take 30 or more hours
109
110 -t = Test if disk has pre-clear signature. This option may NOT be
111 combined with the -c or -n options. The test does not write to
112 the disk. It makes no changes to a disk at all. It only reads
113 the first 512 bytes of the disk to verify a pre-clear signature
114 exists. Note: "-t" does not read the entire disk to verify it
115 it pre-cleared as that could take hours for a large disk. since
116 the pre-clear-signature is written *after* a disk is entirely
117 filled with zeros, if it exists, we assume the disk is cleared.
118
119 -w size = write block size in bytes
120
121 -r size = read block size in bytes
122
123 -b count = number of blocks to read at a time
124
125 -D disable "-d ata" used as argument to smartctl
126 -d device_type = supply "-d device_type" to smartctl used to get device status
127
128 -z = Zero the MBR (first 512 bytes) of the disk. Do nothing else.
129
130 -a = start partition on sector 63. (default when on unRAID 4.X)
131 -A = start partition on sector 64. (not compatible with unRAID 4.6 and prior)
132 On unRAID 4.7 and subsequent, the -a or -A default is set based on the value
133 set on the Settings page in the unRAID web-management console.
134
135 -C 63 = convert an existing pre-cleared disk to use sector 63 as a
136 starting sector.
137
138 -C 64 = convert an existing pre-cleared disk to use sector 64 as a
139 starting sector.
140
141 -W = skip pre-read, start with "write" of zeros to clear the disk.
142 useful if disk has already been completely read to locate bad sectors.
143
144 -v = print version of $progname
145
146 -m email@somedomain.com = optional recipient address. If blank and -M
147 option is used, it will default to default e-mail address of "root"
148
149 -M 1 = Will send an e-mail message at the end of the final results
150 (default if -m is used, but no other -M option given)
151
152 -M 2 = Will send an e-mail same as 1 plus at the end of a cycle (if multiple
153 cycles are specified)
154
155 -M 3 = Will send an e-mail same as 2 plus at the start and end of the pre-read,
156 zeroing, post-read
157
158 -M 4 = Will send an e-mail same as 3 plus also at intervals of 25%
159 during the long tests
160
161 The -m, -M options requires that a valid working mail command is installed.
162
163 -R = supress the copy of the output reports to the flash drive
164 A dated output report, the start and finish SMART reports are saved
165 in a subdirectory named /boot/preclear_reports
166 if the "-R" is NOT given. (The reports are always available
167 in /tmp until you reboot, even if "-R" is specified)
168 -S = name the saved output reports by their linux device instead
169 of by the serial number of the disk.
170
171 Unless the -n option is specified the disk will first have its entire
172 set of blocks read, then, the entire disk will be cleared by writing
173 zeros to it. Once that is done the disk will be partitioned with a
174 special signature that the unRAID software will recognize when the
175 drive is added to the array. This special signature will allow the
176 unraid software to recognize the disk has been pre-cleared and to skip
177 an initial "clearing" step while the server remains off-line.
178
179 The pre-read and post-read phases try their best to exercise the
180 disk in a way to identify a drive prone to early failure. It performs
181 reads of random blocks of data interspersed with reads of sequential
182 blocks on the disk in turn. This program also uses non-buffered reads
183 of the first and last cylinders on the disk, the goal is to perform
184 those reads in between the others, and to keep the disk head
185 moving much more than if it just read each linear block in turn.
186EOF
187 exit 0
188}
189
190cp /dev/null /tmp/preclear_assigned_disks1
191
192list_d() {
193a=0
194
195# read the disk config file so we can tell what is assigned to the array
196exec </boot/config/disk.cfg
197while read config
198do
199 case $config in
200 diskSpinupGroup*|diskSpindownDelay*|diskSecurity*|diskExport*|diskRead*|diskWrite*)
201 continue
202 ;;
203 cacheSpinupGroup*|cacheSpindownDelay*|cacheSecurity*|cacheExport*|cacheRead*|cacheWrite*|*cacheExport*|cacheHost*)
204 continue
205 ;;
206 parity*|disk[0-9]*|cache*)
207 disk=`echo "$config" | sed "s/\([^=]*\)=\([^=]*\)/\1/"`
208 disks[$a]=$disk
209 id=`echo "$config" | sed -e "s/\([^=]*\)=\([^=]*\)/\2/" -e "s/\\r//" -e "s/\"//g"`
210 [ "$id" = "" ] && continue
211 # determine the disk device name
212 device=`ls --time-style='+%Y-%m-%d %I:%M%p' -ld /dev/disk/by-path/$id 2>/dev/null | awk '{ print substr($10,7,3) }'`
213 if [ "$device" = "" ]
214 then
215 device=`ls /sys/devices/$id/block 2>/dev/null`
216 if [ "$device" = "" ]
217 then
218 device=`ls --time-style='+%Y-%m-%d %I:%M%p' -ld /dev/disk/by-id/*$id* 2>/dev/null | sed 1q | awk '{ print substr($10,7,3) }'`
219 fi
220 fi
221 dev[$a]="$device"
222 echo "${device}|C|$config" >>/tmp/preclear_assigned_disks1
223 let a=a+1
224 ;;
225 esac
226done
227if [ -f /var/local/emhttp/disks.ini ]
228then
229exec </var/local/emhttp/disks.ini
230while read ini
231do
232 case $ini in
233 deviceSb*)
234 continue
235 ;;
236 device*)
237 device=`echo "$ini" | sed -e "s/\([^=]*\)=\([^=]*\)/\2/" -e "s/\\r//" -e "s/\"//g"`
238 echo "${device}|I|$ini" >>/tmp/preclear_assigned_disks1
239 dev[$a]="$device"
240 let a=a+1
241 esac
242done
243fi
244
245}
246
247# list the disks that are not assigned to the array. They are the possible drives to pre-clear
248list_device_names() {
249 echo "====================================$ver"
250 echo " Disks not assigned to the unRAID array "
251 echo " (potential candidates for clearing) "
252 echo "========================================"
253 rm /tmp/un_assigned_flag >/dev/null 2>&1
254 cp /dev/null /tmp/preclear_candidates 2>&1
255 list_d
256 ls --time-style='+%Y-%m-%d %I:%M%p' /dev/disk/by-id/* -l | grep -v -- "-part" | cut -c62- | while read a b disk
257 do
258 disk=`echo $disk | cut -c7-`
259 grep "${disk}|" /tmp/preclear_assigned_disks1 >/dev/null 2>&1
260 [ $? = 0 ] && continue
261 m=`mount | grep "/dev/$disk" 2>/dev/null`
262 [ $? = 0 ] && continue
263 grep "$disk" /tmp/preclear_candidates >/dev/null 2>&1
264 if [ $? = 1 ]
265 then
266 echo " /dev/$disk = $a"
267 fi
268 echo $disk >>/tmp/preclear_candidates
269 touch /tmp/un_assigned_flag
270 done
271 if [ ! -f /tmp/un_assigned_flag ]
272 then
273 echo "No un-assigned disks detected"
274 fi
275 rm /tmp/un_assigned_flag >/dev/null 2>&1
276}
277
278
279# Keep track of the elapsed time of the preread/clear/postread process
280timer()
281{
282 if [[ $# -eq 0 ]]; then
283 echo $(date '+%s')
284 else
285 local stime=$1
286 etime=$(date '+%s')
287
288 if [[ -z "$stime" ]]; then stime=$etime; fi
289
290 dt=$((etime - stime))
291 ds=$((dt % 60))
292 dm=$(((dt / 60) % 60))
293 dh=$((dt / 3600))
294 printf '%d:%02d:%02d' $dh $dm $ds
295 fi
296}
297short_test=0 # set to non-zero for short test for script testing - Leave 0 for normal test
298let cycle_count=1
299pre_read_flag=y
300post_read_flag=y
301test_only_flag=n
302partition_64=""
303use_mail=0
304mail_rcpt=""
305postread_error=""
306skip_postread_verify="no"
307read_bs=""
308write_bs=""
309read_blocks=""
310list_drives=""
311convert_type=""
312convert_flag=""
313device_type="-d ata"
314verify_only="n"
315write_flag="n"
316save_report="y"
317zero_mbr_only="n"
318post_read_err="N" #bjp999 4/9/11
319save_report_by_dev="no" # default is to save by model/serial num
320max_mbr_size="0xFFFFFFFF" # max size of MBR partition
321over_mbr_size="n"
322
323sb=1
324default="(partition starting on sector 63)"
325
326while getopts ":tnc:WM:m:hvDNw:r:b:AalC:VRDd:zsS" opt; do
327 case $opt in
328 n ) pre_read_flag=n;post_read_flag=n ;;
329 N ) skip_postread_verify="yes" ;;
330 t ) test_only_flag=y ;;
331 c ) cycle_count=$OPTARG ;;
332 C ) convert_flag=y; convert_type=$OPTARG ;;
333 M ) use_mail=$OPTARG ;;
334 m ) mail_rcpt=$OPTARG ;;
335 r ) read_bs=$OPTARG ;;
336 W ) write_flag="y"; pre_read_flag="n" ;;
337 d ) device_type="-d $OPTARG" ;;
338 D ) device_type="" ;;
339 A ) partition_64=y
340 default="(-A option elected, partition will start on sector 64)"
341 vdefault="(-A option elected. disk to be verified for partition starting on sector 64)"
342 ;;
343 a ) partition_64=n
344 default="(-a option elected, partition will start on sector 63)"
345 vdefault="(-a option elected. disk to be verified for partition starting on sector 63)"
346 ;;
347 l ) list_drives=y ;;
348 z ) zero_mbr_only=y ;;
349 R ) save_report=n ;;
350 S ) save_report_by_dev="yes" ;;
351 V ) pre_read_flag=n; verify_only=y ;;
352 b ) read_blocks=$OPTARG ;;
353 w ) write_bs=$OPTARG ;;
354 v ) echo $progname version: $ver;
355 exit 0
356 ;;
357 h ) usage >&2 ;;
358 s ) short_test=1 ;; # for debugging
359 \?) usage >&2 ;;
360 esac
361done
362
363# if partition_64 not specified, use the default from how unRAID is configured.
364# Look in the disk.cfg file.
365default_format=`grep defaultFormat /boot/config/disk.cfg | sed -e "s/\([^=]*\)=\([^=]*\)/\2/" -e "s/\\r//" -e 's/"//g' | tr -d '\n'`
366if [ "$default_format" != "" -a "$partition_64" = "" ]
367then
368 case "$default_format" in
369 1) partition_64=n
370 default="(MBR unaligned set. Partition will start on sector 63)"
371 vdefault="(MBR unaligned set. disk to be verified for partition starting on sector 63)"
372 ;;
373 2) partition_64=y
374 default="(MBR 4k-aligned set. Partition will start on sector 64)"
375 vdefault="(MBR 4k-aligned set. disk to be verified for partition starting on sector 64)"
376 ;;
377 3) partition_64=y
378 default="(GPT 4k-aligned set. Protective MBR Partition will start on sector 1)"
379 vdefault="(GPT 4k-aligned set. disk to be verified for protective MBR partition starting on sector 64)"
380 ;;
381 esac
382fi
383
384if [ "$partition_64" = "" ]
385then
386 partition_64="n"
387fi
388#exit
389
390
391shift $(($OPTIND - 1))
392
393if [ "$list_drives" = "y" ]
394then
395 if [ $# != 0 ]
396 then
397 echo "Error: The '-l' option may not be combined with other options" >&2
398 echo "usage: $0 -l" >&2
399 exit 2
400 fi
401 list_device_names
402 exit
403fi
404
405if [ "$verify_only" = "y" ]
406then
407 if [ "$write_flag" = "y" ]
408 then
409 echo "Error: -V option may not be combined with -W option" >&2
410 exit 2
411 fi
412 if [ "$post_read_flag" = "n" ]
413 then
414 echo "Error: -V option may not be combined with -n option" >&2
415 exit 2
416 fi
417 if [ "$skip_postread_verify" = "yes" ]
418 then
419 echo "Error: -V option may not be combined with -N option" >&2
420 exit 2
421 fi
422 if [ "$test_only_flag" = "yes" ]
423 then
424 echo "Error: -V option may not be combined with -t option" >&2
425 exit 2
426 fi
427 if [ "$convery_flag" = "y" ]
428 then
429 echo "Error: -V option may not be combined with -C option" >&2
430 exit 2
431 fi
432fi
433
434if [ "$zero_mbr_only" = "y" ]
435then
436 if [ "$verify_only" = "y" ]
437 then
438 echo "Error: -z option may not be combined with -V option" >&2
439 exit 2
440 fi
441 if [ "$write_flag" = "y" ]
442 then
443 echo "Error: -z option may not be combined with -W option" >&2
444 exit 2
445 fi
446 if [ "$post_read_flag" = "n" ]
447 then
448 echo "Error: -z option may not be combined with -n option" >&2
449 exit 2
450 fi
451 if [ "$skip_postread_verify" = "yes" ]
452 then
453 echo "Error: -z option may not be combined with -N option" >&2
454 exit 2
455 fi
456 if [ "$test_only_flag" = "yes" ]
457 then
458 echo "Error: -z option may not be combined with -t option" >&2
459 exit 2
460 fi
461 if [ "$convery_flag" = "y" ]
462 then
463 echo "Error: -z option may not be combined with -C option" >&2
464 exit 2
465 fi
466fi
467
468if [ $# != 1 ]
469then
470 usage >&2
471 exit 2
472fi
473
474expand_number() {
475 echo "$1" | sed -e 's/\([0-9]*\)[mM]$/\1000000/' -e 's/\([0-9]*\)[kK]$/\1000/'
476}
477
478write_bs=`expand_number $write_bs`
479# validate the write block size
480cc="$(echo $write_bs | sed 's/[0-9]//g')"
481if [ ! -z "$cc" ]
482then
483 echo "error: write block size (-w NNN) must be numeric." >&2
484 usage >&2
485 exit 2
486fi
487
488read_bs=`expand_number $read_bs`
489# validate the read block size
490cc="$(echo $read_bs | sed 's/[0-9]//g')"
491if [ ! -z "$cc" ]
492then
493 echo "error: read block size (-r NNN) must be numeric." >&2
494 usage >&2
495 exit 2
496fi
497
498read_blocks=`expand_number $read_blocks`
499# validate the number of blocks to read per pass
500cc="$(echo $read_blocks | sed 's/[0-9]//g')"
501if [ ! -z "$cc" ]
502then
503 echo "error: Block count (-b NNN) must be numeric." >&2
504 usage >&2
505 exit 2
506fi
507
508# validate the cycle count
509cc="$(echo $cycle_count | sed 's/[0-9]//g')"
510if [ ! -z "$cc" ]
511then
512 echo "error: Cycle count must be numeric." >&2
513 usage >&2
514 exit 2
515fi
516if [ $cycle_count -lt 1 ]
517then
518 echo "error: Cycle count must be greater than 0." >&2
519 usage >&2
520 exit 2
521fi
522if [ $cycle_count -gt 20 ]
523then
524 echo "error: Cycle count may not be greater than 20." >&2
525 usage >&2
526 exit 2
527fi
528
529if [ "$test_only_flag" = "y" ]
530then
531 if [ "$cycle_count" != "1" -o $pre_read_flag = "n" ]
532 then
533 echo "error: -t option may not be combined with other options." >&2
534 usage >&2
535 exit 2
536 fi
537fi
538
539if [ "$convert_flag" = "y" ]
540then
541 if [ "$convert_type" != "63" -a "$convert_type" != 64 ]
542 then
543 echo "error: -C option must supply starting sector (63, or 64)." >&2
544 echo "example: -C 64" >&2
545 echo "or -C 63" >&2
546 exit 2
547 fi
548fi
549
550um="$(echo $use_mail | sed 's/[0-9]//g')"
551if [ ! -z "$um" ]
552then
553 echo "error: -M parameter must be numeric." >&2
554 usage >&2
555 exit 2
556fi
557
558if [ $use_mail -gt 4 ]
559then
560 echo "error: -M parameter may not be greater than 4." >&2
561 usage >&2
562 exit 2
563fi
564
565# Check to see if Mail exists if m or M parameter is used.
566if [ $use_mail -gt 0 ] || [ ! -z $mail_rcpt ]
567 then
568 no_mail=`which mail 2>&1 | awk '{print $2}'`
569 if [ "$no_mail" = "no" ]
570 then
571 echo "error: \"mail\" program does not exist." >&2
572 usage >&2
573 exit 2
574 fi
575fi
576
577if [ $use_mail -gt 0 -a -z "$mail_rcpt" ]
578then
579 mail_rcpt="root" #recipient was not specified, send to root.
580fi
581
582if [ ! -z "$mail_rcpt" -a $use_mail -eq 0 ]
583then
584 use_mail=1
585fi
586
587theDisk=$1
588
589disk_basename=`basename $1`
590if [ -f "/tmp/postread_errors$disk_basename" ]
591then
592 rm "/tmp/postread_errors$disk_basename"
593fi
594
595disk_temperature() {
596 temp=`smartctl $device_type -A $theDisk | grep -i temperature | sed 1q | awk '{ print $10; }'`
597
598 if [ "$temp" != "" ]
599 then
600 if [ "$temp" -gt "40" ]
601 then
602 if [[ $# -eq 0 ]]
603 then
604 temp=${bold}$temp${norm}
605 else
606 temp="-->"$temp"<--" # Mail doesn't like bold. Use some alternate form to get attention...
607 fi
608 fi
609 echo -n "Disk Temperature: ${temp}C, "
610 else
611 echo -n ""
612 fi
613}
614
615display_progress() {
616dt=`disk_temperature`
617echo -n $clearscreen #$goto_top
618echo "================================================================== $ver"
619echo "= ${ul}unRAID server Pre-Clear disk $theDisk${noul}"
620echo "= cycle $bold$cc$norm of $cycle_count, partition start on sector $partition_start "
621echo "= $preread"
622echo "= $step1"
623echo "= $step2"
624echo "= $step3"
625echo "= $step4"
626echo "= $step5"
627echo "= $step6"
628echo "= $step7"
629echo "= $step8"
630echo "= $step9"
631echo "= $step10"
632echo -e "= $postread"
633echo "${dt}Elapsed Time: $(timer $tmr)"
634if [ "$2" != "" ]
635then
636 kill -0 $2 >/dev/null 2>&1 && kill -USR1 $2
637 sleep 1
638 tail -3 /tmp/zero$disk_basename
639 bytes_wrote=`tail -1 /tmp/zero$disk_basename | awk '{print $1}'`
640 bw_formatted=`format_number $bytes_wrote`
641 let bw=($bytes_wrote * 100)
642 let percent_wrote=($bw / $total_bytes)
643 nowtmr=$(timer)
644 if [ $bw -gt 0 ] && [ $nowtmr -ne $zerotmr ]
645 then
646 cal_read_speed=$(($bw / ($nowtmr - $zerotmr) / 1000000 / 100))
647 else
648 cal_read_speed=0
649 fi
650
651 if [ "$sb" != "1" ]
652 then
653 let tot_blocks=( $total_bytes / 2048000 )
654 let bytes_skipped=( 2048000 * $sb )
655 skb_formatted=`format_number $bytes_skipped`
656 let sk2=( $bytes_skipped * 100 )
657 let percent_skipped=($sk2 / $total_bytes)
658 echo "Skipping $skb_formatted bytes $sb*2048k ($percent_skipped%)"
659 let percent_wrote=($percent_wrote + $percent_skipped)
660 fi
661 echo "Wrote $bw_formatted bytes out of $tb_formatted bytes ($percent_wrote% Done) "
662
663 if [ $use_mail -eq 4 ]
664 then
665 if [ $percent_wrote -ge $report_percentage ]
666 then
667 let report_percentage=($report_percentage + 25)
668 report_out="Zeroing Disk $theDisk in progress: ${percent_wrote}% complete. \\n"
669 report_out+="( ${bw_formatted} of $tb_formatted bytes Wrote )\\n"
670 report_out+="`disk_temperature 1`\\n "
671 report_out+="Next report at $report_percentage%\\n"
672 report_out+="Calculated Write Speed: $cal_read_speed MB/s \\n"
673 report_out+="Elapsed Time of current cycle: $(timer $zerotmr)\\n"
674 report_out+="Total Elapsed time: $(timer $tmr)"
675
676 echo -e "$report_out" | mail -s "Preclear: Zeroing Disk $disk_basename in Progress ${percent_wrote}% complete cycle $cc of $cycle_count" $mail_rcpt
677 fi
678 fi
679
680 #bjp999 4/9/11
681 echo "$disk_basename|NN|Zeroing$cycle_disp. ${percent_wrote}% @ $cal_read_speed MB/s ($(timer $tmr))" > /tmp/preclear_stat_$disk_basename
682fi
683
684sleep $1
685}
686
687get_start_smart() {
688 # just in case, enable SMART monitoring
689 d=`basename $1`
690 smartctl -s on $1 >/dev/null 2>&1
691 echo "Disk: $1" >/tmp/smart_start_$d
692 #smartctl -d ata -a $1 2>&1 | egrep -v "Power_On_Minutes|Temperature_Celsius" >>/tmp/smart_start_$d
693 smartctl $device_type -a $1 2>&1 >>/tmp/smart_start_$d
694 cp /tmp/smart_start_$d /var/log/
695}
696
697get_finish_smart() {
698 d=`basename $1`
699 echo "Disk: $1" >/tmp/smart_finish_$d
700 #smartctl -d ata -a $1 2>&1 | egrep -v "Power_On_Minutes|Temperature_Celsius" >>/tmp/smart_finish_$d
701 smartctl $device_type -a $1 2>&1 >>/tmp/smart_finish_$d
702 cp /tmp/smart_finish_$d /var/log/
703}
704
705get_mid_smart() {
706 d=`basename $1`
707 echo "Disk: $1" >/tmp/smart_mid_${2}_$d
708 #smartctl -d ata -a $1 2>&1 | egrep -v "Power_On_Minutes|Temperature_Celsius" >>/tmp/smart_mid_${2}_$d
709 smartctl $device_type -a $1 2>&1 >>/tmp/smart_mid_${2}_$d
710 cp /tmp/smart_mid_${2}_$d /var/log/
711}
712
713read_mbr() {
714 # verify MBR boot area is clear
715 out1=`dd bs=446 count=1 if=$theDisk 2>/dev/null |sum|awk '{print $1}'`
716 # verify partitions 2,3, & 4 are cleared
717 out2=`dd bs=1 skip=462 count=48 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
718 # verify partition type byte is clear
719 out3=`dd bs=1 skip=450 count=1 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
720 # verify MBR signature bytes are set as expected
721 out4=`dd bs=1 count=1 skip=511 if=$theDisk 2>/dev/null |sum|awk '{print $1}'`
722 out5=`dd bs=1 count=1 skip=510 if=$theDisk 2>/dev/null |sum|awk '{print $1}'`
723
724 # read bytes to verify partition 1 is set as expected.
725 byte1=`dd bs=1 count=1 skip=446 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
726 byte2=`dd bs=1 count=1 skip=447 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
727 byte3=`dd bs=1 count=1 skip=448 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
728 byte4=`dd bs=1 count=1 skip=449 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
729
730 byte5=`dd bs=1 count=1 skip=450 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
731 byte6=`dd bs=1 count=1 skip=451 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
732 byte7=`dd bs=1 count=1 skip=452 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
733 byte8=`dd bs=1 count=1 skip=453 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
734
735 byte9=`dd bs=1 count=1 skip=454 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
736 byte10=`dd bs=1 count=1 skip=455 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
737 byte11=`dd bs=1 count=1 skip=456 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
738 byte12=`dd bs=1 count=1 skip=457 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
739
740 byte13=`dd bs=1 count=1 skip=458 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
741 byte14=`dd bs=1 count=1 skip=459 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
742 byte15=`dd bs=1 count=1 skip=460 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
743 byte16=`dd bs=1 count=1 skip=461 if=$theDisk 2>/dev/null|sum|awk '{print $1}'`
744
745}
746
747# add commas to a numeric argument for better readability
748# yes, it is a "sed" script with a loop and a "goto"
749# Found on the web, I did not write it myself. Original author unknown.
750format_number() {
751 echo " $1 " | sed -r ':L;s=\b([0-9]+)([0-9]{3})\b=\1,\2=g;t L'
752}
753
754analyze_for_errors() {
755 err=""
756 if [ "$2" = "" ]
757 then
758 sm_err=`analyze_smart $1`
759 else
760 post_err=`analyze_smart $1 $2`
761 sm_err="$post_err"
762 fi
763
764 echo -e "$sm_err"
765}
766
767get_attr() {
768 attribute_name=$1
769
770 case $2 in
771 old*) file=$3 ;;
772 new*) file=$4 ;;
773 esac
774
775 case $2 in
776 *val) col=3 ;;
777 *thresh) col=5 ;;
778 *status) col=8;;
779 *raw) col=9;;
780 esac
781 sed "s/\([0-9]\) /\1-/" <$file | grep $attribute_name | sed 1q | awk '{print $'$col'}' | sed "s/^0\(.\)/\1/" | sed "s/^0\(.\)/\1/"
782}
783
784analyze_smart() {
785 err=""
786 attribute_changed=""
787 chg_attr=""
788
789 if [ "$#" = 2 ]
790 then
791 # look for changes in attributes.
792 #First, get a list of the attributes, then for each list changes in an easy to read format.
793 attributes=`cat $1 | sed -n "/ATTRIBUTE_NAME/,/^$/p" | grep -v "ATTRIBUTE_NAME" | grep -v "^$" | awk '{ print $1 "-" $2}'`
794 chg_attr=`printf "%25s %-7s %-7s %16s %-11s %9s" "ATTRIBUTE" "NEW_VAL" "OLD_VAL" "FAILURE_THRESHOLD" "STATUS" "RAW_VALUE"`"\n"
795 for i in $attributes
796 do
797 oldv=`get_attr $i old_val $1 $2`
798 newv=`get_attr $i new_val $1 $2`
799 let near=$newv-25 2>/dev/null
800 newr=`get_attr $i new_raw $1 $2`
801 oldr=`get_attr $i old_raw $1 $2`
802 fthresh=`get_attr $i new_thresh $1 $2`
803 stat=`get_attr $i new_status $1 $2`
804 #echo "$i oldv=$oldv newv=$newv near=$near newr=$newr oldr=$oldr fthresh=$fthresh stat=$stat"
805 case "$i" in
806 Current_Pending_Sector|Reallocated_Sector_Ct|Reallocated_Event_Count)
807 if [ "$oldr" != "$newr" ]
808 then
809 l=`printf "%25s = %3s %3s %3s %-11s %s" $i $newv $oldv $fthresh $stat $newr`
810 chg_attr="${chg_attr}${l}\n"
811 attribute_changed="yes"
812 continue;
813 fi
814 ;;
815 esac
816 [ "$oldv" = "253" ] && [ "$newv" = "200" -o "$newv" = "100" -o "$newv" = "253" ] && continue
817 [ "$near" -le "$fthresh" -a "$stat" = "-" ] && stat="near_thresh"
818 [ "$stat" = "-" -o "$stat" = "" ] && stat="ok"
819 [ "$stat" = "ok" ] && [ "$oldv" = "$newv" ] && continue # not failing, and unchanged
820 [ "$stat" = "ok" ] && [ "$oldv" = "100" -a "$newv" = "200" ] && continue # initialized to start value
821 attribute_name="${i#*-}"
822 l=`printf "%25s = %3s %3s %3s %-11s %s" $attribute_name $newv $oldv $fthresh $stat $newr`
823 chg_attr="${chg_attr}${l}\n"
824 attribute_changed="yes"
825 done
826 fi
827
828 if [ "$attribute_changed" = "yes" ]
829 then
830 err="${err}** Changed attributes in files: $1 $2\n$chg_attr"
831 fi
832
833 if [ "$#" = 1 ]
834 then
835 smart_file=$1
836 else
837 smart_file=$2
838 fi
839 # next, check for individual attributes that have failed.
840 failed_attributes=`grep 'FAILING_NOW' $smart_file| grep -v "No SMART attributes"`
841 if [ "$failed_attributes" != "" ]
842 then
843 err="${err}\n*** Failing SMART Attributes in $smart_file *** \n"
844 err="${err}ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n"
845 err="$err$failed_attributes\n\n"
846 else
847 err="$err No SMART attributes are FAILING_NOW\n\n"
848 fi
849
850
851 if [ "$#" = 1 ]
852 then
853 # next, look for sectors pending re-allocation
854 pending_sectors=`get_attr "Current_Pending_Sector" old_raw $1`
855 if [ "$pending_sectors" != "" ]
856 then
857 err="$err $pending_sectors sectors are pending re-allocation.\n"
858 fi
859
860 # look for re-allocated sectors
861 reallocated_sectors=`get_attr "Reallocated_Sector_Ct" old_raw $1`
862 if [ "$reallocated_sectors" != "" ]
863 then
864 err="$err $reallocated_sectors sectors had been re-allocated.\n"
865 fi
866 else
867 # next, look for sectors pending re-allocation
868 o_pending_sectors=`get_attr "Current_Pending_Sector" old_raw $1`
869 if [ "$o_pending_sectors" != "" ]
870 then
871 if [ "$o_pending_sectors" = "1" ]
872 then
873 err="$err $o_pending_sectors sector was pending re-allocation before the start of the preclear.\n"
874 else
875 err="$err $o_pending_sectors sectors were pending re-allocation before the start of the preclear.\n"
876 fi
877 fi
878 if [ -f /tmp/smart_mid_pending_reallocate_$d ]
879 then
880 err="$err`cat /tmp/smart_mid_pending_reallocate_$d`\n"
881 fi
882 n_pending_sectors=`get_attr "Current_Pending_Sector" new_raw $1 $2`
883 if [ "$n_pending_sectors" != "" ]
884 then
885 if [ "$n_pending_sectors" = "1" ]
886 then
887 err="$err $n_pending_sectors sector is pending re-allocation at the end of the preclear,\n"
888 else
889 err="$err $n_pending_sectors sectors are pending re-allocation at the end of the preclear,\n"
890 fi
891 fi
892 if [ "$o_pending_sectors" != "$n_pending_sectors" ]
893 then
894 let chg=$n_pending_sectors-$o_pending_sectors
895 err="$err a change of $chg in the number of sectors pending re-allocation.\n"
896 else
897 err="$err the number of sectors pending re-allocation did not change.\n"
898 fi
899
900 # look for re-allocated sectors
901 o_reallocated_sectors=`get_attr "Reallocated_Sector_Ct" old_raw $1 $2`
902 if [ "$o_reallocated_sectors" != "" ]
903 then
904 if [ "$o_reallocated_sectors" = "1" ]
905 then
906 err="$err $o_reallocated_sectors sector had been re-allocated before the start of the preclear.\n"
907 else
908 err="$err $o_reallocated_sectors sectors had been re-allocated before the start of the preclear.\n"
909 fi
910 fi
911 n_reallocated_sectors=`get_attr "Reallocated_Sector_Ct" new_raw $1 $2`
912 if [ "$n_reallocated_sectors" != "" ]
913 then
914 if [ "$n_reallocated_sectors" = "1" ]
915 then
916 err="$err $n_reallocated_sectors sector is re-allocated at the end of the preclear,\n"
917 else
918 err="$err $n_reallocated_sectors sectors are re-allocated at the end of the preclear,\n"
919 fi
920 fi
921 if [ "$o_reallocated_sectors" != "$n_reallocated_sectors" ]
922 then
923 let r_chg=$n_reallocated_sectors-$o_reallocated_sectors
924 err="$err a change of $r_chg in the number of sectors re-allocated.\n"
925 else
926 err="$err the number of sectors re-allocated did not change.\n"
927 fi
928 fi
929
930 # last, check overall health
931 overall_state=`grep 'SMART overall-health self-assessment test result:' $smart_file | cut -d":" -f2`
932 if [ "$overall_state" != " PASSED" ]
933 then
934 err="$err SMART overall-health status = ${overall_state}\n"
935 fi
936
937 echo -e "$err\n"
938}
939
940read_entire_disk( ) {
941 # Get the disk geometry (cylinders, heads, sectors)
942 fgeometry=`fdisk -l $1 2>/dev/null`
943 units=`echo "$fgeometry" | grep Units | awk '{ print $9 }'`
944 tu=$units
945 while [ "$units" -lt 1000000 ]
946 do
947 let units=$units+$tu
948 done
949 if [ "$read_bs" != "" ]
950 then
951 units=$read_bs
952 fi
953
954 if [ $short_test -eq 0 ]
955 then
956 total_bytes=`echo "$fgeometry" | grep "Disk $1" | awk '{ print $5 }'`
957 else
958 actual_bytes=`echo "$fgeometry" | grep "Disk $1" | awk '{ print $5 }'`
959 total_bytes=1000000000 #Debug case.. Set total size to ~1GB disk to speed up test
960 if [ "$actual_bytes" -lt "$total_bytes" ]
961 then
962 let total_bytes=( $actual_bytes / 10 )
963 fi
964 fi
965 tb_formatted=`format_number $total_bytes`
966 let blocks=($total_bytes / $units)
967 let last_block=($blocks - 1)
968 skip=0
969 if [ "$read_blocks" != "" ]
970 then
971 bcount=$read_blocks
972 else
973 bcount=200 # count of blocks to read each time through the loop linearly
974 fi
975 end_of_disk="n"
976 report_percentage=25
977 read_speed=""
978 echo "" >/tmp/read_speed$disk_basename
979
980 while true
981 do
982 read_speed=`cat /tmp/read_speed$disk_basename 2>/dev/null`
983 if [ "$2" = "postread" ]
984 then
985 let bytes_read=($skip * $units)
986 let br=($bytes_read * 100)
987 let percent_read=(${br} / $total_bytes)
988 tb_read=`format_number $bytes_read`
989 postread="${bold}Post-Read in progress: ${percent_read}% complete. $norm \\n( $tb_read of $tb_formatted bytes read ) $read_speed"
990 nowtmr=$(timer)
991 if [ $br -gt 0 ] && [ $nowtmr -ne $posttmr ]
992 then
993 cal_read_speed=$(($br / ($nowtmr - $posttmr) / 1000000 / 100))
994 else
995 cal_read_speed=0
996 fi
997 if [ $use_mail -ge 3 ] && [ $percent_read -eq 0 ] && [ $br -eq 0 ]
998 then
999 report_out="Post Read Started on $theDisk ${percent_read}% complete. \\n"
1000 report_out+="( `format_number ${bytes_read}` of $tb_formatted bytes read ) \\n"
1001 report_out+="`disk_temperature 1`\\n"
1002 report_out+="Using Block size of `format_number $units` Bytes\\n "
1003 report_out+="Next report at $report_percentage%"
1004
1005 echo -e "$report_out" | mail -s "Preclear: Post Read Started on $disk_basename. Cycle $cc of $cycle_count" $mail_rcpt
1006 fi
1007
1008 if [ $use_mail -eq 4 ]
1009 then
1010 if [ $percent_read -ge $report_percentage ]
1011 then
1012 let report_percentage=($report_percentage + 25)
1013 report_out="Post Read in progress on $theDisk: ${percent_read}% complete. \\n"
1014 report_out+="( `format_number ${bytes_read}` of $tb_formatted bytes read )at ${read_speed}\\n"
1015 report_out+=" `disk_temperature 1` \\n "
1016 report_out+="Using Block size of `format_number $units` Bytes\\n "
1017 report_out+="Next report at $report_percentage% \\n"
1018 report_out+="Calculated Read Speed: $cal_read_speed MB/s \\n"
1019 report_out+="Elapsed Time of current cycle: $(timer $posttmr)\\n"
1020 report_out+="Total Elapsed time: $(timer $tmr)"
1021
1022 echo -e "$report_out" | mail -s "Preclear: Post Read in Progress on $disk_basename ${percent_read}% complete ($read_speed) cycle $cc of $cycle_count" $mail_rcpt
1023 fi
1024 fi
1025 #bjp999 4/9/11
1026 echo "$disk_basename|N" post_read_err "|Post-Read$cycle_disp. ${percent_read}% @ $cal_read_speed MB/s ($(timer $tmr))" > /tmp/preclear_stat_$disk_basename
1027 fi
1028
1029 if [ "$2" = "preread" ]
1030 then
1031 let bytes_read=($skip * $units)
1032 let br=($bytes_read * 100)
1033 let percent_read=(${br} / $total_bytes)
1034 bytes_read=`format_number $bytes_read`
1035 preread="${bold}Disk Pre-Read in progress: ${percent_read}% complete${norm}"
1036 step1="(${bytes_read} bytes of $tb_formatted read ) $read_speed"
1037 nowtmr=$(timer)
1038 if [ $br -gt 0 ] && [ $nowtmr -ne $pretmr ]
1039 then
1040 cal_read_speed=$(($br / ($nowtmr - $pretmr) / 1000000 / 100))
1041 else
1042 cal_read_speed=0
1043 fi
1044 if [ $use_mail -ge 3 ] && [ $percent_read -eq 0 ] && [ $br -eq 0 ]
1045 then
1046 report_out="Pre Read Started on $theDisk ${percent_read}% complete. \\n"
1047 report_out+="( ${bytes_read} of $tb_formatted bytes read ) \\n"
1048 report_out+="`disk_temperature 1`\\n"
1049 report_out+="Using Block size of `format_number $units` Bytes\\n "
1050 report_out+="Next report at $report_percentage%"
1051
1052 echo -e "$report_out" | mail -s "Preclear: Pre Read Started on $disk_basename. Cycle $cc of $cycle_count " $mail_rcpt
1053 fi
1054
1055 if [ $use_mail -eq 4 ]
1056 then
1057 if [ $percent_read -ge $report_percentage ]
1058 then
1059 let report_percentage=($report_percentage + 25)
1060 report_out="Pre Read in progress on $theDisk: ${percent_read}% complete. \\n"
1061 report_out+="( ${bytes_read} of $tb_formatted bytes read )at ${read_speed}\\n"
1062 report_out+=" `disk_temperature 1` \\n "
1063 report_out+="Using Block size of `format_number $units` Bytes\\n "
1064 report_out+="Next report at $report_percentage% \\n"
1065 report_out+="Calculated Read Speed: $cal_read_speed MB/s \\n"
1066 report_out+="Elapsed Time of current cycle: $(timer $pretmr)\\n"
1067 report_out+="Total Elapsed time: $(timer $tmr)"
1068
1069 echo -e "$report_out" | mail -s "Preclear: Pre Read in Progress on $disk_basename ${percent_read}% complete ($read_speed) cycle $cc of $cycle_count" $mail_rcpt
1070 fi
1071 fi
1072 #bjp999 4/9/11
1073 echo "$disk_basename|NN|Pre-Read$cycle_disp. ${percent_read}% @ $cal_read_speed MB/s ($(timer $tmr))" > /tmp/preclear_stat_$disk_basename
1074 fi
1075
1076 if [ "$3" = "display_progress" ]
1077 then
1078 display_progress 0
1079 fi
1080
1081 # Torture the disk, by reading random blocks from all over
1082 # calculate three (random) block numbers to be read somewhere
1083 # between block 1 and the max blocks on the drive, the goal is to shake the drive to an early
1084 # death if it has any mechanical issues, before it is holding data in our unRAID array.
1085 skip_b=$(( 0+(`head -c4 /dev/urandom| od -An -tu4`)%($blocks) ))
1086 skip_b2=$(( 0+(`head -c4 /dev/urandom| od -An -tu4`)%($blocks) ))
1087 skip_b3=$(( 0+(`head -c4 /dev/urandom| od -An -tu4`)%($blocks) ))
1088
1089 # Dont read past the end of the disk. (Some disks do not like it at all)
1090 let last_block_read=($skip + $bcount - 1)
1091 if [ $last_block_read -gt $blocks ]
1092 then
1093 let skip=($blocks - $bcount)
1094 end_of_disk="y"
1095 fi
1096
1097 ( # start of a subshell to work around 4096 "wait" bug in shell
1098
1099 # read three random blocks from the disk and two fixed blocks. We use a random
1100 # blocks to try to ensure they are not in the cache memory
1101 # and to get the disk head moving randomly on the disk.
1102 #
1103 # the two fixed blocks are "direct" read, bypassing the buffer cache. They are the first
1104 # and last cylinder on the disk.
1105
1106 # read a random block.
1107 dd if=$1 of=/dev/null count=1 bs=$units skip=$skip_b >/dev/null 2>&1 &
1108 rb1=$!
1109
1110 # read the first block here, bypassing the buffer cache by use of iflag=direct
1111 dd if=$1 of=/dev/null count=1 bs=$units iflag=direct >/dev/null 2>&1 &
1112 rb2=$!
1113
1114 # read a random block.
1115 dd if=$1 of=/dev/null count=1 bs=$units skip=$skip_b2 >/dev/null 2>&1 &
1116 rb3=$!
1117
1118 # read the last block here, bypassing the buffer cache by use of iflag=direct
1119 dd if=$1 of=/dev/null count=1 bs=$units skip=$last_block iflag=direct >/dev/null 2>&1 &
1120 rb4=$!
1121
1122 # read a random block.
1123 dd if=$1 of=/dev/null count=1 bs=$units skip=$skip_b3 >/dev/null 2>&1 &
1124 rb5=$!
1125
1126
1127 # Now, also read the blocks linearly, from start to end, $bcount cylinders at a time.
1128 read_speed=`dd if=$1 bs=$units of=/dev/null count=$bcount skip=$skip conv=noerror 2>&1| sed -n 3p | awk '{ print $8,$9 }'`
1129 echo $read_speed >/tmp/read_speed$disk_basename
1130 if [ "$2" = "postread" -a "$skip_postread_verify" = "no" ]
1131 then
1132 # first block must be treated differently
1133 if [ "$skip" != "0" ]
1134 then
1135 # verify all zeros... complain if not. This read should be fast, as blocks should be in cache from prior read.
1136 rsum=`dd if=$1 bs=$units count=$bcount skip=$skip conv=noerror 2>/dev/null|sum| awk '{print $1}'`
1137 if [ "$rsum" != "00000" ]
1138 then
1139 echo "skip=$skip count=$bcount bs=$units returned $rsum instead of 00000" >>/tmp/postread_errors$disk_basename
1140 post_read_err = "Y" #bjp999 4/9/11
1141 fi
1142 else
1143 rsum=`dd if=$1 bs=512 count=8192 skip=1 conv=noerror 2>/dev/null|sum| awk '{print $1}'`
1144 if [ "$rsum" != "00000" ]
1145 then
1146 echo "skip=0 bs=512 count=8192 returned $rsum instead of 00000" >>/tmp/postread_errors$disk_basename
1147 post_read_err = "Y" #bjp999 4/9/11
1148 fi
1149 fi
1150 fi
1151
1152 kill -0 $rb1 2>/dev/null && wait $rb1 # make sure the background random blocks are read before continuing
1153 kill -0 $rb2 2>/dev/null && wait $rb2 # make sure the background random blocks are read before continuing
1154 kill -0 $rb3 2>/dev/null && wait $rb3 # make sure the background random blocks are read before continuing
1155 kill -0 $rb4 2>/dev/null && wait $rb4 # make sure the background random blocks are read before continuing
1156 kill -0 $rb5 2>/dev/null && wait $rb5 # make sure the background random blocks are read before continuing
1157
1158 ) # end of the subshell to work around the 4096 "wait" bug in bash 3.2
1159
1160 if [ "$end_of_disk" = "y" ]
1161 then
1162 break
1163 fi
1164
1165 let skip=($skip + $bcount)
1166
1167 done
1168
1169 if [ "$2" = "postread" ]
1170 then
1171 dposttmr=$(timer $posttmr) #calculate post read cycle time
1172 postdonetmr=$(timer)
1173 cal_post_read_speed=$(($br / ($postdonetmr - $posttmr) / 1000000 / 100))
1174 postread="Disk Post-Clear-Read completed ${bold}DONE${norm}"
1175 if [ $use_mail -ge 3 ]
1176 then
1177 report_out="Post Read finished on $theDisk \\n"
1178 report_out+="( ${tb_read} of $tb_formatted bytes read )\\n"
1179 report_out+="Post Read Elapsed Time: $dposttmr \\n"
1180 report_out+="Total Elapsed Time: $(timer $tmr)\\n"
1181 report_out+="`disk_temperature 1`\\n"
1182 report_out+="Using Block size of `format_number $units` Bytes\\n "
1183 report_out+="Calculated Read Speed - $cal_post_read_speed MB/s"
1184
1185 echo -e "$report_out" | mail -s "Preclear: Post Read finished on $disk_basename. Cycle $cc of $cycle_count" $mail_rcpt
1186 fi
1187 fi
1188 if [ "$2" = "preread" ]
1189 then
1190 dpretmr=$(timer $pretmr) #Calculate Pre-read cycle time
1191 predonetmr=$(timer)
1192 preread="Disk Pre-Clear-Read completed ${bold}DONE${norm}"
1193 cal_pre_read_speed=$(($br / ($predonetmr - $pretmr) / 1000000 / 100))
1194 step1=""
1195 if [ $use_mail -ge 3 ]
1196 then
1197 report_out="Pre Read finished on $theDisk \\n"
1198 report_out+="( `format_number ${bytes_read}` of $tb_formatted bytes read) \\n "
1199 report_out+="Pre Read Elapsed Time: $dpretmr \\n"
1200 report_out+="Total Elapsed Time: $(timer $tmr)\\n"
1201 report_out+="`disk_temperature 1`\\n"
1202 report_out+="Using Block size of `format_number $units` Bytes\\n "
1203 report_out+="Calculated Read Speed - $cal_pre_read_speed MB/s"
1204
1205 echo -e "$report_out" | mail -s "Preclear: Pre Read finished on $disk_basename. Cycle $cc of $cycle_count" $mail_rcpt
1206 fi
1207 fi
1208 if [ "$3" = "display_progress" ]
1209 then
1210 display_progress 0
1211 fi
1212}
1213
1214if [ -x /usr/bin/tput ]
1215then
1216 clearscreen=`tput clear`
1217 goto_top=`tput cup 0 1`
1218 screen_line_three=`tput cup 3 1`
1219 bold=`tput smso`
1220 norm=`tput rmso`
1221 ul=`tput smul`
1222 noul=`tput rmul`
1223else
1224 clearscreen=`echo -n -e "\033[H\033[2J"`
1225 goto_top=`echo -n -e "\033[1;2H"`
1226 screen_line_three=`echo -n -e "\033[4;2H"`
1227 bold=`echo -n -e "\033[7m"`
1228 norm=`echo -n -e "\033[27m"`
1229 ul=`echo -n -e "\033[4m"`
1230 noul=`echo -n -e "\033[24m"`
1231fi
1232
1233#----------------------------------------------------------------------------------
1234# Verify the disk is a block device
1235#----------------------------------------------------------------------------------
1236if [ ! -b $theDisk ]
1237then
1238 echo $clearscreen$screen_line_three
1239 echo "Sorry: $theDisk does not exist as a block device"
1240 echo "Clearing will NOT be performed"
1241 exit 2
1242fi
1243
1244# read the disk config file to see if the disk is assigned to the array, just in case this
1245# command is run with the array stopped.
1246exec </boot/config/disk.cfg
1247#cat /boot/config/disk.cfg | while read config
1248while read config
1249do
1250 device=""
1251 case $config in
1252 diskSpinupGroup*|diskSpindownDelay*|diskSecurity*|diskExport*|diskRead*|diskWrite*)
1253 continue;
1254 ;;
1255 parity*|disk[0-9]*|cache*)
1256 disk=`echo "$config" | sed "s/\([^=]*\)=\([^=]*\)/\1/"`
1257 disks[$a]=$disk
1258 id=`echo "$config" | sed -e "s/\([^=]*\)=\([^=]*\)/\2/" -e "s/\\r//"`
1259 device=`ls --time-style='+%Y-%m-%d %I:%M%p' -ld /dev/disk/by-path/$id 2>/dev/null | awk '{ print substr($10,7,3) }'`
1260 if [ "$device" = "" ]
1261 then
1262 device=`ls /sys/devices/$id/block 2>/dev/null`
1263 if [ "$device" = "" ]
1264 then
1265 device=`ls --time-style='+%Y-%m-%d %I:%M%p' -ld /dev/disk/by-id/*$id* 2>/dev/null | sed 1q | awk '{ print substr($10,7,3) }'`
1266 fi
1267 fi
1268 ;;
1269 esac
1270 device=/dev/$device
1271 if [ "$theDisk" = "$device" ]
1272 then
1273 echo $clearscreen$screen_line_three
1274 echo "Sorry, $theDisk is already assigned as part of the unRAID array."
1275 echo "Clearing will NOT be performed"
1276 exit 2
1277 fi
1278done
1279exec </dev/tty
1280
1281#----------------------------------------------------------------------------------
1282# First, do some basic tests to ensure the disk is not part of the arrray
1283# and not mounted, and not in use in any way.
1284#----------------------------------------------------------------------------------
1285devices=`/root/mdcmd status | strings | grep rdevName | sed 's/\([^=]*\)=\([^=]\)/\/dev\/\2/'`
1286
1287echo $devices | grep $theDisk >/dev/null 2>&1
1288if [ $? = 0 ]
1289then
1290 echo $clearscreen$screen_line_three
1291 echo "Sorry, but $theDisk is already assigned as part of the unRAID array."
1292 echo "Clearing will NOT be performed"
1293 exit 2
1294fi
1295
1296#----------------------------------------------------------------------------------
1297#Check to see if the disk is mounted, this should detect the cache drive and the boot drive.
1298#----------------------------------------------------------------------------------
1299m=`mount | grep $theDisk 2>/dev/null`
1300if [ $? = 0 ]
1301then
1302 echo $clearscreen$screen_line_three
1303 echo "Sorry, but $theDisk is currently mounted and in use:"
1304 echo "$m"
1305 echo "Clearing will NOT be performed"
1306 exit 2
1307fi
1308
1309
1310#----------------------------------------------------------------------------------
1311# first verify the device is not busy
1312#----------------------------------------------------------------------------------
1313sfdisk -R $theDisk
1314ret=$?
1315if [ $ret != 0 ]
1316then
1317 #If device is busy, exit here.
1318 echo "Sorry: Device $theDisk is busy.: $ret"
1319 exit 2
1320fi
1321
1322#----------------------------------------------------------------------------------
1323# Is the disk responding at all?
1324#----------------------------------------------------------------------------------
1325fgeometry=`fdisk -l $theDisk 2>/dev/null`
1326if [ "$fgeometry" = "" ]
1327then
1328 echo "Sorry: Device $theDisk is not responding to an fdisk -l $theDisk command."
1329 echo "You might try power-cycling it to see if it will start responding."
1330 exit 2
1331fi
1332
1333# get the disk size to determine if a GPT partition will be used by unRAID
1334disk_blocks=`blockdev --getsz $theDisk | awk '{ print $1 }'`
1335max_mbr_blocks=`printf "%d" $max_mbr_size`
1336if [ $disk_blocks -ge $max_mbr_blocks ]
1337then
1338 over_mbr_size="y"
1339fi
1340
1341#----------------------------------------------------------------------------------
1342# Get the disk geometry (cylinders, heads, sectors)
1343#----------------------------------------------------------------------------------
1344#geometry=`sfdisk -g $theDisk | grep sectors`
1345#num_cylinders=`echo "$geometry" | awk '{ print $2 }'`
1346#num_heads=`echo "$geometry" | awk '{ print $4 }'`
1347if [ "$partition_64" = "y" ]
1348then
1349 num_sectors=64
1350else
1351 #num_sectors=`echo "$geometry" | awk '{ print $6 }'`
1352 num_sectors=63
1353fi
1354
1355#----------------------------------------------------------------------------------
1356# Calculate the partition size we will create and where we will start it.
1357# unRAID starts its first partition on a full cylinder. To be recognized as zeroed,
1358# we need to create an initial partition the same way.
1359#----------------------------------------------------------------------------------
1360full_size=`blockdev --getsz $theDisk | awk '{ print $1 }'`
1361let partition_size=($full_size - $num_sectors)
1362partition_start=$num_sectors
1363#echo SIZE $partition_size
1364#echo START $partition_start
1365size1=0
1366size2=0
1367if [ "$over_mbr_size" = "y" ]
1368then
1369 size1=`printf "%d" "0x00020000"`
1370 size2=`printf "%d" "0xFFFFFF00"`
1371 partition_start=1
1372 partition_size=`printf "%d" 0xFFFFFFFF`
1373fi
1374
1375
1376
1377verify_mbr() {
1378 read_mbr
1379 if [ "$out1" != "00000" -o "$out2" != "00000" -o "$out3" != "00000" -o "$out4" != "00170" -o "$out5" != "00085" ]
1380 then
1381 cleared_ok="n"
1382 echo "failed test 1"
1383 fi
1384
1385#failed test 2 00000 00000 00002 00000
1386#failed test 3 00000 00255 00255 00255
1387
1388 if [ "$over_mbr_size" != "y" ]
1389 then
1390 if [ "$byte1" != "00000" -o "$byte2" != "00000" -o "$byte3" != "00000" -o "$byte4" != "00000" ]
1391 then
1392 cleared_ok="n"
1393 echo "failed test 2 $byte1 $byte2 $byte3 $byte4"
1394 fi
1395
1396 if [ "$byte5" != "00000" -o "$byte6" != "00000" -o "$byte7" != "00000" -o "$byte8" != "00000" ]
1397 then
1398 cleared_ok="n"
1399 echo "failed test 3 $byte5 $byte6 $byte7 $byte8"
1400 fi
1401 else
1402 if [ "$byte1" != "00000" -o "$byte2" != "00000" -o "$byte3" != "00002" -o "$byte4" != "00000" ]
1403 then
1404 cleared_ok="n"
1405 echo "failed test 2 $byte1 $byte2 $byte3 $byte4"
1406 fi
1407
1408 if [ "$byte5" != "00000" -o "$byte6" != "00255" -o "$byte7" != "00255" -o "$byte8" != "00255" ]
1409 then
1410 cleared_ok="n"
1411 echo "failed test 3 $byte5 $byte6 $byte7 $byte8"
1412 fi
1413 fi
1414
1415 byte9h=`echo $byte9|awk '{printf("%02x", $1)}'`
1416 byte10h=`echo $byte10|awk '{printf("%02x", $1)}'`
1417 byte11h=`echo $byte11|awk '{printf("%02x", $1)}'`
1418 byte12h=`echo $byte12|awk '{printf("%02x", $1)}'`
1419 byte13h=`echo $byte13|awk '{printf("%02x", $1)}'`
1420 byte14h=`echo $byte14|awk '{printf("%02x", $1)}'`
1421 byte15h=`echo $byte15|awk '{printf("%02x", $1)}'`
1422 byte16h=`echo $byte16|awk '{printf("%02x", $1)}'`
1423 sc=`printf "%d" "0x"$byte12h$byte11h$byte10h$byte9h`
1424 sl=`printf "%d" "0x"$byte16h$byte15h$byte14h$byte13h`
1425
1426 case "$sc" in
1427 63)
1428 let partition_size=($full_size - $sc)
1429 ;;
1430 64)
1431 let partition_size=($full_size - $sc)
1432 ;;
1433 1)
1434 if [ "$over_mbr_size" != "y" ]
1435 then
1436 cleared_ok="n"
1437 echo "failed test 4"
1438 fi
1439 ;;
1440 *)
1441 cleared_ok="n"
1442 echo "failed test 5"
1443 ;;
1444 esac
1445
1446 if [ $partition_size -ne $sl ]
1447 then
1448 cleared_ok="n"
1449 echo "failed test 6"
1450 fi
1451}
1452
1453echo $clearscreen$goto_top${bold}Pre-Clear unRAID Disk $theDisk$norm
1454echo "################################################################## $ver"
1455# first, try without a device type.
1456sm_out=`smartctl -a $theDisk`
1457smartstat=$(($? & 7))
1458if [ "$smartstat" = "0" ]
1459then
1460 device_type=""
1461fi
1462sm_out=`smartctl -a $device_type $theDisk`
1463smartstat=$(($? & 7))
1464if [ "$smartstat" != "0" ]
1465then
1466 echo
1467 if [ "$device_type" != "" ]
1468 then
1469 echo "${bold}smartctl may not be able to run on $theDisk with the $device_type option.${norm}"
1470 else
1471 echo "${bold}smartctl may not be able to run on $theDisk.${norm}"
1472 fi
1473 echo "${bold}however this should not affect the clearing of a disk.${norm}"
1474 echo "smartctl exit status = $smartstat"
1475 echo "$sm_out"$
1476 echo "${bold}Do you wish to continue?${norm}"
1477 echo -n "(Answer ${ul}Yes${noul} to continue. Capital 'Y', lower case 'es'): "
1478 read ans
1479 if [ "$ans" != "Yes" ]
1480 then
1481 exit 1
1482 fi
1483fi
1484
1485echo "$sm_out" | awk '/Model/,/User Capacity/'
1486model=`echo "$sm_out" | awk '/Device Model/ { printf substr($0, 18,length($0)) }'`
1487serial=`echo "$sm_out" | awk '/Serial Number/ { printf substr($0, 18,length($0)) }'`
1488if [ "$convert_flag" != "y" -a "$zero_mbr_only" != "y" ]
1489then
1490 fdisk -l -u $theDisk
1491fi
1492echo "########################################################################"
1493
1494if [ "$test_only_flag" = "y" ]
1495then
1496 cleared_ok="y"
1497 verify_mbr
1498
1499 if [ "$cleared_ok" != "y" ]
1500 then
1501 echo "========================================================================$ver"
1502 echo "=="
1503 echo "== Disk $theDisk is ${bold}NOT${norm} precleared"
1504 echo "==" $sc $sl $partition_size
1505 echo "============================================================================"
1506 else
1507 echo "========================================================================$ver"
1508 echo "=="
1509 if [ "$over_mbr_size" != "y" ]
1510 then
1511 echo "== ${bold}DISK $theDisk IS PRECLEARED${norm} with a starting sector of $sc"
1512 else
1513 echo "== ${bold}DISK $theDisk IS PRECLEARED${norm} with a GPT Protective MBR"
1514 fi
1515 echo "=="
1516 echo "============================================================================"
1517 fi
1518 exit 0
1519fi
1520
1521if [ "$convert_flag" = "y" -a "$verify_only" = "n" ]
1522then
1523 cleared_ok="y"
1524 echo " Converting existing pre-cleared disk to start partition on sector $convert_type"
1525 echo "========================================================================$ver"
1526 echo -n " Step 1. Verifying existing pre-clear signature prior to conversion. "
1527 verify_mbr
1528 sleep 1
1529 echo "${bold}DONE${norm}"
1530
1531 if [ "$cleared_ok" != "y" ]
1532 then
1533 echo "========================================================================$ver"
1534 echo "=="
1535 echo "== Disk $theDisk is ${bold}NOT${norm} precleared"
1536 echo "== Conversion not possible"
1537 echo "==" $sc $sl $partition_size
1538 echo "============================================================================"
1539 exit 2
1540 fi
1541 if [ "$over_mbr_size" = "y" ]
1542 then
1543 echo "========================================================================$ver"
1544 echo "=="
1545 echo "== ${bold}DISK $theDisk IS PRECLEARED${norm} with a GPT Protective MBR"
1546 echo "== Conversion not possible"
1547 echo "=="
1548 echo "============================================================================"
1549 exit 2
1550 fi
1551 case "$convert_type" in
1552 63)
1553 #convert precleared sector 64 to precleared sector 63
1554 if [ "$sc" = "63" ]
1555 then
1556 echo "========================================================================$ver"
1557 echo "== ${bold}DISK $theDisk IS ALREADY PRECLEARED with a starting sector of $sc${norm}"
1558 echo "=="
1559 echo "== Conversion is not needed."
1560 echo "============================================================================"
1561 exit 2
1562 else
1563 partition_start=63
1564 let partition_size=($partition_size + 1)
1565 fi
1566 ;;
1567 64)
1568 #convert precleared sector 63 to precleared sector 64
1569 if [ "$sc" = "64" ]
1570 then
1571 echo "========================================================================$ver"
1572 echo "== ${bold}DISK $theDisk IS ALREADY PRECLEARED with a starting sector of $sc${norm}"
1573 echo "=="
1574 echo "== Conversion is not needed."
1575 echo "============================================================================"
1576 exit 2
1577 else
1578 partition_start=64
1579 let partition_size=($partition_size - 1)
1580 fi
1581 ;;
1582 esac
1583 echo -n " Step 2. converting existing pre-clear signature: "
1584 awk 'BEGIN{
1585 printf ("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
1586 0,0,0,0,0,0,0,0,
1587 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),7,2)),
1588 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),5,2)),
1589 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),3,2)),
1590 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),1,2)),
1591 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),7,2)),
1592 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),5,2)),
1593 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),3,2)),
1594 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),1,2)))
1595 }' $partition_start $partition_size | dd seek=446 bs=1 count=16 of=$theDisk 2>/dev/null
1596 sleep 1
1597 echo "${bold}DONE${norm}"
1598 echo "========================================================================$ver"
1599 echo "=="
1600 echo "== Conversion complete."
1601 echo "== ${bold}DISK $theDisk is now PRECLEARED with a starting sector of $partition_start${norm}"
1602 echo "=="
1603 echo "============================================================================"
1604 exit 0
1605fi
1606
1607# validate the disk basename is the full disk and not a partition
1608bn="$(basename ${theDisk} | sed 's/[^0-9]//g')"
1609if [ ! -z "$bn" ]
1610then
1611 echo "error: $disk_basename is not a valid three character device name." >&2
1612 exit 2
1613fi
1614
1615get_start_smart $theDisk >/dev/null 2>&1
1616# If the drive has already failed, warn the user now
1617d=`basename $1`
1618errs=`analyze_for_errors /tmp/smart_start_$d | grep FAILING_NOW | grep -v "No SMART attributes"`
1619if [ "$errs" != "" ]
1620then
1621 echo "error: $disk_basename is currently failing SMART tests." >&2
1622 echo "$errs"
1623 echo "Full SMART report is in /tmp/smart_start_$d"
1624 echo "########################################################################"
1625fi
1626
1627echo "invoked as " $progname $options
1628echo "########################################################################"
1629if [ "$partition_64" = "y" ]
1630then
1631 if [ "$verify_only" = "y" ]
1632 then
1633 #echo "the '-A' option requests this disk be verified for a 4k-aligned partition"
1634 echo $vdefault
1635 else
1636 if [ "$zero_mbr_only" = "y" ]
1637 then
1638 echo "The -z option requests that $theDisk will have its MBR zeroed"
1639 else
1640 echo $default
1641 fi
1642 fi
1643else
1644 if [ "$verify_only" = "y" ]
1645 then
1646 #echo "This disk will be verified for a traditional partition starting on sector 63."
1647 echo $vdefault
1648 else
1649 if [ "$zero_mbr_only" = "y" ]
1650 then
1651 echo "The -z option requests that $theDisk will have its MBR zeroed"
1652 else
1653 #echo "This disk will be cleared for a traditional partition starting on sector 63."
1654 echo $default
1655 echo "(it will not be 4k-aligned)"
1656 fi
1657 fi
1658fi
1659
1660if [ "$zero_mbr_only" = "y" ]
1661then
1662 echo "Are you absolutely sure you want to zero the MBR of this drive?"
1663 echo -n "(Answer ${ul}Yes${noul} to continue. Capital 'Y', lower case 'es'): "
1664 read ans
1665 if [ "$ans" = "Yes" ]
1666 then
1667 echo "zeroing MBR only"
1668 dd if=/dev/zero bs=512 count=1 of=$theDisk
1669 echo "zeroing MBR complete."
1670 echo "Verification of MBR zero starting."
1671 read_mbr
1672 if [ "$out1" != "00000" -o "$out2" != "00000" -o "$out3" != "00000" -o "$out4" != "00000" -o "$out5" != "00000" ]
1673 then
1674 echo "==================================================$ver"
1675 echo "== ${bold}SORRY: Disk $theDisk MBR was NOT zeroed${norm}"
1676 echo "======================================================"
1677 else
1678 echo "==================================================$ver"
1679 echo "== ${bold}Disk $theDisk MBR was zeroed${norm}"
1680 echo "======================================================"
1681 fi
1682 else
1683 echo "==================================================$ver"
1684 echo "== ${bold}Disk $theDisk was not changed${norm}"
1685 echo "======================================================"
1686 fi
1687 exit
1688fi
1689
1690if [ "$verify_only" = "y" ]
1691then
1692 echo "Are you sure you want to verify this drive? (it will not be writen to at all)"
1693else
1694 echo "Are you absolutely sure you want to clear this drive?"
1695fi
1696echo -n "(Answer ${ul}Yes${noul} to continue. Capital 'Y', lower case 'es'): "
1697read ans
1698if [ "$ans" != "Yes" ]
1699then
1700 if [ "$verify_only" = "y" ]
1701 then
1702 echo "${bold}Verification will NOT be performed${norm}"
1703 else
1704 echo "${bold}Clearing will NOT be performed${norm}"
1705 fi
1706 exit 2
1707fi
1708tmr=$(timer)
1709cyctmr=$tmr #Set start of 1st cycle timer
1710disk_start_temp=`smartctl $device_type -A $theDisk | grep -i temperature | sed 1q | awk '{ print $10; }'`
1711
1712let cc=0
1713
1714get_start_smart $theDisk >/dev/null 2>&1
1715mid_err=""
1716cp /dev/null /tmp/smart_mid_pending_reallocate_$d
1717
1718while test $cc -lt $cycle_count
1719do
1720 preread=""
1721 step1=""
1722 step2=""
1723 step3=""
1724 step4=""
1725 step5=""
1726 step6=""
1727 step7=""
1728 step8=""
1729 step9=""
1730 step10=""
1731 postread=""
1732 let cc=($cc+1)
1733
1734 #bjp999 4/9/11 V
1735 if [ $cycle_count -eq 1 ]
1736 then
1737 cycle_disp=""
1738 else
1739 cycle_disp=" ($cc of $cycle_count)"
1740 fi
1741 #bjp999 4/9/11 ^
1742
1743 if [ "$pre_read_flag" = "y" -a $cc = 1 ]
1744 then
1745 pretmr=$(timer) #get preread start time
1746 read_entire_disk $theDisk preread display_progress
1747 get_mid_smart $theDisk preread$cc >/dev/null 2>&1
1748
1749 m_pending_sectors=`get_attr "Current_Pending_Sector" old_raw /tmp/smart_mid_preread${cc}_$d`
1750 if [ "$m_pending_sectors" != "" ]
1751 then
1752 if [ "$m_pending_sectors" = "1" ]
1753 then
1754 echo " $m_pending_sectors sector was pending re-allocation after pre-read in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
1755 else
1756 echo " $m_pending_sectors sectors were pending re-allocation after pre-read in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
1757 fi
1758 fi
1759 fi
1760
1761 zerotmr=$(timer) #get zeroing start time
1762 if [ "$verify_only" != "y" ]
1763 then
1764
1765 step1="${bold}Step 1 of 10 - Copying zeros to first 2048k bytes${norm}"
1766 display_progress 5
1767
1768 #----------------------------------------------------------------------------------
1769 # skip the MBR, clear remainder of first 2048k bytes.
1770 #----------------------------------------------------------------------------------
1771 dd if=/dev/zero bs=512 seek=1 of=$theDisk count=4096 2>/dev/null
1772 step1="Step 1 of 10 - Copying zeros to first 2048k bytes ${bold}DONE${norm}"
1773
1774 display_progress 5
1775
1776 step2="${bold}Step 2 of 10 - Copying zeros to remainder of disk to clear it ${norm}"
1777 step3=" **** This will take a while... you can follow progress below:"
1778
1779 report_percentage=25
1780 if [ $use_mail -ge 3 ]
1781 then
1782 echo -e "Zeroing Disk $theDisk Started. \\n`disk_temperature 1`\\n" | mail -s "Preclear: Zeroing Disk $disk_basename Started. Cycle $cc of $cycle_count" $mail_rcpt
1783 fi
1784
1785
1786
1787 display_progress 5
1788
1789 #----------------------------------------------------------------------------------
1790 # Get total bytes so we can calculate percentage done. (if Pre read wasn't run)
1791 #----------------------------------------------------------------------------------
1792 fgeometry=`fdisk -l $1`
1793 units=`echo "$fgeometry" | grep Units | awk '{ print $9 }'`
1794 if [ $short_test -eq 0 ]
1795 then
1796 total_bytes=`echo "$fgeometry" | grep "Disk $1" | awk '{ print $5 }'`
1797 else
1798 total_bytes=8589934592 # 2048k * 4096
1799 #total_bytes=1073741824 # 2048k * 512
1800 fi
1801
1802 tb_formatted=`format_number $total_bytes`
1803
1804
1805
1806 #----------------------------------------------------------------------------------
1807 # clear remainder of drive from MBR onward (using a slightly larger block size)
1808 #----------------------------------------------------------------------------------
1809 # dd if=/dev/zero bs=2048k seek=1 of=$theDisk &
1810 if [ "$write_bs" = "" ]
1811 then
1812 write_bs="2048k"
1813 fi
1814
1815 if [ $short_test -eq 0 ]
1816 then
1817 dd if=/dev/zero bs=$write_bs seek=$sb of=$theDisk 2> /tmp/zero$disk_basename &
1818 else
1819 dd if=/dev/zero bs=2048k seek=1 of=$theDisk count=4096 2> /tmp/zero$disk_basename & #If short test is requested.. Do only 4096 blocks
1820 fi
1821 dd_pid=$!
1822
1823 # if we are interrupted, kill the background zero of the disk.
1824 trap 'kill $dd_pid 2>/dev/null;exit' 2
1825 while kill -0 $dd_pid >/dev/null 2>&1
1826 do
1827 display_progress 10 $dd_pid
1828 done
1829 get_mid_smart $theDisk after_zero$cc >/dev/null 2>&1
1830#/tmp/smart_mid_after_zero1_sdb
1831#/tmp/smart_mid_after_zero2_sdb
1832#/tmp/smart_mid_after_zero3_sdb
1833#/tmp/smart_mid_pending_reallocate_sdb
1834#/tmp/smart_mid_post_read1_sdb
1835#/tmp/smart_mid_post_read2_sdb
1836#/tmp/smart_mid_preread1_sdb
1837 m_pending_sectors=`get_attr "Current_Pending_Sector" old_raw /tmp/smart_mid_after_zero${cc}_$d`
1838 if [ "$m_pending_sectors" != "" ]
1839 then
1840 if [ "$m_pending_sectors" = "1" ]
1841 then
1842 echo " $m_pending_sectors sector was pending re-allocation after zero of disk in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
1843 else
1844 echo " $m_pending_sectors sectors were pending re-allocation after zero of disk in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
1845 fi
1846 fi
1847 dzerotmr=$(timer $zerotmr)
1848 zerodonetmr=$(timer)
1849 cal_zero_write_speed=$(($total_bytes / ($zerodonetmr - $zerotmr) / 1000000 ))
1850 if [ $use_mail -ge 3 ]
1851 then
1852 report_out="Zeroing Disk $theDisk Done. \\n"
1853 report_out+="Zeroing Elapsed Time: $dzerotmr \\n"
1854 report_out+="Total Elapsed Time: $(timer $tmr)\\n"
1855 report_out+="`disk_temperature 1`\\n"
1856 report_out+="Calculated Write Speed: $cal_zero_write_speed MB/s"
1857
1858 echo -e "$report_out" | mail -s "Preclear: Zeroing Disk $disk_basename Done. Cycle $cc of $cycle_count" $mail_rcpt
1859 fi
1860
1861 #bjp999 4/9/11
1862 echo "$disk_basename|NN|Creating Boot Record /^nPartition Table ($(timer $tmr))" > /tmp/preclear_stat_$disk_basename
1863
1864 step2="Step 2 of 10 - Copying zeros to remainder of disk to clear it ${bold}DONE${norm}"
1865 step3="Step 3 of 10 - Disk is now cleared from MBR onward. ${bold}DONE${norm}"
1866
1867 display_progress 5
1868
1869 step4="${bold}Step 4 of 10 - Clearing MBR bytes for partition 2,3 & 4${norm}"
1870
1871 display_progress 5
1872
1873 dd if=/dev/zero bs=1 seek=462 count=48 of=$theDisk
1874
1875 step4="Step 4 of 10 - Clearing MBR bytes for partition 2,3 & 4 ${bold}DONE${norm}"
1876
1877 display_progress 5
1878
1879 step5="${bold}Step 5 of 10 - Clearing MBR code area${norm}"
1880
1881 display_progress 5
1882
1883 dd if=/dev/zero bs=446 count=1 of=$theDisk
1884
1885 step5="Step 5 of 10 - Clearing MBR code area ${bold}DONE${norm}"
1886
1887 display_progress 5
1888
1889 step6="${bold}Step 6 of 10 - Setting MBR signature bytes${norm}"
1890
1891 display_progress 2
1892
1893 # set MBR signature in last two bytes in MBR
1894 # two byte MBR signature
1895 echo -ne "\0252" | dd bs=1 count=1 seek=511 of=$theDisk
1896 echo -ne "\0125" | dd bs=1 count=1 seek=510 of=$theDisk
1897
1898 step6="Step 6 of 10 - Setting MBR signature bytes ${bold}DONE${norm}"
1899
1900 display_progress 5
1901
1902 step7="${bold}Step 7 of 10 - Setting partition 1 to precleared state${norm}"
1903
1904 display_progress 5
1905
1906 #----------------------------------------------------------------------------------
1907 # Create the partition data for the 16 bytes in the MBR that define the first
1908 # partition. Write it to the MBR. These bytes define the start and
1909 # end of the first partition
1910 #----------------------------------------------------------------------------------
1911 awk 'BEGIN{
1912 printf ("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
1913 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),7,2)),
1914 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),5,2)),
1915 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),3,2)),
1916 strtonum("0x" substr(sprintf( "%08x\n", ARGV[1]),1,2)),
1917 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),7,2)),
1918 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),5,2)),
1919 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),3,2)),
1920 strtonum("0x" substr(sprintf( "%08x\n", ARGV[2]),1,2)),
1921 strtonum("0x" substr(sprintf( "%08x\n", ARGV[3]),7,2)),
1922 strtonum("0x" substr(sprintf( "%08x\n", ARGV[3]),5,2)),
1923 strtonum("0x" substr(sprintf( "%08x\n", ARGV[3]),3,2)),
1924 strtonum("0x" substr(sprintf( "%08x\n", ARGV[3]),1,2)),
1925 strtonum("0x" substr(sprintf( "%08x\n", ARGV[4]),7,2)),
1926 strtonum("0x" substr(sprintf( "%08x\n", ARGV[4]),5,2)),
1927 strtonum("0x" substr(sprintf( "%08x\n", ARGV[4]),3,2)),
1928 strtonum("0x" substr(sprintf( "%08x\n", ARGV[4]),1,2)))
1929 }' $size1 $size2 $partition_start $partition_size | dd seek=446 bs=1 count=16 of=$theDisk
1930
1931 step7="Step 7 of 10 - Setting partition 1 to precleared state ${bold}DONE${norm}"
1932
1933 step8="${bold}Step 8 of 10 - Notifying kernel we changed the partitioning${norm}"
1934 display_progress 5
1935
1936 # let the kernel know we changed the partitioning
1937 sfdisk -R $theDisk
1938
1939 step8="Step 8 of 10 - Notifying kernel we changed the partitioning ${bold}DONE${norm}"
1940 step9="${bold}Step 9 of 10 - Creating the /dev/disk/by* entries${norm}"
1941
1942 display_progress 5
1943
1944 #----------------------------------------------------------------------------------
1945 # create the /dev/disk/by* entries
1946 #----------------------------------------------------------------------------------
1947 /etc/rc.d/rc.udev restart 2>/dev/null 2>&1
1948 sleep 5
1949
1950 step9="Step 9 of 10 - Creating the /dev/disk/by* entries ${bold}DONE${norm}"
1951 step10="${bold}Step 10 of 10 - Verifying the clear has been successful.${norm}"
1952
1953 display_progress 5
1954 else
1955 step7="Step 1 through 9 skipped, verify phase will be performed next"
1956 fi
1957
1958 #now, verify the clear has been successful. Set the "out" variables...
1959
1960 if [ "$verify_only" = "y" ]
1961 then
1962 step1="invoked as: $progname $options"
1963 step8="Step 10 of 10 - Verifying if the MBR is cleared."
1964 display_progress 1
1965 cleared_ok="y" # assume ok until we learn otherwise
1966 verify_mbr
1967 if [ "$cleared_ok" = "y" ]
1968 then
1969 if [ "$sc" = "63" -a "$partition_64" = "y" ]
1970 then
1971 step8="Step 10 of 10 - ${bold}The MBR is NOT verified 4k-aligned cleared.${norm}"
1972 step9="${bold}However, its MBR is verified for non-4k-alignment${norm}"
1973 step10="${bold}starting on sector 63${norm}"
1974 else
1975 if [ "$sc" = "64" -a "$partition_64" = "n" ]
1976 then
1977 step8="Step 10 of 10 - ${bold}The MBR is NOT verified un-aligned cleared.${norm}"
1978 step9="${bold}However, its MBR is verified cleared for 4k-alignment${norm}"
1979 step10="${bold}starting on sector 64${norm}"
1980 else
1981 step9="Step 10 of 10 - The MBR is verified cleared ${bold}DONE${norm}"
1982 step10="for a partition starting on sector $sc."
1983 fi
1984 fi
1985 else
1986 step9="Step 10 of 10 - ${bold}The MBR is NOT verified cleared.${norm} ${bold}DONE${norm}"
1987 fi
1988 else
1989 read_mbr
1990 step10="Step 10 of 10 - Verifying if the MBR is cleared. ${bold}DONE${norm}"
1991 fi
1992
1993
1994
1995 display_progress 1
1996
1997 if [ "$out1" != "00000" -o "$out2" != "00000" -o "$out3" != "00000" -o "$out4" != "00170" -o "$out5" != "00085" ]
1998 then
1999 echo "========================================================================$ver"
2000 echo "=="
2001 if [ "$verify_only" = "y" ]
2002 then
2003 echo "== ${bold}SORRY: Disk $theDisk MBR NOT precleared${norm}"
2004 else
2005 echo "== ${bold}SORRY: Disk $theDisk MBR could NOT be precleared${norm}"
2006 fi
2007 echo "=="
2008 [ "$out1" != "00000" ] && echo "== out1= $out1"
2009 [ "$out2" != "00000" ] && echo "== out2= $out2"
2010 [ "$out3" != "00000" ] && echo "== out3= $out3"
2011 [ "$out4" != "00170" ] && echo "== out4= $out4"
2012 [ "$out5" != "00085" ] && echo "== out5= $out5"
2013 [ "$postread_error" != "" ] && echo "== $postread_error"
2014 echo "============================================================================"
2015 dd if=$theDisk count=1 | od -x
2016 if [ $use_mail -ge 1 ]
2017 then
2018 if [ "$verify_only" = "y" ]
2019 then
2020 echo -e "Preclear Verify Disk $theDisk FAILED!!!!. " | mail -s "Preclear: FAIL! Verify Disk $disk_basename Failed!!! Cycle $cc of $cycle_count" $mail_rcpt
2021 else
2022 echo -e "Preclear Disk $theDisk FAILED!!!!. " | mail -s "Preclear: FAIL! Preclearing Disk $disk_basename Failed!!! Cycle $cc of $cycle_count" $mail_rcpt
2023 fi
2024 fi
2025
2026 exit 1
2027 else
2028 if [ "$post_read_flag" = "y" ]
2029 then
2030 posttmr=$(timer) #get postread start time
2031 read_entire_disk $theDisk postread display_progress
2032 if [ "$cc" != "$cycle_count" ]
2033 then
2034 get_mid_smart $theDisk post_read$cc >/dev/null 2>&1
2035 m_pending_sectors=`get_attr "Current_Pending_Sector" old_raw /tmp/smart_mid_post_read${cc}_$d`
2036 if [ "$m_pending_sectors" != "" ]
2037 then
2038 if [ "$m_pending_sectors" = "1" ]
2039 then
2040 echo " $m_pending_sectors sector was pending re-allocation after post-read in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
2041 else
2042 echo " $m_pending_sectors sectors were pending re-allocation after post-read in cycle $cc of $cycle_count." >>/tmp/smart_mid_pending_reallocate_$d
2043 fi
2044 fi
2045 fi
2046 fi
2047 fi
2048 dcyctmr=$(timer $cyctmr) #delta cycle time
2049 cyctmr=$(timer) #reset cycle timer
2050 if [ $use_mail -ge 2 ]
2051 then
2052 if [ $cc -lt $cycle_count ]
2053 then
2054 report_out="========================================================================$ver\n"
2055 report_out+="==\n"
2056 report_out+="== Disk $theDisk has successfully finished a preclear cycle\n"
2057 report_out+="==\n"
2058 report_out+="== Finished Cycle $cc of $cycle_count cycles\n"
2059 report_out+="==\n"
2060 if [ "$pre_read_flag" = "y" ] # Don't report Pre read time if there was no Pre/Post read.
2061 then
2062 report_out+="== Using read block size = `format_number ${units}` Bytes\n"
2063 report_out+="== Last Cycle's Pre Read Time : $dpretmr ($cal_pre_read_speed MB/s)\n"
2064 fi
2065 if [ "$verify_only" != "y" ] # Don't report zero time if there was no zeroing.
2066 then
2067 report_out+="== Last Cycle's Zeroing time : $dzerotmr ($cal_zero_write_speed MB/s)\n"
2068 fi
2069 if [ "$pre_read_flag" = "y" ] # Don't report Post read time if there was no Pre/Post read.
2070 then
2071 report_out+="== Last Cycle's Post Read Time : $dposttmr ($cal_post_read_speed MB/s)\n"
2072 fi
2073 report_out+="== Last Cycle's Total Time : $dcyctmr\n"
2074 report_out+="==\n"
2075 report_out+="== Total Elapsed Time $(timer $tmr)\n"
2076 report_out+="==\n"
2077 if [ "$disk_start_temp" != "" ] # Don't report Disk Temperature if there was no Temp reported.
2078 then
2079 report_out+="== Disk Start Temperature: ${disk_start_temp}C\n"
2080 report_out+="==\n"
2081 report_out+="== Current `disk_temperature 1`\n"
2082 fi
2083 report_out+="==\n"
2084 report_out+="== Starting next cycle\n"
2085 report_out+="==\n"
2086 report_out+="========================================================================$ver\n"
2087 echo -e "$report_out" | mail -s "Preclear: Disk $disk_basename PASSED cycle $cc! Starting Next cycle" $mail_rcpt
2088 fi
2089 fi
2090done
2091
2092# if debug mode, make certain the disk is not mistaken for a fully cleared disk.
2093if [ $short_test -ne 0 -a "$verify_only" != "y" ]
2094then
2095 echo -ne "\001" | dd bs=1 count=1 of=$theDisk
2096fi
2097if [ -f "/tmp/postread_errors$disk_basename" ]
2098then
2099 postread_error=`head "/tmp/postread_errors$disk_basename" 2>/dev/null`
2100else
2101 postread_error=""
2102fi
2103
2104if [ "$verify_only" = "y" ]
2105then
2106 if [ "$postread_error" != "" ]
2107 then
2108 echo "========================================================================$ver"
2109 echo "=="
2110 echo "== ${bold}Disk $theDisk has NOT been verified successfully${norm}"
2111 echo "==" $postread_error
2112 echo "============================================================================"
2113 report_out="========================================================================$ver\n"
2114 report_out+="== invoked as: $progname $options\n"
2115 report_out+="==\n"
2116 report_out+="== Disk $theDisk has NOT been successfully verified as precleared\n"
2117 report_out+="== Postread detected un-expected non-zero bytes on disk"
2118 report_out+="==\n"
2119 status_out="YY|Disk Not Verified Precleared" #bjp999 4/9/11
2120 else
2121 echo "========================================================================$ver"
2122 echo "=="
2123 echo "== ${bold}Disk $theDisk has been verified precleared${norm}"
2124 echo "== with a starting sector of $partition_start"
2125 echo "============================================================================"
2126 report_out="========================================================================$ver\n"
2127 report_out+="== invoked as: $progname $options\n"
2128 report_out+="==\n"
2129 report_out+="== Disk $theDisk has been verified precleared\n"
2130 report_out+="== with a starting sector of $partition_start \n"
2131 status_out="YN|Disk Verified Precleared" #bjp999 4/9/11
2132 fi
2133else
2134 if [ "$postread_error" != "" ]
2135 then
2136 echo "========================================================================$ver"
2137 echo "== $model $serial"
2138 echo "== ${bold}Disk $theDisk has NOT been precleared successfully${norm}"
2139 echo "==" $postread_error
2140 echo "============================================================================"
2141 report_out="========================================================================$ver\n"
2142 report_out+="== invoked as: $progname $options\n"
2143 report_out+="==\n"
2144 report_out+="== Disk $theDisk has NOT been successfully precleared\n"
2145 report_out+="== Postread detected un-expected non-zero bytes on disk"
2146 report_out+="==\n"
2147 status_out="YY|Preclear Not Successful" #bjp999 4/9/11
2148 else
2149 echo "========================================================================$ver"
2150 echo "== $model $serial"
2151 echo "== ${bold}Disk $theDisk has been successfully precleared${norm}"
2152 echo "== with a starting sector of $partition_start"
2153 echo "============================================================================"
2154 report_out="========================================================================$ver\n"
2155 report_out+="== invoked as: $progname $options\n"
2156 report_out+="== $model $serial\n"
2157
2158 report_out+="== Disk $theDisk has been successfully precleared\n"
2159 report_out+="== with a starting sector of $partition_start \n"
2160 status_out="YN|Preclear Successful" #bjp999 4/9/11
2161 fi
2162fi
2163
2164#bjp999 4/9/11 V
2165stat_pre=""
2166stat_post=""
2167stat_zero=""
2168#echo "pre_read_flag = '$pre_read_flag'"
2169#echo "verify_only = '$verify_only'"
2170if [ "$pre_read_flag" = "y" ]
2171then
2172 stat_pre="^n... Pre-Read time $dpretmr ($cal_pre_read_speed MB/s)"
2173 stat_post="^n... Post-Read time $dposttmr ($cal_post_read_speed MB/s)"
2174fi
2175if [ "$verify_only" != "y" ]
2176then
2177 stat_zero="^n... Zeroing time $dzerotmr ($cal_zero_write_speed MB/s)"
2178fi
2179#echo "status_out= $status_out"
2180echo "$disk_basename|${status_out}^n... Total time $(timer $tmr)${stat_pre}${stat_zero}${stat_post}" > /tmp/preclear_stat_$disk_basename
2181#bjp999 4/9/11 ^
2182
2183if [ "$cycle_count" -eq "1" ]
2184then
2185 report_out+="== Ran 1 cycle\n"
2186else
2187 report_out+="== Ran $cycle_count cycles\n"
2188fi
2189report_out+="==\n"
2190if [ "$pre_read_flag" = "y" ] # Don't report Pre read time if there was no Pre/Post read.
2191then
2192 report_out+="== Using :Read block size = ${units} Bytes\n"
2193 report_out+="== Last Cycle's Pre Read Time : $dpretmr ($cal_pre_read_speed MB/s)\n"
2194fi
2195
2196if [ "$verify_only" != "y" ] # Don't report zero time if there was no zeroing.
2197then
2198 report_out+="== Last Cycle's Zeroing time : $dzerotmr ($cal_zero_write_speed MB/s)\n"
2199fi
2200if [ "$pre_read_flag" = "y" ] # Don't report Post read time if there was no Pre/Post read.
2201then
2202 report_out+="== Last Cycle's Post Read Time : $dposttmr ($cal_post_read_speed MB/s)\n"
2203fi
2204report_out+="== Last Cycle's Total Time : $dcyctmr\n"
2205report_out+="==\n"
2206report_out+="== Total Elapsed Time $(timer $tmr)\n"
2207report_out+="==\n"
2208if [ "$disk_start_temp" != "" ] # Don't report Disk Temperature if there was no Temp reported.
2209then
2210 report_out+="== Disk Start Temperature: ${disk_start_temp}C\n"
2211 report_out+="==\n"
2212 report_out+="== Current `disk_temperature 1`\n"
2213fi
2214report_out+="==\n"
2215report_out+="============================================================================\n"
2216
2217
2218get_finish_smart $theDisk >/dev/null 2>&1
2219
2220errs=`analyze_for_errors /tmp/smart_start_$d /tmp/smart_finish_$d`
2221
2222echo "$errs "
2223
2224
2225report_out+="$errs \n"
2226report_out+="============================================================================\n"
2227echo -e "$report_out" >/tmp/preclear_report_$d
2228if [ "$save_report" = "y" ]
2229then
2230 mkdir -p /boot/preclear_reports
2231 dt=`date "+%Y-%m-%d"`
2232 if [ "$save_report_by_dev" = "yes" ]
2233 then
2234 cp /tmp/preclear_report_$d /boot/preclear_reports/preclear_rpt_${d}_${dt}
2235 cp /tmp/smart_start_$d /boot/preclear_reports/preclear_start_${d}_${dt}
2236 cp /tmp/smart_finish_$d /boot/preclear_reports/preclear_finish_${d}_${dt}
2237 else # name the reports by their serial number
2238 cp /tmp/preclear_report_$d "/boot/preclear_reports/preclear_rpt_${serial}_${dt}"
2239 cp /tmp/smart_start_$d "/boot/preclear_reports/preclear_start_${serial}_${dt}"
2240 cp /tmp/smart_finish_$d "/boot/preclear_reports/preclear_finish_${serial}_${dt}"
2241 fi
2242fi
2243report_out+="============================================================================\n"
2244report_out+="==\n"
2245report_out+="== S.M.A.R.T Initial Report for $theDisk \n"
2246report_out+="==\n"
2247report_out+="`cat /tmp/smart_start_$d` \n"
2248report_out+="==\n"
2249report_out+="============================================================================\n"
2250report_out+="\n"
2251report_out+="\n"
2252report_out+="\n"
2253report_out+="============================================================================\n"
2254report_out+="==\n"
2255report_out+="== S.M.A.R.T Final Report for $theDisk \n"
2256report_out+="==\n"
2257report_out+="`cat /tmp/smart_finish_$d` \n"
2258report_out+="==\n"
2259report_out+="============================================================================\n"
2260echo -e "$report_out " | logger -tpreclear_disk-diff -plocal7.info -i
2261
2262if [ $use_mail -ge 1 ]
2263then
2264 echo -e "${report_out}" | mail -s "Preclear: PASS! Preclearing Disk $disk_basename Finished!!! Cycle $cc of $cycle_count" $mail_rcpt
2265fi