diskcheck 21 KB
Newer Older
Dan Reading's avatar
Dan Reading committed
1
#! /bin/bash
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# Copyright (c) 2013 University of Utah and the Flux Group.
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
#
Dan Reading's avatar
Dan Reading committed
24
25
26
27
28
29
30
31
32
33
34
35
echo -n ' Starting diskcheck..'

# find the number of disks
# find the size of each disk
# first arg is the log output file, if not set then /tmp/...

declare error=""
declare err=""

source checkutils.sh
source hbis.sh

36
37
38
x=$(caller)
[[ "${x/NULL}" = "$x" ]] && declare -ri diskcheck_standalone=0 || declare -ri diskcheck_standalone=1

Dan Reading's avatar
Dan Reading committed
39
40
## declare -p todo_exit

41
42
43
main_diskcheck() {
    initialize $@
    cp /dev/null $tmplog
Dan Reading's avatar
Dan Reading committed
44
45
46
47

    SMARTCTL=$(findSmartctl)
    drivenames=$(getdrivenames)

Dan Reading's avatar
Dan Reading committed
48
49
50
51
52
53
54
55
56
    # run through the drivelist filtering out non-local drives or other devices 
    for i in $drivenames ; do
        model=$(getmodel $i)
    	if [ "$model" == "iSCSIDisk" ] ; then
	    echo "Filter out $i because $model"
	    drivenames=${drivenames/${i}}
	fi
    done
    
Dan Reading's avatar
Dan Reading committed
57
58
    if [ -z "$drivenames" ] ; then
	echo "No drives found. exit"
59
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    fi

    # array to put drive inventory
    unset -v driveinv ; declare -a driveinv=()
    # array of drives to hold each drive inventory
    unset -v drive ; declare -a drive=($drivenames)

    numberofdrives=${#drive[*]}

   # the index into dirveinv array
    # DISKUNIT SN=<serial> TYPE=<PATA|SATA|SCSI|RAID> SECSIZE=<#> SECTORS=<#> RSPE ED=<MBs> WSPEED=<MBs> 
    declare -i -r header=0
    declare -i -r header_val=1
    declare -i -r name=2
    declare -i -r name_val=3
    declare -i -r driver=4
    declare -i -r driver_val=5
    declare -i -r type=6
    declare -i -r type_val=7
    declare -i -r size=8
    declare -i -r size_val=9
    declare -i -r temp=10
    declare -i -r temp_val=11
    declare -i -r model=12
    declare -i -r model_val=13
    declare -i -r serial=14 
    declare -i -r serial_val=15
    declare -i -r bpers=16
    declare -i -r bpers_val=17
    declare -i -r sectors=18
    declare -i -r sectors_val=19
    declare -i -r wspeed=20    
    declare -i -r wspeed_val=21
    declare -i -r rspeed=22
    declare -i -r rspeed_val=23
95
96
97
    declare -i -r wcache=24
    declare -i -r wcache_val=25
    declare -i -r lastslot=25
Dan Reading's avatar
Dan Reading committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

    # init a default string
    unset -v d; declare -a d=()
    for ((i=0;i<=$lastslot;i++)) ; do
	case $i in
	    $header ) d[$header]="DISKUNIT" ;;
	    $header_val ) d[$header_val]="$header_val" ;;
	    $name ) d[$name]="Device=" ;;
	    $name_val ) d[$name_val]="unset " ;;
	    $driver ) d[$driver]="Driver=" ;;
	    $driver_val ) d[$driver_val]="\"UNKNOWN\" " ;;
	    $type ) d[$type]="TYPE=" ;;
	    $type_val ) d[$type_val]="\"UNKNOWN\"" ;;
	    $size ) d[$size]="Size=" ;;
	    $size_val ) d[$size_val]="unk" ;;
	    $temp ) d[$temp]="Temp=" ;;
	    $temp_val ) d[$temp_val]="unk" ;;
	    $model ) d[$model]="Model=" ;;
	    $model_val ) d[$model_val]="unk" ;;
	    $serial  ) d[$serial]="SN=" ;;
	    $serial_val ) d[$serial_val]="\"UNKNOWN\"" ;;
