LCOV - code coverage report
Current view: top level - basic - limits-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 52 74 70.3 %
Date: 2019-08-23 13:36:53 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 23 66 34.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "alloc-util.h"
       4                 :            : #include "cgroup-util.h"
       5                 :            : #include "limits-util.h"
       6                 :            : #include "memory-util.h"
       7                 :            : #include "parse-util.h"
       8                 :            : #include "process-util.h"
       9                 :            : #include "procfs-util.h"
      10                 :            : #include "string-util.h"
      11                 :            : 
      12                 :        152 : uint64_t physical_memory(void) {
      13                 :        152 :         _cleanup_free_ char *root = NULL, *value = NULL;
      14                 :            :         uint64_t mem, lim;
      15                 :            :         size_t ps;
      16                 :            :         long sc;
      17                 :            :         int r;
      18                 :            : 
      19                 :            :         /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
      20                 :            :          * memory.
      21                 :            :          *
      22                 :            :          * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
      23                 :            :          * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
      24                 :            : 
      25                 :        152 :         sc = sysconf(_SC_PHYS_PAGES);
      26         [ -  + ]:        152 :         assert(sc > 0);
      27                 :            : 
      28                 :        152 :         ps = page_size();
      29                 :        152 :         mem = (uint64_t) sc * (uint64_t) ps;
      30                 :            : 
      31                 :        152 :         r = cg_get_root_path(&root);
      32         [ -  + ]:        152 :         if (r < 0) {
      33         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
      34                 :          0 :                 return mem;
      35                 :            :         }
      36                 :            : 
      37                 :        152 :         r = cg_all_unified();
      38         [ -  + ]:        152 :         if (r < 0) {
      39         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
      40                 :          0 :                 return mem;
      41                 :            :         }
      42         [ -  + ]:        152 :         if (r > 0) {
      43                 :          0 :                 r = cg_get_attribute("memory", root, "memory.max", &value);
      44         [ #  # ]:          0 :                 if (r < 0) {
      45         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
      46                 :          0 :                         return mem;
      47                 :            :                 }
      48                 :            : 
      49         [ #  # ]:          0 :                 if (streq(value, "max"))
      50                 :          0 :                         return mem;
      51                 :            :         } else {
      52                 :        152 :                 r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
      53         [ -  + ]:        152 :                 if (r < 0) {
      54         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
      55                 :          0 :                         return mem;
      56                 :            :                 }
      57                 :            :         }
      58                 :            : 
      59                 :        152 :         r = safe_atou64(value, &lim);
      60         [ -  + ]:        152 :         if (r < 0) {
      61         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
      62                 :          0 :                 return mem;
      63                 :            :         }
      64         [ -  + ]:        152 :         if (lim == UINT64_MAX)
      65                 :          0 :                 return mem;
      66                 :            : 
      67                 :            :         /* Make sure the limit is a multiple of our own page size */
      68                 :        152 :         lim /= ps;
      69                 :        152 :         lim *= ps;
      70                 :            : 
      71                 :        152 :         return MIN(mem, lim);
      72                 :            : }
      73                 :            : 
      74                 :         60 : uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
      75                 :            :         uint64_t p, m, ps, r;
      76                 :            : 
      77         [ -  + ]:         60 :         assert(max > 0);
      78                 :            : 
      79                 :            :         /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
      80                 :            :          * the result is a multiple of the page size (rounds down). */
      81                 :            : 
      82                 :         60 :         ps = page_size();
      83         [ -  + ]:         60 :         assert(ps > 0);
      84                 :            : 
      85                 :         60 :         p = physical_memory() / ps;
      86         [ -  + ]:         60 :         assert(p > 0);
      87                 :            : 
      88                 :         60 :         m = p * v;
      89         [ +  + ]:         60 :         if (m / p != v)
      90                 :          4 :                 return UINT64_MAX;
      91                 :            : 
      92                 :         56 :         m /= max;
      93                 :            : 
      94                 :         56 :         r = m * ps;
      95         [ -  + ]:         56 :         if (r / ps != m)
      96                 :          0 :                 return UINT64_MAX;
      97                 :            : 
      98                 :         56 :         return r;
      99                 :            : }
     100                 :            : 
     101                 :         64 : uint64_t system_tasks_max(void) {
     102                 :            : 
     103                 :         64 :         uint64_t a = TASKS_MAX, b = TASKS_MAX;
     104                 :        128 :         _cleanup_free_ char *root = NULL;
     105                 :            :         int r;
     106                 :            : 
     107                 :            :         /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
     108                 :            :          * limit:
     109                 :            :          *
     110                 :            :          * a) the maximum tasks value the kernel allows on this architecture
     111                 :            :          * b) the cgroups pids_max attribute for the system
     112                 :            :          * c) the kernel's configured maximum PID value
     113                 :            :          *
     114                 :            :          * And then pick the smallest of the three */
     115                 :            : 
     116                 :         64 :         r = procfs_tasks_get_limit(&a);
     117         [ -  + ]:         64 :         if (r < 0)
     118         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
     119                 :            : 
     120                 :         64 :         r = cg_get_root_path(&root);
     121         [ -  + ]:         64 :         if (r < 0)
     122         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
     123                 :            :         else {
     124                 :         64 :                 _cleanup_free_ char *value = NULL;
     125                 :            : 
     126                 :         64 :                 r = cg_get_attribute("pids", root, "pids.max", &value);
     127         [ +  - ]:         64 :                 if (r < 0)
     128         [ -  + ]:         64 :                         log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
     129         [ #  # ]:          0 :                 else if (!streq(value, "max")) {
     130                 :          0 :                         r = safe_atou64(value, &b);
     131         [ #  # ]:          0 :                         if (r < 0)
     132         [ #  # ]:          0 :                                 log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
     133                 :            :                 }
     134                 :            :         }
     135                 :            : 
     136   [ +  -  +  - ]:         64 :         return MIN3(TASKS_MAX,
     137                 :            :                     a <= 0 ? TASKS_MAX : a,
     138                 :            :                     b <= 0 ? TASKS_MAX : b);
     139                 :            : }
     140                 :            : 
     141                 :         56 : uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
     142                 :            :         uint64_t t, m;
     143                 :            : 
     144         [ -  + ]:         56 :         assert(max > 0);
     145                 :            : 
     146                 :            :         /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
     147                 :            :          * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
     148                 :            : 
     149                 :         56 :         t = system_tasks_max();
     150         [ -  + ]:         56 :         assert(t > 0);
     151                 :            : 
     152                 :         56 :         m = t * v;
     153         [ +  + ]:         56 :         if (m / t != v) /* overflow? */
     154                 :          4 :                 return UINT64_MAX;
     155                 :            : 
     156                 :         52 :         return m / max;
     157                 :            : }

Generated by: LCOV version 1.14