naccyde / rpms / systemd

Forked from rpms/systemd a year ago
Clone
803fb7
From 33ca0f1f0d4b9a91588c84067d2fb30968e41235 Mon Sep 17 00:00:00 2001
803fb7
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
803fb7
Date: Tue, 14 Jun 2016 14:20:56 +0200
803fb7
Subject: [PATCH] manager: reduce complexity of unit_gc_sweep (#3507)
803fb7
803fb7
When unit is marked as UNSURE, we are trying to find if it state was
803fb7
changed over and over again. So lets not go through the UNSURE states
803fb7
again. Also when we find a GOOD unit lets propagate the GOOD state to
803fb7
all units that this unit reference.
803fb7
803fb7
This is a problem on machines with a lot of initscripts with different
803fb7
starting priority, since those units will reference each other and the
803fb7
original algorithm might get to n! complexity.
803fb7
803fb7
Thanks HATAYAMA Daisuke for the expand_good_state code.
803fb7
Cherry-picked from: 4892084f096c19da0e83f28f250ca187b58c22b2
803fb7
Resolves: #1344556
803fb7
---
803fb7
 src/core/manager.c | 16 +++++++++++++++-
803fb7
 1 file changed, 15 insertions(+), 1 deletion(-)
803fb7
803fb7
diff --git a/src/core/manager.c b/src/core/manager.c
803fb7
index 370c8cbbe..e5226a8a6 100644
803fb7
--- a/src/core/manager.c
803fb7
+++ b/src/core/manager.c
803fb7
@@ -838,6 +838,19 @@ enum {
803fb7
         _GC_OFFSET_MAX
803fb7
 };
803fb7
 
803fb7
+static void unit_gc_mark_good(Unit *u, unsigned gc_marker)
803fb7
+{
803fb7
+        Iterator i;
803fb7
+        Unit *other;
803fb7
+
803fb7
+        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
803fb7
+
803fb7
+        /* Recursively mark referenced units as GOOD as well */
803fb7
+        SET_FOREACH(other, u->dependencies[UNIT_REFERENCES], i)
803fb7
+                if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE)
803fb7
+                        unit_gc_mark_good(other, gc_marker);
803fb7
+}
803fb7
+
803fb7
 static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
803fb7
         Iterator i;
803fb7
         Unit *other;
803fb7
@@ -847,6 +860,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
803fb7
 
803fb7
         if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
803fb7
             u->gc_marker == gc_marker + GC_OFFSET_BAD ||
803fb7
+            u->gc_marker == gc_marker + GC_OFFSET_UNSURE ||
803fb7
             u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
803fb7
                 return;
803fb7
 
803fb7
@@ -887,7 +901,7 @@ bad:
803fb7
         return;
803fb7
 
803fb7
 good:
803fb7
-        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
803fb7
+        unit_gc_mark_good(u, gc_marker);
803fb7
 }
803fb7
 
803fb7
 static unsigned manager_dispatch_gc_queue(Manager *m) {