diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-04-29 20:17:55 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-05-02 11:17:06 +0200 |
commit | 5d2036b5f3506bd0ff07042aee8d69c26db32298 (patch) | |
tree | 36715e8eb2aacc2cae221a3ca3d03041b0b22961 /src | |
parent | 9a50e3caab82f8406ecfac6048ac8e2ce98b0ab8 (diff) |
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')
-rw-r--r-- | src/machine/image-dbus.c | 35 |
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( |