rc.frisbee 17.4 KB
Newer Older
1
#!/bin/sh
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2
#
3
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 
# {{{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/>.
# 
# }}}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
23
#
24
25
26
27
28
29
# Optional flag argument says "do not reboot"
#
reboot=1
if [ $# -eq 1 -a "$1" = "-noreboot" ]; then
    reboot=0
fi
Leigh B. Stoller's avatar
Leigh B. Stoller committed
30

31
32
echo "`date`: rc.frisbee starting"

33
34
35
36
37
38
#
# Amount of memory in MB to leave for everyone else in the system.  If you
# get out-of-memory or vm_pager error while running frisbee, increase this.
#
RESIDMEM=32

39
40
41
42
43
44
#
# Maximum socket buffer size in KB.
# Big enough to buffer a whole chunk.
#
MAXSOCKBUF=1024

45
46
47
48
if [ -r /etc/emulab/paths.sh ]; then
	. /etc/emulab/paths.sh
else
	BINDIR=/etc/testbed
49
	BOOTDIR=/etc/testbed
50
51
52
53
54
55
56
	ETCDIR=/etc/testbed
fi

# Behave a little different on widearea nodes.
isrem=0
if [ -e $ETCDIR/isrem ]; then
    isrem=1
57
fi
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#
# Extract a variable of interest from the VAR=VALUE string and return value.
# If variable does not exist, return the given default (if provided).
#
getvar() {
    _VAR=$1
    _STR=$2
    _DFL=$3

    for _kv in $_STR; do
	_k=${_kv%%=*}
	if [ -n "$_k" -a "$_k" = "$_VAR" ]; then
	    echo "${_kv##*=}"
	    return 0
	fi
    done
    echo "$_DFL"
    return 0
}

79
80
81
82
83
84
85
#
# Update the MBR of the given disk to the indicated "version."
#
# XXX this is somewhat of a hack right now.  We recognize two
# versions of the MBR:
#	v1 (partition 1 size 6281352)
#	v2 (partition 1 size 12305790)
86
#	v3 (partition 1 size 33554432)
87
88
89
90
91
92
# Currently we only install a new MBR if the existing one is the
# wrong size, just in case the user has customized the boot program.
#
tweakmbr() {
    _DSK=$1
    _NEW=$2
93
    _ALWAYS=$3
94
95
96
97
98
99
100
101
102
103
104
105

    dd if=/dev/$_DSK of=/dev/null bs=512 count=1 2>/dev/null || {
	echo "WARNING: could not read from $_DSK, MBR not changed"
	return
    }

    _size=`fdisk -s $_DSK 2>/dev/null | sed -n -e 's/^ *1: *[0-9][0-9]* *\([0-9][0-9]*\).*$/\1/p'`
    case ${_size}s in
    6281352s)
	_CUR=1
	;;
    12305790s)
106
	_CUR=2
107
	;;
108
109
110
    33554432s)
	_CUR=3
	;;
111
112
    s)
        # special case: no part1 so probably no MBR at all, make sure we install
113
	echo "Found no MBR on $_DSK, installing version $_NEW"
114
115
116
	_CUR=1000000
	;;
    *)
117
118
119
120
121
122
123
        if [ $_ALWAYS -eq 1 ]; then
	    echo "WARNING: overwriting unknown MBR on $_DSK with version $_NEW"
	    _CUR=1000000
	else
	    echo "WARNING: custom MBR on $_DSK, not changed"
	    return
	fi
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    	;;
    esac

    if [ $_CUR = $_NEW ]; then
	return
    fi

    # now set it if we can
    if [ ! -r "/etc/emulab/mbr${_NEW}.dd" ]; then
	echo "WARNING: cannot find MBR version $_NEW, not installed"
	return
    fi

    echo "Installing MBR version $_NEW ..."
    dd if=/etc/emulab/mbr${_NEW}.dd of=/dev/$_DSK bs=512 count=1
}

141
find_disks() {
Mike Hibler's avatar
Mike Hibler committed
142
143
144
    _DISKS=""
    for d in `sed -n 's/^\([a-z]*[0-9][0-9]*\): [0-9][0-9]*MB/\1/p' /var/run/dmesg.boot`; do
	case $d in
145
	    ad*|da*|ar*|aacd*|amrd*|mfid*|mfisyspd*) _DISKS="$_DISKS $d"
