2017-01-24 00:25:47 -06:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
case $1 in
|
|
|
|
prereqs)
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
set -e
|
|
|
|
# set -x
|
|
|
|
total_mem=$(free | awk '/^Mem:/{print $2}')
|
|
|
|
tmpfs_size=$(( $total_mem / 20 * 17 ))
|
|
|
|
free_mem_thres=$(( $total_mem / 20 * 18 ))
|
|
|
|
tmp_mnt='/mnt/ramdisk-convfs'
|
|
|
|
root_mnt='/mnt/root-convfs'
|
|
|
|
root_dev=''
|
|
|
|
flash_dev=''
|
|
|
|
block_flash=''
|
|
|
|
aboot_flag=''
|
|
|
|
backup_file=''
|
|
|
|
|
|
|
|
# Get the fullpath of flash device, e.g., /dev/sda
|
|
|
|
get_flash_dev() {
|
|
|
|
for dev in $(ls /sys/block); do
|
|
|
|
local is_mmc=$(echo "$dev" | grep 'mmcblk.*boot.*' | cat)
|
|
|
|
if [ -n "$is_mmc" ]; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
local devid=$(realpath "/sys/block/$dev/device")
|
|
|
|
local is_device=$(echo "$devid" | grep '^/sys/devices/' | cat)
|
|
|
|
local is_flash=$(echo "$devid" | grep "$block_flash" | cat)
|
|
|
|
if [ -n "$is_device" -a -n "$is_flash" ]; then
|
|
|
|
flash_dev="/dev/$dev"
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# Wait for root_dev to be ready
|
|
|
|
wait_for_root_dev() {
|
|
|
|
local try_rounds=30
|
|
|
|
while [ $try_rounds -gt 0 ]; do
|
|
|
|
if [ -e "$root_dev" ]; then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
sleep 1
|
|
|
|
try_rounds=$(( $try_rounds - 1 ))
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# Alway run cleanup before exit
|
|
|
|
cleanup() {
|
|
|
|
if grep -q "$root_mnt" /proc/mounts; then
|
|
|
|
umount "$root_mnt"
|
|
|
|
fi
|
|
|
|
if grep -q "$tmp_mnt" /proc/mounts; then
|
|
|
|
umount "$tmp_mnt"
|
|
|
|
fi
|
|
|
|
[ -e "$root_mnt" ] && rmdir "$root_mnt"
|
|
|
|
[ -e "$tmp_mnt" ] && rmdir "$tmp_mnt"
|
|
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
|
|
|
|
notification() {
|
|
|
|
cat << EOF
|
|
|
|
A failure happend in modifying the root file system which stopped the upgrade. Manual interventions are needed to fix the issue. Note that:
|
|
|
|
1) files in the old root file system may have been lost and the old partition table may have been corrupted;
|
|
|
|
2) The files in the old root file system were copied to $tmp_mnt;
|
|
|
|
3) The old partition table was dumped to the file $tmp_mnt/$backup_file by sfdisk;
|
|
|
|
4) Quitting the current shell will lose all files mentioned above permanently.
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
run_cmd() {
|
|
|
|
if ! eval "$1"; then
|
|
|
|
echo "$2"
|
|
|
|
notification
|
|
|
|
sh
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2017-04-07 17:28:30 -05:00
|
|
|
create_varlog_file() {
|
|
|
|
local err_msg="Error: create var-log ext4 file"
|
2017-06-02 03:31:53 -05:00
|
|
|
local cmd="[ -n "$varlog_size" ] && mkdir -p $root_mnt/disk-img && dd if=/dev/zero of=$root_mnt/disk-img/var-log.ext4 count=$((2048*$varlog_size)) && mke2fs -t ext4 -q -F $root_mnt/disk-img/var-log.ext4"
|
2017-04-07 17:28:30 -05:00
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
}
|
|
|
|
|
|
|
|
mount_and_create_varlog_file() {
|
|
|
|
[ -z "$varlog_size" ] && exit 0
|
|
|
|
mkdir -p "$root_mnt"
|
|
|
|
mount -t ext4 "$root_dev" "$root_mnt"
|
|
|
|
# exit when the var_log.ext4 exists and the size matches
|
|
|
|
if [ -e "$root_mnt/disk-img/var-log.ext4" ]; then
|
|
|
|
cur_varlog_size=$(ls -l $root_mnt/disk-img/var-log.ext4 | awk '{print $5}')
|
|
|
|
if [ $cur_varlog_size == $((1024*1024*$varlog_size)) ]; then
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
create_varlog_file
|
|
|
|
umount "$root_mnt"
|
|
|
|
exit 0
|
|
|
|
}
|
|
|
|
|
2017-01-24 00:25:47 -06:00
|
|
|
# Extract kernel parameters
|
|
|
|
set -- $(cat /proc/cmdline)
|
|
|
|
for x in "$@"; do
|
|
|
|
case "$x" in
|
|
|
|
block_flash=*)
|
|
|
|
block_flash="${x#block_flash=}"
|
|
|
|
;;
|
|
|
|
Aboot=*)
|
|
|
|
aboot_flag="${x#Aboot=}"
|
2017-04-07 17:28:30 -05:00
|
|
|
;;
|
|
|
|
varlog_size=*)
|
|
|
|
varlog_size="${x#varlog_size=}"
|
2017-04-21 19:23:36 -05:00
|
|
|
;;
|
2017-04-24 15:39:29 -05:00
|
|
|
loop=*)
|
2017-04-21 19:23:36 -05:00
|
|
|
x1="${x#loop=}"
|
|
|
|
image_dir="${x1%/*}"
|
2017-01-24 00:25:47 -06:00
|
|
|
esac
|
|
|
|
done
|
|
|
|
root_dev="$ROOT"
|
|
|
|
|
|
|
|
#Check aboot and root_dev is vfat
|
|
|
|
[ -z "$aboot_flag" ] && exit 0
|
|
|
|
if [ -z "$root_dev" ]; then
|
|
|
|
echo "Error: root device name is not provided"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if ! wait_for_root_dev; then
|
|
|
|
echo "Error: timeout in waiting for $root_dev"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2017-04-07 17:28:30 -05:00
|
|
|
# mount, create varlog file and exit when the root is ext4
|
|
|
|
blkid | grep "$root_dev.*vfat" -q || mount_and_create_varlog_file
|
2017-01-24 00:25:47 -06:00
|
|
|
|
|
|
|
# Get flash dev name
|
|
|
|
if [ -z "$block_flash" ]; then
|
|
|
|
echo "Error: flash device info is not provided"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if ! get_flash_dev; then
|
|
|
|
echo "Error: flash device is not found"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Check memory size for tmpfs
|
|
|
|
free_mem=$(free | awk '/^Mem:/{print $4}')
|
|
|
|
if [ "$free_mem" -lt "$free_mem_thres" ]; then
|
|
|
|
echo "Error: memory is not enough"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Backup partition table
|
|
|
|
mkdir -p "$root_mnt"
|
|
|
|
mount "$root_dev" "$root_mnt"
|
|
|
|
backup_file=backup.$(date +%Y-%m-%d.%H-%M-%S)
|
|
|
|
sfdisk -d "$flash_dev" > "$root_mnt/$backup_file"
|
|
|
|
|
|
|
|
# Check total size of files in root
|
|
|
|
total_file_size=$(du -s "$root_mnt" | awk '{print $1}')
|
|
|
|
if [ "$total_file_size" -gt "$tmpfs_size" ]; then
|
|
|
|
echo "Error: total file size is too large"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Create tmpfs, and copy files to tmpfs
|
|
|
|
mkdir -p "$tmp_mnt"
|
|
|
|
mount -t tmpfs -o size="${tmpfs_size}k" tmpfs "$tmp_mnt"
|
|
|
|
cp -a "$root_mnt/." "$tmp_mnt/"
|
|
|
|
umount "$root_mnt"
|
|
|
|
|
|
|
|
#### Lines below will modify the root file system, so any failure will be trapped to shell for manual interventions.
|
|
|
|
|
|
|
|
# Create a new partition table (content in flash_dev will be deleted)
|
|
|
|
err_msg="Error: repartitioning $flash_dev failed"
|
2017-08-05 22:56:32 -05:00
|
|
|
cmd="echo ';' | sfdisk $flash_dev || (sleep 3; blockdev --rereadpt $flash_dev && fdisk -l $flash_dev | grep -q ${root_dev}.*Linux)"
|
2017-01-24 00:25:47 -06:00
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
|
|
|
|
sleep 5
|
|
|
|
err_msg="Error: timeout in waiting for $root_dev after repartition"
|
|
|
|
cmd="wait_for_root_dev"
|
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
|
|
|
|
err_msg="Error: formatting to ext4 failed"
|
|
|
|
cmd="mke2fs -t ext4 -m2 -F -O '^huge_file' $root_dev"
|
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
|
|
|
|
err_msg="Error: mounting $root_dev to $root_mnt failed"
|
|
|
|
cmd="mount -t ext4 $root_dev $root_mnt"
|
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
|
2017-02-06 00:11:52 -06:00
|
|
|
err_msg="Error: extract docker directory"
|
2017-04-21 19:23:36 -05:00
|
|
|
cmd="[ -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} ] && rm -rf $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && mkdir -p $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && tar xzf $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && rm -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }}"
|
2017-02-06 00:11:52 -06:00
|
|
|
run_cmd "$cmd" "$err_msg"
|
|
|
|
|
2017-01-24 00:25:47 -06:00
|
|
|
err_msg="Error: copying files form $tmp_mnt to $root_mnt failed"
|
|
|
|
cmd="cp -a $tmp_mnt/. $root_mnt/"
|
|
|
|
run_cmd "$cmd" "$err_msg"
|
2017-04-07 17:28:30 -05:00
|
|
|
|
|
|
|
create_varlog_file
|