119
120
	    $wcache  ) d[$wcache]="wcache=" ;;
	    $wcache_val ) d[$wcache_val]="\"UNKNOWN\"" ;;
Dan Reading's avatar
Dan Reading committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	    $bpers ) d[$bpers]="SECSIZE=" ;;
	    $bpers_val ) d[$bpers_val]="unk" ;;
	    $sectors ) d[$sectors]="SECTORS=" ;;
	    $sectors_val ) d[$sectors_val]="\"UNKNOWN\"" ;;
	    $wspeed   ) d[$wspeed]="WSPEED=" ;;
	    $wspeed_val ) d[$wspeed_val]="\"UNKNOWN\"" ;;
	    $rspeed ) d[$rspeed]="RSPEED=" ;;
	    $rspeed_val ) d[$rspeed_val]="\"UNKNOWN\"" ;;
	esac
    done

    #default string
    driveinvinit="${d[@]}"

    # initalize the driveinv array
    for ((idx=0; idx<$numberofdrives; idx++)) ; do
	driveinv[$idx]="$driveinvinit" 
    done

    #now fill in the array values
    for ((idx=0; idx<$numberofdrives; idx++)) ; do
	unset -v d ; declare -a d=(${driveinv[$idx]})
	for ((i=0;i<=$lastslot;i++)) ; do
	    case $i in
		$header_val ) d[$header_val]="$idx" ;;
		$name_val ) d[$name_val]="${drive[$idx]}" ;;
		$sectors_val ) d[$sectors_val]=$(getsectors ${drive[$idx]}) ;;
		$bpers_val ) d[$bpers_val]=$(getbpers ${drive[$idx]}) ;;
		$driver_val ) d[$driver_val]=$(getdriver ${drive[$idx]}) ;;
		$type_val ) d[$type_val]=$(gettype ${drive[$idx]}) ;;
		$temp_val ) d[$temp_val]=$(gettemp ${drive[$idx]}) ;;
		$model_val ) d[$model_val]=$(getmodel ${drive[$idx]}) ;;
		$serial_val ) d[$serial_val]=$(getserial ${drive[$idx]}) ;;
	    esac
	done
156
	# Must have sectors_val an bpers_val before calculating size
Dan Reading's avatar
Dan Reading committed
157
158
159
160
161
162
163
164
	for ((i=0;i<=$lastslot;i++)) ; do
	    case $i in
		$size_val ) 
		x=$((${d[$sectors_val]}*${d[$bpers_val]}))
		d[$size_val]=$(($x / 1000000000))		
		;;
	    esac
	done
165
166
167
	# Must have size val before attempting disk speed tests
	if (( $mfsmode == 1 )) ; then
	    for ((i=0;i<=$lastslot;i++)) ; do
168
169
		# moved here getwcache so it will only run in mfsmode, and will run befor read/write test 
		d[$wcache_val]=$(getwcache ${drive[$idx]})
170
171
172
		case $i in
		    $rspeed_val ) 
		# check the size, if small then might be a USB drive
173
		    if [ ${d[$size_val]} -gt 8 ] ; then
174
175
			d[$rspeed_val]=$(getrspeed ${drive[$idx]})
		    else
176
			d[$type_val]="SMALL"
177
178
179
		    fi
		    ;;
		    $wspeed_val ) 
Dan Reading's avatar
Dan Reading committed
180
# XXX test to call getwcache a second time just before write-test - really for testing only
181
		    d[$wcache_val]=$(getwcache ${drive[$idx]})
182
		    if [ ${d[$size_val]} -gt 8 ] ; then
183
184
			d[$wspeed_val]=$(getwspeed ${drive[$idx]})
		    else
185
			d[$type_val]="SMALL"
186
187
188
189
190
191
		    fi
		    ;;
		esac
	    done
	fi
	
Dan Reading's avatar
Dan Reading committed
192
193
194
	# update driveinv with modified data
	driveinv[$idx]=${d[@]}
    done
Dan Reading's avatar
Dan Reading committed
195
    