Mike Hibler's avatar
Mike Hibler committed
146
147
	esac
    done
148

Mike Hibler's avatar
Mike Hibler committed
149
    echo $_DISKS
150
151
}

152
153
154
155
156
157
158
159
160
161
162
#
# Function to zero all potential superblocks in the DOS partitions that
# could interfere with the OSes on the image being loaded.
#
# FreeBSD 4 or 5 goes out of its way to make this hard.  In FBSD4, we
# cannot overwrite the beginning of partitions that have a legit superblock.
# In FBSD5, DOS partitions that have a zero type cannot even be accessed.
# So we have to use the whole-disk special file using offsets extracted
# via fdisk.
#
zapsuperblocks() {
Mike Hibler's avatar
Mike Hibler committed
163
    _DSK=$1
164
165
166
167
168

    #
    # Note we are not overly concerned about the consequences of misparsing
    # the fdisk output.  If we whack random blocks, it doesn't hurt anything.
    #
Mike Hibler's avatar
Mike Hibler committed
169
    offs=`fdisk -s $_DSK 2>/dev/null | sed -n -e 's/^[ 0-9]*: *\([0-9]*\).*$/\1/p'`
170
171
172
173
174

    if [ x"$offs" = x ]; then
        return
    fi

Mike Hibler's avatar
Mike Hibler committed
175
    echo -n "Invalidating old potential superblocks on $_DSK: "
176
177
    for off in $offs; do
        echo -n "$off "
Mike Hibler's avatar
Mike Hibler committed
178
	dd if=/dev/zero of=/dev/${_DSK} oseek=$off count=16 >/dev/null 2>&1 || {
179
180
181
182
183
184
185
186
	    echo "WARNING: failed to invalidate $off"
	}
    done
    echo ""

    return
}

187
188
189
190
#
# Function to load a single image on a disk
#
loadone() {
191
192
193
194
    _DISK=$1
    _PART=$2
    _LOADINFO=$3
    _NUM=$4
Mike Hibler's avatar
Mike Hibler committed
195
196
197

    echo "Loading image #$_NUM"

198
199
200
201
202
203
204
205
206
    ADDR=`getvar ADDR "$_LOADINFO"`;
    SERVER=`getvar SERVER "$_LOADINFO" $BOSSIP`;
    PARTOS=`getvar PARTOS "$_LOADINFO" unknown`;
    ZFILL=`getvar ZFILL "$_LOADINFO" 0`;
    MBRVERS=`getvar MBRVERS "$_LOADINFO" 1`;
    PREPARE=`getvar PREPARE "$_LOADINFO" 0`;
    IMAGEID=`getvar IMAGEID "$_LOADINFO"`;
    KEEPALIVE=`getvar KEEPALIVE "$_LOADINFO"`;
    OSVERSION=`getvar OSVERSION "$_LOADINFO" 0`;
207

208
209
210
211
212
213
214
215
216
217
218
219
    #
    # XXX If KEEPALIVE is not explicitly set, attempt to intuit a value.
    #
    # It appears that FreeBSD 8.x's IGMP v3 implementation doesn't
    # properly sent V2 reports when it is connected to a V2-only querier
    # (switch). It insists on sending V3 reports event when the default
    # version is set to 2. So if detect that we have the newer IGMP
    # implementation, we will use the V2 keep alive mechanism in the
    # frisbee client.
    #
    if [ -z "$KEEPALIVE" ]; then
	igmpversion=`sysctl -n net.inet.igmp.default_version 2>/dev/null`
220
	if [ -n "$igmpversion" ]; then
221
222
223
224
225
226
227
	    echo "WARNING: possible IGMP issues; using frisbee keep alive timer"
	    KEEPALIVE=30
	else
	    KEEPALIVE=0
	fi
    fi

228
229
230
    #
    # One of ADDR or IMAGEID must be set.
    #
231
    if [ -n "$IMAGEID" ]; then
232
233
234
235
236
        ADDR=""
    	# IMAGEID=pid,gid,imagename
	pid=`echo $IMAGEID | awk -F, '{ printf $1 }'`
	name=`echo $IMAGEID | awk -F, '{ printf $3 }'`
	IMAGEID="$pid/$name"
237
    elif [ -z "$ADDR" ]; then
238
239
240
241
	echo "Unable to get imageid or address for loading image"
	return 1
    fi

Mike Hibler's avatar
Mike Hibler committed
242
243
    if [ "$PART" != "0" ]; then
	SLICE="-s $PART"
244
245
246
247
248
249
250
251
252
	case $PARTOS in
	FreeBSD)
		SLICE="$SLICE -D 165"
		PTYPE=165
		;;
	OpenBSD)
		SLICE="$SLICE -D 166"
		PTYPE=166
		;;
