static int32_t get_num_hugepages(const char *subdir) { char path[PATH_MAX]; long unsigned num_pages = 0; const char *nr_hp_file; /* if secondary process, just look at the number of hugepages, * otherwise look at number of free hugepages */ if (internal_config.process_type == RTE_PROC_SECONDARY) nr_hp_file = "nr_hugepages"; else nr_hp_file = "free_hugepages"; rte_snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); if (eal_parse_sysfs_value(path, &num_pages) < 0) return 0; if (num_pages == 0) RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n", subdir); return (int32_t)num_pages; }
/** * Get memory size configuration from /sys/devices/virtual/misc/dom0_mm * /memsize-mB/memsize file, and the size unit is mB. */ static int get_xen_memory_size(void) { char path[PATH_MAX]; unsigned long mem_size = 0; static const char *file_name; file_name = "memsize"; snprintf(path, sizeof(path), "%s/%s", sys_dir_path, file_name); if (eal_parse_sysfs_value(path, &mem_size) < 0) return -1; if (mem_size == 0) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s was not" " configured.\n",sys_dir_path, file_name); if (mem_size % 2) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s must be" " even number.\n",sys_dir_path, file_name); if (mem_size > DOM0_CONFIG_MEMSIZE) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s should not be larger" " than %d mB\n",sys_dir_path, file_name, DOM0_CONFIG_MEMSIZE); return mem_size; }
static int32_t get_num_hugepages(const char *subdir) { char path[PATH_MAX]; long unsigned resv_pages, num_pages = 0; const char *nr_hp_file; const char *nr_rsvd_file = "resv_hugepages"; /* first, check how many reserved pages kernel reports */ snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_rsvd_file); if (eal_parse_sysfs_value(path, &resv_pages) < 0) return 0; /* if secondary process, just look at the number of hugepages, * otherwise look at number of free hugepages */ if (internal_config.process_type == RTE_PROC_SECONDARY) nr_hp_file = "nr_hugepages"; else nr_hp_file = "free_hugepages"; memset(path, 0, sizeof(path)); snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); if (eal_parse_sysfs_value(path, &num_pages) < 0) return 0; if (num_pages == 0) RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n", subdir); /* adjust num_pages in case of primary process */ if (num_pages > 0 && internal_config.process_type == RTE_PROC_PRIMARY) num_pages -= resv_pages; return (int32_t)num_pages; }
/* this function is only called from eal_hugepage_info_init which itself * is only called from a primary process */ static uint32_t get_num_hugepages(const char *subdir) { char path[PATH_MAX]; long unsigned resv_pages, num_pages = 0; const char *nr_hp_file = "free_hugepages"; const char *nr_rsvd_file = "resv_hugepages"; /* first, check how many reserved pages kernel reports */ snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_rsvd_file); if (eal_parse_sysfs_value(path, &resv_pages) < 0) return 0; snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); if (eal_parse_sysfs_value(path, &num_pages) < 0) return 0; if (num_pages == 0) RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n", subdir); /* adjust num_pages */ if (num_pages >= resv_pages) num_pages -= resv_pages; else if (resv_pages) num_pages = 0; /* we want to return a uint32_t and more than this looks suspicious * anyway ... */ if (num_pages > UINT32_MAX) num_pages = UINT32_MAX; return num_pages; }
/* Get CPU socket id (NUMA node) by reading directory * /sys/devices/system/cpu/cpuX looking for symlink "nodeY" * which gives the NUMA topology information. * Note: physical package id != NUMA node, but we use it as a * fallback for kernels which don't create a nodeY link */ static unsigned cpu_socket_id(unsigned lcore_id) { const char node_prefix[] = "node"; const size_t prefix_len = sizeof(node_prefix) - 1; char path[PATH_MAX]; DIR *d; unsigned long id = 0; struct dirent *e; char *endptr = NULL; int len = rte_snprintf(path, sizeof(path), SYS_CPU_DIR, lcore_id); if (len <= 0 || (unsigned)len >= sizeof(path)) goto err; d = opendir(path); if (!d) goto err; while ((e = readdir(d)) != NULL) { if (strncmp(e->d_name, node_prefix, prefix_len) == 0) { id = strtoul(e->d_name+prefix_len, &endptr, 0); break; } } closedir(d); if (endptr == NULL || *endptr!='\0' || endptr == e->d_name+prefix_len) { RTE_LOG(ERR, EAL, "Error reading numa node link " "for lcore %u - using physical package id instead\n", lcore_id); len = rte_snprintf(path, sizeof(path), SYS_CPU_DIR "/%s", lcore_id, PHYS_PKG_FILE); if (len <= 0 || (unsigned)len >= sizeof(path)) goto err; if (eal_parse_sysfs_value(path, &id) != 0) goto err; } return (unsigned)id; err: RTE_LOG(ERR, EAL, "Error getting NUMA socket information from %s " "for lcore %u - assuming NUMA socket 0\n", SYS_CPU_DIR, lcore_id); return 0; }
/* Get the cpu core id value from the /sys/.../cpuX core_id value */ static unsigned cpu_core_id(unsigned lcore_id) { char path[PATH_MAX]; unsigned long id; int len = snprintf(path, sizeof(path), SYS_CPU_DIR "/%s", lcore_id, CORE_ID_FILE); if (len <= 0 || (unsigned)len >= sizeof(path)) goto err; if (eal_parse_sysfs_value(path, &id) != 0) goto err; return (unsigned)id; err: RTE_LOG(ERR, EAL, "Error reading core id value from %s " "for lcore %u - assuming core 0\n", SYS_CPU_DIR, lcore_id); return 0; }
static int test_parse_sysfs_value(void) { char filename[PATH_MAX] = ""; char proc_path[PATH_MAX]; char file_template[] = "/tmp/eal_test_XXXXXX"; int tmp_file_handle = -1; FILE *fd = NULL; unsigned valid_number; unsigned long retval = 0; printf("Testing function eal_parse_sysfs_value()\n"); /* get a temporary filename to use for all tests - create temp file handle and then * use /proc to get the actual file that we can open */ tmp_file_handle = mkstemp(file_template); if (tmp_file_handle == -1) { perror("mkstemp() failure"); goto error; } rte_snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", tmp_file_handle); if (readlink(proc_path, filename, sizeof(filename)) < 0) { perror("readlink() failure"); goto error; } printf("Temporary file is: %s\n", filename); /* test we get an error value if we use file before it's created */ printf("Test reading a missing file ...\n"); if (eal_parse_sysfs_value("/dev/not-quite-null", &retval) == 0) { printf("Error with eal_parse_sysfs_value() - returned success on reading empty file\n"); goto error; } printf("Confirmed return error when reading empty file\n"); /* test reading a valid number value with "\n" on the end */ printf("Test reading valid values ...\n"); valid_number = 15; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%u\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) < 0) { printf("eal_parse_sysfs_value() returned error - test failed\n"); goto error; } if (retval != valid_number) { printf("Invalid value read by eal_parse_sysfs_value() - test failed\n"); goto error; } printf("Read '%u\\n' ok\n", valid_number); /* test reading a valid hex number value with "\n" on the end */ valid_number = 25; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"0x%x\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) < 0) { printf("eal_parse_sysfs_value() returned error - test failed\n"); goto error; } if (retval != valid_number) { printf("Invalid value read by eal_parse_sysfs_value() - test failed\n"); goto error; } printf("Read '0x%x\\n' ok\n", valid_number); printf("Test reading invalid values ...\n"); /* test reading an empty file - expect failure!*/ fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a valid number value *without* "\n" on the end - expect failure!*/ valid_number = 3; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%u", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a valid number value followed by string - expect failure!*/ valid_number = 3; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%uJ\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a non-numeric value - expect failure!*/ fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"error\n"); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } close(tmp_file_handle); unlink(filename); printf("eal_parse_sysfs_value() - OK\n"); return 0; error: if (fd) fclose(fd); if (tmp_file_handle > 0) close(tmp_file_handle); if (filename[0] != '\0') unlink(filename); return -1; }