diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index 364ede47d872c035ae24360425395c6aaa484f7e..a932497d37dbb4fd619bdfd21008c11961d35443 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -541,6 +541,69 @@ pv_runtime_constructed (GObject *object)
   g_return_if_fail (self->tools_dir != NULL);
 }
 
+static void
+pv_runtime_maybe_garbage_collect_subdir (const char *description,
+                                         const char *parent,
+                                         int parent_fd,
+                                         const char *member)
+{
+  g_autoptr(GError) local_error = NULL;
+  g_autoptr(PvBwrapLock) temp_lock = NULL;
+  g_autofree gchar *keep = NULL;
+  g_autofree gchar *ref = NULL;
+  struct stat ignore;
+
+  g_return_if_fail (parent != NULL);
+  g_return_if_fail (parent_fd >= 0);
+  g_return_if_fail (member != NULL);
+
+  g_debug ("Found %s %s/%s, considering whether to delete it...",
+           description, parent, member);
+
+  keep = g_build_filename (member, "keep", NULL);
+
+  if (glnx_fstatat (parent_fd, keep, &ignore,
+                    AT_SYMLINK_NOFOLLOW, &local_error))
+    {
+      g_debug ("Not deleting \"%s/%s\": ./keep exists",
+               parent, member);
+      return;
+    }
+  else if (!g_error_matches (local_error, G_IO_ERROR,
+                             G_IO_ERROR_NOT_FOUND))
+    {
+      /* EACCES or something? Give it the benefit of the doubt */
+      g_warning ("Not deleting \"%s/%s\": unable to stat ./keep: %s",
+               parent, member, local_error->message);
+      return;
+    }
+
+  g_clear_error (&local_error);
+
+  ref = g_build_filename (member, ".ref", NULL);
+  temp_lock = pv_bwrap_lock_new (parent_fd, ref,
+                                 (PV_BWRAP_LOCK_FLAGS_CREATE |
+                                  PV_BWRAP_LOCK_FLAGS_WRITE),
+                                 &local_error);
+
+  if (temp_lock == NULL)
+    {
+      g_info ("Not deleting \"%s/%s\": unable to get lock: %s",
+              parent, member, local_error->message);
+      return;
+    }
+
+  g_debug ("Deleting \"%s/%s\"...", parent, member);
+
+  /* We have the lock, which would not have happened if someone was
+   * still using the runtime, so we can safely delete it. */
+  if (!glnx_shutil_rm_rf_at (parent_fd, member, NULL, &local_error))
+    {
+      g_debug ("Unable to delete %s/%s: %s",
+               parent, member, local_error->message);
+    }
+}
+
 static gboolean
 pv_runtime_garbage_collect (PvRuntime *self,
                             PvBwrapLock *variable_dir_lock,
@@ -561,12 +624,7 @@ pv_runtime_garbage_collect (PvRuntime *self,
 
   while (TRUE)
     {
-      g_autoptr(GError) local_error = NULL;
-      g_autoptr(PvBwrapLock) temp_lock = NULL;
-      g_autofree gchar *keep = NULL;
-      g_autofree gchar *ref = NULL;
       struct dirent *dent;
-      struct stat ignore;
 
       if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&iter, &dent,
                                                        NULL, error))
@@ -619,58 +677,10 @@ pv_runtime_garbage_collect (PvRuntime *self,
           continue;
         }
 
-      g_debug ("Found temporary runtime %s/%s, considering whether to "
-               "delete it...",
-               self->variable_dir, dent->d_name);
-
-      keep = g_build_filename (dent->d_name, "keep", NULL);
-
-      if (glnx_fstatat (self->variable_dir_fd, keep, &ignore,
-                        AT_SYMLINK_NOFOLLOW, &local_error))
-        {
-          g_debug ("Not deleting \"%s/%s\": ./keep exists",
-                   self->variable_dir, dent->d_name);
-          continue;
-        }
-      else if (!g_error_matches (local_error, G_IO_ERROR,
-                                 G_IO_ERROR_NOT_FOUND))
-        {
-          /* EACCES or something? Give it the benefit of the doubt */
-          g_warning ("Not deleting \"%s/%s\": unable to stat ./keep: %s",
-                   self->variable_dir, dent->d_name, local_error->message);
-          g_clear_error (&local_error);
-          continue;
-        }
-
-      g_clear_error (&local_error);
-
-      ref = g_build_filename (dent->d_name, ".ref", NULL);
-      temp_lock = pv_bwrap_lock_new (self->variable_dir_fd, ref,
-                                     (PV_BWRAP_LOCK_FLAGS_CREATE |
-                                      PV_BWRAP_LOCK_FLAGS_WRITE),
-                                     &local_error);
-
-      if (temp_lock == NULL)
-        {
-          g_info ("Not deleting \"%s/%s\": unable to get lock: %s",
-                  self->variable_dir, dent->d_name,
-                  local_error->message);
-          g_clear_error (&local_error);
-          continue;
-        }
-
-      g_debug ("Deleting \"%s/%s\"...", self->variable_dir, dent->d_name);
-
-      /* We have the lock, which would not have happened if someone was
-       * still using the runtime, so we can safely delete it. */
-      if (!glnx_shutil_rm_rf_at (self->variable_dir_fd, dent->d_name,
-                                 NULL, &local_error))
-        {
-          g_debug ("Unable to delete %s/%s: %s",
-                   self->variable_dir, dent->d_name, local_error->message);
-          g_clear_error (&local_error);
-          continue;
-        }
+      pv_runtime_maybe_garbage_collect_subdir ("temporary runtime",
+                                               self->variable_dir,
+                                               self->variable_dir_fd,
+                                               dent->d_name);
     }
 
   return TRUE;