]> git.ozlabs.org Git - petitboot/commitdiff
discover/paths: Add network jobs to queue
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Thu, 23 Mar 2017 06:42:37 +0000 (17:42 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 11 Jul 2017 04:32:26 +0000 (14:32 +1000)
Load tasks that start before the network is available will fail. Rather
than just fail these tasks, add them to a queue that is processed once
the network is ready. This helps users who try to request files early in
setup, as well as very early running load tasks.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
discover/device-handler.c
discover/network.c
discover/paths.c
discover/paths.h
test/parser/handler.c

index a0c21b71b906e5eea8c3d986a6bb9c4d3f9fc921..730be857f5e564fdfea8938dbfc134d1f3c679be 100644 (file)
@@ -361,6 +361,7 @@ void device_handler_reinit(struct device_handler *handler)
 
        /* Cancel any remaining async jobs */
        process_stop_async_all();
+       pending_network_jobs_cancel();
 
        /* free unresolved boot options */
        list_for_each_entry_safe(&handler->unresolved_boot_options,
@@ -1083,6 +1084,8 @@ int device_handler_dhcp(struct device_handler *handler,
                        _("Processing DHCP lease response (ip: %s)"),
                        event_get_param(event, "ip"));
 
+       pending_network_jobs_start();
+
        /* create our context */
        ctx = device_handler_discover_context_create(handler, dev);
        talloc_steal(ctx, event);
index 8ca4561614f866fc1c45ef77f44ffc03c8c7fd85..5035b7ce0895cfe0f2a3c12992ca0d1d57c06f24 100644 (file)
@@ -23,6 +23,7 @@
 #include "sysinfo.h"
 #include "platform.h"
 #include "device-handler.h"
+#include "paths.h"
 
 #define HWADDR_SIZE    6
 #define PIDFILE_BASE   (LOCAL_STATE_DIR "/petitboot/")
@@ -489,6 +490,8 @@ static void configure_interface(struct network *network,
 
        } else if (config->method == CONFIG_METHOD_STATIC) {
                configure_interface_static(network, interface, config);
+               /* Nothing left to do for static interfaces */
+               pending_network_jobs_start();
        }
 
        interface->state = IFSTATE_CONFIGURED;
index e76dc35ecb1038c15b9cd2c6580cc1e454f4c850..3a69488e3e87e44dcd508a4ac4ba650d4c18571a 100644 (file)
 
 #include "paths.h"
 #include "device-handler.h"
+#include "sysinfo.h"
 
 #define DEVICE_MOUNT_BASE (LOCAL_STATE_DIR "/petitboot/mnt")
 
+
+struct list    pending_network_jobs;
+
+struct network_job {
+       struct load_task        *task;
+       int                     flags;
+
+       struct list_item        list;
+};
+
 struct load_task {
        struct pb_url           *url;
        struct process          *process;
@@ -437,6 +448,86 @@ static void load_local(struct load_task *task)
        }
 }
 
+static void load_url_async_start_pending(struct load_task *task, int flags)
+{
+       pb_log("Starting pending job for %s\n", task->url->full);
+
+       switch (task->url->scheme) {
+       case pb_url_ftp:
+       case pb_url_http:
+               load_wget(task, flags);
+               break;
+       case pb_url_https:
+               flags |= wget_no_check_certificate;
+               load_wget(task, flags);
+               break;
+       case pb_url_nfs:
+               load_nfs(task);
+               break;
+       case pb_url_sftp:
+               load_sftp(task);
+               break;
+       case pb_url_tftp:
+               load_tftp(task);
+               break;
+       default:
+               /* Shouldn't be a need via this path but.. */
+               load_local(task);
+               break;
+       }
+
+       if (task->result->status == LOAD_ERROR) {
+               pb_log("Pending job failed for %s\n", task->url->full);
+               load_url_result_cleanup_local(task->result);
+               talloc_free(task->result);
+               talloc_free(task);
+       }
+}
+
+void pending_network_jobs_start(void)
+{
+       struct network_job *job, *tmp;
+
+       if (!pending_network_jobs.head.next)
+               return;
+
+       list_for_each_entry_safe(&pending_network_jobs, job, tmp, list) {
+               load_url_async_start_pending(job->task, job->flags);
+               list_remove(&job->list);
+       }
+}
+
+void pending_network_jobs_cancel(void)
+{
+       struct network_job *job, *tmp;
+
+       if (!pending_network_jobs.head.next)
+               return;
+
+       list_for_each_entry_safe(&pending_network_jobs, job, tmp, list)
+               talloc_free(job);
+       list_init(&pending_network_jobs);
+}
+
+static void pending_network_jobs_add(struct load_task *task, int flags)
+{
+       struct network_job *job;
+
+       if (!pending_network_jobs.head.next)
+               list_init(&pending_network_jobs);
+
+       job = talloc(task, struct network_job);
+       if (!job) {
+               pb_log("Failed to allocate space for pending job\n");
+               return;
+       }
+
+       job->task = task;
+       job->flags = flags;
+       list_add_tail(&pending_network_jobs, &job->list);
+}
+
+
 /**
  * load_url - Loads a (possibly) remote URL and returns the local file
  * path.
@@ -487,6 +578,15 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
                task->process->keep_stdout = true;
        }
 
+       /* If the url is remote but network is not yet available queue up this
+        * load for later */
+       if (!system_info_network_available() && url->scheme != pb_url_file) {
+               pb_log("load task for %s queued pending network\n", url->full);
+               pending_network_jobs_add(task, flags);
+               task->result->status = LOAD_ASYNC;
+               return task->result;
+       }
+
        switch (url->scheme) {
        case pb_url_ftp:
        case pb_url_http:
index 35673b7eaef6cc1228d95019fd6ccfe0f5302612..67fe8a300ebb70d6e5081f94aafa7c57dc8b354a 100644 (file)
@@ -43,6 +43,10 @@ struct load_url_result {
  */
 typedef void (*load_url_complete)(struct load_url_result *result, void *data);
 
+/* Start transfers that were waiting for network connectivity */
+void pending_network_jobs_start(void);
+void pending_network_jobs_cancel(void);
+
 /* Load a (potentially remote) file, and return a guaranteed-local name */
 struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
                load_url_complete complete, void *data,
index e35640712770c9a0c13692691f6a660e1d60868e..e455c2221a6c0c8a0819cc1f5b2c65736f584b9d 100644 (file)
@@ -102,3 +102,11 @@ void boot_cancel(struct boot_task *task)
 {
        (void)task;
 }
+
+void pending_network_jobs_start(void)
+{
+}
+
+void pending_network_jobs_cancel(void)
+{
+}