bugfix: Increase available memory during upgrade/install process

It is possible for the system to run out of memory when dealing
with large file uploads and installs.

As part of the upgrade procedure shutdown services that are not
essential for node operations to allow more memory for install
to take place.

Includes changes to linkled to indicate this new state as it will
be shutdown as part of the cleanup process.

Memory gain (approximate)

dropbear 100kb
linkled  200kb
logd     200kb
odhcp    100kb
snmpd    500kb
xinetd   100kb

Total(approximate): 1200kb (around %4 on 32mb devices)

This is somewhat similar to files/usr/local/bin/upgrade_kill_prep
except that it kills only a select group of services
so that the system can handle the file upload while
upgrade_kill_prep does the final system cleanup to run the full
upgrade.

ref AREDN->ticket:204

Change-Id: Ic6d3aa028725064a97c4723f6d9b36e1e51d87a7
This commit is contained in:
Conrad Lara - KG6JEI 2017-01-12 11:47:03 -08:00 committed by KG6JEI
parent a2208dbc5a
commit 8ee8fbefe0
6 changed files with 149 additions and 12 deletions

View File

@ -0,0 +1,3 @@
*/5 * * * * /usr/local/bin/fccid
* * * * * /usr/local/bin/rssi_monitor

View File

@ -30,7 +30,27 @@ case "$BOARD_TYPE" in
esac
firmware_upgrade_mode() {
# Put the LED in "upgrade" mode
echo timer > "$LINK1LED/trigger"
echo 100 > "$LINK1LED/delay_on"
echo 100 > "$LINK1LED/delay_off"
echo 1 > "$LINK1LED/brightness"
}
reset_led() {
# Reset the LED to a blank state
echo none > "$LINK1LED/trigger"
echo 0 > "$LINK1LED/brightness"
}
link_state() {
{
reset_led
while true; do
sleep 5;
if echo /neighbors | nc 127.0.0.1 2006 2>/dev/null | grep -q YES; then
@ -39,4 +59,17 @@ esac
echo 0 > "$LINK1LED/brightness"
fi
done;
} &
} & # Push into the background
}
case $1 in
"upgrade" )
firmware_upgrade_mode
;;
"restore" )
reset_led
;;
*)
link_state
;;
esac

View File

@ -0,0 +1,73 @@
#!/bin/sh
# Alphabetical except where noted below
# log needs to start before cron (and maybe others) to be detected for logging.
serviceslist="log cron dropbear linkled odhcpd snmpd vtund vtundsrv xinetd"
start_upgrade_mode() {
touch /tmp/.upgrade_mode
# drop the page cache to take pressure of tmps when uploading file
echo 3 > /proc/sys/vm/drop_caches
#Kill processes
for name in $serviceslist
do
"/etc/init.d/${name}" stop
done
# Switch to a limited crontab list
/usr/sbin/crond -b -c /etc/crontabs.upgrademode -l 5
# Some services need to kill the last remaining processes
killall -9 dropbear
# Put the LED in "upgrade" mode
/usr/local/bin/linkled upgrade
# Purge the /tmp/ filesystem of unneeded files.
rm -Rf /tmp/node.history /tmp/olsrd.log /tmp/olsrd.watchdog /tmp/snrlog/ /tmp/snr.dat /tmp/web/firmware.list /tmp/.uci
}
remove_opkg_lists() {
rm -Rf /tmp/opkg-lists/
}
return_to_operating_mode() {
killall -9 crond
# If anything goes wrong after this point return the error code to the calling process
# as we could be in an unstable state.
set -e
# Start up the services we stopped
for name in $serviceslist
do
"/etc/init.d/${name}" start
done
rm /tmp/.upgrade_mode
}
case $1 in
"upgrade" )
start_upgrade_mode
remove_opkg_lists
;;
"opkginstall" )
start_upgrade_mode
;;
"restore" )
return_to_operating_mode
;;
*)
echo "This program is not intended to be called by users."
;;
esac

View File

