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