]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: also make image removal operation asynchronous
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Apr 2016 18:17:55 +0000 (20:17 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 2 May 2016 09:17:06 +0000 (11:17 +0200)
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.

src/machine/image-dbus.c

index db0ed03b69390c080ce841008b97020f3e9d6835..e07edae6efd59ffc59322f3e506694590383e4a2 100644 (file)
@@ -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(