summaryrefslogtreecommitdiffstats
path: root/discover
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2013-10-14 13:10:38 +0800
committerJeremy Kerr <jk@ozlabs.org>2013-10-14 15:27:11 +0800
commite983d818be18a975c519bd76294519a01ce7a1c3 (patch)
tree5f956f8e2ff866f1629266babd6f22249a4ef249 /discover
parentd2a32f50660d32885ee20b6e3b5bbabfecd2b4e9 (diff)
downloadtalos-petitboot-e983d818be18a975c519bd76294519a01ce7a1c3.tar.gz
talos-petitboot-e983d818be18a975c519bd76294519a01ce7a1c3.zip
discover: Add load_url_cancel
We'd like a way to cancel pending loads, as part of aborting the boot process. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover')
-rw-r--r--discover/paths.c31
-rw-r--r--discover/paths.h11
2 files changed, 38 insertions, 4 deletions
diff --git a/discover/paths.c b/discover/paths.c
index c352ca0..aa977fd 100644
--- a/discover/paths.c
+++ b/discover/paths.c
@@ -1,5 +1,6 @@
#define _GNU_SOURCE
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -79,9 +80,14 @@ static void load_url_process_exit(struct process *process)
data = task->async_data;
cb = task->async_cb;
- result->status = process->exit_status == 0 ? LOAD_OK : LOAD_ERROR;
- if (result->status == LOAD_ERROR)
+ if (result->status == LOAD_CANCELLED) {
load_url_result_cleanup_local(result);
+ } else if (process->exit_status == 0) {
+ result->status = LOAD_OK;
+ } else {
+ result->status = LOAD_ERROR;
+ load_url_result_cleanup_local(result);
+ }
/* The load callback may well free the ctx, which was the
* talloc parent of the task. Therefore, we want to do our cleanup
@@ -89,6 +95,7 @@ static void load_url_process_exit(struct process *process)
*/
process_release(process);
talloc_free(task);
+ result->task = NULL;
cb(result, data);
}
@@ -359,6 +366,7 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
task->url = url;
task->async = async_cb != NULL;
task->result = talloc_zero(ctx, struct load_url_result);
+ task->result->task = task;
task->process = process_create(task);
if (task->async) {
task->async_cb = async_cb;
@@ -407,3 +415,22 @@ struct load_url_result *load_url(void *ctx, struct pb_url *url)
{
return load_url_async(ctx, url, NULL, NULL);
}
+
+void load_url_async_cancel(struct load_url_result *res)
+{
+ struct load_task *task = res->task;
+
+ /* the completion callback may have already been called; this clears
+ * res->task */
+ if (!task)
+ return;
+
+ if (res->status == LOAD_CANCELLED)
+ return;
+
+ assert(task->async);
+ assert(task->process);
+
+ res->status = LOAD_CANCELLED;
+ process_stop_async(task->process);
+}
diff --git a/discover/paths.h b/discover/paths.h
index e905094..ed0e153 100644
--- a/discover/paths.h
+++ b/discover/paths.h
@@ -16,6 +16,7 @@ char *join_paths(void *alloc_ctx, const char *a, const char *b);
*/
const char *mount_base(void);
+struct load_task;
struct load_url_result {
enum {
@@ -26,9 +27,12 @@ struct load_url_result {
* (sync will see a NULL result) */
LOAD_ASYNC, /* async load still in progress */
+
+ LOAD_CANCELLED,
} status;
- const char *local;
- bool cleanup_local;
+ const char *local;
+ bool cleanup_local;
+ struct load_task *task;
};
/* callback type for asynchronous loads. The callback implementation is
@@ -40,6 +44,9 @@ typedef void (*load_url_complete)(struct load_url_result *result, void *data);
struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
load_url_complete complete, void *data);
+/* Cancel a pending load */
+void load_url_async_cancel(struct load_url_result *res);
+
struct load_url_result *load_url(void *ctx, struct pb_url *url);
#endif /* PATHS_H */
OpenPOWER on IntegriCloud