Hey, thanks for all your answers!
On 07/07/2016 07:52 AM, Olivier Hardouin wrote: > Though I like the idea of being able to upgrade using a usb stick, I > wonder if mountd is the correct place to implement this. > Indeed mountd is sending events via hotplug, so some other subsystems > could listen to these ones and decide whether the upgrade should be > based on some file of an attached usb disk or some other place (in the > network). > I think mountd should only do what it is good at, meaning detecting > disk, finding partition, mounting filesystem and inform other > subsystems. Yes, good point. But then we should rewrite/redesign the whole update process including the sysupgrade binary in my opinion. For example writing a small library and a daemon which does the updates for us. A daemon which executes a sysupgrade tool doesn't make more sense for me as the mountd solution. > > On Wed, Jul 6, 2016 at 12:34 PM, Wang Linetkux <china...@gmail.com> wrote: >> Another possible solution is to record the HASH of system image after >> system upgrade is done. Next time when we try to do the system >> upgrade, we can compare the recorded HASH value and the compute value >> from system upgrade file? Also a good idea but normally this should be done by the sysupgrade util itself. Building upgrade logic into the mountd is not the way we should go. See above. >> >> 2016-07-06 18:18 GMT+08:00 Bruno Randolf <b...@einfach.org>: >>> On 06/07/16 06:58, John Crispin wrote: >>>> Hi Philipp >>>> >>>> the thing that i am worried about is this process >>>> >>>> 1) plug a stick >>>> 2) mountd detects the upgrade file >>>> 3) mountd triggers sysupgrade >>>> 4) system reboots >>>> 5) goto 1) >>>> >>>> there is no way to know at what point between 3 and 4 we need to unplug >>>> the usb stick Yep, I totally agree. A better solution based on this patch would be copying the update to tmp and execute it after the storage device is removed. >>> One possible solution is to write a file, something like >>> ".sysupgrade-applied" or remove the upgrade file before actually doing >>> the upgrade, or during first boot. >>> >>> bruno I think this solution is lacking the feature "batch update" on for example 20 devices in row. >>>> John >>>> >>>> On 04/07/2016 18:56, Philipp Deppenwiese wrote: >>>>> Extend the mountd with the ability to apply sysupgrades from mounted >>>>> devices. >>>>> Upgrade files are identified by filename and executed through the >>>>> commandline sysupgrade utility of LEDE. >>>>> >>>>> Option List: >>>>> >>>>> config mountd 'sysupgrade' >>>>> option check_filename firmware.bin (required) >>>>> option save_config 1 (optional, default disabled) >>>>> option delay 10 (optional, default disabled) >>>>> option preserve_part 1 (optional, default disabled) >>>>> option enabled 1 >>>>> >>>>> The so called "filesearch" is done only in the root of a mounted >>>>> devices. >>>>> >>>>> Signed-off-by: Philipp Deppenwiese <zao...@das-labor.org> >>>>> --- >>>>> CMakeLists.txt | 2 +- >>>>> autofs.c | 19 ++++++- >>>>> include/upgrade.h | 6 ++ >>>>> mount.c | 2 + >>>>> upgrade.c | 162 >>>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>>>> 5 files changed, 189 insertions(+), 2 deletions(-) >>>>> create mode 100644 include/upgrade.h >>>>> create mode 100644 upgrade.c >>>>> >>>>> diff --git a/CMakeLists.txt b/CMakeLists.txt >>>>> index 2e712cd..ed3602e 100644 >>>>> --- a/CMakeLists.txt >>>>> +++ b/CMakeLists.txt >>>>> @@ -5,7 +5,7 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 >>>>> -Wmissing-declarations) >>>>> >>>>> SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") >>>>> >>>>> -ADD_EXECUTABLE(mountd main.c log.c sys.c autofs.c mount.c timer.c >>>>> signal.c ucix.c led.c fs.c ucix.c) >>>>> +ADD_EXECUTABLE(mountd main.c log.c sys.c autofs.c mount.c timer.c >>>>> signal.c ucix.c led.c fs.c ucix.c upgrade.c) >>>>> TARGET_LINK_LIBRARIES(mountd uci ubox) >>>>> >>>>> INSTALL(TARGETS mountd >>>>> diff --git a/autofs.c b/autofs.c >>>>> index 4ad782d..79a3e97 100644 >>>>> --- a/autofs.c >>>>> +++ b/autofs.c >>>>> @@ -37,6 +37,13 @@ dev_t dev; >>>>> time_t uci_timeout; >>>>> char uci_path[32]; >>>>> >>>>> +// Sysupgrade uci options >>>>> +char uci_upgrade_filename[255]; >>>>> +int uci_upgrade_backup; >>>>> +int uci_upgrade_delay; >>>>> +int uci_upgrade_enabled; >>>>> +int uci_upgrade_preserve_partition; >>>>> + >>>>> static void umount_autofs(void) >>>>> { >>>>> system_printf("umount %s 2> /dev/null", "/tmp/run/mountd/"); >>>>> @@ -186,18 +193,28 @@ static void autofs_cleanup_handler(void) >>>>> static void autofs_init(void) >>>>> { >>>>> int kproto_version; >>>>> - char *p; >>>>> + char *p, *filename = NULL; >>>>> struct uci_context *ctx; >>>>> signal_init(autofs_cleanup_handler); >>>>> ctx = ucix_init("mountd"); >>>>> uci_timeout = ucix_get_option_int(ctx, "mountd", "mountd", >>>>> "timeout", 60); >>>>> p = ucix_get_option(ctx, "mountd", "mountd", "path"); >>>>> + filename = ucix_get_option(ctx, "mountd", "sysupgrade", >>>>> "check_filename"); >>>>> + uci_upgrade_backup = ucix_get_option_int(ctx, "mountd", >>>>> "sysupgrade", "save_config", 0); >>>>> + uci_upgrade_delay = ucix_get_option_int(ctx, "mountd", "sysupgrade", >>>>> "delay", 0); >>>>> + uci_upgrade_enabled = ucix_get_option_int(ctx, "mountd", >>>>> "sysupgrade", "enabled", 0); >>>>> + uci_upgrade_preserve_partition = ucix_get_option_int(ctx, "mountd", >>>>> "sysupgrade", "preserve_part", 0); >>>>> ucix_cleanup(ctx); >>>>> if(p) >>>>> snprintf(uci_path, 31, "%s", p); >>>>> else >>>>> snprintf(uci_path, 31, "/tmp/mounts/"); >>>>> uci_path[31] = '\0'; >>>>> + >>>>> + if(filename) { >>>>> + snprintf(uci_upgrade_filename, 255, "%s", filename); >>>>> + } >>>>> + >>>>> mkdir("/tmp/run/", 0555); >>>>> mkdir("/tmp/mounts", 0555); >>>>> system_printf("rm -rf %s*", uci_path); >>>>> diff --git a/include/upgrade.h b/include/upgrade.h >>>>> new file mode 100644 >>>>> index 0000000..6b5ace9 >>>>> --- /dev/null >>>>> +++ b/include/upgrade.h >>>>> @@ -0,0 +1,6 @@ >>>>> +#ifndef _UPGRADE_H__ >>>>> +#define _UPGRADE_H__ >>>>> + >>>>> +int sysupgrade_scan(const char *mount_path); >>>>> + >>>>> +#endif >>>>> diff --git a/mount.c b/mount.c >>>>> index 7cbb8ff..0bec25e 100644 >>>>> --- a/mount.c >>>>> +++ b/mount.c >>>>> @@ -28,6 +28,7 @@ >>>>> #include "include/ucix.h" >>>>> #include "include/fs.h" >>>>> #include "include/mount.h" >>>>> +#include "include/upgrade.h" >>>>> >>>>> int mount_new(char *path, char *dev); >>>>> >>>>> @@ -300,6 +301,7 @@ int mount_new(char *path, char *dev) >>>>> { >>>>> mount->mounted = 1; >>>>> mount_dump_uci_state(); >>>>> + sysupgrade_scan(tmp); >>>>> } else return -1; >>>>> return 0; >>>>> } >>>>> diff --git a/upgrade.c b/upgrade.c >>>>> new file mode 100644 >>>>> index 0000000..6992e65 >>>>> --- /dev/null >>>>> +++ b/upgrade.c >>>>> @@ -0,0 +1,162 @@ >>>>> +/* >>>>> + * This program is free software; you can redistribute it and/or modify >>>>> + * it under the terms of the GNU General Public License as published by >>>>> + * the Free Software Foundation; either version 2 of the License, or >>>>> + * (at your option) any later version. >>>>> + * >>>>> + * This program is distributed in the hope that it will be useful, >>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>>>> + * GNU General Public License for more details. >>>>> + * >>>>> + * Provided by 9elements GmbH >>>>> + * Copyright (C) 2016 Philipp Deppenwiese >>>>> <philipp.deppenwi...@9elements.com> >>>>> + */ >>>>> + >>>>> +#include <errno.h> >>>>> +#include <linux/limits.h> >>>>> +#include <stdio.h> >>>>> +#include <stdlib.h> >>>>> +#include <stdarg.h> >>>>> +#include <string.h> >>>>> +#include <sys/stat.h> >>>>> +#include <sys/types.h> >>>>> +#include <sys/wait.h> >>>>> +#include <unistd.h> >>>>> + >>>>> +#include "include/upgrade.h" >>>>> +#include "include/log.h" >>>>> + >>>>> +#define SYSUPGRADE_CMD "/sbin/sysupgrade" >>>>> + >>>>> +extern char uci_upgrade_filename[255]; >>>>> +extern int uci_upgrade_backup; >>>>> +extern int uci_upgrade_delay; >>>>> +extern int uci_upgrade_enabled; >>>>> +extern int uci_upgrade_preserve_partition; >>>>> + >>>>> +static unsigned option_index = 0; >>>>> +static char **parameters = NULL; >>>>> + >>>>> +static int execute_sysupgrade() >>>>> +{ >>>>> + pid_t pid; >>>>> + int status; >>>>> + char * const envp[] = { NULL }; >>>>> + >>>>> + if (!parameters) { >>>>> + return 1; >>>>> + } >>>>> + >>>>> + if ((pid = fork()) < 0) { >>>>> + perror("Can't fork child process for command invocation!"); >>>>> + return 1; >>>>> + } else if (pid == 0) { >>>>> + if (execve(SYSUPGRADE_CMD, parameters, envp) < 0) { >>>>> + log_printf("Error was reported on sysupgrade: %s\n", >>>>> strerror(errno)); >>>>> + return 1; >>>>> + } >>>>> + } else { >>>>> + waitpid(pid, &status, 0); >>>>> + } >>>>> + return 0; >>>>> +} >>>>> + >>>>> +static int find_upgrade_filepath(const char *mount_path, char >>>>> *update_file) >>>>> +{ >>>>> + struct stat file; >>>>> + >>>>> + if (snprintf(update_file, PATH_MAX, "%s/%s", mount_path, >>>>> + uci_upgrade_filename) < 0) { >>>>> + perror(NULL); >>>>> + return 1; >>>>> + } >>>>> + >>>>> + if (stat(update_file, &file) < 0) { >>>>> + log_printf("No upgrade file found for device path: %s! \n", >>>>> mount_path); >>>>> + return 1; >>>>> + } >>>>> + return 0; >>>>> +} >>>>> + >>>>> +static void add_sysupgrade_option(const char *parameter, ...) >>>>> +{ >>>>> + va_list arguments; >>>>> + char *option = NULL; >>>>> + >>>>> + parameters = realloc(parameters, ++option_index * sizeof(char*)); >>>>> + >>>>> + if (parameter) { >>>>> + option = (char*)calloc(PATH_MAX, sizeof(char)); >>>>> + >>>>> + va_start(arguments, parameter); >>>>> + vsnprintf(option, PATH_MAX, parameter, arguments); >>>>> + va_end(arguments); >>>>> + } >>>>> + >>>>> + parameters[option_index - 1] = option; >>>>> +} >>>>> + >>>>> +static void free_all() >>>>> +{ >>>>> + unsigned i; >>>>> + >>>>> + if (!parameters) { >>>>> + return; >>>>> + } >>>>> + >>>>> + for (i = 0; i < option_index; i++) { >>>>> + if (parameters[i]) { >>>>> + free(parameters[i]); >>>>> + } >>>>> + } >>>>> + >>>>> + free(parameters); >>>>> + parameters = NULL; >>>>> + option_index = 0; >>>>> +} >>>>> + >>>>> +int sysupgrade_scan(const char *mount_path) >>>>> +{ >>>>> + char update_file[PATH_MAX]; >>>>> + >>>>> + if (!uci_upgrade_enabled) { >>>>> + log_printf("Sysupgrade via usb device is disabled..\n"); >>>>> + return 0; >>>>> + } >>>>> + >>>>> + if (find_upgrade_filepath(mount_path, update_file)) { >>>>> + log_printf("No upgrade file could be found..\n"); >>>>> + return 0; >>>>> + } >>>>> + >>>>> + log_printf("Starting sysupgrade routine..\n"); >>>>> + >>>>> + add_sysupgrade_option("%s", SYSUPGRADE_CMD); >>>>> + >>>>> + if (uci_upgrade_delay) { >>>>> + add_sysupgrade_option("-d %i", uci_upgrade_delay); >>>>> + } >>>>> + >>>>> + if (uci_upgrade_backup) { >>>>> + add_sysupgrade_option("-c"); >>>>> + } else { >>>>> + add_sysupgrade_option("-n"); >>>>> + } >>>>> + >>>>> + if (uci_upgrade_preserve_partition) { >>>>> + add_sysupgrade_option("-p"); >>>>> + } >>>>> + >>>>> + add_sysupgrade_option("%s", update_file); >>>>> + add_sysupgrade_option(NULL); >>>>> + >>>>> + if (execute_sysupgrade()) { >>>>> + free_all(); >>>>> + log_printf("Try to start sysupgrade but it failed! \n"); >>>>> + return 1; >>>>> + } >>>>> + >>>>> + free_all(); >>>>> + return 0; >>>>> +} >>>>> >>>> _______________________________________________ >>>> Lede-dev mailing list >>>> Lede-dev@lists.infradead.org >>>> http://lists.infradead.org/mailman/listinfo/lede-dev >>>> >>> >>> _______________________________________________ >>> Lede-dev mailing list >>> Lede-dev@lists.infradead.org >>> http://lists.infradead.org/mailman/listinfo/lede-dev >> _______________________________________________ >> Lede-dev mailing list >> Lede-dev@lists.infradead.org >> http://lists.infradead.org/mailman/listinfo/lede-dev > _______________________________________________ > Lede-dev mailing list > Lede-dev@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/lede-dev
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev