fshalt 2.9 KB

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