Fix: implicit declarations caused by buffer size checks.
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Tue, 16 Oct 2018 19:23:22 +0000 (15:23 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 17 Oct 2018 04:27:12 +0000 (00:27 -0400)
Issue
=====
Three kernel functions used in the following commit are unavailable on
some supported kernels:

commit 1f0ab1eb0409d23de5f67cc588c3ea4cee4d10e0
Prevent allocation of buffers if exceeding available memory

* si_mem_available() was added in kernel 4.6 with commit d02bd27.
* {set, clear}_current_oom_origin() were added in kernel 3.8 with commit:
  e1e12d2f

Solution
========
Add wrappers around these functions such that older kernels will build
with these functions defined as NOP or trivial return value.

wrapper_check_enough_free_pages() uses the si_mem_available() kernel
function to compute if the number pages requested passed as parameter is
smaller than the number of pages available on the machine. If the
si_mem_available() kernel function is unavailable, we always return
true.

wrapper_set_current_oom_origin() function wraps the
set_current_oom_origin() kernel function when it is available.
If set_current_oom_origin() is unavailable the wrapper is empty.

wrapper_clear_current_oom_origin() function wraps the
clear_current_oom_origin() kernel function when it is available.
If clear_current_oom_origin() is unavailable the wrapper is empty.

Drawbacks
=========
None.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
lib/ringbuffer/ring_buffer_backend.c
wrapper/mm.h [new file with mode: 0644]

index 8207f764377a34f5cb0fda0e41da8e56985dbd45..d4bec25ff956bfc21bc9c184b8230ca2963cbabc 100644 (file)
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/oom.h>
 #include <linux/cpu.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 
+#include <wrapper/mm.h>
 #include <wrapper/vmalloc.h>   /* for wrapper_vmalloc_sync_all() */
 #include <wrapper/ringbuffer/config.h>
 #include <wrapper/ringbuffer/backend.h>
@@ -46,11 +46,13 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config
        num_pages = size >> PAGE_SHIFT;
 
        /*
-        * Verify that the number of pages requested for that buffer is smaller
-        * than the number of available pages on the system. si_mem_available()
-        * returns an _estimate_ of the number of available pages.
+        * Verify that there is enough free pages available on the system for
+        * the current allocation request.
+        * wrapper_check_enough_free_pages uses si_mem_available() if available
+        * and returns if there should be enough free pages based on the
+        * current estimate.
         */
-       if (num_pages > si_mem_available())
+       if (!wrapper_check_enough_free_pages(num_pages))
                goto not_enough_pages;
 
        /*
@@ -59,7 +61,7 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config
         * end up running out of memory because of this buffer allocation, we
         * want to kill the offending app first.
         */
-       set_current_oom_origin();
+       wrapper_set_current_oom_origin();
 
        num_pages_per_subbuf = num_pages >> get_count_order(num_subbuf);
        subbuf_size = chanb->subbuf_size;
@@ -155,7 +157,7 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config
         * will not fault.
         */
        wrapper_vmalloc_sync_all();
-       clear_current_oom_origin();
+       wrapper_clear_current_oom_origin();
        vfree(pages);
        return 0;
 
@@ -172,7 +174,7 @@ depopulate:
 array_error:
        vfree(pages);
 pages_error:
-       clear_current_oom_origin();
+       wrapper_clear_current_oom_origin();
 not_enough_pages:
        return -ENOMEM;
 }
diff --git a/wrapper/mm.h b/wrapper/mm.h
new file mode 100644 (file)
index 0000000..672855b
--- /dev/null
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
+ *
+ * wrapper/mm.h
+ *
+ * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
+ */
+
+#ifndef _LTTNG_WRAPPER_MM_H
+#define _LTTNG_WRAPPER_MM_H
+
+#include <linux/mm.h>
+#include <linux/oom.h>
+
+#include <lttng-kernel-version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) \
+               || LTTNG_UBUNTU_KERNEL_RANGE(4,4,25,44, 4,5,0,0))
+
+/*
+ * Returns true if the current estimation of the number of page available is
+ * larger than the number of pages passed as parameter.
+ */
+static inline
+bool wrapper_check_enough_free_pages(unsigned long num_pages)
+{
+       return num_pages < si_mem_available();
+}
+
+#else
+
+static inline
+bool wrapper_check_enough_free_pages(unsigned long num_pages)
+{
+       /*
+        * The si_mem_available function is not available on this kernel. Since
+        * we can't reliably know if there is enough memory available, so we
+        * return true.
+        */
+       return true;
+}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+static inline
+void wrapper_set_current_oom_origin(void)
+{
+       return set_current_oom_origin();
+}
+
+static inline
+void wrapper_clear_current_oom_origin(void)
+{
+       return clear_current_oom_origin();
+}
+
+#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) */
+
+static inline
+void wrapper_set_current_oom_origin(void)
+{
+       return;
+}
+
+static inline
+void wrapper_clear_current_oom_origin()
+{
+       return;
+}
+#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) */
+#endif /* _LTTNG_WRAPPER_MM_H */
This page took 0.028415 seconds and 4 git commands to generate.