196
    if (( $collect_flag )) ; then
197
198
199
	printf "%s%d\n"  "DISKINFO UNITS=" ${numberofdrives} >> ${logfile4tb}
	for (( idx=0; idx<$numberofdrives; idx++)) ; do
	    unset -v d ; declare -a d=(${driveinv[$idx]})
200
	    printf "%s %s\""%s\"" %s\""%s\"" %s%s %s%s %s%s %s%s %s%s" \
201
202
		${d[$header]} \
		${d[$serial]} ${d[$serial_val]} \
203
		${d[$wcache]} ${d[$wcache_val]} \
204
205
206
207
208
209
210
211
212
213
214
215
216
		${d[$type]} ${d[$type_val]} \
		${d[$bpers]} ${d[$bpers_val]} \
		${d[$sectors]} ${d[$sectors_val]} \
		${d[$wspeed]} ${d[$wspeed_val]} \
		${d[$rspeed]} ${d[$rspeed_val]} >> ${logfile4tb}
	    printf " %s%s %s%s %s%s %s%s %s%s\n" \
		${d[$name]} ${d[$name_val]} \
		${d[$size]} ${d[$size_val]} \
		${d[$temp]} ${d[$temp_val]} \
		${d[$model]} ${d[$model_val]} \
		${d[$driver]} ${d[$driver_val]} >> ${logfile4tb}
	done
    fi
Dan Reading's avatar
Dan Reading committed
217
218

# we are done if in MFS mode
219
220
221
if (( $mfsmode )) ; then
    (( $diskcheck_standalone )) && exit 0 || return 0
fi
222

Dan Reading's avatar
Dan Reading committed
223
224
#output to log file
{
225
echo "Diskcheck $(date): "
226
echo -e "name\t\tdriver\ttype\tsize\ttemp\tmodel\t\t\tserial\t\twcache"
Dan Reading's avatar
Dan Reading committed
227
228
for ((idx=0; idx<${numberofdrives}; idx++)) ; do
    unset -v d ; declare -a d=(${driveinv[$idx]})
229
    echo -e "${d[$name_val]}\t${d[$driver_val]}\t${d[$type_val]}\t${d[$size_val]}\t${d[$temp_val]}\t${d[$model_val]}\t\t${d[$serial_val]}\t${d[$wcache_val]}"
Dan Reading's avatar
Dan Reading committed
230
231
232
233
234
235
236
237
done
} > ${tmplog} 2>&1
cat ${tmplog} >> ${logfile} 