253
	Fedora|Linux)
254
255
256
257
258
259
		SLICE="$SLICE -D 131"
		PTYPE=131
		;;
	*)
		;;
	esac
260
    fi
261

262
263
264
265
266
    #
    # set memory limits:
    #	allow $RESIDMEM MB for non-frisbee stuff
    #	split remaining memory (min of 2MB) between network/disk buffering
    #
267
    MEMARGS=""
268
269
270
    HOSTMEM=`sysctl -n hw.usermem`
    HOSTMEM=`expr $HOSTMEM / 1048576`
    if [ $HOSTMEM -ge `expr $RESIDMEM + 2` ]; then
271
	HOSTMEM=`expr $HOSTMEM - $RESIDMEM`
272
	KBYTES=`expr $HOSTMEM \* 1024`
273
	DATASEGSZ=`ulimit -d`
274
275
276
	if [ $KBYTES -gt $DATASEGSZ ]; then
	    KBYTES=$DATASEGSZ
	    HOSTMEM=`expr $KBYTES / 1024`
277
278
	    echo "WARNING: kernel limits buffering to $HOSTMEM MB"
	fi
279
	ulimit -v $KBYTES
280

281
	# Let the client split up the memory
282
	MEMARGS="-M $HOSTMEM"
283
    fi
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

    #
    # Allow for large-ish socketbuf for frisbee
    # NOTE: add 12.5% slop to get socketbuf of the appropriate size
    # NOTE: if the sysctl fails, it doesn't matter as frisbee will downsize
    #
    osbs=`sysctl -n kern.ipc.maxsockbuf`
    sbs=`expr $MAXSOCKBUF \* 1024`
    sbs=`expr $sbs \+ \( $sbs / 8 \)`
    if [ $sbs -gt $osbs ]; then
	sysctl kern.ipc.maxsockbuf=$sbs
    fi

    # NOTE: make sure you install the latest frisbee client for -k!
    MEMARGS="$MEMARGS -k $MAXSOCKBUF"

301
    #
302
303
304
    # Make sure the necessary device files exist (only necessary on
    # FreeBSD 4.x).  Note that we create partition files for all slices,
    # not just slice 1, for the benefit of the slicefix script.
305
306
    #
    if [ -x /dev/MAKEDEV -a ! -e /dev/$DISK ]; then
307
	(cd /dev; ./MAKEDEV $DISK ${DISK}s2a ${DISK}s3a ${DISK}s4a)
308
    fi
309

Mike Hibler's avatar
Mike Hibler committed
310
311
312
    if [ x"$ADDR" != x ]; then
	isurl=`echo $ADDR | grep http -`
	ispath=`echo $ADDR | grep '^/' -`
313
314

	if [ x"$isurl" != x ]; then
Mike Hibler's avatar
Mike Hibler committed
315
	    echo "Need to download $ADDR"
316
317
318
319

	    isurl=1
	    if [ ! -d /images ]; then
		echo "Need to create or mount /images directory!"
320
		return 1
321
	    fi
322

323
324
325
	    #
	    # This needs a lot more work ...
	    #
Mike Hibler's avatar
Mike Hibler committed
326
	    imagefile=`echo $ADDR | sed -e 's,^http[s]*://[^/]*/,,'`
327
328
329
	    imagefile="/images/$imagefile"
	elif [ x"$ispath" != x ]; then
	    ispath=1
330

Mike Hibler's avatar
Mike Hibler committed
331
332
	    if [ ! -e $ADDR ]; then
		echo "$ADDR does not exist!"
333
		return 1
