0108-base-files-always-use-staged-sysupgrade.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. From: Matthias Schiffer <mschiffer@universe-factory.net>
  2. Date: Sat, 22 Apr 2017 00:54:50 +0200
  3. Subject: base-files: always use staged sysupgrade
  4. Support for the -d and -p options is dropped; it may be added again at some
  5. point by adding these flags to the ubus sysupgrade call.
  6. A downside of this is that we get a lot less information about the progress
  7. of the upgrade: as soon as the actual upgrade starts, all shell sessions
  8. are killed to allow unmounting the root filesystem.
  9. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
  10. diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
  11. index 2064adf775c491725dbff5826b94bd6132d8d060..23f18ceb775caac057ee7a757922954f812f77ce 100644
  12. --- a/package/base-files/files/lib/upgrade/common.sh
  13. +++ b/package/base-files/files/lib/upgrade/common.sh
  14. @@ -92,51 +92,37 @@ run_ramfs() { # <command> [...]
  15. exec /bin/busybox ash -c "$*"
  16. }
  17. -kill_remaining() { # [ <signal> ]
  18. +kill_remaining() { # [ <signal> [ <loop> ] ]
  19. local sig="${1:-TERM}"
  20. + local loop="${2:-0}"
  21. + local run=true
  22. + local stat
  23. +
  24. echo -n "Sending $sig to remaining processes ... "
  25. - local my_pid=$$
  26. - local my_ppid=$(cut -d' ' -f4 /proc/$my_pid/stat)
  27. - local my_ppisupgraded=
  28. - grep -q upgraded /proc/$my_ppid/cmdline >/dev/null && {
  29. - local my_ppisupgraded=1
  30. - }
  31. -
  32. - local stat
  33. - for stat in /proc/[0-9]*/stat; do
  34. - [ -f "$stat" ] || continue
  35. -
  36. - local pid name state ppid rest
  37. - read pid name state ppid rest < $stat
  38. - name="${name#(}"; name="${name%)}"
  39. -
  40. - local cmdline
  41. - read cmdline < /proc/$pid/cmdline
  42. -
  43. - # Skip kernel threads
  44. - [ -n "$cmdline" ] || continue
  45. -
  46. - if [ $$ -eq 1 ] || [ $my_ppid -eq 1 ] && [ -n "$my_ppisupgraded" ]; then
  47. - # Running as init process, kill everything except me
  48. - if [ $pid -ne $$ ] && [ $pid -ne $my_ppid ]; then
  49. - echo -n "$name "
  50. - kill -$sig $pid 2>/dev/null
  51. - fi
  52. - else
  53. - case "$name" in
  54. - # Skip essential services
  55. - *procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*) : ;;
  56. -
  57. - # Killable process
  58. - *)
  59. - if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then
  60. - echo -n "$name "
  61. - kill -$sig $pid 2>/dev/null
  62. - fi
  63. - ;;
  64. - esac
  65. - fi
  66. + while $run; do
  67. + run=false
  68. + for stat in /proc/[0-9]*/stat; do
  69. + [ -f "$stat" ] || continue
  70. +
  71. + local pid name state ppid rest
  72. + read pid name state ppid rest < $stat
  73. + name="${name#(}"; name="${name%)}"
  74. +
  75. + # Skip PID1, ourself and our children
  76. + [ $pid -ne 1 -a $pid -ne $$ -a $ppid -ne $$ ] || continue
  77. +
  78. + local cmdline
  79. + read cmdline < /proc/$pid/cmdline
  80. +
  81. + # Skip kernel threads
  82. + [ -n "$cmdline" ] || continue
  83. +
  84. + echo -n "$name "
  85. + kill -$sig $pid 2>/dev/null
  86. +
  87. + [ $loop -eq 1 ] && run=true
  88. + done
  89. done
  90. echo ""
  91. }
  92. @@ -171,28 +157,31 @@ v() {
  93. [ "$VERBOSE" -ge 1 ] && echo "$@"
  94. }
  95. +json_string() {
  96. + local v="$1"
  97. + v="${v//\\/\\\\}"
  98. + v="${v//\"/\\\"}"
  99. + echo "\"$v\""
  100. +}
  101. +
  102. rootfs_type() {
  103. /bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }'
  104. }
  105. get_image() { # <source> [ <command> ]
  106. local from="$1"
  107. - local conc="$2"
  108. - local cmd
  109. -
  110. - case "$from" in
  111. - http://*|ftp://*) cmd="wget -O- -q";;
  112. - *) cmd="cat";;
  113. - esac
  114. - if [ -z "$conc" ]; then
  115. - local magic="$(eval $cmd \"$from\" 2>/dev/null | dd bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
  116. + local cat="$2"
  117. +
  118. + if [ -z "$cat" ]; then
  119. + local magic="$(dd if="$from" bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
  120. case "$magic" in
  121. - 1f8b) conc="zcat";;
  122. - 425a) conc="bzcat";;
  123. + 1f8b) cat="zcat";;
  124. + 425a) cat="bzcat";;
  125. + *) cat="cat";;
  126. esac
  127. fi
  128. - eval "$cmd \"$from\" 2>/dev/null ${conc:+| $conc}"
  129. + $cat "$from" 2>/dev/null
  130. }
  131. get_magic_word() {
  132. @@ -316,12 +305,14 @@ default_do_upgrade() {
  133. fi
  134. }
  135. -do_upgrade() {
  136. +do_upgrade_stage2() {
  137. v "Performing system upgrade..."
  138. - if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
  139. - platform_do_upgrade "$ARGV"
  140. + if [ -n "$do_upgrade" ]; then
  141. + $do_upgrade "$IMAGE"
  142. + elif type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
  143. + platform_do_upgrade "$IMAGE"
  144. else
  145. - default_do_upgrade "$ARGV"
  146. + default_do_upgrade "$IMAGE"
  147. fi
  148. if [ "$SAVE_CONFIG" -eq 1 ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then
  149. @@ -329,11 +320,11 @@ do_upgrade() {
  150. fi
  151. v "Upgrade completed"
  152. - [ -n "$DELAY" ] && sleep "$DELAY"
  153. - ask_bool 1 "Reboot" && {
  154. - v "Rebooting system..."
  155. - reboot -f
  156. - sleep 5
  157. - echo b 2>/dev/null >/proc/sysrq-trigger
  158. - }
  159. + sleep 1
  160. +
  161. + v "Rebooting system..."
  162. + umount -a
  163. + reboot -f
  164. + sleep 5
  165. + echo b 2>/dev/null >/proc/sysrq-trigger
  166. }
  167. diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh
  168. index ec2a014a00461ca897d521e2d065f5399f1f8c48..05940e2567e22fe1936fb5afdc7c1df4826570ee 100644
  169. --- a/package/base-files/files/lib/upgrade/nand.sh
  170. +++ b/package/base-files/files/lib/upgrade/nand.sh
  171. @@ -272,7 +272,16 @@ nand_upgrade_tar() {
  172. }
  173. # Recognize type of passed file and start the upgrade process
  174. -nand_do_upgrade_stage2() {
  175. +nand_do_upgrade() {
  176. + if [ -n "$IS_PRE_UPGRADE" ]; then
  177. + # Previously, nand_do_upgrade was called from the platform_pre_upgrade
  178. + # hook; this piece of code handles scripts that haven't been
  179. + # updated. All scripts should gradually move to call nand_do_upgrade
  180. + # from platform_do_upgrade instead.
  181. + export do_upgrade=nand_do_upgrade
  182. + return
  183. + fi
  184. +
  185. local file_type=$(identify $1)
  186. [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
  187. @@ -284,46 +293,6 @@ nand_do_upgrade_stage2() {
  188. esac
  189. }
  190. -nand_upgrade_stage2() {
  191. - [ $1 = "nand" ] && {
  192. - [ -f "$2" ] && {
  193. - touch /tmp/sysupgrade
  194. -
  195. - killall -9 telnetd
  196. - killall -9 dropbear
  197. - killall -9 ash
  198. -
  199. - kill_remaining TERM
  200. - sleep 3
  201. - kill_remaining KILL
  202. -
  203. - sleep 1
  204. -
  205. - if [ -n "$(rootfs_type)" ]; then
  206. - v "Switching to ramdisk..."
  207. - run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2"
  208. - else
  209. - nand_do_upgrade_stage2 $2
  210. - fi
  211. - return 0
  212. - }
  213. - echo "Nand upgrade failed"
  214. - exit 1
  215. - }
  216. -}
  217. -
  218. -nand_upgrade_stage1() {
  219. - [ -f /tmp/sysupgrade-nand-path ] && {
  220. - path="$(cat /tmp/sysupgrade-nand-path)"
  221. - [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] &&
  222. - rm $CONF_TAR
  223. -
  224. - ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }"
  225. - exit 0
  226. - }
  227. -}
  228. -append sysupgrade_pre_upgrade nand_upgrade_stage1
  229. -
  230. # Check if passed file is a valid one for NAND sysupgrade. Currently it accepts
  231. # 3 types of files:
  232. # 1) UBI - should contain an ubinized image, header is checked for the proper
  233. @@ -353,13 +322,3 @@ nand_do_platform_check() {
  234. return 0
  235. }
  236. -
  237. -# Start NAND upgrade process
  238. -#
  239. -# $(1): file to be used for upgrade
  240. -nand_do_upgrade() {
  241. - echo -n $1 > /tmp/sysupgrade-nand-path
  242. - install_bin /sbin/upgraded
  243. - ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded
  244. - nand_upgrade_stage1
  245. -}
  246. diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2
  247. new file mode 100755
  248. index 0000000000000000000000000000000000000000..4e2aa3a23c3bab07a795762a30a4d4f701081934
  249. --- /dev/null
  250. +++ b/package/base-files/files/lib/upgrade/stage2
  251. @@ -0,0 +1,50 @@
  252. +#!/bin/sh
  253. +
  254. +. /lib/functions.sh
  255. +. /lib/functions/system.sh
  256. +
  257. +export IMAGE="$1"
  258. +COMMAND="$2"
  259. +
  260. +export ARGV="$IMAGE"
  261. +export ARGC=1
  262. +
  263. +export SAVE_CONFIG=1
  264. +export SAVE_PARTITIONS=1
  265. +
  266. +export INTERACTIVE=0
  267. +export VERBOSE=1
  268. +export CONFFILES=/tmp/sysupgrade.conffiles
  269. +export CONF_TAR=/tmp/sysupgrade.tgz
  270. +
  271. +
  272. +[ -f "$CONF_TAR" ] || export SAVE_CONFIG=0
  273. +[ -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap ] && export SAVE_PARTITIONS=0
  274. +
  275. +include /lib/upgrade
  276. +
  277. +
  278. +killall -9 telnetd
  279. +killall -9 dropbear
  280. +killall -9 ash
  281. +
  282. +kill_remaining TERM
  283. +sleep 3
  284. +kill_remaining KILL 1
  285. +
  286. +sleep 1
  287. +
  288. +
  289. +if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
  290. + IS_PRE_UPGRADE=1 platform_pre_upgrade "$IMAGE"
  291. +
  292. + # Needs to be unset again because of busybox weirdness ...
  293. + IS_PRE_UPGRADE=
  294. +fi
  295. +
  296. +if [ -n "$(rootfs_type)" ]; then
  297. + echo "Switching to ramdisk..."
  298. + run_ramfs "$COMMAND"
  299. +else
  300. + exec /bin/busybox ash -c "$COMMAND"
  301. +fi
  302. diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade
  303. index 759c841e131a415c8009995c372cce1f55fb78a0..d48416f6de244b97f426ae0b83d425ac5c1bc5b3 100755
  304. --- a/package/base-files/files/sbin/sysupgrade
  305. +++ b/package/base-files/files/sbin/sysupgrade
  306. @@ -1,4 +1,7 @@
  307. #!/bin/sh
  308. +
  309. +[ "$1" = "nand" ] && exec /lib/upgrade/stage2 "$2" "$3"
  310. +
  311. . /lib/functions.sh
  312. . /lib/functions/system.sh
  313. @@ -11,7 +14,6 @@ export VERBOSE=1
  314. export SAVE_CONFIG=1
  315. export SAVE_OVERLAY=0
  316. export SAVE_PARTITIONS=1
  317. -export DELAY=
  318. export CONF_IMAGE=
  319. export CONF_BACKUP_LIST=0
  320. export CONF_BACKUP=
  321. @@ -25,7 +27,6 @@ export TEST=0
  322. while [ -n "$1" ]; do
  323. case "$1" in
  324. -i) export INTERACTIVE=1;;
  325. - -d) export DELAY="$2"; shift;;
  326. -v) export VERBOSE="$(($VERBOSE + 1))";;
  327. -q) export VERBOSE="$(($VERBOSE - 1))";;
  328. -n) export SAVE_CONFIG=0;;
  329. @@ -50,10 +51,9 @@ done
  330. export CONFFILES=/tmp/sysupgrade.conffiles
  331. export CONF_TAR=/tmp/sysupgrade.tgz
  332. -export ARGV="$*"
  333. -export ARGC="$#"
  334. +IMAGE="$1"
  335. -[ -z "$ARGV" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && {
  336. +[ -z "$IMAGE" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && {
  337. cat <<EOF
  338. Usage: $0 [<upgrade-option>...] <image file or URL>
  339. $0 [-q] [-i] <backup-command> <file>
  340. @@ -90,7 +90,7 @@ EOF
  341. exit 1
  342. }
  343. -[ -n "$ARGV" -a -n "$NEED_IMAGE" ] && {
  344. +[ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && {
  345. cat <<-EOF
  346. -b|--create-backup and -r|--restore-backup do not perform a firmware upgrade.
  347. Do not specify both -b|-r and a firmware image.
  348. @@ -134,14 +134,13 @@ sysupgrade_image_check="platform_check_image"
  349. include /lib/upgrade
  350. -[ "$1" = "nand" ] && nand_upgrade_stage2 $@
  351. -
  352. do_save_conffiles() {
  353. local conf_tar="${1:-$CONF_TAR}"
  354. [ -z "$(rootfs_type)" ] && {
  355. echo "Cannot save config while running from ramdisk."
  356. ask_bool 0 "Abort" && exit
  357. + rm -f "$conf_tar"
  358. return 0
  359. }
  360. run_hooks "$CONFFILES" $sysupgrade_init_conffiles
  361. @@ -182,8 +181,33 @@ type platform_check_image >/dev/null 2>/dev/null || {
  362. exit 1
  363. }
  364. +case "$IMAGE" in
  365. + http://*)
  366. + wget -O/tmp/sysupgrade.img "$IMAGE"
  367. + IMAGE=/tmp/sysupgrade.img
  368. + ;;
  369. +esac
  370. +
  371. +IMAGE="$(readlink -f "$IMAGE")"
  372. +
  373. +case "$IMAGE" in
  374. + '')
  375. + echo "Image file not found."
  376. + exit 1
  377. + ;;
  378. + /tmp/*) ;;
  379. + *)
  380. + v "Image not in /tmp, copying..."
  381. + cp -f "$IMAGE" /tmp/sysupgrade.img
  382. + IMAGE=/tmp/sysupgrade.img
  383. + ;;
  384. +esac
  385. +
  386. +export ARGV="$IMAGE"
  387. +export ARGC=1
  388. +
  389. for check in $sysupgrade_image_check; do
  390. - ( eval "$check \"\$ARGV\"" ) || {
  391. + ( $check "$IMAGE" ) || {
  392. if [ $FORCE -eq 1 ]; then
  393. echo "Image check '$check' failed but --force given - will update anyway!"
  394. break
  395. @@ -209,6 +233,7 @@ elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
  396. [ $TEST -eq 1 ] || do_save_conffiles
  397. export SAVE_CONFIG=1
  398. else
  399. + [ $TEST -eq 1 ] || rm -f "$CONF_TAR"
  400. export SAVE_CONFIG=0
  401. fi
  402. @@ -216,28 +241,18 @@ if [ $TEST -eq 1 ]; then
  403. exit 0
  404. fi
  405. -run_hooks "" $sysupgrade_pre_upgrade
  406. -
  407. -# Some platforms/devices may want different sysupgrade process, e.g. without
  408. -# killing processes yet or calling ubus system upgrade method.
  409. -# This is needed e.g. on NAND devices where we just want to trigger stage1 at
  410. -# this point.
  411. -if type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
  412. - platform_pre_upgrade "$ARGV"
  413. +if [ $SAVE_PARTITIONS -eq 0 ]; then
  414. + touch /tmp/sysupgrade.always.overwrite.bootdisk.partmap
  415. +else
  416. + rm -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap
  417. fi
  418. -ubus call system upgrade
  419. -touch /tmp/sysupgrade
  420. -
  421. -if [ ! -f /tmp/failsafe ] ; then
  422. - kill_remaining TERM
  423. - sleep 3
  424. - kill_remaining KILL
  425. -fi
  426. +run_hooks "" $sysupgrade_pre_upgrade
  427. -if [ -n "$(rootfs_type)" ]; then
  428. - v "Switching to ramdisk..."
  429. - run_ramfs '. /lib/functions.sh; include /lib/upgrade; do_upgrade'
  430. -else
  431. - do_upgrade
  432. -fi
  433. +install_bin /sbin/upgraded
  434. +v "Commencing upgrade. All shell sessions will be closed now."
  435. +ubus call system sysupgrade "{
  436. + \"prefix\": \"$RAM_ROOT\",
  437. + \"path\": $(json_string "$IMAGE"),
  438. + \"command\": \". /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2\"
  439. +}"