5ce0b3549cf68d523bab774e01841044fd558c19
[openwrt/openwrt.git] / package / base-files / files / lib / upgrade / stage2
1 #!/bin/sh
2
3 . /lib/functions.sh
4 . /lib/functions/system.sh
5
6 export IMAGE="$1"
7 COMMAND="$2"
8
9 export INTERACTIVE=0
10 export VERBOSE=1
11 export CONFFILES=/tmp/sysupgrade.conffiles
12
13 RAMFS_COPY_BIN= # extra programs for temporary ramfs root
14 RAMFS_COPY_DATA= # extra data files
15
16 include /lib/upgrade
17
18
19 supivot() { # <new_root> <old_root>
20 /bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1
21 mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \
22 /bin/mount -o noatime,move /proc $1/proc && \
23 pivot_root $1 $1$2 || {
24 /bin/umount -l $1 $1
25 return 1
26 }
27
28 /bin/mount -o noatime,move $2/sys /sys
29 /bin/mount -o noatime,move $2/dev /dev
30 /bin/mount -o noatime,move $2/tmp /tmp
31 /bin/mount -o noatime,move $2/overlay /overlay 2>&-
32 return 0
33 }
34
35 switch_to_ramfs() {
36 RAMFS_COPY_LOSETUP="$(command -v /usr/sbin/losetup)"
37 RAMFS_COPY_LVM="$(command -v lvm)"
38
39 for binary in \
40 /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \
41 pivot_root mount_root reboot sync kill sleep \
42 md5sum hexdump cat zcat dd tar gzip \
43 ls basename find cp mv rm mkdir rmdir mknod touch chmod \
44 '[' printf wc grep awk sed cut sort tail \
45 mtd partx losetup mkfs.ext4 nandwrite flash_erase \
46 ubiupdatevol ubiattach ubiblock ubiformat \
47 ubidetach ubirsvol ubirmvol ubimkvol \
48 snapshot snapshot_tool date logger \
49 /usr/sbin/fw_printenv /usr/bin/fwtool \
50 $RAMFS_COPY_LOSETUP $RAMFS_COPY_LVM \
51 $RAMFS_COPY_BIN
52 do
53 local file="$(command -v "$binary" 2>/dev/null)"
54 [ -n "$file" ] && install_bin "$file"
55 done
56 install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh \
57 /lib/upgrade/*.sh /lib/upgrade/do_stage2 \
58 /usr/share/libubox/jshn.sh /usr/sbin/fw_setenv \
59 /etc/fw_env.config $RAMFS_COPY_DATA
60
61 mkdir -p $RAM_ROOT/var/lock
62
63 [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64
64
65 supivot $RAM_ROOT /mnt || {
66 v "Failed to switch over to ramfs. Please reboot."
67 exit 1
68 }
69
70 /bin/mount -o remount,ro /mnt
71 /bin/umount -l /mnt
72
73 grep -e "^/dev/dm-.*" -e "^/dev/loop.*" /proc/mounts | while read bdev mp _r; do
74 umount $mp
75 done
76
77 [ "$RAMFS_COPY_LOSETUP" ] && losetup -D
78 [ "$RAMFS_COPY_LVM" ] && {
79 mkdir -p /tmp/lvm/cache
80 $RAMFS_COPY_LVM vgchange -aln --ignorelockingfailure
81 }
82
83 grep /overlay /proc/mounts > /dev/null && {
84 /bin/mount -o noatime,remount,ro /overlay
85 /bin/umount -l /overlay
86 }
87 }
88
89 kill_remaining() { # [ <signal> [ <loop> ] ]
90 local loop_limit=10
91
92 local sig="${1:-TERM}"
93 local loop="${2:-0}"
94 local run=true
95 local stat
96 local proc_ppid=$(cut -d' ' -f4 /proc/$$/stat)
97
98 v "Sending $sig to remaining processes ..."
99
100 while $run; do
101 run=false
102 for stat in /proc/[0-9]*/stat; do
103 [ -f "$stat" ] || continue
104
105 local pid name state ppid rest
106 read pid rest < $stat
107 name="${rest#\(}" ; rest="${name##*\) }" ; name="${name%\)*}"
108 set -- $rest ; state="$1" ; ppid="$2"
109
110 # Skip PID1, our parent, ourself and our children
111 [ $pid -ne 1 -a $pid -ne $proc_ppid -a $pid -ne $$ -a $ppid -ne $$ ] || continue
112
113 [ -f "/proc/$pid/cmdline" ] || continue
114
115 local cmdline
116 read cmdline < /proc/$pid/cmdline
117
118 # Skip kernel threads
119 [ -n "$cmdline" ] || continue
120
121 v "Sending signal $sig to $name ($pid)"
122 kill -$sig $pid 2>/dev/null
123
124 [ $loop -eq 1 ] && sleep 2 && run=true
125 done
126
127 let loop_limit--
128 [ $loop_limit -eq 0 ] && {
129 v "Failed to kill all processes."
130 exit 1
131 }
132 done
133 }
134
135 indicate_upgrade
136
137 while read -r a b c; do
138 case "$a" in
139 MemT*) mem="$b" ;; esac
140 done < /proc/meminfo
141
142 [ "$mem" -gt 32768 ] && \
143 skip_services="dnsmasq log network"
144 for service in /etc/init.d/*; do
145 service=${service##*/}
146
147 case " $skip_services " in
148 *" $service "*) continue ;; esac
149
150 ubus call service delete '{ "name": "'"$service"'" }' 2>/dev/null
151 done
152
153 killall -9 telnetd 2>/dev/null
154 killall -9 dropbear 2>/dev/null
155 killall -9 ash 2>/dev/null
156
157 kill_remaining TERM
158 sleep 4
159 kill_remaining KILL 1
160
161 sleep 6
162
163 echo 3 > /proc/sys/vm/drop_caches
164
165 if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
166 platform_pre_upgrade "$IMAGE"
167 fi
168
169 if [ -n "$(rootfs_type)" ]; then
170 v "Switching to ramdisk..."
171 switch_to_ramfs
172 fi
173
174 # Exec new shell from ramfs
175 exec /bin/busybox ash -c "$COMMAND"