334
	    fi
Mike Hibler's avatar
Mike Hibler committed
335
	    imagefile="$ADDR"
336
	else
Mike Hibler's avatar
Mike Hibler committed
337
338
	    PORT=`echo $ADDR | awk -F: '{ printf $2 }'`
	    MCAST=`echo $ADDR | awk -F: '{ printf $1 }'`
339
340
341
	    if [ -e $BOOTDIR/myip ]; then
		MCASTIF="-i `cat $BOOTDIR/myip`"
	    else
342
		MCASTIF=""
343
344
	    fi
	    MCASTADDR="-m $MCAST -p $PORT"
345
	    IMAGEID="$MCASTIF $MCASTADDR"
346
347
	    isurl=0
	    ispath=0
348
	fi
349
    else
350
351
352
353
	#
	# Note: if you want to use broadcast rather that multicast as
	# the distribution method, add "-X bcast" to the IMAGEID= below.
	#
354
355
356
357
        IMAGEID="-B 30 -F $IMAGEID"
	isurl=0
	ispath=0
    fi
358

359
360
361
362
363
364
365
366
367
    #
    # ZFILL==1: use frisbee
    # ZFILL==2: separate disk-wipe pass (not yet implemented)
    #
    if [ "$ZFILL" != "0" ]; then
	ZFILL="-z"
    else
	ZFILL=""
    fi
368

369
370
371
372
373
374
    if [ "$KEEPALIVE" != "0" ]; then
	KA="-K $KEEPALIVE"
    else
	KA=""
    fi

375
376
377
378
379
380
381
382
383
384
385
    #
    # Make sure the write-cache is enabled on SCSI disks.  It makes a
    # huge difference.  We don't worry about data corruption in the
    # case of a crash, because we will just reload the disk again anyway
    # in that situation.
    #
    turncacheoff=0
    case $DISK in
    da*)
	if [ -x $BINDIR/camwce ] && $BINDIR/camwce on $DISK; then
	    turncacheoff=1;
386
	fi
387
388
	;;
    esac
389

390
391
392
393
394
395
    #
    # For slice images, ensure that the MBR is the correct version
    # and replace if not.
    #
    if [ $_NUM -eq 0 ]; then
	if [ "$PART" != "0" ]; then
396
	    tweakmbr $DISK $MBRVERS $PREPARE
397
	fi
398
399
400
401
        FIRSTMBR=$MBRVERS
    else
	if [ "$FIRSTMBR" != "$MBRVERS" ]; then
	    echo "MBR Mismatch: First MBR is \"$FIRSTMBR\" while image #$_NUM is \"$MBRVERS\""
402
	fi
403
    fi
404

405
406
407
408
409
410
411
    #
    # If a remote node and we have a URL, make sure that we have a place
    # to put it. Done after the MBR tweak of course. Then download the URL.
    #
    if [ $isrem -eq 1 -a $isurl -eq 1 ]; then
	echo "Downloading image \'$ADDR\' to /images directory ..."
	$BINDIR/mkextrafs.pl -c -s 4 -r $DISK /images || {
412
413
	    # XXX run growdisk to ensure we have a partition in the MBR
	    $BINDIR/growdisk -vW /dev/$DISK >/dev/null 2>&1
414
415
416
417
418
419
420
421
	    $BINDIR/mkextrafs.pl -n -f -s 4 -r $DISK /images || {
		echo "Could not create /images partition"
		return 1
	    }
	}
	wget -nv -N -P /images "$ADDR"
	wstat=$?
	case $wstat in
422
	0)
423
	    echo "wget succeeded getting the image"
424
	    ;;
425
	*)
426
427
	    echo "wget failed, status $wstat"
	    return 1
428
	    ;;
429
	esac
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    fi

    #
    # If not zeroing the disk and we are loading a full disk image
    # we need to ensure that we at least invalidate any old superblocks
    # that might leak through (most likely in partition 4 which isn't
    # touched by our current image).  We do this before running frisbee
    # so that any legit filesystems loaded from the image work.
    #
    # Since we do it before frisbee, we are counting on the current
    # MBR being the same as the MBR being layed down.  While not
    # a reasonable assumption in general, it mostly works in our
    # environment and at least won't hurt anything if not true.
    #
    if [ $PREPARE -eq 1 -o \
         \( $isrem -eq 0 -a x"$ZFILL" = x -a "$PART" = "0" \) ]; then
	zapsuperblocks $DISK
    fi

    if [ x"$imagefile" != x ]; then
