]> sourceware.org Git - systemtap.git/commitdiff
runtime: use RCU-protected get_mm_exe_file() on old kernels that have it
authorSultan Alsawaf <sultan@openresty.com>
Thu, 21 Apr 2022 20:58:58 +0000 (13:58 -0700)
committerSultan Alsawaf <sultan@openresty.com>
Thu, 21 Apr 2022 21:11:14 +0000 (14:11 -0700)
Some old kernels (such as the one in CentOS 7) have the RCU-protected
get_mm_exe_file() patch backported to them, in which case it's preferable
to make use of the RCU optimization to avoid sporadic failures from the
down_read_trylock() due to mmap_sem contention. Since the commit that adds
the RCU protection to get_mm_exe_file() also adds a get_file_rcu() macro,
we can just check for the existence of get_file_rcu() on kernels < 4.1. If
the macro doesn't exist for some reason despite the old kernel having the
RCU optimization, we just fall back to using down_read_trylock() the same
as before. If the old kernel has get_file_rcu() despite lacking the RCU
protection that goes along with it, then said kernel has bigger problems.

runtime/task_finder_vma.c
runtime/transport/transport.c

index 134df8c50bf0c6e861b94bea61bd9549936a0e7f..5d8bab8db35803f91abec21d273b8a4219a83a1c 100644 (file)
@@ -420,14 +420,23 @@ stap_find_exe_file(struct mm_struct* mm)
        // still use our own code. The original get_mm_exe_file() can
        // sleep (since it calls down_read()), so we'll have to roll
        // our own.
-#if defined(STAPCONF_GET_MM_EXE_FILE_EXPORTED) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0))
+       //
+       // Some old kernels have the above kernel commit backported, in which
+       // case it's preferable to make use of the RCU optimization to avoid the
+       // failure-prone down_read_trylock(). The commit that adds the RCU
+       // optimization also adds a get_file_rcu() macro, so we can just check
+       // for the existence of that on kernels < 4.1. A false negative this way
+       // just leads to using the down_read_trylock() fallback as usual.
+#if defined(get_file_rcu) || LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#ifdef STAPCONF_GET_MM_EXE_FILE_EXPORTED
        return get_mm_exe_file(mm);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0))
+#else
         typedef typeof(&get_mm_exe_file) get_mm_exe_file_fn;
         if (kallsyms_get_mm_exe_file == NULL)
           return NULL; /* can't happen; _stp_handle_start would abort before this point */
         else
           return (* (get_mm_exe_file_fn) kallsyms_get_mm_exe_file)(mm);
+#endif
 #else
        struct file *exe_file = NULL;
 
index c6c3da52d52ceeed8b996330932cc9ae03675285..c8bf221dcb9bf5f0cdd854362954d473bad5c4a9 100644 (file)
@@ -366,7 +366,7 @@ static int _stp_handle_kallsyms_lookups(void)
                 goto err0;
         }
 #endif
-#if !defined(STAPCONF_GET_MM_EXE_FILE_EXPORTED) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0))
+#if !defined(STAPCONF_GET_MM_EXE_FILE_EXPORTED) && (defined(get_file_rcu) || LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0))
         kallsyms_get_mm_exe_file = (void*) kallsyms_lookup_name ("get_mm_exe_file");
         if (kallsyms_get_mm_exe_file == NULL) {
                 _stp_error("Can't resolve get_mm_exe_file!");
This page took 0.03087 seconds and 5 git commands to generate.