8d419f
From 78105a206a21133f87f5982f29d7aa3c4cc72b0d Mon Sep 17 00:00:00 2001
8d419f
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
8d419f
Date: Wed, 16 Mar 2022 09:28:46 +0100
8d419f
Subject: [PATCH] shared/install: skip unnecessary chasing of symlinks in
8d419f
 disable
8d419f
8d419f
We use the symlink source name and destination names to decide whether to remove
8d419f
the symlink. But if the source name is enough to decide to remove the symlink,
8d419f
we'd still look up the destination for no good reason. This is a slow operation,
8d419f
let's skip it.
8d419f
8d419f
(cherry picked from commit 7a6c73dabf6451d6ef22d0cdfbb1749a77450d5b)
8d419f
8d419f
Related: #2082131
8d419f
---
8d419f
 src/shared/install.c | 43 +++++++++++++++++++++++++------------------
8d419f
 1 file changed, 25 insertions(+), 18 deletions(-)
8d419f
8d419f
diff --git a/src/shared/install.c b/src/shared/install.c
8d419f
index ad0238ab50..08a9892260 100644
8d419f
--- a/src/shared/install.c
8d419f
+++ b/src/shared/install.c
8d419f
@@ -599,8 +599,7 @@ static int remove_marked_symlinks_fd(
8d419f
                                 r = q;
8d419f
 
8d419f
                 } else if (de->d_type == DT_LNK) {
8d419f
-                        _cleanup_free_ char *p = NULL, *dest = NULL;
8d419f
-                        const char *rp;
8d419f
+                        _cleanup_free_ char *p = NULL;
8d419f
                         bool found;
8d419f
                         int q;
8d419f
 
8d419f
@@ -612,24 +611,32 @@ static int remove_marked_symlinks_fd(
8d419f
                                 return -ENOMEM;
8d419f
                         path_simplify(p);
8d419f
 
8d419f
-                        q = chase_symlinks(p, lp->root_dir, CHASE_NONEXISTENT, &dest, NULL);
8d419f
-                        if (q == -ENOENT)
8d419f
-                                continue;
8d419f
-                        if (q < 0) {
8d419f
-                                log_debug_errno(q, "Failed to resolve symlink \"%s\": %m", p);
8d419f
-                                unit_file_changes_add(changes, n_changes, q, p, NULL);
8d419f
+                        /* We remove all links pointing to a file or path that is marked, as well as all
8d419f
+                         * files sharing the same name as a file that is marked. Do path chasing only if
8d419f
+                         * we don't already know that we want to remove the symlink. */
8d419f
+                        found = set_contains(remove_symlinks_to, de->d_name);
8d419f
 
8d419f
-                                if (r == 0)
8d419f
-                                        r = q;
8d419f
-                                continue;
8d419f
-                        }
8d419f
+                        if (!found) {
8d419f
+                                _cleanup_free_ char *dest = NULL;
8d419f
+
8d419f
+
8d419f
+                                q = chase_symlinks(p, lp->root_dir, CHASE_NONEXISTENT, &dest, NULL);
8d419f
+                                if (q == -ENOENT)
8d419f
+                                        continue;
8d419f
+                                if (q < 0) {
8d419f
+                                        log_debug_errno(q, "Failed to resolve symlink \"%s\": %m", p);
8d419f
+                                        unit_file_changes_add(changes, n_changes, q, p, NULL);
8d419f
 
8d419f
-                        /* We remove all links pointing to a file or path that is marked, as well as all files sharing
8d419f
-                         * the same name as a file that is marked. */
8d419f
+                                        if (r == 0)
8d419f
+                                                r = q;
8d419f
+                                        continue;
8d419f
+                                }
8d419f
+
8d419f
+                                found = set_contains(remove_symlinks_to, dest) ||
8d419f
+                                        set_contains(remove_symlinks_to, basename(dest));
8d419f
+
8d419f
+                        }
8d419f
 
8d419f
-                        found = set_contains(remove_symlinks_to, dest) ||
8d419f
-                                set_contains(remove_symlinks_to, basename(dest)) ||
8d419f
-                                set_contains(remove_symlinks_to, de->d_name);
8d419f
 
8d419f
                         if (!found)
8d419f
                                 continue;
8d419f
@@ -650,7 +657,7 @@ static int remove_marked_symlinks_fd(
8d419f
                         /* Now, remember the full path (but with the root prefix removed) of
8d419f
                          * the symlink we just removed, and remove any symlinks to it, too. */
8d419f
 
8d419f
-                        rp = skip_root(lp->root_dir, p);
8d419f
+                        const char *rp = skip_root(lp->root_dir, p);
8d419f
                         q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p);
8d419f
                         if (q < 0)
8d419f
                                 return q;