@ -152,6 +152,8 @@ if($parms{button_ul_fw} and -f "/tmp/web/upload/file")
push @fw_output, "Firmware CANNOT be updated\n";
push @fw_output, "firmware file is not valid\n";
$fw_install = 0;
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
}
elsif($parms{firmfile} =~ /^patch\S+\.tgz$/) # firmware patch
@ -162,6 +164,8 @@ if($parms{button_ul_fw} and -f "/tmp/web/upload/file")
{
push @fw_output, "Firmware CANNOT be updated\n";
push @fw_output, "the uploaded file is not recognized\n";
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
}
@ -171,6 +175,7 @@ if($parms{button_dl_fw} and $parms{dl_fw} ne "default")
if(get_default_gw() ne "none")
{
unlink "$tmpdir/firmware";
system("/usr/local/bin/uploadctlservices","upgrade");
$ok = 0;
foreach $serverpath (@serverpaths)
{
@ -196,6 +201,8 @@ if($parms{button_dl_fw} and $parms{dl_fw} ne "default")
push @fw_output, "Firmware CANNOT be updated\n";
push @fw_output, "firmware file is not valid\n";
$fw_install = 0;
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
}
elsif($parms{dl_fw} =~ /^patch\S+\.tgz$/) # firmware patch
@ -216,12 +223,16 @@ if($parms{button_dl_fw} and $parms{dl_fw} ne "default")
push @fw_output, "Firmware CANNOT be updated\n";
push @fw_output, "patch file is not valid\n";
$patch_install = 0;
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
}
else
{
push @fw_output, "Firmware CANNOT be updated\n";
push @fw_output, "the downloaded file is not recognized\n";
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
}
else
@ -388,6 +399,10 @@ if($patch_install and -f "$tmpdir/firmware")
push(@fw_output, `cat $tmpdir/patch.out`) if $parms{dev};
push @fw_output, "Done.\n";
}
unlink("$tmpdir/firmware");
system("/usr/local/bin/uploadctlservices","restore") and push @fw_output, "Failed to restart all services, please reboot this node.\n";
}
@ -411,6 +426,8 @@ if($parms{button_ul_pkg} and -f "/tmp/web/upload/file")
system "mv -f /tmp/web/upload/file /tmp/web/upload/newpkg.ipk";
push @pkg_output, `opkg -force-overwrite install /tmp/web/upload/newpkg.ipk 2>&1`;
system "rm -rf /tmp/opkg-*";
unlink("/tmp/web/upload/newpkg.ipk");
system("/usr/local/bin/uploadctlservices","restore") and push @pkg_output, "Failed to restart all services, please reboot this node.\n";
}
# download package
@ -418,7 +435,9 @@ if($parms{button_dl_pkg} and $parms{dl_pkg} ne "default")
{
if(get_default_gw() ne "none")
{
system("/usr/local/bin/uploadctlservices","opkginstall");
push @pkg_output, `opkg -force-overwrite install $parms{dl_pkg} 2>&1`;
system("/usr/local/bin/uploadctlservices","restore") and push @pkg_output, "Failed to restart all services, please reboot this node.\n";
}
else
{
@ -490,6 +509,8 @@ if($parms{button_ul_key} and -f "/tmp/web/upload/file")
{
push @key_output, "Key installed.\n";
}
unlink("/tmp/web/upload/file");
system("/usr/local/bin/uploadctlservices","restore") and push @key_output, "Failed to restart all services, please reboot this node.\n";
}
# remove key

View File

@ -212,8 +212,8 @@ sub read_postdata
$line = fgets(10);
push(@parse_errors, "not blank: '$line'") unless $line eq "\r\n";
$tmp = "";
# drop the page cache to take pressure of tmps when uploading file
`echo 3 > /proc/sys/vm/drop_caches`;
# Put us in upgrade mode (purge files, shutdown services)
system("/usr/local/bin/uploadctlservices","upgrade");
system "mkdir -p /tmp/web/upload";
open($handle, ">/tmp/web/upload/file");
while(1)

View File

@ -681,6 +681,13 @@ for download, but don't do this frivolously. The package information database
gets stored locally and will use about 100KB of space in flash memory. The
average user will probably never have to use this function.
</p>
<p>
NOTE: When uploading any file (Firmware, Patch, or Package) a node operating
as a tunnel client or server will shutdown the tunnels before accepting the
file for upload. If your connection path to the node being updated requires
you to connect via a tunnel on the node the upload will not succeed.
</P>
<p>
The <strong>Remove Package</strong> list shows all packages on the
node. Selecting a package and clicking <strong>Remove</strong> will remove