blob: c45897fc83b8002d09da32216b904fa514fc7a71 [file] [log] [blame]
Damjan Marion3b64d632017-09-08 12:26:12 +02001/*
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
Damjan Marion01914ce2017-09-14 19:04:50 +020016#include <vppinfra/clib.h>
17#include <vppinfra/clib_error.h>
18#include <vppinfra/format.h>
Damjan Marion3b64d632017-09-08 12:26:12 +020019
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <dirent.h>
24
25clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +020026clib_sysfs_write (char *file_name, char *fmt, ...)
Damjan Marion3b64d632017-09-08 12:26:12 +020027{
28 u8 *s;
29 int fd;
30 clib_error_t *error = 0;
31
32 fd = open (file_name, O_WRONLY);
33 if (fd < 0)
34 return clib_error_return_unix (0, "open `%s'", file_name);
35
36 va_list va;
37 va_start (va, fmt);
38 s = va_format (0, fmt, &va);
39 va_end (va);
40
41 if (write (fd, s, vec_len (s)) < 0)
42 error = clib_error_return_unix (0, "write `%s'", file_name);
43
44 vec_free (s);
45 close (fd);
46 return error;
47}
48
49clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +020050clib_sysfs_read (char *file_name, char *fmt, ...)
Damjan Marion3b64d632017-09-08 12:26:12 +020051{
52 unformat_input_t input;
53 u8 *s = 0;
54 int fd;
55 ssize_t sz;
56 uword result;
57
58 fd = open (file_name, O_RDONLY);
59 if (fd < 0)
60 return clib_error_return_unix (0, "open `%s'", file_name);
61
62 vec_validate (s, 4095);
63
64 sz = read (fd, s, vec_len (s));
65 if (sz < 0)
66 {
67 close (fd);
68 vec_free (s);
69 return clib_error_return_unix (0, "read `%s'", file_name);
70 }
71
72 _vec_len (s) = sz;
73 unformat_init_vector (&input, s);
74
75 va_list va;
76 va_start (va, fmt);
77 result = va_unformat (&input, fmt, &va);
78 va_end (va);
79
80 vec_free (s);
81 close (fd);
82
83 if (result == 0)
84 return clib_error_return (0, "unformat error");
85
86 return 0;
87}
88
89u8 *
Damjan Marion01914ce2017-09-14 19:04:50 +020090clib_sysfs_link_to_name (char *link)
Damjan Marion3b64d632017-09-08 12:26:12 +020091{
92 char *p, buffer[64];
93 unformat_input_t in;
94 u8 *s = 0;
95 int r;
96
97 r = readlink (link, buffer, sizeof (buffer) - 1);
98
99 if (r < 0)
100 return 0;
101
102 buffer[r] = 0;
103 p = strrchr (buffer, '/');
104
105 if (!p)
106 return 0;
107
108 unformat_init_string (&in, p + 1, strlen (p + 1));
109 if (unformat (&in, "%s", &s) != 1)
110 clib_unix_warning ("no string?");
111 unformat_free (&in);
112
113 return s;
114}
115
116clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200117clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
Damjan Marion3b64d632017-09-08 12:26:12 +0200118{
119 clib_error_t *error = 0;
120 struct stat sb;
121 u8 *p = 0;
Damjan Marion9787f5f2018-10-24 12:56:32 +0200122 uword page_size;
123
124 if (log2_page_size == 0)
125 log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
126
127 page_size = 1ULL << (log2_page_size - 10);
Damjan Marion3b64d632017-09-08 12:26:12 +0200128
129 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
130
131 if (stat ((char *) p, &sb) == 0)
132 {
133 if (S_ISDIR (sb.st_mode) == 0)
134 {
135 error = clib_error_return (0, "'%s' is not directory", p);
136 goto done;
137 }
138 }
139 else if (numa_node == 0)
140 {
141 vec_reset_length (p);
142 p = format (p, "/sys/kernel/mm%c", 0);
143 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
144 {
145 error = clib_error_return (0, "'%s' does not exist or it is not "
146 "directory", p);
147 goto done;
148 }
149 }
150 else
151 {
152 error = clib_error_return (0, "'%s' does not exist", p);
153 goto done;
154 }
155
156 _vec_len (p) -= 1;
157 p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200158 clib_sysfs_write ((char *) p, "%d", nr);
Damjan Marion3b64d632017-09-08 12:26:12 +0200159
160done:
161 vec_free (p);
162 return error;
163}
164
165
166static clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200167clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200168 int log2_page_size, int *val)
Damjan Marion3b64d632017-09-08 12:26:12 +0200169{
170 clib_error_t *error = 0;
171 struct stat sb;
172 u8 *p = 0;
Damjan Marion9787f5f2018-10-24 12:56:32 +0200173
174 uword page_size;
175
176 if (log2_page_size == 0)
177 log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
178
179 page_size = 1ULL << (log2_page_size - 10);
180
Damjan Marion3b64d632017-09-08 12:26:12 +0200181
182 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
183
184 if (stat ((char *) p, &sb) == 0)
185 {
186 if (S_ISDIR (sb.st_mode) == 0)
187 {
188 error = clib_error_return (0, "'%s' is not directory", p);
189 goto done;
190 }
191 }
192 else if (numa_node == 0)
193 {
194 vec_reset_length (p);
195 p = format (p, "/sys/kernel/mm%c", 0);
196 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
197 {
198 error = clib_error_return (0, "'%s' does not exist or it is not "
199 "directory", p);
200 goto done;
201 }
202 }
203 else
204 {
205 error = clib_error_return (0, "'%s' does not exist", p);
206 goto done;
207 }
208
209 _vec_len (p) -= 1;
210 p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
211 type, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200212 error = clib_sysfs_read ((char *) p, "%d", val);
Damjan Marion3b64d632017-09-08 12:26:12 +0200213
214done:
215 vec_free (p);
216 return error;
217}
218
219clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200220clib_sysfs_get_free_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200221{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200222 return clib_sysfs_get_xxx_hugepages ("free", numa_node, log2_page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200223}
224
225clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200226clib_sysfs_get_nr_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200227{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200228 return clib_sysfs_get_xxx_hugepages ("nr", numa_node, log2_page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200229}
230
231clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200232clib_sysfs_get_surplus_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200233{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200234 return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, log2_page_size,
235 v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200236}
237
238clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200239clib_sysfs_prealloc_hugepages (int numa_node, int log2_page_size, int nr)
Damjan Marion3b64d632017-09-08 12:26:12 +0200240{
241 clib_error_t *error = 0;
242 int n, needed;
Damjan Marion9787f5f2018-10-24 12:56:32 +0200243 uword page_size;
244
245 if (log2_page_size == 0)
246 log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
247
248 page_size = 1ULL << (log2_page_size - 10);
249
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200250 error = clib_sysfs_get_free_hugepages (numa_node, log2_page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200251 if (error)
252 return error;
253 needed = nr - n;
254 if (needed <= 0)
255 return 0;
256
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200257 error = clib_sysfs_get_nr_hugepages (numa_node, log2_page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200258 if (error)
259 return error;
260 clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
261 needed, page_size, numa_node);
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200262 return clib_sysfs_set_nr_hugepages (numa_node, log2_page_size, n + needed);
Damjan Marion3b64d632017-09-08 12:26:12 +0200263}
264
265
266/*
267 * fd.io coding-style-patch-verification: ON
268 *
269 * Local Variables:
270 * eval: (c-set-style "gnu")
271 * End:
272 */