Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <sys/file.h>
7 : : #include <dirent.h>
8 : : #include <fcntl.h>
9 : : #include <stdint.h>
10 : : #include <stdlib.h>
11 : : #include <stdio.h>
12 : : #include <fnmatch.h>
13 : : #include <inttypes.h>
14 : : #include <unistd.h>
15 : : #include <errno.h>
16 : : #include <sys/mman.h>
17 : : #include <sys/stat.h>
18 : :
19 : : #include <linux/mman.h> /* for hugetlb-related flags */
20 : :
21 : : #include <rte_lcore.h>
22 : : #include <rte_debug.h>
23 : : #include <rte_log.h>
24 : : #include <rte_common.h>
25 : : #include "rte_string_fns.h"
26 : :
27 : : #include "eal_private.h"
28 : : #include "eal_internal_cfg.h"
29 : : #include "eal_hugepages.h"
30 : : #include "eal_filesystem.h"
31 : :
32 : : static const char sys_dir_path[] = "/sys/kernel/mm/hugepages";
33 : : static const char sys_pages_numa_dir_path[] = "/sys/devices/system/node";
34 : :
35 : : /*
36 : : * Uses mmap to create a shared memory area for storage of data
37 : : * Used in this file to store the hugepage file map on disk
38 : : */
39 : : static void *
40 [ - + ]: 81 : map_shared_memory(const char *filename, const size_t mem_size, int flags)
41 : : {
42 : : void *retval;
43 : : int fd = open(filename, flags, 0600);
44 [ + - ]: 81 : if (fd < 0)
45 : : return NULL;
46 [ - + ]: 81 : if (ftruncate(fd, mem_size) < 0) {
47 : 0 : close(fd);
48 : 0 : return NULL;
49 : : }
50 : 81 : retval = mmap(NULL, mem_size, PROT_READ | PROT_WRITE,
51 : : MAP_SHARED, fd, 0);
52 : 81 : close(fd);
53 [ - + ]: 81 : return retval == MAP_FAILED ? NULL : retval;
54 : : }
55 : :
56 : : static void *
57 : : open_shared_memory(const char *filename, const size_t mem_size)
58 : : {
59 : 27 : return map_shared_memory(filename, mem_size, O_RDWR);
60 : : }
61 : :
62 : : static void *
63 : : create_shared_memory(const char *filename, const size_t mem_size)
64 : : {
65 : 54 : return map_shared_memory(filename, mem_size, O_RDWR | O_CREAT);
66 : : }
67 : :
68 : 264 : static int get_hp_sysfs_value(const char *subdir, const char *file, unsigned long *val)
69 : : {
70 : : char path[PATH_MAX];
71 : :
72 : : snprintf(path, sizeof(path), "%s/%s/%s",
73 : : sys_dir_path, subdir, file);
74 : 264 : return eal_parse_sysfs_value(path, val);
75 : : }
76 : :
77 : : /* this function is only called from eal_hugepage_info_init which itself
78 : : * is only called from a primary process */
79 : : static uint32_t
80 : 66 : get_num_hugepages(const char *subdir, size_t sz, unsigned int reusable_pages)
81 : : {
82 : : unsigned long resv_pages, num_pages, over_pages, surplus_pages;
83 : : const char *nr_hp_file = "free_hugepages";
84 : : const char *nr_rsvd_file = "resv_hugepages";
85 : : const char *nr_over_file = "nr_overcommit_hugepages";
86 : : const char *nr_splus_file = "surplus_hugepages";
87 : :
88 : : /* first, check how many reserved pages kernel reports */
89 [ + - ]: 66 : if (get_hp_sysfs_value(subdir, nr_rsvd_file, &resv_pages) < 0)
90 : : return 0;
91 : :
92 [ + - ]: 66 : if (get_hp_sysfs_value(subdir, nr_hp_file, &num_pages) < 0)
93 : : return 0;
94 : :
95 [ - + ]: 66 : if (get_hp_sysfs_value(subdir, nr_over_file, &over_pages) < 0)
96 : 0 : over_pages = 0;
97 : :
98 [ - + ]: 66 : if (get_hp_sysfs_value(subdir, nr_splus_file, &surplus_pages) < 0)
99 : 0 : surplus_pages = 0;
100 : :
101 : : /* adjust num_pages */
102 [ + - ]: 66 : if (num_pages >= resv_pages)
103 : 66 : num_pages -= resv_pages;
104 : : else if (resv_pages)
105 : 0 : num_pages = 0;
106 : :
107 [ + - ]: 66 : if (over_pages >= surplus_pages)
108 : 66 : over_pages -= surplus_pages;
109 : : else
110 : 0 : over_pages = 0;
111 : :
112 [ + + + - : 66 : if (num_pages == 0 && over_pages == 0 && reusable_pages)
- + ]
113 : 0 : EAL_LOG(WARNING, "No available %zu kB hugepages reported",
114 : : sz >> 10);
115 : :
116 : 66 : num_pages += over_pages;
117 [ - + ]: 66 : if (num_pages < over_pages) /* overflow */
118 : 0 : num_pages = UINT32_MAX;
119 : :
120 : 66 : num_pages += reusable_pages;
121 [ - + ]: 66 : if (num_pages < reusable_pages) /* overflow */
122 : 0 : num_pages = UINT32_MAX;
123 : :
124 : : /* we want to return a uint32_t and more than this looks suspicious
125 : : * anyway ... */
126 [ - + ]: 66 : if (num_pages > UINT32_MAX)
127 : 0 : num_pages = UINT32_MAX;
128 : :
129 : 66 : return num_pages;
130 : : }
131 : :
132 : : static uint32_t
133 : 116 : get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz)
134 : : {
135 : : char path[PATH_MAX], socketpath[PATH_MAX];
136 : : DIR *socketdir;
137 : 116 : unsigned long num_pages = 0;
138 : : const char *nr_hp_file = "free_hugepages";
139 : :
140 : : snprintf(socketpath, sizeof(socketpath), "%s/node%u/hugepages",
141 : : sys_pages_numa_dir_path, socket);
142 : :
143 : 116 : socketdir = opendir(socketpath);
144 [ + - ]: 116 : if (socketdir) {
145 : : /* Keep calm and carry on */
146 : 116 : closedir(socketdir);
147 : : } else {
148 : : /* Can't find socket dir, so ignore it */
149 : : return 0;
150 : : }
151 : :
152 : : snprintf(path, sizeof(path), "%s/%s/%s",
153 : : socketpath, subdir, nr_hp_file);
154 [ + - ]: 116 : if (eal_parse_sysfs_value(path, &num_pages) < 0)
155 : : return 0;
156 : :
157 [ + + ]: 116 : if (num_pages == 0)
158 : 6 : EAL_LOG(WARNING, "No free %zu kB hugepages reported on node %u",
159 : : sz >> 10, socket);
160 : :
161 : : /*
162 : : * we want to return a uint32_t and more than this looks suspicious
163 : : * anyway ...
164 : : */
165 [ - + ]: 116 : if (num_pages > UINT32_MAX)
166 : 0 : num_pages = UINT32_MAX;
167 : :
168 : 116 : return num_pages;
169 : : }
170 : :
171 : : static uint64_t
172 : 57 : get_default_hp_size(void)
173 : : {
174 : 57 : const char proc_meminfo[] = "/proc/meminfo";
175 : 57 : const char str_hugepagesz[] = "Hugepagesize:";
176 : : unsigned hugepagesz_len = sizeof(str_hugepagesz) - 1;
177 : : char buffer[256];
178 : : unsigned long long size = 0;
179 : :
180 : 57 : FILE *fd = fopen(proc_meminfo, "r");
181 [ - + ]: 57 : if (fd == NULL)
182 : 0 : rte_panic("Cannot open %s\n", proc_meminfo);
183 [ + - ]: 2793 : while(fgets(buffer, sizeof(buffer), fd)){
184 [ + + ]: 2793 : if (strncmp(buffer, str_hugepagesz, hugepagesz_len) == 0){
185 : 57 : size = rte_str_to_size(&buffer[hugepagesz_len]);
186 : 57 : break;
187 : : }
188 : : }
189 : 57 : fclose(fd);
190 [ - + ]: 57 : if (size == 0)
191 : 0 : rte_panic("Cannot get default hugepage size from %s\n", proc_meminfo);
192 : 57 : return size;
193 : : }
194 : :
195 : : static int
196 : 118 : get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
197 : : {
198 : : enum proc_mount_fieldnames {
199 : : DEVICE = 0,
200 : : MOUNTPT,
201 : : FSTYPE,
202 : : OPTIONS,
203 : : _FIELDNAME_MAX
204 : : };
205 : : static uint64_t default_size = 0;
206 : 118 : const char proc_mounts[] = "/proc/mounts";
207 : 118 : const char hugetlbfs_str[] = "hugetlbfs";
208 : : const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
209 : 118 : const char pagesize_opt[] = "pagesize=";
210 : : const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
211 : : const char split_tok = ' ';
212 : : char *splitstr[_FIELDNAME_MAX];
213 : 118 : char found[PATH_MAX] = "";
214 : : char buf[BUFSIZ];
215 : : const struct internal_config *internal_conf =
216 : 118 : eal_get_internal_configuration();
217 : 118 : const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL) ?
218 [ + + ]: 118 : strlen(internal_conf->hugepage_dir) : 0;
219 : : struct stat st;
220 : :
221 : : /*
222 : : * If the specified dir doesn't exist, we can't match it.
223 : : */
224 [ + + + + ]: 126 : if (internal_conf->hugepage_dir != NULL &&
225 : 8 : stat(internal_conf->hugepage_dir, &st) != 0) {
226 : : return -1;
227 : : }
228 : :
229 : 114 : FILE *fd = fopen(proc_mounts, "r");
230 [ - + ]: 114 : if (fd == NULL)
231 : 0 : rte_panic("Cannot open %s\n", proc_mounts);
232 : :
233 [ + + ]: 114 : if (default_size == 0)
234 : 57 : default_size = get_default_hp_size();
235 : :
236 [ + + ]: 2921 : while (fgets(buf, sizeof(buf), fd)){
237 : : const char *pagesz_str;
238 : : size_t mountpt_len = 0;
239 : :
240 [ - + ]: 2862 : if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX,
241 : : split_tok) != _FIELDNAME_MAX) {
242 : 0 : EAL_LOG(ERR, "Error parsing %s", proc_mounts);
243 : 0 : break; /* return NULL */
244 : : }
245 : :
246 [ + + ]: 2862 : if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) != 0)
247 : 2748 : continue;
248 : :
249 : 114 : pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
250 : :
251 : : /* if no explicit page size, the default page size is compared */
252 [ - + ]: 114 : if (pagesz_str == NULL) {
253 [ # # ]: 0 : if (hugepage_sz != default_size)
254 : 0 : continue;
255 : : }
256 : : /* there is an explicit page size, so check it */
257 : : else {
258 : 114 : uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
259 [ + + ]: 114 : if (pagesz != hugepage_sz)
260 : 57 : continue;
261 : : }
262 : :
263 : : /*
264 : : * If no --huge-dir option has been given, we're done.
265 : : */
266 [ + + ]: 57 : if (internal_conf->hugepage_dir == NULL) {
267 : 55 : strlcpy(found, splitstr[MOUNTPT], len);
268 : : break;
269 : : }
270 : :
271 : 2 : mountpt_len = strlen(splitstr[MOUNTPT]);
272 : :
273 : : /*
274 : : * Ignore any mount that doesn't contain the --huge-dir directory
275 : : * or where mount point is not a parent path of --huge-dir
276 : : */
277 [ + - ]: 2 : if (strncmp(internal_conf->hugepage_dir, splitstr[MOUNTPT],
278 [ + + ]: 2 : mountpt_len) != 0 ||
279 : 1 : (hugepage_dir_len > mountpt_len &&
280 [ - + ]: 1 : internal_conf->hugepage_dir[mountpt_len] != '/')) {
281 : 0 : continue;
282 : : }
283 : :
284 : : /*
285 : : * We found a match, but only prefer it if it's a longer match
286 : : * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
287 : : */
288 [ + - ]: 2 : if (mountpt_len > strlen(found))
289 : 2 : strlcpy(found, splitstr[MOUNTPT], len);
290 : : } /* end while fgets */
291 : :
292 : 114 : fclose(fd);
293 : :
294 [ + + ]: 114 : if (found[0] != '\0') {
295 : : /* If needed, return the requested dir, not the mount point. */
296 [ + + ]: 57 : strlcpy(hugedir, internal_conf->hugepage_dir != NULL ?
297 : : internal_conf->hugepage_dir : found, len);
298 : 57 : return 0;
299 : : }
300 : :
301 : : return -1;
302 : : }
303 : :
304 : : struct walk_hugedir_data {
305 : : int dir_fd;
306 : : int file_fd;
307 : : const char *file_name;
308 : : void *user_data;
309 : : };
310 : :
311 : : typedef void (walk_hugedir_t)(const struct walk_hugedir_data *whd);
312 : :
313 : : /*
314 : : * Search the hugepage directory for whatever hugepage files there are.
315 : : * Check if the file is in use by another DPDK process.
316 : : * If not, execute a callback on it.
317 : : */
318 : : static int
319 : 57 : walk_hugedir(const char *hugedir, walk_hugedir_t *cb, void *user_data)
320 : : {
321 : : DIR *dir;
322 : : struct dirent *dirent;
323 : : int dir_fd, fd, lck_result;
324 : 57 : const char filter[] = "*map_*"; /* matches hugepage files */
325 : :
326 : 57 : dir = opendir(hugedir);
327 [ - + ]: 57 : if (!dir) {
328 : 0 : EAL_LOG(ERR, "Unable to open hugepage directory %s",
329 : : hugedir);
330 : 0 : goto error;
331 : : }
332 : 57 : dir_fd = dirfd(dir);
333 : :
334 : 57 : dirent = readdir(dir);
335 [ - + ]: 57 : if (!dirent) {
336 : 0 : EAL_LOG(ERR, "Unable to read hugepage directory %s",
337 : : hugedir);
338 : 0 : goto error;
339 : : }
340 : :
341 [ + + ]: 229 : while (dirent != NULL) {
342 : : /* skip files that don't match the hugepage pattern */
343 [ + + ]: 172 : if (fnmatch(filter, dirent->d_name, 0) > 0) {
344 : 122 : dirent = readdir(dir);
345 : 122 : continue;
346 : : }
347 : :
348 : : /* try and lock the file */
349 : : fd = openat(dir_fd, dirent->d_name, O_RDONLY);
350 : :
351 : : /* skip to next file */
352 [ - + ]: 50 : if (fd == -1) {
353 : 0 : dirent = readdir(dir);
354 : 0 : continue;
355 : : }
356 : :
357 : : /* non-blocking lock */
358 : 50 : lck_result = flock(fd, LOCK_EX | LOCK_NB);
359 : :
360 : : /* if lock succeeds, execute callback */
361 [ + + ]: 50 : if (lck_result != -1)
362 : 30 : cb(&(struct walk_hugedir_data){
363 : : .dir_fd = dir_fd,
364 : : .file_fd = fd,
365 : : .file_name = dirent->d_name,
366 : : .user_data = user_data,
367 : : });
368 : :
369 : 50 : close (fd);
370 : 50 : dirent = readdir(dir);
371 : : }
372 : :
373 : 57 : closedir(dir);
374 : 57 : return 0;
375 : :
376 : 0 : error:
377 [ # # ]: 0 : if (dir)
378 : 0 : closedir(dir);
379 : :
380 : 0 : EAL_LOG(ERR, "Error while walking hugepage dir: %s",
381 : : strerror(errno));
382 : :
383 : 0 : return -1;
384 : : }
385 : :
386 : : static void
387 : 30 : clear_hugedir_cb(const struct walk_hugedir_data *whd)
388 : : {
389 : 30 : unlinkat(whd->dir_fd, whd->file_name, 0);
390 : 30 : }
391 : :
392 : : /* Remove hugepage files not used by other DPDK processes from a directory. */
393 : : static int
394 : : clear_hugedir(const char *hugedir)
395 : : {
396 : 56 : return walk_hugedir(hugedir, clear_hugedir_cb, NULL);
397 : : }
398 : :
399 : : static void
400 : 0 : inspect_hugedir_cb(const struct walk_hugedir_data *whd)
401 : : {
402 : 0 : uint64_t *total_size = whd->user_data;
403 : : struct stat st;
404 : :
405 [ # # ]: 0 : if (fstat(whd->file_fd, &st) < 0)
406 : 0 : EAL_LOG(DEBUG, "%s(): stat(\"%s\") failed: %s",
407 : : __func__, whd->file_name, strerror(errno));
408 : : else
409 : 0 : (*total_size) += st.st_size;
410 : 0 : }
411 : :
412 : : /*
413 : : * Count the total size in bytes of all files in the directory
414 : : * not mapped by other DPDK process.
415 : : */
416 : : static int
417 : : inspect_hugedir(const char *hugedir, uint64_t *total_size)
418 : : {
419 : 1 : return walk_hugedir(hugedir, inspect_hugedir_cb, total_size);
420 : : }
421 : :
422 : : static int
423 : 3 : compare_hpi(const void *a, const void *b)
424 : : {
425 : : const struct hugepage_info *hpi_a = a;
426 : : const struct hugepage_info *hpi_b = b;
427 : :
428 : 3 : return hpi_b->hugepage_sz - hpi_a->hugepage_sz;
429 : : }
430 : :
431 : : static void
432 : 60 : calc_num_pages(struct hugepage_info *hpi, struct dirent *dirent,
433 : : unsigned int reusable_pages)
434 : : {
435 : : uint64_t total_pages = 0;
436 : : unsigned int i;
437 : : const struct internal_config *internal_conf =
438 : 60 : eal_get_internal_configuration();
439 : :
440 : : /*
441 : : * first, try to put all hugepages into relevant sockets, but
442 : : * if first attempts fails, fall back to collecting all pages
443 : : * in one socket and sorting them later
444 : : */
445 : : total_pages = 0;
446 : :
447 : : /*
448 : : * We also don't want to do this for legacy init.
449 : : * When there are hugepage files to reuse it is unknown
450 : : * what NUMA node the pages are on.
451 : : * This could be determined by mapping,
452 : : * but it is precisely what hugepage file reuse is trying to avoid.
453 : : */
454 [ + + + - ]: 60 : if (!internal_conf->legacy_mem && reusable_pages == 0)
455 [ + + ]: 174 : for (i = 0; i < rte_socket_count(); i++) {
456 : 116 : int socket = rte_socket_id_by_idx(i);
457 : : unsigned int num_pages =
458 : 116 : get_num_hugepages_on_node(
459 : 116 : dirent->d_name, socket,
460 : : hpi->hugepage_sz);
461 : 116 : hpi->num_pages[socket] = num_pages;
462 : 116 : total_pages += num_pages;
463 : : }
464 : : /*
465 : : * we failed to sort memory from the get go, so fall
466 : : * back to old way
467 : : */
468 [ + + ]: 58 : if (total_pages == 0) {
469 : 5 : hpi->num_pages[0] = get_num_hugepages(dirent->d_name,
470 : : hpi->hugepage_sz, reusable_pages);
471 : :
472 : : #ifndef RTE_ARCH_64
473 : : /* for 32-bit systems, limit number of hugepages to
474 : : * 1GB per page size */
475 : : hpi->num_pages[0] = RTE_MIN(hpi->num_pages[0],
476 : : RTE_PGSIZE_1G / hpi->hugepage_sz);
477 : : #endif
478 : : }
479 : 60 : }
480 : :
481 : : static int
482 : 59 : hugepage_info_init(void)
483 : 59 : { const char dirent_start_text[] = "hugepages-";
484 : : const size_t dirent_start_len = sizeof(dirent_start_text) - 1;
485 : : unsigned int i, num_sizes = 0;
486 : : uint64_t reusable_bytes;
487 : : unsigned int reusable_pages;
488 : : DIR *dir;
489 : : struct dirent *dirent;
490 : : struct internal_config *internal_conf =
491 : 59 : eal_get_internal_configuration();
492 : :
493 : 59 : dir = opendir(sys_dir_path);
494 [ - + ]: 59 : if (dir == NULL) {
495 : 0 : EAL_LOG(ERR,
496 : : "Cannot open directory %s to read system hugepage info",
497 : : sys_dir_path);
498 : 0 : return -1;
499 : : }
500 : :
501 [ + + ]: 295 : for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
502 : : struct hugepage_info *hpi;
503 : :
504 [ + + ]: 236 : if (strncmp(dirent->d_name, dirent_start_text,
505 : : dirent_start_len) != 0)
506 : 118 : continue;
507 : :
508 [ + - ]: 118 : if (num_sizes >= MAX_HUGEPAGE_SIZES)
509 : : break;
510 : :
511 : 118 : hpi = &internal_conf->hugepage_info[num_sizes];
512 : 118 : hpi->hugepage_sz =
513 : 118 : rte_str_to_size(&dirent->d_name[dirent_start_len]);
514 : :
515 : : /* first, check if we have a mountpoint */
516 [ + + ]: 118 : if (get_hugepage_dir(hpi->hugepage_sz,
517 : 118 : hpi->hugedir, sizeof(hpi->hugedir)) < 0) {
518 : : uint32_t num_pages;
519 : :
520 : 61 : num_pages = get_num_hugepages(dirent->d_name,
521 : : hpi->hugepage_sz, 0);
522 [ + + ]: 61 : if (num_pages > 0)
523 : 2 : EAL_LOG(NOTICE,
524 : : "%" PRIu32 " hugepages of size "
525 : : "%" PRIu64 " reserved, but no mounted "
526 : : "hugetlbfs found for that size",
527 : : num_pages, hpi->hugepage_sz);
528 : : /* if we have kernel support for reserving hugepages
529 : : * through mmap, and we're in in-memory mode, treat this
530 : : * page size as valid. we cannot be in legacy mode at
531 : : * this point because we've checked this earlier in the
532 : : * init process.
533 : : */
534 : : #ifdef MAP_HUGE_SHIFT
535 [ + + ]: 61 : if (internal_conf->in_memory) {
536 : 3 : EAL_LOG(DEBUG, "In-memory mode enabled, "
537 : : "hugepages of size %" PRIu64 " bytes "
538 : : "will be allocated anonymously",
539 : : hpi->hugepage_sz);
540 : 3 : calc_num_pages(hpi, dirent, 0);
541 : 3 : num_sizes++;
542 : : }
543 : : #endif
544 : 61 : continue;
545 : : }
546 : :
547 : : /* try to obtain a writelock */
548 : 57 : hpi->lock_descriptor = open(hpi->hugedir, O_RDONLY);
549 : :
550 : : /* if blocking lock failed */
551 [ - + ]: 57 : if (flock(hpi->lock_descriptor, LOCK_EX) == -1) {
552 : 0 : EAL_LOG(CRIT,
553 : : "Failed to lock hugepage directory!");
554 : 0 : break;
555 : : }
556 : :
557 : : /*
558 : : * Check for existing hugepage files and either remove them
559 : : * or count how many of them can be reused.
560 : : */
561 : : reusable_pages = 0;
562 [ + + ]: 57 : if (!internal_conf->hugepage_file.unlink_existing) {
563 : 1 : reusable_bytes = 0;
564 [ + - ]: 1 : if (inspect_hugedir(hpi->hugedir,
565 : : &reusable_bytes) < 0)
566 : : break;
567 : : RTE_ASSERT(reusable_bytes % hpi->hugepage_sz == 0);
568 : 1 : reusable_pages = reusable_bytes / hpi->hugepage_sz;
569 [ + - ]: 56 : } else if (clear_hugedir(hpi->hugedir) < 0) {
570 : : break;
571 : : }
572 : 57 : calc_num_pages(hpi, dirent, reusable_pages);
573 : :
574 : 57 : num_sizes++;
575 : : }
576 : 59 : closedir(dir);
577 : :
578 : : /* something went wrong, and we broke from the for loop above */
579 [ + - ]: 59 : if (dirent != NULL)
580 : : return -1;
581 : :
582 : 59 : internal_conf->num_hugepage_sizes = num_sizes;
583 : :
584 : : /* sort the page directory entries by size, largest to smallest */
585 : 59 : qsort(&internal_conf->hugepage_info[0], num_sizes,
586 : : sizeof(internal_conf->hugepage_info[0]), compare_hpi);
587 : :
588 : : /* now we have all info, check we have at least one valid size */
589 [ + + ]: 62 : for (i = 0; i < num_sizes; i++) {
590 : : /* pages may no longer all be on socket 0, so check all */
591 : : unsigned int j, num_pages = 0;
592 : : struct hugepage_info *hpi = &internal_conf->hugepage_info[i];
593 : :
594 [ + + ]: 1980 : for (j = 0; j < RTE_MAX_NUMA_NODES; j++)
595 : 1920 : num_pages += hpi->num_pages[j];
596 [ + + ]: 60 : if (num_pages > 0)
597 : : return 0;
598 : : }
599 : :
600 : : /* no valid hugepage mounts available, return error */
601 : : return -1;
602 : : }
603 : :
604 : : /*
605 : : * when we initialize the hugepage info, everything goes
606 : : * to socket 0 by default. it will later get sorted by memory
607 : : * initialization procedure.
608 : : */
609 : : int
610 : 59 : eal_hugepage_info_init(void)
611 : : {
612 : : struct hugepage_info *hpi, *tmp_hpi;
613 : : unsigned int i;
614 : : struct internal_config *internal_conf =
615 : 59 : eal_get_internal_configuration();
616 : :
617 [ + + ]: 59 : if (hugepage_info_init() < 0)
618 : : return -1;
619 : :
620 : : /* for no shared files mode, we're done */
621 [ + + ]: 57 : if (internal_conf->no_shconf)
622 : : return 0;
623 : :
624 : 54 : hpi = &internal_conf->hugepage_info[0];
625 : :
626 : 54 : tmp_hpi = create_shared_memory(eal_hugepage_info_path(),
627 : : sizeof(internal_conf->hugepage_info));
628 [ - + ]: 54 : if (tmp_hpi == NULL) {
629 : 0 : EAL_LOG(ERR, "Failed to create shared memory!");
630 : 0 : return -1;
631 : : }
632 : :
633 : : memcpy(tmp_hpi, hpi, sizeof(internal_conf->hugepage_info));
634 : :
635 : : /* we've copied file descriptors along with everything else, but they
636 : : * will be invalid in secondary process, so overwrite them
637 : : */
638 [ + + ]: 216 : for (i = 0; i < RTE_DIM(internal_conf->hugepage_info); i++) {
639 : 162 : struct hugepage_info *tmp = &tmp_hpi[i];
640 : 162 : tmp->lock_descriptor = -1;
641 : : }
642 : :
643 [ - + ]: 54 : if (munmap(tmp_hpi, sizeof(internal_conf->hugepage_info)) < 0) {
644 : 0 : EAL_LOG(ERR, "Failed to unmap shared memory!");
645 : 0 : return -1;
646 : : }
647 : : return 0;
648 : : }
649 : :
650 : 27 : int eal_hugepage_info_read(void)
651 : : {
652 : : struct internal_config *internal_conf =
653 : 27 : eal_get_internal_configuration();
654 : 27 : struct hugepage_info *hpi = &internal_conf->hugepage_info[0];
655 : : struct hugepage_info *tmp_hpi;
656 : :
657 : 27 : tmp_hpi = open_shared_memory(eal_hugepage_info_path(),
658 : : sizeof(internal_conf->hugepage_info));
659 [ - + ]: 27 : if (tmp_hpi == NULL) {
660 : 0 : EAL_LOG(ERR, "Failed to open shared memory!");
661 : 0 : return -1;
662 : : }
663 : :
664 : : memcpy(hpi, tmp_hpi, sizeof(internal_conf->hugepage_info));
665 : :
666 [ - + ]: 27 : if (munmap(tmp_hpi, sizeof(internal_conf->hugepage_info)) < 0) {
667 : 0 : EAL_LOG(ERR, "Failed to unmap shared memory!");
668 : 0 : return -1;
669 : : }
670 : : return 0;
671 : : }
|