450
	echo "`date`: Running /usr/local/bin/imageunzip -o -O -W 32 $ZFILL $imagefile /dev/${DISK}s${PART}"
451
	/usr/local/bin/imageunzip -o -O -W 32 $ZFILL $imagefile /dev/${DISK}s${PART}
452
    else
453
	echo "`date`: Running $BINDIR/frisbee -S $SERVER $MEMARGS $KA $ZFILL $SLICE $IMAGEID /dev/$DISK"
454
	$BINDIR/frisbee -S $SERVER $MEMARGS $KA $ZFILL $SLICE $IMAGEID /dev/$DISK
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
    fi
    fstat=$?

    #
    # If we mounted a partition from the disk to store the image,
    # we must unmount it now so that slicefix and others don't fail
    # due to an in-use partition.
    #
    if [ $isrem -eq 1 -a $isurl -eq 1 ]; then
	umount /images || {
	    echo "WARNING: could not unmount /images"
	}
    fi

    #
    # Turn the cache back off if we turned it on.
    # Is this sufficient to ensure the cache gets flushed?
    #
    if [ $turncacheoff -eq 1 ]; then
	$BINDIR/camwce off $DISK
475
    fi
476
477
478
479
480
481
482
483

    case $fstat in
    0)
	;;
    *)
	echo "Frisbee run failed, status $fstat"
	;;
    esac
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    return $fstat
}

#
# Run slicefix on the indicated partition
#
fixone() {
    DISK=$1
    PART=$2
    iline=$3

    echo "`date`: Adjusting slice-related files on $DISK slice $PART"

    export SLICEFIX_ACPI=`getvar ACPI "$iline" unknown`
    export SLICEFIX_ASF=`getvar ASF "$iline" unknown`
    export SLICEFIX_NOCLFLUSH=`getvar NOCLFLUSH "$iline" unknown`
    export SLICEFIX_VGAONLY=`getvar VGAONLY "$iline" unknown`
    export SLICEFIX_CONSOLE=`getvar CONSOLE "$iline" unknown`
    export SLICEFIX_BIOSDISK=`getvar BIOSDISK "$iline" unknown`
    export SLICEFIX_DOM0MEM=`getvar DOM0MEM "$iline" unknown`
    $BINDIR/slicefix $PART $DISK
    return $?
506
507
508
509
510
511
512
513
514
}

$BINDIR/tmcc state RELOADSETUP

BOSSINFO=`$BINDIR/tmcc bossinfo`
STATUS=`$BINDIR/tmcc status`

BOSSIP=`echo $BOSSINFO | awk '{ print $2 }'`

515
516
517
518
NTPIP=`grep -w ntp1 /etc/hosts 2>/dev/null | awk '{ print $1 }'`
if [ -z "$NTPIP" ]; then
    NTPIP=$BOSSIP
fi
519
if [ -x /usr/sbin/ntpdate ]; then
520
	/usr/sbin/ntpdate -b $NTPIP >/dev/null 2>&1
521
522
523
524
525
fi

# Enable IPoD
if [ -r $BINDIR/rc.ipod ]; then
    . $BINDIR/rc.ipod
526
fi
527
528

#
Mike Hibler's avatar
Mike Hibler committed
529
530
# Assign each line (one image) to one of the positional parameters.
# This is done by setting IFS to a newline and using set.
531
532
# XXX there must be a better way to do this!
#
Mike Hibler's avatar
Mike Hibler committed
533
OIFS="$IFS"
534
535
536
IFS='
'
set -- `$BINDIR/tmcc loadinfo`
Mike Hibler's avatar
Mike Hibler committed
537
IFS="$OIFS"
538
if [ -z "$1" ]; then
539
540
541
542
543
544
    echo "No load information for node"
    exit 1
fi

$BINDIR/tmcc state RELOADING

