xref: /plan9/rc/bin/fshalt (revision 15bfe97de97771872f389e30cbf1ae2973fc2dfe)
1#!/bin/rc
2# fshalt [-r] [new-kernel] - sync (flush) and, if possible, halt all
3#	file servers and optionally reboot
4rfork nes
5kern=()
6kerncopy=()
7reboot=no
8fn usage {
9	echo usage: $1 '[-r] [new-kernel]' >[1=2]
10	exit usage
11}
12if (! ~ $#* 0)
13	switch ($1) {
14	case -r
15		reboot=yes
16		shift
17	case -*
18		usage $0
19	}
20switch ($#*) {
21case 0
22case 1
23	kern = $1
24case *
25	usage $0
26}
27
28path=(/bin)
29builtin cd /
309fs boot		# in case of odd namespace
31ramfs			# stash files here that we'll need after the fs halts
32
33setrtc
34
35# turn off graphics, if any
36if (test -e '#v/vgactl' && test -e '#P/realmode') {
37	vgatype=`{read '#v/vgactl'}
38	if (! ~ $vgatype(2) cga) {
39		prompt=''
40		kill rio | rc -i &
41		sleep 2
42		aux/vga -l text
43	}
44}
45
46fn isbootable {
47	test -e $1 && ~ `{file $1} *' plan 9 boot image' \
48		*' plan 9 executable'* *ELF*' executable'
49}
50fn usekernel {
51	kerncopy=kern
52	cp $1 /tmp/$kerncopy && echo -n using kernel $1...
53}
54
55# make a copy of the right kernel
56if (~ $reboot yes) {
57	if (~ $#kern 0)
58		kern=`{echo $terminal |
59			sed 's;^([^ ]+) .*/([^/ ]+).*$;/n/boot/'$cputype'/9\2;'}
60	if (isbootable $kern)
61		usekernel $kern
62	if not {
63		# $kern is probably a raw binary, try s^name as boot image
64		kern=`{ echo $kern | sed 's;.*/;&s;' }
65		if (isbootable $kern)
66			usekernel $kern
67		if not
68			echo -n using default kernel...
69	}
70}
71
72# start venti flushing
73venti/sync -h localhost >[2]/dev/null &
74venti/sync  >[2]/dev/null &
75
76unmount /mnt/consoles >[2]/dev/null
77kill consolefs | rc			# don't compete with /mnt/consoles
78kill cron | rc				# unlock /cron/lock
79kill watchdog | rc
80sleep 1
81
82f=`{ls /srv/fscons*>[2]/dev/null}
83k=`{ls /srv/kfs*cmd >[2]/dev/null|sort -r}
84
85echo -n syncing...
86for(i in $f) @ {
87	echo -n $i...
88	{
89		echo
90		dial/drain &
91		sleep 2
92		echo fsys all sync
93		if(! dial/expect -t 120 ': ')
94			echo -n 'not synced...' > /dev/cons
95	} < $i >> $i
96}
97
98# flush the last bit of possible fossil traffic
99if (ls /srv | grep -s fossil) {
100	echo -n venti...
101	venti/sync -h localhost >[2]/dev/null &
102	venti/sync  >[2]/dev/null &
103	sleep 5
104}
105
106for (i in $k){
107	echo -n $i...
108	switch($i){
109	case /srv/kfs.cmd
110		disk/kfscmd sync
111	case *
112		disk/kfscmd -n `{echo $i | sed -n 's%/srv/kfs.(.*).cmd%\1%p'} sync
113	}
114	sleep 2
115}
116
117# halting (binaries we run can't be on the fs we're halting)
118builtin cd /bin
119cp dial/expect echo disk/kfscmd rc sed /tmp
120builtin cd /tmp
121mkdir /tmp/lib
122cp /rc/lib/rcmain /tmp/lib
123bind /tmp /rc
124bind /tmp /bin
125
126# put this in a shell function so this rc script doesn't get read
127# when it's no longer accessible
128fn x {
129	rfork s
130	echo
131	echo -n halting...
132	for(i in $f) @ {
133		echo -n $i...
134		{
135			echo fsys all halt
136			if(! expect -t 60 ': ')
137				echo -n 'not halted...' > /dev/cons
138		} < $i >> $i
139	}
140
141	for (i in $k){
142		echo -n $i...
143		switch($i){
144		case /srv/kfs.cmd
145			kfscmd halt
146		case *
147			kfscmd -n `{echo $i | sed -n 's%/srv/kfs.(.*).cmd%\1%p'} halt
148		}
149	}
150	echo
151	echo done halting
152
153	if (~ $reboot yes)
154		echo reboot $kerncopy >'#c/reboot'
155}
156
157x
158