LCOV - code coverage report
Current view: top level - vppinfra/linux - sysfs.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 31 121 25.6 %
Date: 2023-10-26 01:39:38 Functions: 2 9 22.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vppinfra/clib.h>
      17             : #include <vppinfra/clib_error.h>
      18             : #include <vppinfra/format.h>
      19             : #include <vppinfra/bitmap.h>
      20             : 
      21             : #include <sys/types.h>
      22             : #include <sys/stat.h>
      23             : #include <fcntl.h>
      24             : #include <dirent.h>
      25             : 
      26             : __clib_export clib_error_t *
      27           0 : clib_sysfs_write (char *file_name, char *fmt, ...)
      28             : {
      29             :   u8 *s;
      30             :   int fd;
      31           0 :   clib_error_t *error = 0;
      32             : 
      33           0 :   fd = open (file_name, O_WRONLY);
      34           0 :   if (fd < 0)
      35           0 :     return clib_error_return_unix (0, "open `%s'", file_name);
      36             : 
      37             :   va_list va;
      38           0 :   va_start (va, fmt);
      39           0 :   s = va_format (0, fmt, &va);
      40           0 :   va_end (va);
      41             : 
      42           0 :   if (write (fd, s, vec_len (s)) < 0)
      43           0 :     error = clib_error_return_unix (0, "write `%s'", file_name);
      44             : 
      45           0 :   vec_free (s);
      46           0 :   close (fd);
      47           0 :   return error;
      48             : }
      49             : 
      50             : __clib_export clib_error_t *
      51     1049020 : clib_sysfs_read (char *file_name, char *fmt, ...)
      52             : {
      53             :   unformat_input_t input;
      54     1049020 :   u8 *s = 0;
      55             :   int fd;
      56             :   ssize_t sz;
      57             :   uword result;
      58             : 
      59     1049020 :   fd = open (file_name, O_RDONLY);
      60     1049020 :   if (fd < 0)
      61      172500 :     return clib_error_return_unix (0, "open `%s'", file_name);
      62             : 
      63      876520 :   vec_validate (s, 4095);
      64             : 
      65      876520 :   sz = read (fd, s, vec_len (s));
      66      876520 :   if (sz < 0)
      67             :     {
      68           0 :       close (fd);
      69           0 :       vec_free (s);
      70           0 :       return clib_error_return_unix (0, "read `%s'", file_name);
      71             :     }
      72             : 
      73      876520 :   vec_set_len (s, sz);
      74      876520 :   unformat_init_vector (&input, s);
      75             : 
      76             :   va_list va;
      77      876520 :   va_start (va, fmt);
      78      876520 :   result = va_unformat (&input, fmt, &va);
      79      876520 :   va_end (va);
      80             : 
      81      876520 :   vec_free (s);
      82      876520 :   close (fd);
      83             : 
      84      876520 :   if (result == 0)
      85           0 :     return clib_error_return (0, "unformat error");
      86             : 
      87      876520 :   return 0;
      88             : }
      89             : 
      90             : 
      91             : clib_error_t *
      92           0 : clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
      93             : {
      94           0 :   clib_error_t *error = 0;
      95             :   struct stat sb;
      96           0 :   u8 *p = 0;
      97             :   uword page_size;
      98             : 
      99           0 :   if (log2_page_size == 0)
     100           0 :     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
     101             : 
     102           0 :   page_size = 1ULL << (log2_page_size - 10);
     103             : 
     104           0 :   p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
     105             : 
     106           0 :   if (stat ((char *) p, &sb) == 0)
     107             :     {
     108           0 :       if (S_ISDIR (sb.st_mode) == 0)
     109             :         {
     110           0 :           error = clib_error_return (0, "'%s' is not directory", p);
     111           0 :           goto done;
     112             :         }
     113             :     }
     114           0 :   else if (numa_node == 0)
     115             :     {
     116           0 :       vec_reset_length (p);
     117           0 :       p = format (p, "/sys/kernel/mm%c", 0);
     118           0 :       if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
     119             :         {
     120           0 :           error = clib_error_return (0, "'%s' does not exist or it is not "
     121             :                                      "directory", p);
     122           0 :           goto done;
     123             :         }
     124             :     }
     125             :   else
     126             :     {
     127           0 :       error = clib_error_return (0, "'%s' does not exist", p);
     128           0 :       goto done;
     129             :     }
     130             : 
     131           0 :   vec_dec_len (p, 1);
     132           0 :   p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
     133           0 :   clib_sysfs_write ((char *) p, "%d", nr);
     134             : 
     135           0 : done:
     136           0 :   vec_free (p);
     137           0 :   return error;
     138             : }
     139             : 
     140             : 
     141             : static clib_error_t *
     142           0 : clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
     143             :                               int log2_page_size, int *val)
     144             : {
     145           0 :   clib_error_t *error = 0;
     146             :   struct stat sb;
     147           0 :   u8 *p = 0;
     148             : 
     149             :   uword page_size;
     150             : 
     151           0 :   if (log2_page_size == 0)
     152           0 :     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
     153             : 
     154           0 :   page_size = 1ULL << (log2_page_size - 10);
     155             : 
     156             : 
     157           0 :   p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
     158             : 
     159           0 :   if (stat ((char *) p, &sb) == 0)
     160             :     {
     161           0 :       if (S_ISDIR (sb.st_mode) == 0)
     162             :         {
     163           0 :           error = clib_error_return (0, "'%s' is not directory", p);
     164           0 :           goto done;
     165             :         }
     166             :     }
     167           0 :   else if (numa_node == 0)
     168             :     {
     169           0 :       vec_reset_length (p);
     170           0 :       p = format (p, "/sys/kernel/mm%c", 0);
     171           0 :       if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
     172             :         {
     173           0 :           error = clib_error_return (0, "'%s' does not exist or it is not "
     174             :                                      "directory", p);
     175           0 :           goto done;
     176             :         }
     177             :     }
     178             :   else
     179             :     {
     180           0 :       error = clib_error_return (0, "'%s' does not exist", p);
     181           0 :       goto done;
     182             :     }
     183             : 
     184           0 :   vec_dec_len (p, 1);
     185           0 :   p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
     186             :               type, 0);
     187           0 :   error = clib_sysfs_read ((char *) p, "%d", val);
     188             : 
     189           0 : done:
     190           0 :   vec_free (p);
     191           0 :   return error;
     192             : }
     193             : 
     194             : clib_error_t *
     195           0 : clib_sysfs_get_free_hugepages (int numa_node, int log2_page_size, int *v)
     196             : {
     197           0 :   return clib_sysfs_get_xxx_hugepages ("free", numa_node, log2_page_size, v);
     198             : }
     199             : 
     200             : clib_error_t *
     201           0 : clib_sysfs_get_nr_hugepages (int numa_node, int log2_page_size, int *v)
     202             : {
     203           0 :   return clib_sysfs_get_xxx_hugepages ("nr", numa_node, log2_page_size, v);
     204             : }
     205             : 
     206             : clib_error_t *
     207           0 : clib_sysfs_get_surplus_hugepages (int numa_node, int log2_page_size, int *v)
     208             : {
     209           0 :   return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, log2_page_size,
     210             :                                        v);
     211             : }
     212             : 
     213             : clib_error_t *
     214           0 : clib_sysfs_prealloc_hugepages (int numa_node, int log2_page_size, int nr)
     215             : {
     216           0 :   clib_error_t *error = 0;
     217             :   int n, needed;
     218             :   uword page_size;
     219             : 
     220           0 :   if (log2_page_size == 0)
     221           0 :     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
     222             : 
     223           0 :   page_size = 1ULL << (log2_page_size - 10);
     224             : 
     225           0 :   error = clib_sysfs_get_free_hugepages (numa_node, log2_page_size, &n);
     226           0 :   if (error)
     227           0 :     return error;
     228           0 :   needed = nr - n;
     229           0 :   if (needed <= 0)
     230           0 :     return 0;
     231             : 
     232           0 :   error = clib_sysfs_get_nr_hugepages (numa_node, log2_page_size, &n);
     233           0 :   if (error)
     234           0 :     return error;
     235           0 :   clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
     236             :                 needed, page_size, numa_node);
     237           0 :   return clib_sysfs_set_nr_hugepages (numa_node, log2_page_size, n + needed);
     238             : }
     239             : 
     240             : __clib_export uword *
     241        1150 : clib_sysfs_list_to_bitmap (char *filename)
     242             : {
     243             :   FILE *fp;
     244        1150 :   uword *r = 0;
     245             : 
     246        1150 :   fp = fopen (filename, "r");
     247             : 
     248        1150 :   if (fp != NULL)
     249             :     {
     250        1150 :       u8 *buffer = 0;
     251        1150 :       vec_validate (buffer, 256 - 1);
     252        1150 :       if (fgets ((char *) buffer, 256, fp))
     253             :         {
     254             :           unformat_input_t in;
     255        1150 :           unformat_init_string (&in, (char *) buffer,
     256        1150 :                                 strlen ((char *) buffer));
     257        1150 :           if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1)
     258           0 :             clib_warning ("unformat_bitmap_list failed");
     259        1150 :           unformat_free (&in);
     260             :         }
     261        1150 :       vec_free (buffer);
     262        1150 :       fclose (fp);
     263             :     }
     264        1150 :   return r;
     265             : }
     266             : 
     267             : /*
     268             :  * fd.io coding-style-patch-verification: ON
     269             :  *
     270             :  * Local Variables:
     271             :  * eval: (c-set-style "gnu")
     272             :  * End:
     273             :  */

Generated by: LCOV version 1.14