driveinfo=""
# echo name,size and serial to stdout, addr serialnumber
for ((idx=0; idx<${#driveinv[*]}; idx++)) ; do
    unset -v d ; declare -a d=(${driveinv[$idx]})
238
    echo -n "${d[$name_val]} ${d[$size_val]} ${d[$serial_val]} ${d[$wcache_val]}  "
239
    driveinfo+="${d[$serial_val]} "
Dan Reading's avatar
Dan Reading committed
240
done
241
echo ""
Dan Reading's avatar
Dan Reading committed
242
243
244

driveinfo=${driveinfo% } # get rid of trailing space

245
if (( $check_flag )) ; then
Dan Reading's avatar
Dan Reading committed
246
# Now check against the testbed DB
247
248
249
250
251
252
# readtmcinfo /proj/emulab-ops/nodecheck/pc507/pc507  tmccinfo
    tbinfo=$(getfromtb DISKUNIT)
    tbinfo=${tbinfo% }  # get rid of trailing space
    
# echo driveinfo:$driveinfo: tbinfo:$tbinfo: 
{
Dan Reading's avatar
Dan Reading committed
253
#save for both output to stdout and log file 
254
255
256
257
258
259
260
261
    if [ -z "$tbinfo" ] ; then
	failed="TBmiss no info"
	echo "TBmiss empty info returned. "
    fi
    
#upper case
    tbinfo=${tbinfo^^}
    driveinfo=${driveinfo^^}
262

Dan Reading's avatar
Dan Reading committed
263
# turn space seperated string into array
264
265
    unset -v tb; declare -a tb=(${tbinfo// / })
    unset -v have; declare -a have=(${driveinfo// / })
266
267

#   lines commented with #-# disable the checking of HD order
268
269
270
    
    havecnt=${#have[*]}
    tbcnt=${#tb[*]}
271
272
273
#-#     numserial=${tbcnt}
#-#     maxcnt=${tbcnt}
#-#     
274
    if [[ ${tbcnt} -ne ${havecnt} ]] ; then
275
276
	failed="TBmiss "
#-#     [[ ${tbcnt} -gt ${havecnt} ]] && maxcnt=${tbcnt} || maxcnt=${havecnt}
277
    fi
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#-#     
#-#     for ((idx=0; idx<$maxcnt; idx++)) ; do
#-# 	for ((ifi=0; ifi<$havecnt; ifi++)) ; do
#-# 	    for ((tbi=0; tbi<$tbcnt; tbi++)) ; do
#-# 		if [ "${have[$ifi]}" = "${tb[$tbi]}" ] ; then
#-# 		    have[$ifi]=''
#-# 		    tb[$tbi]=''
#-# 	    fi
#-# 	    done
#-# 	done
#-#     done
#-# #turn array into string
     haveresult=${have[@]-""}
     tbresult=${tb[@]-""}
# comment out the next if statment and uncommet the #-# lines for drive
# ordering not to matter when comparing drives found with tbdb
Dan Reading's avatar
Dan Reading committed
294
295
     if [[ "$haveresult" != "$tbresult" ]] ; then
	 failed=" found $haveresult but tbdb says $tbresult "
296
297
     fi
#-#     
Dan Reading's avatar
Dan Reading committed
298
#-#     if [[ "$haveresult" != "$tbresult" ]] ; then
299
300
301
302
303
304
305
#-# 	if [[ $haveresult ]] ; then
#-# 	    failed="${failed}: NotIn TB $haveresult"
#-# 	fi
#-# 	if [[ $tbresult ]] ; then
#-# 	    failed="${failed}: TB Claims $tbresult"
#-# 	fi
#-#     fi
306
307
308
309
    
    echo -n "Have $havecnt drive"
    [[ ${havecnt} -gt 1 ]] && echo -n "s" 
    [[ -z ${failed} ]] && echo " OK" || echo " $failed" FAILED
Dan Reading's avatar
Dan Reading committed
310
311

} > ${tmplog} 2>&1
312
313
    cat ${tmplog} >> $logfile
    cat ${tmplog}
314
fi # matching endif of (( $check_flag ))
Dan Reading's avatar
Dan Reading committed
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
}

getdriveinfo () {
#need to make sure smartcrl is installed
{
#    echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "args::$@::"
    declare buildscan=""
    logout="$1"
    tmpout="$2"

    if [ "${SMARTCTL}" != "$NOSM" ] ; then
	rtn=$($SMARTCTL --scan)
	# unrecongnized
	if [ -n "$(echo $rtn | grep 'UNRECOGNIZED OPTION')" ] ; then
	    error="(smartctl option '--scan' not supported. Attempt alternet method) "
	    err=scan
	elif [ -n "$(echo $rtn | grep -v 'device')" ] ; then
            # output in unexpected format - missing deliminator "device"
	    error="(smartctl option '--scan' strange ouput. Attempt alternet method) "
	    err=scan
	# empty
	elif [ -z "$rtn" ] ; then
	    dt=$(df / | grep /dev)
	    dt=${dt:5}
	    dt=${dt%% *}
	    error="(smartctl device_type '$dt' not supported"
	    err=device
	fi
	[[ $error ]] && echo "$error"
    else
	error="smartmontools missing."
	err="missing"
	echo "$error. FAIL "
    fi
} > ${logout} 2>&1

# put smartctl --scan into driveinv array
# a better control flow control could be used 

placeholder=" . . . . . device"
case $err in
    scan | missing | device )
	case $os in
	    Linux )
		list="a b c d e f g h i j k l m n o p"
		for i in $list
		do
		    if [ -b /dev/sd${i} ] ; then
			buildscan+="/dev/sd${i} $placeholder"
		    fi
		done
		;;
	    FreeBSD )
		list="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
		for i in $list
		do
		    [[ -b /dev/da${i} ]] && buildscan+="/dev/da${i} $placeholder " 
		    [[ -c /dev/ad${i} ]] && buildscan+="/dev/ad${i} $placeholder " 
		    [[ -c /dev/amrd${i} ]] && buildscan+="/dev/amrd${i} $placeholder " 
		done
		;;
	    * )
		echo "${FUNCNAME[0]}:${LINENO} Internal error"
378
		(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
		;;
	esac
	unset -v scan
	[[ $buildscan ]] && declare -a scan=($buildscan) || declare -a scan=("")
#	echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "buildscan::${buildscan}::"
	;;
    root )
	echo -n "$error. FAIL " >> ${tmpout}
	echo "Last attempt return roots mount point" >> ${tmpout}
	x=$(df / | grep /dev)
	lastattempt="${x%% *} $placeholder "
	unset -v scan ; declare -a scan=($lastattempt)
	;;
    * )
        # get the output of --scan into array scan
	 unset -v scan ; declare -a scan=($rtn)
#	 echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "rtn::${rtn}::"
	;;
esac

# the result
echo -n "${scan[@]}"

}

getdriver() { 
    # don't support this right now
#    smtcl=$(findSmartctl)
#    if [ "${smtcl/smartcl}" == "$smtcl" ] ; then
#	echo "UNKNOWN"
#	return 0
#    fi
411
    echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
412
413
414
415
416
    return 0
}
gettype() { 
    smtcl=$(findSmartctl)
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
417
	echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
	return 0
    fi
    res=$($smtcl -i $1 | grep "ATA Version is")
    if [ -n "$res" ] ; then
	res=${res##*is: }
	res=${res// /} #get rid of spaces
	[[ $res > 6 ]] && res="SATA" || res="PATA"
	echo $res
	return 0
    fi
    res=$($smtcl -i $1 | grep "SAS")
    if [ -n "$res" ] ; then
	echo "SAS"
	return 0
    fi
    res=$($smtcl -i $1 | grep "SCSI")
    if [ -n "$res" ] ; then
	echo "SCSI"
	return 0
    fi
    echo "UNKNOWN"
    return 0
}
gettemp() { 
    smtcl=$(findSmartctl)
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
444
	echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
445
446
447
448
449
450
451
452
453
454
455
456
	return 0
    fi
    res="$($smtcl  -l scttempsts $1 | grep -i "Current Temperature:" | awk '{print $3}')"
    if [ -z $res ] ; then
        #type 2
	res="$($smtcl -a $1 | grep -i "Current Drive Temperature:" | awk '{print $4}')"
    fi
    [[ $res ]] && echo $res || echo "UNKNOWN"
    return 0
}
getmodel() { 
    smtcl=$(findSmartctl)
Dan Reading's avatar
Dan Reading committed
457

Dan Reading's avatar
Dan Reading committed
458
459
460
461
462
463
464
465
466
467
468
469
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use hdparm
	hdp=$(which hdparm)
	if [ "${hdp/hdparm}" != "${hdp}" ] ; then
	    x=$(hdparm -I $1 | grep -i 'Model Number:')
	    x=${x/Model Number: }
	    res=${x/# */}
	    res=${res%# */}
	    # note: can get the model from '/proc/scsi/scsi'
	else
	    # XXX 	# note: 'camcontrol devlist'
	                # will give model on FreeBSD
470
	    echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
471
472
473
474
475
476
477
478
479
480
	    return 0
	fi
    else
	res=$($smtcl -a $1 | grep 'Device Model:')
	res=${res/Device Model: }
	if [ -z "$res" ] ; then
	    res=$($smtcl -a $1 | grep 'Product:')
	    res=${res/Product: }
	fi
        # remove leading spaces
Dan Reading's avatar
Dan Reading committed
481
#	res=${res##* }
Dan Reading's avatar
Dan Reading committed
482
483
484
485
    fi
    # no internal spaces
    res=${res// /}
    res=${res// /-}
Dan Reading's avatar
Dan Reading committed
486
487


Dan Reading's avatar
Dan Reading committed
488
489
490
491
492
493
494
495
496
497
498
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
getserial() {
    res=""
    if [ "$os" == "Linux" ] ; then
	smtcl=$(findSmartctl)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use hdparm
	    hdp=$(which hdparm)
	    if [ "${hdp/hdparm}" != "${hdp}" ] ; then
499
		res=$(hdparm -I $1 2>/dev/null | grep -i 'Serial number:')
Dan Reading's avatar
Dan Reading committed
500
501
502
503
504
505
506
507
508
509
510
511
	    fi
	else
	    res=$($smtcl -a $1 | grep -i 'Serial number:')
	fi
	res=${res,,} # lower case
	res=${res/serial number: }
#	res=$(echo $res | tr 'a-z' 'A-Z') # upper case
	res=${res^^} # upper case
    fi
    if [ "$os" == "FreeBSD" ] ; then
	# note: if the device is mfi then 'mfiutil show drives' will list
	# serial numbers 
512
513
514
515
516
517
518
	smtcl=$(findSmartctl)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use camcontrol
	    cmc=$(which camcontrol)
	    if [ "${cmc/camcontrol}" != "${cmc}" ] ; then
		sd=$1
		sd=${sd#/dev/}
519
		res=$(camcontrol inquiry $sd -S 2>/dev/null)
520
521
522
523
524
525
526
	    fi
	else
	    res=$($smtcl -a $1 | grep -i 'Serial number:')
	    res=${res,,} # lower case
	    res=${res/serial number: }
#	    res=$(echo $res | tr 'a-z' 'A-Z') # upper case
	    res=${res^^} # upper case
Dan Reading's avatar
Dan Reading committed
527
528
529
530
531
	fi
    fi
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
532
getwcache() {
533
    res="NA"
534
535
536
    if [ "$os" == "Linux" ] ; then
	smtcl=$(findSmartctl_getopt)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
537
	    # don't have smartctl, maybe we can use hdparm
538
539
540
	    hdp=$(which hdparm)
	    if [ "${hdp/hdparm}" != "${hdp}" ] ; then
		x=$(hdparm -W $1 2>/dev/null | grep -i 'write-caching')
541
		if [ "${x/on}" != "$x" ] ; then
542
		    res="enabled"
543
544
		elif [ "${x/off}" != "$x" ] ; then
		    res="disabled"
545
		    hdparm -W1 $1  > /dev/null 2>&1
546
547
548
		fi
	    fi
	else
549
550
	    x=$($smtcl --get=wcache $1 | grep -i Write | grep -i cache)
	    if [ "${x/Enabled}" != "$x" ] ; then
551
		res="enabled"
552
553
	    elif [ "${x/Disabled}" != "$x" ] ; then
		res="disabled"
554
		$smtcl --set=wcache,on $1 > /dev/null 2>&1
555
556
	    else
		res="WCE_not_supported"
557
558
	    fi
	fi
559
560
561
    elif [ "$os" == "FreeBSD" ] ; then
	# try camcontrol first
	cmc=$(which camcontrol)
562
#set -x
563
564
	if [ "${cmc/camcontrol}" != "${cmc}" ] ; then
	    sd=${1#/dev/}		
Mike Hibler's avatar
Mike Hibler committed
565
	    x=$(camcontrol modepage $sd -m8 2>/dev/null | grep WCE)
566
567
568
569
	    if [ "${x/1}" != "$x" ] ; then
		res="enabled"
	    elif [ "${x/0}" != "$x" ] ; then
		res="disabled"
570
		printf " %s:%d "  "Setting WCE" ${$sd} >> ${logfile4tb}
571
572
		/usr/local/etc/emulab/camwce -P on $sd  > /dev/null 2>&1
	    fi
573
#set +x
574
575
576
577
578
579
	else
	# don't have don't have camcontrol, maybe we can use smartctl
	    smtcl=$(findSmartctl_getopt)
	    if [ "${smtcl/smartctl}" != "$smtcl" ] ; then
		x=$($smtcl --get=wcache $1 | grep -i Write | grep -i cache)
		if [ "${x/Enabled}" != "$x" ] ; then
580
		    res="enabled"
581
		elif [ "${x/Disabled}" != "$x" ] ; then
582
		    res="disabled"
583
		    $smtcl --set=wcache,on $1 > /dev/null 2>&1
584
585
586
		fi
	    fi
	fi
587
588
589
    else
	echo "try to get WCE unknown OS $os"
	return 0
590
591
592
593
    fi
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
Dan Reading's avatar
Dan Reading committed
594
595
596
597
598
599
600
getbpers() { 
    hdname=$1
    case $os in
	Linux )
	    hdname=${hdname##*/}
	    res=$(dmesg | grep "logical blocks" | grep $hdname)
	    if [ -z "$res" ] ; then
601
		res=$(dmesg | grep "hardware sectors" | grep $hdname)
Dan Reading's avatar
Dan Reading committed
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	    fi
	    res=${res%%-byte *}
	    res=${res##*] }
	    res=${res#* }
	    [[ $res ]] || res=512
	    ;;
	FreeBSD )
	    hdname=${hdname##*/}
	    res=$(grep sectors /var/run/dmesg.boot | grep $hdname)
	    if [ -z "$res" ] ; then
		hdnamex=${hdname/ad/ada}
		res=$(grep sectors /var/run/dmesg.boot | grep $hdnamex)
		if [ -z "$res" ] ; then
		    echo 512
		    return 0
		fi
	    fi
	    if [ "$res" == "${res/sectors)}" ] ; then
		# this format: "da0: 140014MB (286749480 512 byte sectors: 255H 63S/T 17849C)"
		res=${res%%byte sectors*}
		res=${res##*(}
		res=${res#* }
	    else
		# this format: "mfid0: 5869927MB (12021612416 sectors) RAID volume '' is optimal"
		# just assume 512
		res=512
	    fi
	    [[ $res ]] || res=512
	    ;;
	* ) echo "$FUNCNAME internal error"
632
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
633
634
635
636
637
638
639
640
641
642
643
644
645
	    ;;
    esac
    echo $res
    return 0
}

getsectors() { 
    hdname=$1
    case $os in
	Linux )
	    hdname=${hdname##*/}
	    res=$(dmesg | grep "logical blocks" | grep $hdname)
	    if [ -z "$res" ] ; then
646
647
648
		res=$(dmesg | grep "hardware sectors" | grep $hdname)
	    else
		res=${res%%-byte *}
Dan Reading's avatar
Dan Reading committed
649
650
	    fi
	    res=${res##*] }
651
            res=${res%% *}
Dan Reading's avatar
Dan Reading committed
652
653
654
655
656
657
	    [[ $res ]] || res=0
	    ;;
	FreeBSD )
	    hdname=${hdname##*/}
	    res=$(grep sectors /var/run/dmesg.boot | grep $hdname)
	    if [ -z "$res" ] ; then
Mike Hibler's avatar
Mike Hibler committed
658
659
660
661
662
663
664
665
666
667
668
669
		# XXX fixme right
		case $hdname in
		    ad4 ) hdnamex="ada0" ;;
		    ad6 ) hdnamex="ada1" ;;
		    ad8 ) hdnamex="ada2" ;;
		    ad10 ) hdnamex="ada3" ;;
		    ad12 ) hdnamex="ada4" ;;
		    ad14 ) hdnamex="ada5" ;;
		    ad16 ) hdnamex="ada6" ;;
		    ad18 ) hdnamex="ada7" ;;
		    * )   hdnamex=$hdname ;;
		esac
Dan Reading's avatar
Dan Reading committed
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
		res=$(grep sectors /var/run/dmesg.boot | grep $hdnamex)
		if [ -z "$res" ] ; then
		    res=$(grep ${hdname} /var/run/dmesg.boot)
		    if [ -z "$res" ] ; then
			echo 0
			return 0
		    fi
		    # fake and go by the size 
		    res=${res%%MB*}
		    res=${res##* }
		    echo $(( $res * 2048 )) # assume 512 byte sectors
		    return 0
		fi
	    fi
	    if [ "$res" == "${res/sectors)}" ] ; then
	        # this format: "da0: 140014MB (286749480 512 byte sectors: 255H 63S/T 17849C)"
		res=${res%%byte sectors*} # truncate 'byte sectors' to end
		res=${res##*(} # chop off begining to sector number
		res=${res%% *} # get rid of everthing after the space
	    else
		# this format: "mfid0: 5869927MB (12021612416 sectors) RAID volume '' is optimal"
		res=${res%%sectors)*}
		res=${res##*(}
		res=${res%% *}
	    fi
	    [[ $res ]] || res=0
	    ;;
	* ) echo "$FUNCNAME internal error"
698
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
699
700
701
702
703
704
	    ;;
    esac
    echo $res
    return 0
}

705
706
707
708
709
710
711

getwspeed() {
    hdname=$1
    # disk is mounted somewhere then don't do the raw write speed
    canwe=$(df | grep $hdname)
    [[ $canwe ]] && { echo mounted; return 0; }

Dan Reading's avatar
Dan Reading committed
712
    dd=$USE_DD
713
714
715
    [[ -x $dd ]] || { echo "$dd"; return 0; }
    args=$(ddargs)

Dan Reading's avatar
Dan Reading committed
716
    add_on_exit 'rm -f /tmp/ddresultw'
Dan Reading's avatar
Dan Reading committed
717
    [[ -n "$TDD_DD" ]] && export TDD_DD
Mike Hibler's avatar
Mike Hibler committed
718
    $dd if=/dev/zero of=$hdname $args >/tmp/ddresultw 2>&1
Dan Reading's avatar
Dan Reading committed
719
    res=$(grep bytes /tmp/ddresultw)
720

Dan Reading's avatar
Dan Reading committed
721
722
723
    echo $(parsedd $res)
    return 0
}
724

Dan Reading's avatar
Dan Reading committed
725
726
getrspeed() { 
    hdname=$1
727

Dan Reading's avatar
Dan Reading committed
728
    # do we have a working dd
Dan Reading's avatar
Dan Reading committed
729
    dd=$USE_DD
730
731
    [[ -x $dd ]] || { echo "$dd"; return 0; }
    args=$(ddargs)
732

Dan Reading's avatar
Dan Reading committed
733
    add_on_exit 'rm -f /tmp/ddresultr'
Dan Reading's avatar
Dan Reading committed
734
    [[ -n "$TDD_DD" ]] && export TDD_DD
Mike Hibler's avatar
Mike Hibler committed
735
    $dd of=/dev/null if=$hdname $args >/tmp/ddresultr 2>&1
Dan Reading's avatar
Dan Reading committed
736
    res=$(grep bytes /tmp/ddresultr)
737

Dan Reading's avatar
Dan Reading committed
738
739
740
741
742
743
744
745
    echo $(parsedd $res)
    return 0
}

parsedd() {
    if [ "$os" == "Linux" ] ; then 
	# linux dd returns 9 positional elements
	if [ $# -lt 9 ] ; then
746
	    x="DDparseERR"
Dan Reading's avatar
Dan Reading committed
747
748
749
750
751
	else
	    y=$9
	    if [ $y != ${y/MB} ] ; then
		x=$8
	    else
752
		x="ParesddError"
Dan Reading's avatar
Dan Reading committed
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
	    fi
	fi
    elif [ "$os" == "FreeBSD" ] ; then 
	if [ $# -lt 8 ] ; then
	    x="DDtimeinERR"
	else
            x=$7
	    x=${x#(}
	    y=$8
	    # FreeBSD seems to return val in bytes/sec, check and convirt to Mb/sec
	    if [ "$y" == "bytes/sec)" ] ; then
		x=$(( $x / 1048576 ))
	    fi
	fi
    fi
    echo $x
    return 0
}

772
main_diskcheck $@
Dan Reading's avatar
Dan Reading committed
773

774
(( $diskcheck_standalone )) && exit 0 || return 0