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