blob: 199e6bbfd69604607bd2ad7cbea961b5a716d522 [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
Damjan Marion6f3f1cb2018-10-22 13:01:46 +020025#define DEFAULT_HUGETLB_SIZE 2048
26
Damjan Marion3b64d632017-09-08 12:26:12 +020027clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +020028clib_sysfs_write (char *file_name, char *fmt, ...)
Damjan Marion3b64d632017-09-08 12:26:12 +020029{
30 u8 *s;
31 int fd;
32 clib_error_t *error = 0;
33
34 fd = open (file_name, O_WRONLY);
35 if (fd < 0)
36 return clib_error_return_unix (0, "open `%s'", file_name);
37
38 va_list va;
39 va_start (va, fmt);
40 s = va_format (0, fmt, &va);
41 va_end (va);
42
43 if (write (fd, s, vec_len (s)) < 0)
44 error = clib_error_return_unix (0, "write `%s'", file_name);
45
46 vec_free (s);
47 close (fd);
48 return error;
49}
50
51clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +020052clib_sysfs_read (char *file_name, char *fmt, ...)
Damjan Marion3b64d632017-09-08 12:26:12 +020053{
54 unformat_input_t input;
55 u8 *s = 0;
56 int fd;
57 ssize_t sz;
58 uword result;
59
60 fd = open (file_name, O_RDONLY);
61 if (fd < 0)
62 return clib_error_return_unix (0, "open `%s'", file_name);
63
64 vec_validate (s, 4095);
65
66 sz = read (fd, s, vec_len (s));
67 if (sz < 0)
68 {
69 close (fd);
70 vec_free (s);
71 return clib_error_return_unix (0, "read `%s'", file_name);
72 }
73
74 _vec_len (s) = sz;
75 unformat_init_vector (&input, s);
76
77 va_list va;
78 va_start (va, fmt);
79 result = va_unformat (&input, fmt, &va);
80 va_end (va);
81
82 vec_free (s);
83 close (fd);
84
85 if (result == 0)
86 return clib_error_return (0, "unformat error");
87
88 return 0;
89}
90
91u8 *
Damjan Marion01914ce2017-09-14 19:04:50 +020092clib_sysfs_link_to_name (char *link)
Damjan Marion3b64d632017-09-08 12:26:12 +020093{
94 char *p, buffer[64];
95 unformat_input_t in;
96 u8 *s = 0;
97 int r;
98
99 r = readlink (link, buffer, sizeof (buffer) - 1);
100
101 if (r < 0)
102 return 0;
103
104 buffer[r] = 0;
105 p = strrchr (buffer, '/');
106
107 if (!p)
108 return 0;
109
110 unformat_init_string (&in, p + 1, strlen (p + 1));
111 if (unformat (&in, "%s", &s) != 1)
112 clib_unix_warning ("no string?");
113 unformat_free (&in);
114
115 return s;
116}
117
118clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200119clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
Damjan Marion3b64d632017-09-08 12:26:12 +0200120{
121 clib_error_t *error = 0;
122 struct stat sb;
123 u8 *p = 0;
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200124 int page_size = log2_page_size ? 1ULL << (log2_page_size - 10) :
125 DEFAULT_HUGETLB_SIZE;
Damjan Marion3b64d632017-09-08 12:26:12 +0200126
127 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
128
129 if (stat ((char *) p, &sb) == 0)
130 {
131 if (S_ISDIR (sb.st_mode) == 0)
132 {
133 error = clib_error_return (0, "'%s' is not directory", p);
134 goto done;
135 }
136 }
137 else if (numa_node == 0)
138 {
139 vec_reset_length (p);
140 p = format (p, "/sys/kernel/mm%c", 0);
141 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
142 {
143 error = clib_error_return (0, "'%s' does not exist or it is not "
144 "directory", p);
145 goto done;
146 }
147 }
148 else
149 {
150 error = clib_error_return (0, "'%s' does not exist", p);
151 goto done;
152 }
153
154 _vec_len (p) -= 1;
155 p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200156 clib_sysfs_write ((char *) p, "%d", nr);
Damjan Marion3b64d632017-09-08 12:26:12 +0200157
158done:
159 vec_free (p);
160 return error;
161}
162
163
164static clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200165clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200166 int log2_page_size, int *val)
Damjan Marion3b64d632017-09-08 12:26:12 +0200167{
168 clib_error_t *error = 0;
169 struct stat sb;
170 u8 *p = 0;
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200171 int page_size = log2_page_size ? 1ULL << (log2_page_size - 10) :
172 DEFAULT_HUGETLB_SIZE;
Damjan Marion3b64d632017-09-08 12:26:12 +0200173
174 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
175
176 if (stat ((char *) p, &sb) == 0)
177 {
178 if (S_ISDIR (sb.st_mode) == 0)
179 {
180 error = clib_error_return (0, "'%s' is not directory", p);
181 goto done;
182 }
183 }
184 else if (numa_node == 0)
185 {
186 vec_reset_length (p);
187 p = format (p, "/sys/kernel/mm%c", 0);
188 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
189 {
190 error = clib_error_return (0, "'%s' does not exist or it is not "
191 "directory", p);
192 goto done;
193 }
194 }
195 else
196 {
197 error = clib_error_return (0, "'%s' does not exist", p);
198 goto done;
199 }
200
201 _vec_len (p) -= 1;
202 p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
203 type, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200204 error = clib_sysfs_read ((char *) p, "%d", val);
Damjan Marion3b64d632017-09-08 12:26:12 +0200205
206done:
207 vec_free (p);
208 return error;
209}
210
211clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200212clib_sysfs_get_free_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200213{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200214 return clib_sysfs_get_xxx_hugepages ("free", numa_node, log2_page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200215}
216
217clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200218clib_sysfs_get_nr_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200219{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200220 return clib_sysfs_get_xxx_hugepages ("nr", numa_node, log2_page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200221}
222
223clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200224clib_sysfs_get_surplus_hugepages (int numa_node, int log2_page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200225{
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200226 return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, log2_page_size,
227 v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200228}
229
230clib_error_t *
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200231clib_sysfs_prealloc_hugepages (int numa_node, int log2_page_size, int nr)
Damjan Marion3b64d632017-09-08 12:26:12 +0200232{
233 clib_error_t *error = 0;
234 int n, needed;
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200235 int page_size = log2_page_size ? 1ULL << (log2_page_size - 10) :
236 DEFAULT_HUGETLB_SIZE;
237 error = clib_sysfs_get_free_hugepages (numa_node, log2_page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200238 if (error)
239 return error;
240 needed = nr - n;
241 if (needed <= 0)
242 return 0;
243
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200244 error = clib_sysfs_get_nr_hugepages (numa_node, log2_page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200245 if (error)
246 return error;
247 clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
248 needed, page_size, numa_node);
Damjan Marion6f3f1cb2018-10-22 13:01:46 +0200249 return clib_sysfs_set_nr_hugepages (numa_node, log2_page_size, n + needed);
Damjan Marion3b64d632017-09-08 12:26:12 +0200250}
251
252
253/*
254 * fd.io coding-style-patch-verification: ON
255 *
256 * Local Variables:
257 * eval: (c-set-style "gnu")
258 * End:
259 */