summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--discover/device-handler.c3
-rw-r--r--discover/network.c3
-rw-r--r--discover/paths.c100
-rw-r--r--discover/paths.h4
-rw-r--r--test/parser/handler.c8
5 files changed, 118 insertions, 0 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index a0c21b7..730be85 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -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);
diff --git a/discover/network.c b/discover/network.c
index 8ca4561..5035b7c 100644
--- a/discover/network.c
+++ b/discover/network.c
@@ -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;
diff --git a/discover/paths.c b/discover/paths.c
index e76dc35..3a69488 100644
--- a/discover/paths.c
+++ b/discover/paths.c
@@ -18,9 +18,20 @@
#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:
diff --git a/discover/paths.h b/discover/paths.h
index 35673b7..67fe8a3 100644
--- a/discover/paths.h
+++ b/discover/paths.h
@@ -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,
diff --git a/test/parser/handler.c b/test/parser/handler.c
index e356407..e455c22 100644
--- a/test/parser/handler.c
+++ b/test/parser/handler.c
@@ -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)
+{
+}
OpenPOWER on IntegriCloud