blob: 5f611e6a341fd2cf058e562368d1de0f8e30e615 [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 Marion01914ce2017-09-14 19:04:50 +0200117clib_sysfs_set_nr_hugepages (int numa_node, int 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;
122
123 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
124
125 if (stat ((char *) p, &sb) == 0)
126 {
127 if (S_ISDIR (sb.st_mode) == 0)
128 {
129 error = clib_error_return (0, "'%s' is not directory", p);
130 goto done;
131 }
132 }
133 else if (numa_node == 0)
134 {
135 vec_reset_length (p);
136 p = format (p, "/sys/kernel/mm%c", 0);
137 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
138 {
139 error = clib_error_return (0, "'%s' does not exist or it is not "
140 "directory", p);
141 goto done;
142 }
143 }
144 else
145 {
146 error = clib_error_return (0, "'%s' does not exist", p);
147 goto done;
148 }
149
150 _vec_len (p) -= 1;
151 p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200152 clib_sysfs_write ((char *) p, "%d", nr);
Damjan Marion3b64d632017-09-08 12:26:12 +0200153
154done:
155 vec_free (p);
156 return error;
157}
158
159
160static clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200161clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
Damjan Marion3b64d632017-09-08 12:26:12 +0200162 int page_size, int *val)
163{
164 clib_error_t *error = 0;
165 struct stat sb;
166 u8 *p = 0;
167
168 p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
169
170 if (stat ((char *) p, &sb) == 0)
171 {
172 if (S_ISDIR (sb.st_mode) == 0)
173 {
174 error = clib_error_return (0, "'%s' is not directory", p);
175 goto done;
176 }
177 }
178 else if (numa_node == 0)
179 {
180 vec_reset_length (p);
181 p = format (p, "/sys/kernel/mm%c", 0);
182 if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
183 {
184 error = clib_error_return (0, "'%s' does not exist or it is not "
185 "directory", p);
186 goto done;
187 }
188 }
189 else
190 {
191 error = clib_error_return (0, "'%s' does not exist", p);
192 goto done;
193 }
194
195 _vec_len (p) -= 1;
196 p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
197 type, 0);
Damjan Marion01914ce2017-09-14 19:04:50 +0200198 error = clib_sysfs_read ((char *) p, "%d", val);
Damjan Marion3b64d632017-09-08 12:26:12 +0200199
200done:
201 vec_free (p);
202 return error;
203}
204
205clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200206clib_sysfs_get_free_hugepages (int numa_node, int page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200207{
Damjan Marion01914ce2017-09-14 19:04:50 +0200208 return clib_sysfs_get_xxx_hugepages ("free", numa_node, page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200209}
210
211clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200212clib_sysfs_get_nr_hugepages (int numa_node, int page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200213{
Damjan Marion01914ce2017-09-14 19:04:50 +0200214 return clib_sysfs_get_xxx_hugepages ("nr", numa_node, page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200215}
216
217clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200218clib_sysfs_get_surplus_hugepages (int numa_node, int page_size, int *v)
Damjan Marion3b64d632017-09-08 12:26:12 +0200219{
Damjan Marion01914ce2017-09-14 19:04:50 +0200220 return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, page_size, v);
Damjan Marion3b64d632017-09-08 12:26:12 +0200221}
222
223clib_error_t *
Damjan Marion01914ce2017-09-14 19:04:50 +0200224clib_sysfs_prealloc_hugepages (int numa_node, int page_size, int nr)
Damjan Marion3b64d632017-09-08 12:26:12 +0200225{
226 clib_error_t *error = 0;
227 int n, needed;
Damjan Marion01914ce2017-09-14 19:04:50 +0200228 error = clib_sysfs_get_free_hugepages (numa_node, page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200229 if (error)
230 return error;
231 needed = nr - n;
232 if (needed <= 0)
233 return 0;
234
Damjan Marion01914ce2017-09-14 19:04:50 +0200235 error = clib_sysfs_get_nr_hugepages (numa_node, page_size, &n);
Damjan Marion3b64d632017-09-08 12:26:12 +0200236 if (error)
237 return error;
238 clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
239 needed, page_size, numa_node);
Damjan Marion01914ce2017-09-14 19:04:50 +0200240 return clib_sysfs_set_nr_hugepages (numa_node, page_size, n + needed);
Damjan Marion3b64d632017-09-08 12:26:12 +0200241}
242
243
244/*
245 * fd.io coding-style-patch-verification: ON
246 *
247 * Local Variables:
248 * eval: (c-set-style "gnu")
249 * End:
250 */