Skip to content

Commit 7f351ce

Browse files
committed
linux: fix the discovery of hugepages on btrfs fsroot
btrfs always returns 1 in directory stat.st_nlink. It breaks make check in tests/hwloc/linux/ because the hugepages discovery uses st_nlink to allocate the memory page_types array. Always allocate at least 3 page_types slots (enough for all known cases, 1 for normal, 2 for huge pages) and realloc later if needed. Thanks to Ludovic Courtes for the report. Signed-off-by: Brice Goglin <[email protected]>
1 parent a720f86 commit 7f351ce

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

hwloc/topology-linux.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,7 @@ static void
24592459
hwloc_parse_hugepages_info(struct hwloc_linux_backend_data_s *data,
24602460
const char *dirpath,
24612461
struct hwloc_numanode_attr_s *memory,
2462+
unsigned allocated_page_types,
24622463
uint64_t *remaining_local_memory)
24632464
{
24642465
DIR *dir;
@@ -2473,6 +2474,14 @@ hwloc_parse_hugepages_info(struct hwloc_linux_backend_data_s *data,
24732474
int err;
24742475
if (strncmp(dirent->d_name, "hugepages-", 10))
24752476
continue;
2477+
if (index_ >= allocated_page_types) {
2478+
/* we must increase the page_types array */
2479+
struct hwloc_memory_page_type_s *tmp = realloc(memory->page_types, allocated_page_types * 2 * sizeof(*tmp));
2480+
if (!tmp)
2481+
break;
2482+
memory->page_types = tmp;
2483+
allocated_page_types *= 2;
2484+
}
24762485
memory->page_types[index_].size = strtoul(dirent->d_name+10, NULL, 0) * 1024ULL;
24772486
err = snprintf(path, sizeof(path), "%s/%s/nr_hugepages", dirpath, dirent->d_name);
24782487
if ((size_t) err < sizeof(path)
@@ -2500,7 +2509,14 @@ hwloc_get_machine_meminfo(struct hwloc_linux_backend_data_s *data,
25002509

25012510
err = hwloc_stat("/sys/kernel/mm/hugepages", &st, data->root_fd);
25022511
if (!err) {
2503-
types = 1 + st.st_nlink-2;
2512+
types = 1 /* normal non-huge size */ + st.st_nlink - 2 /* ignore . and .. */;
2513+
if (types < 3)
2514+
/* some buggy filesystems (e.g. btrfs when reading from fsroot)
2515+
* return wrong st_nlink for directories (always 1 for btrfs).
2516+
* use 3 as a sane default (default page + 2 huge sizes).
2517+
* hwloc_parse_hugepages_info() will extend it if needed.
2518+
*/
2519+
types = 3;
25042520
has_sysfs_hugepages = 1;
25052521
}
25062522

@@ -2518,7 +2534,8 @@ hwloc_get_machine_meminfo(struct hwloc_linux_backend_data_s *data,
25182534

25192535
if (has_sysfs_hugepages) {
25202536
/* read from node%d/hugepages/hugepages-%skB/nr_hugepages */
2521-
hwloc_parse_hugepages_info(data, "/sys/kernel/mm/hugepages", memory, &remaining_local_memory);
2537+
hwloc_parse_hugepages_info(data, "/sys/kernel/mm/hugepages", memory, types, &remaining_local_memory);
2538+
/* memory->page_types_len may have changed */
25222539
}
25232540

25242541
/* use remaining memory as normal pages */
@@ -2542,7 +2559,14 @@ hwloc_get_sysfs_node_meminfo(struct hwloc_linux_backend_data_s *data,
25422559
sprintf(path, "%s/node%d/hugepages", syspath, node);
25432560
err = hwloc_stat(path, &st, data->root_fd);
25442561
if (!err) {
2545-
types = 1 + st.st_nlink-2;
2562+
types = 1 /* normal non-huge size */ + st.st_nlink - 2 /* ignore . and .. */;
2563+
if (types < 3)
2564+
/* some buggy filesystems (e.g. btrfs when reading from fsroot)
2565+
* return wrong st_nlink for directories (always 1 for btrfs).
2566+
* use 3 as a sane default (default page + 2 huge sizes).
2567+
* hwloc_parse_hugepages_info() will extend it if needed.
2568+
*/
2569+
types = 3;
25462570
has_sysfs_hugepages = 1;
25472571
}
25482572

@@ -2561,7 +2585,8 @@ hwloc_get_sysfs_node_meminfo(struct hwloc_linux_backend_data_s *data,
25612585

25622586
if (has_sysfs_hugepages) {
25632587
/* read from node%d/hugepages/hugepages-%skB/nr_hugepages */
2564-
hwloc_parse_hugepages_info(data, path, memory, &remaining_local_memory);
2588+
hwloc_parse_hugepages_info(data, path, memory, types, &remaining_local_memory);
2589+
/* memory->page_types_len may have changed */
25652590
}
25662591

25672592
/* use remaining memory as normal pages */

0 commit comments

Comments
 (0)