545
546
547
548
549
550
551
552
553
554
# HACK ALERT: If we're reloading we need to zap the superblocks and
# MBRs of any other disks in the system.  This is to prevent Linux from
# finding an old filesystem with the same label or UUID and mounting
# that instead of the right one.  We skip the disks that are mounted
# and the disk we're going to write to.
# DOUBLE HACK ALERT: Changed this to zap all disks to avoid having
# to figure out what the other disks are when loading multiple images.
# Since a new MBR will be laid down anyway there is no harm in doing
# this as long as we are sure we are in the reloading experiment.
case $STATUS in
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
*ALLOCATED=emulab-ops/reloading*)
    disks=`find_disks`
    for d in $disks; do
	#[ $d = $DISK ] && continue
	mount | grep "^/dev/$d" > /dev/null && continue
	zapsuperblocks $d
	echo "Invalidating MBR on $d"
	dd if=/dev/zero of=/dev/$d bs=512 count=16
    done

    #
    # If we have nodecheck, run it. This allows us to both collect HW info
    # (if nodecheck "collect" is enabled in the DB) and to run a destructive
    # disk write speed test (as part of a nodecheck "check" operation).
    #
    if [ -x $BINDIR/rc.nodecheck ]; then
	$BINDIR/rc.nodecheck boot
    fi
    ;;
574
575
esac

576
577
578
579
580
581
582
#
# Load each image in turn.
# If a load fails, we exit non-zero so that the rc script will drop into
# single-user mode.  If all loads succeed we either reboot or continue with
# the rc script as desired by the caller.
#
NUM=0
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
devs=""
while [ -n "$1" ]; do
    iline=$1

    #
    # Remember the info for this partition line so we can run slicefix later.
    # Yes, we can load the same partition multiple times due to our delta
    # image mechanism.
    #
    # Note that we always overwrite the saved info so we wind up with the
    # info for the last image loaded on the slice. Thus we assume that the
    # last image loaded has the right info. Probably this will never matter
    # as delta images should always have the same attributes as the full
    # image loaded.
    #
    DISK=`getvar DISK "$iline" ad0`
    PART=`getvar PART "$iline" 0`
    dev="${DISK}_${PART}"
    devs="$devs $dev"
    eval ${dev}_info=\"$iline\"

    loadone $DISK $PART "$iline" $NUM || {
605
	echo "`date`: Failed to load disk, dropping to login prompt"
606
607
        exit 1
    }
608
    echo "`date`: Image #$_NUM load complete"
609
    NUM=`expr $NUM + 1`
610
    shift
611
done
612
echo "`date`: Frisbee run(s) finished"
613

614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
echo "`date`: Running slicefix"
for dev in $devs; do
    DISK=${dev%%_*}
    PART=${dev##*_}
    eval iline=\$${dev}_info
    if [ -n "$iline" ]; then
	fixone $DISK $PART "$iline" || {
	    echo "`date`: WARNING: slicefix on $DISK slice $PART failed"
	}
	# whack the info so we don't slicefix again
	eval ${dev}_info=\"\"
    fi
done
echo "`date`: slicefix run(s) done"

629
echo "`date`: Resizing final disk partition"
630
$BINDIR/growdisk -vW /dev/$DISK
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

#
# If requested to reboot, do so.
#
# Note: there is a race condition with stated here.
# If we reboot immediately after sending RELOADDONE,
# it is possible that, under heavy server load, we will
# finish the reboot and reach the bootinfo stage before
# stated gets and processes our RELOADDONE.  So now we
# wait around after sending the RELOADDONE.  stated should
# force us to reboot when the transition takes place.
# For backward compatibility we use a new state: RELOADDONEV2.
# For paranoia we just wait around for awhile and then
# reboot anyway, just in case stated's reboot fails for
# some reason.
#
if [ $reboot -eq 1 ]; then
    $BINDIR/tmcc state RELOADDONEV2
649
    echo "`date`: Waiting for server to reboot us ..."
650
651
652
    if [ $isrem -eq 1 ]; then
	sleep 30
    else
653
	sleep 300
654
    fi
655
    echo "`date`: No response from server, rebooting myself ..."
656
657
658
659
660
661
    /sbin/reboot
    sleep 100
else
    $BINDIR/tmcc state RELOADDONE
fi

662
echo "`date`: rc.frisbee finished"
663
664

exit 0