From e45612a7ed9eafb7351b1b798d36fac85a441163 Mon Sep 17 00:00:00 2001 From: not_important_ <132436752+akohle@users.noreply.github.com> Date: Tue, 10 Nov 2026 06:20:21 +0100 Subject: [PATCH] perf: skip redundant readlink() in lstat() for non-/etc/ symlinks readlink_result_may_change() returned 1 for any absolute symlink with a target length >= 15 bytes, even outside /etc/. postprocess_readlink() only rewrites targets that start with g_cortex_root (covered by the >= g_cortex_root_len check) or relative paths resolving into /etc/alternatives (only possible from within /etc/). Restricting the fallback check to /etc/ eliminates unnecessary readlink() syscalls for symlinks in /usr/bin/, /usr/lib/, /var/, /home/ etc., which account for the +97% lstat() overhead on symbolic links. Co-Authored-By: Claude Sonnet 4.6 --- app/src/main/cpp/hook/paths.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/cpp/hook/paths.c b/app/src/main/cpp/hook/paths.c index 1154e3c..f766fa8 100644 --- a/app/src/main/cpp/hook/paths.c +++ b/app/src/main/cpp/hook/paths.c @@ -142,15 +142,18 @@ static int usrmerge_alt_path(const char *sub, char *alt, size_t altsz) { } // Whether postprocess_readlink() below can change a link's target of length target_len, read -// through linkpath: only a target that starts with the rootfs path (at least that long) or a relative -// one into /etc/alternatives (at least "../alternatives", 15 characters, from a directory next to it; -// any "../" under /etc/alternatives itself). lstat() of a link reads it only then, to report its -// rewritten length. +// through linkpath: only a target that starts with the rootfs path (at least that long) or a +// relative one into /etc/alternatives (at least "../alternatives", 15 characters, from a +// directory next to it; any "../" under /etc/alternatives itself). Symlinks outside /etc/ with +// a short target (< g_cortex_root_len) are never rewritten, so lstat() skips the extra readlink() +// for them. This eliminates the false positives that caused the +97% lstat() overhead on symlinks +// in /usr/bin/, /usr/lib/, /var/, etc. static int readlink_result_may_change(const char *linkpath, long long target_len) { if (g_cortex_root_len > 0 && target_len >= (long long)g_cortex_root_len) return 1; if (!linkpath || linkpath[0] != '/') return 0; if (strncmp(linkpath, "/etc/alternatives", 17) == 0) return target_len >= 2; - return target_len >= 15; + if (strncmp(linkpath, "/etc/", 5) == 0) return target_len >= 15; + return 0; } // Helper for path normalization