summaryrefslogtreecommitdiff
path: root/src/machine
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-04-29 20:32:56 +0200
committerLennart Poettering <lennart@poettering.net>2016-05-02 11:17:06 +0200
commit795c5d31affeb3b3edbf673940cc0f16afebc7a8 (patch)
treeffd79868bad763f8bfa094f7a4b6c0e824333bb5 /src/machine
parent5d2036b5f3506bd0ff07042aee8d69c26db32298 (diff)
machined: rework copy-from/copy-to operation to use generic Operation object
With this all potentially slow operations are done out-of-process, asynchronously, using the same "Operation" object.
Diffstat (limited to 'src/machine')
-rw-r--r--src/machine/image-dbus.c4
-rw-r--r--src/machine/machine-dbus.c66
-rw-r--r--src/machine/machine.c24
-rw-r--r--src/machine/machine.h20
-rw-r--r--src/machine/operation.c23
-rw-r--r--src/machine/operation.h4
6 files changed, 33 insertions, 108 deletions
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index e07edae6ef..0eed9b81bb 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -81,7 +81,7 @@ int bus_image_method_remove(
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
- r = operation_new(m, child, message, errno_pipe_fd[0]);
+ r = operation_new(m, NULL, child, message, errno_pipe_fd[0]);
if (r < 0) {
(void) sigkill_wait(child);
return r;
@@ -193,7 +193,7 @@ int bus_image_method_clone(
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
- r = operation_new(m, child, message, errno_pipe_fd[0]);
+ r = operation_new(m, NULL, child, message, errno_pipe_fd[0]);
if (r < 0) {
(void) sigkill_wait(child);
return r;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 5121bfdd18..7b9aa66d63 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -1085,52 +1085,11 @@ finish:
return r;
}
-static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- MachineOperation *o = userdata;
- int r;
-
- assert(o);
- assert(si);
-
- o->pid = 0;
-
- if (si->si_code != CLD_EXITED) {
- r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
- goto fail;
- }
-
- if (si->si_status != EXIT_SUCCESS) {
- if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r))
- r = sd_bus_error_set_errnof(&error, r, "%m");
- else
- r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed.");
-
- goto fail;
- }
-
- r = sd_bus_reply_method_return(o->message, NULL);
- if (r < 0)
- log_error_errno(r, "Failed to reply to message: %m");
-
- machine_operation_unref(o);
- return 0;
-
-fail:
- r = sd_bus_reply_method_error(o->message, &error);
- if (r < 0)
- log_error_errno(r, "Failed to reply to message: %m");
-
- machine_operation_unref(o);
- return 0;
-}
-
int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
_cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
_cleanup_close_ int hostfd = -1;
Machine *m = userdata;
- MachineOperation *o;
bool copy_from;
pid_t child;
char *t;
@@ -1139,7 +1098,7 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
assert(message);
assert(m);
- if (m->n_operations >= MACHINE_OPERATIONS_MAX)
+ if (m->manager->n_operations >= OPERATIONS_MAX)
return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
if (m->class != MACHINE_CONTAINER)
@@ -1249,27 +1208,14 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
- /* Copying might take a while, hence install a watch the
- * child, and return */
+ /* Copying might take a while, hence install a watch on the child, and return */
- o = new0(MachineOperation, 1);
- if (!o)
- return log_oom();
-
- o->pid = child;
- o->message = sd_bus_message_ref(message);
- o->errno_fd = errno_pipe_fd[0];
- errno_pipe_fd[0] = -1;
-
- r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
+ r = operation_new(m->manager, m, child, message, errno_pipe_fd[0]);
if (r < 0) {
- machine_operation_unref(o);
- return log_oom();
+ (void) sigkill_wait(child);
+ return r;
}
-
- LIST_PREPEND(operations, m->operations, o);
- m->n_operations++;
- o->machine = m;
+ errno_pipe_fd[0] = -1;
return 1;
}
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 7d4270a8ff..c1fae57084 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -89,7 +89,7 @@ void machine_free(Machine *m) {
assert(m);
while (m->operations)
- machine_operation_unref(m->operations);
+ operation_free(m->operations);
if (m->in_gc_queue)
LIST_REMOVE(gc_queue, m->manager->machine_gc_queue, m);
@@ -596,28 +596,6 @@ int machine_open_terminal(Machine *m, const char *path, int mode) {
}
}
-MachineOperation *machine_operation_unref(MachineOperation *o) {
- if (!o)
- return NULL;
-
- sd_event_source_unref(o->event_source);
-
- safe_close(o->errno_fd);
-
- if (o->pid > 1)
- (void) kill(o->pid, SIGKILL);
-
- sd_bus_message_unref(o->message);
-
- if (o->machine) {
- LIST_REMOVE(operations, o->machine->operations, o);
- o->machine->n_operations--;
- }
-
- free(o);
- return NULL;
-}
-
void machine_release_unit(Machine *m) {
assert(m);
diff --git a/src/machine/machine.h b/src/machine/machine.h
index 1d8cc5911a..e5d75361a9 100644
--- a/src/machine/machine.h
+++ b/src/machine/machine.h
@@ -20,11 +20,11 @@
***/
typedef struct Machine Machine;
-typedef struct MachineOperation MachineOperation;
typedef enum KillWho KillWho;
#include "list.h"
#include "machined.h"
+#include "operation.h"
typedef enum MachineState {
MACHINE_OPENING, /* Machine is being registered */
@@ -49,17 +49,6 @@ enum KillWho {
_KILL_WHO_INVALID = -1
};
-#define MACHINE_OPERATIONS_MAX 64
-
-struct MachineOperation {
- Machine *machine;
- pid_t pid;
- sd_bus_message *message;
- int errno_fd;
- sd_event_source *event_source;
- LIST_FIELDS(MachineOperation, operations);
-};
-
struct Machine {
Manager *manager;
@@ -88,10 +77,9 @@ struct Machine {
int *netif;
unsigned n_netif;
- LIST_FIELDS(Machine, gc_queue);
+ LIST_HEAD(Operation, operations);
- MachineOperation *operations;
- unsigned n_operations;
+ LIST_FIELDS(Machine, gc_queue);
};
Machine* machine_new(Manager *manager, MachineClass class, const char *name);
@@ -109,8 +97,6 @@ void machine_release_unit(Machine *m);
MachineState machine_get_state(Machine *u);
-MachineOperation *machine_operation_unref(MachineOperation *o);
-
const char* machine_class_to_string(MachineClass t) _const_;
MachineClass machine_class_from_string(const char *s) _pure_;
diff --git a/src/machine/operation.c b/src/machine/operation.c
index e8564c29f7..e6ddc41a55 100644
--- a/src/machine/operation.c
+++ b/src/machine/operation.c
@@ -66,15 +66,20 @@ fail:
return 0;
}
-int operation_new(Manager *m, pid_t child, sd_bus_message *message, int errno_fd) {
+int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd) {
Operation *o;
int r;
+ assert(manager);
+ assert(child > 1);
+ assert(message);
+ assert(errno_fd >= 0);
+
o = new0(Operation, 1);
if (!o)
return -ENOMEM;
- r = sd_event_add_child(m->event, &o->event_source, child, WEXITED, operation_done, o);
+ r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
if (r < 0) {
free(o);
return r;
@@ -84,9 +89,14 @@ int operation_new(Manager *m, pid_t child, sd_bus_message *message, int errno_fd
o->message = sd_bus_message_ref(message);
o->errno_fd = errno_fd;
- LIST_PREPEND(operations, m->operations, o);
- m->n_operations++;
- o->manager = m;
+ LIST_PREPEND(operations, manager->operations, o);
+ manager->n_operations++;
+ o->manager = manager;
+
+ if (machine) {
+ LIST_PREPEND(operations_by_machine, machine->operations, o);
+ o->machine = machine;
+ }
log_debug("Started new operation " PID_FMT ".", child);
@@ -113,6 +123,9 @@ Operation *operation_free(Operation *o) {
o->manager->n_operations--;
}
+ if (o->machine)
+ LIST_REMOVE(operations_by_machine, o->machine->operations, o);
+
free(o);
return NULL;
}
diff --git a/src/machine/operation.h b/src/machine/operation.h
index 9d4c3afe45..7ca47bc3af 100644
--- a/src/machine/operation.h
+++ b/src/machine/operation.h
@@ -34,12 +34,14 @@ typedef struct Operation Operation;
struct Operation {
Manager *manager;
+ Machine *machine;
pid_t pid;
sd_bus_message *message;
int errno_fd;
sd_event_source *event_source;
LIST_FIELDS(Operation, operations);
+ LIST_FIELDS(Operation, operations_by_machine);
};
-int operation_new(Manager *m, pid_t child, sd_bus_message *message, int errno_fd);
+int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd);
Operation *operation_free(Operation *o);