summaryrefslogtreecommitdiff
path: root/src/machine/image-dbus.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-04-29 20:17:55 +0200
committerLennart Poettering <lennart@poettering.net>2016-05-02 11:17:06 +0200
commit5d2036b5f3506bd0ff07042aee8d69c26db32298 (patch)
tree36715e8eb2aacc2cae221a3ca3d03041b0b22961 /src/machine/image-dbus.c
parent9a50e3caab82f8406ecfac6048ac8e2ce98b0ab8 (diff)
downloadsystemd-5d2036b5f3506bd0ff07042aee8d69c26db32298.tar.gz
machined: also make image removal operation asynchronous
If we remove a directory image (i.e. not a btrfs snapshot) then things might get quite expensive, hence run this asynchronous in a forked off process, too.
Diffstat (limited to 'src/machine/image-dbus.c')
-rw-r--r--src/machine/image-dbus.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index db0ed03b69..e07edae6ef 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -35,13 +35,18 @@ int bus_image_method_remove(
void *userdata,
sd_bus_error *error) {
+ _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
Image *image = userdata;
Manager *m = image->userdata;
+ pid_t child;
int r;
assert(message);
assert(image);
+ if (m->n_operations >= OPERATIONS_MAX)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
@@ -56,11 +61,35 @@ int bus_image_method_remove(
if (r == 0)
return 1; /* Will call us back */
- r = image_remove(image);
- if (r < 0)
+ if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
+ return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
+
+ child = fork();
+ if (child < 0)
+ return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
+ if (child == 0) {
+ errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
+
+ r = image_remove(image);
+ if (r < 0) {
+ (void) write(errno_pipe_fd[1], &r, sizeof(r));
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
+
+ r = operation_new(m, child, message, errno_pipe_fd[0]);
+ if (r < 0) {
+ (void) sigkill_wait(child);
return r;
+ }
- return sd_bus_reply_method_return(message, NULL);
+ errno_pipe_fd[0] = -1;
+
+ return 1;
}
int bus_image_method_rename(