Line data Source code
1 : #include "configure.h"
2 :
3 : #include <stdio.h>
4 : #include <dirent.h>
5 : #include <sys/stat.h>
6 : #include <sys/mount.h>
7 : #include <linux/capability.h>
8 :
9 : static void
10 : init_perm( fd_caps_ctx_t * caps,
11 0 : config_t * const config ) {
12 0 : (void)config;
13 0 : fd_caps_check_root( caps, "hugetlbfs", "increase `/proc/sys/vm/nr_hugepages`" );
14 0 : fd_caps_check_capability( caps, "hugetlbfs", CAP_SYS_ADMIN, "mount hugetlbfs filesystems" );
15 0 : }
16 :
17 : static void
18 : fini_perm( fd_caps_ctx_t * caps,
19 0 : config_t * const config ) {
20 0 : (void)config;
21 0 : fd_caps_check_root( caps, "hugetlbfs", "remove directories from `/mnt`" );
22 0 : fd_caps_check_capability( caps, "hugetlbfs", CAP_SYS_ADMIN, "unmount hugetlbfs filesystems" );
23 :
24 0 : }
25 :
26 : void
27 0 : try_defragment_memory( void ) {
28 0 : write_uint_file( "/proc/sys/vm/compact_memory", 1 );
29 : /* Sleep a little to give the OS some time to perform the
30 : compaction. */
31 0 : nanosleep1( 0, 250000000 /* 250 millis */ );
32 0 : }
33 :
34 : static const char * ERR_MSG = "please confirm your host is configured for gigantic pages,";
35 :
36 : static char const * TOTAL_HUGE_PAGE_PATH[ 2 ] = {
37 : "/sys/devices/system/node/node%lu/hugepages/hugepages-2048kB/nr_hugepages",
38 : "/sys/devices/system/node/node%lu/hugepages/hugepages-1048576kB/nr_hugepages",
39 : };
40 :
41 : static char const * FREE_HUGE_PAGE_PATH[ 2 ] = {
42 : "/sys/devices/system/node/node%lu/hugepages/hugepages-2048kB/free_hugepages",
43 : "/sys/devices/system/node/node%lu/hugepages/hugepages-1048576kB/free_hugepages",
44 : };
45 :
46 : static ulong PAGE_SIZE[ 2 ] = {
47 : 2097152,
48 : 1073741824,
49 : };
50 :
51 : static char const * PAGE_NAMES[ 2 ] = {
52 : "huge",
53 : "gigantic"
54 : };
55 :
56 : static void
57 0 : init( config_t * const config ) {
58 0 : char const * mount_path[ 2 ] = {
59 0 : config->hugetlbfs.huge_page_mount_path,
60 0 : config->hugetlbfs.gigantic_page_mount_path,
61 0 : };
62 :
63 0 : ulong numa_node_cnt = fd_shmem_numa_cnt();
64 0 : for( ulong i=0UL; i<numa_node_cnt; i++ ) {
65 0 : ulong required_pages[ 2 ] = {
66 0 : fd_topo_huge_page_cnt( &config->topo, i, 0 ),
67 0 : fd_topo_gigantic_page_cnt( &config->topo, i ),
68 0 : };
69 :
70 0 : for( ulong j=0UL; j<2UL; j++ ) {
71 0 : char free_page_path[ PATH_MAX ];
72 0 : FD_TEST( fd_cstr_printf_check( free_page_path, PATH_MAX, NULL, FREE_HUGE_PAGE_PATH[ j ], i ) );
73 0 : ulong free_pages = read_uint_file( free_page_path, ERR_MSG );
74 :
75 : /* There is a TOCTOU race condition here, but it's not avoidable. There's
76 : no way to atomically increment the page count. */
77 0 : try_defragment_memory();
78 0 : FD_TEST( required_pages[ j ]<=UINT_MAX );
79 0 : if( FD_UNLIKELY( free_pages<required_pages[ j ] ) ) {
80 0 : char total_page_path[ PATH_MAX ];
81 0 : FD_TEST( fd_cstr_printf_check( total_page_path, PATH_MAX, NULL, TOTAL_HUGE_PAGE_PATH[ j ], i ) );
82 0 : ulong total_pages = read_uint_file( total_page_path, ERR_MSG );
83 0 : ulong additional_pages_needed = required_pages[ j ]-free_pages;
84 :
85 0 : FD_LOG_NOTICE(( "RUN: `echo \"%u\" > %s`", (uint)(total_pages+additional_pages_needed), total_page_path ));
86 0 : write_uint_file( total_page_path, (uint)(total_pages+additional_pages_needed) );
87 0 : uint raised_free_pages = read_uint_file( free_page_path, ERR_MSG );
88 0 : if( FD_UNLIKELY( raised_free_pages<required_pages[ j ] ) )
89 0 : FD_LOG_ERR(( "ENOMEM-Out of memory when trying to reserve %s pages for Firedancer on NUMA node %lu. Your Firedancer "
90 0 : "configuration requires %lu GiB of memory total consisting of %lu gigantic (1GiB) pages and %lu huge (2MiB) "
91 0 : "pages on this NUMA node but only %u %s pages were available according to `%s` (raised from %lu). If your "
92 0 : "system has the required amount of memory, this can be because it is not configured with %s page support, or "
93 0 : "Firedancer cannot increase the value of `%s` at runtime. You might need to enable huge pages in grub at boot "
94 0 : "time. This error can also happen because system uptime is high and memory is fragmented. You can fix this by "
95 0 : "rebooting the machine and running the `hugetlbfs` stage immediately on boot.",
96 0 : PAGE_NAMES[ j ],
97 0 : i,
98 0 : required_pages[ 1 ] + (required_pages[ 0 ] / 512),
99 0 : required_pages[ 1 ],
100 0 : required_pages[ 0 ],
101 0 : raised_free_pages,
102 0 : PAGE_NAMES[ j ],
103 0 : free_page_path,
104 0 : free_pages,
105 0 : PAGE_NAMES[ j ],
106 0 : total_page_path ));
107 0 : }
108 0 : }
109 0 : }
110 :
111 : /* Do NOT include anonymous huge pages in the min_size count that
112 : we reserve here, because they do not come from the hugetlbfs.
113 : Counting them towards that reservation would prevent the
114 : anonymous mmap which maps them in from succeeding.
115 :
116 : The kernel min_size option for the hugetlbfs does not include an
117 : option to reserve pages from a specific NUMA node, so we simply
118 : take the sum here and hope they are distributed correctly. If
119 : they are not, creating files in the mount on a specific node may
120 : fail later with ENOMEM. */
121 :
122 0 : ulong min_size[ 2 ] = {0};
123 0 : for( ulong i=0UL; i<numa_node_cnt; i++ ) {
124 0 : min_size[ 0 ] += PAGE_SIZE[ 0 ] * fd_topo_huge_page_cnt( &config->topo, i, 0 );
125 0 : min_size[ 1 ] += PAGE_SIZE[ 1 ] * fd_topo_gigantic_page_cnt( &config->topo, i );
126 0 : }
127 :
128 0 : for( ulong i=0UL; i<2UL; i++ ) {
129 0 : FD_LOG_NOTICE(( "RUN: `mkdir -p %s`", mount_path[ i ] ));
130 0 : mkdir_all( mount_path[ i ], config->uid, config->gid );
131 0 : char options[ 256 ];
132 0 : FD_TEST( fd_cstr_printf_check( options, sizeof(options), NULL, "pagesize=%lu,min_size=%lu", PAGE_SIZE[ i ], min_size[ i ] ) );
133 0 : FD_LOG_NOTICE(( "RUN: `mount -t hugetlbfs none %s -o %s`", mount_path[ i ], options ));
134 0 : if( FD_UNLIKELY( mount( "none", mount_path[ i ], "hugetlbfs", 0, options) ) )
135 0 : FD_LOG_ERR(( "mount of hugetlbfs at `%s` failed (%i-%s)", mount_path[ i ], errno, fd_io_strerror( errno ) ));
136 0 : if( FD_UNLIKELY( chown( mount_path[ i ], config->uid, config->gid ) ) )
137 0 : FD_LOG_ERR(( "chown of hugetlbfs at `%s` failed (%i-%s)", mount_path[ i ], errno, fd_io_strerror( errno ) ));
138 0 : if( FD_UNLIKELY( chmod( mount_path[ i ], S_IRUSR | S_IWUSR | S_IXUSR ) ) )
139 0 : FD_LOG_ERR(( "chmod of hugetlbfs at `%s` failed (%i-%s)", mount_path[ i ], errno, fd_io_strerror( errno ) ));
140 0 : }
141 0 : }
142 :
143 : static void
144 : cmdline( char * buf,
145 0 : ulong buf_sz ) {
146 0 : FILE * fp = fopen( "/proc/self/cmdline", "r" );
147 0 : if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "error opening `/proc/self/cmdline` (%i-%s)", errno, fd_io_strerror( errno ) ));
148 :
149 0 : ulong read = fread( buf, 1UL, buf_sz - 1UL, fp );
150 0 : if( FD_UNLIKELY( ferror( fp ) ) ) FD_LOG_ERR(( "error reading `/proc/self/cmdline` (%i-%s)", errno, fd_io_strerror( errno ) ));
151 0 : if( FD_UNLIKELY( fclose( fp ) ) ) FD_LOG_ERR(( "error closing `/proc/self/cmdline` (%i-%s)", errno, fd_io_strerror( errno ) ));
152 :
153 0 : buf[ read ] = '\0';
154 0 : }
155 :
156 : static void
157 0 : warn_mount_users( char const * mount_path ) {
158 0 : DIR * dir = opendir( "/proc" );
159 0 : if( FD_UNLIKELY( !dir ) ) FD_LOG_ERR(( "error opening `/proc` (%i-%s)", errno, fd_io_strerror( errno ) ));
160 :
161 0 : struct dirent * entry;
162 0 : while(( FD_LIKELY( entry = readdir( dir ) ) )) {
163 0 : if( FD_UNLIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue;
164 0 : char * endptr;
165 0 : ulong pid = strtoul( entry->d_name, &endptr, 10 );
166 0 : if( FD_UNLIKELY( *endptr ) ) continue;
167 :
168 0 : char path[ PATH_MAX ];
169 0 : FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/proc/%lu/maps", pid ) );
170 0 : FILE * fp = fopen( path, "r" );
171 0 : if( FD_UNLIKELY( !fp && errno!=ENOENT ) ) FD_LOG_ERR(( "error opening `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
172 :
173 0 : char self_cmdline[ PATH_MAX ];
174 0 : cmdline( self_cmdline, PATH_MAX );
175 :
176 0 : char line[ 4096 ];
177 0 : while( FD_LIKELY( fgets( line, 4096, fp ) ) ) {
178 0 : if( FD_UNLIKELY( strlen( line )==4095 ) ) FD_LOG_ERR(( "line too long in `%s`", path ));
179 0 : if( FD_UNLIKELY( strstr( line, mount_path ) ) ) {
180 0 : FD_LOG_WARNING(( "process `%lu`:`%s` has a file descriptor open in `%s`", pid, self_cmdline, mount_path ));
181 0 : break;
182 0 : }
183 0 : }
184 0 : if( FD_UNLIKELY( ferror( fp ) ) )
185 0 : FD_LOG_ERR(( "error reading `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
186 0 : if( FD_LIKELY( fclose( fp ) ) )
187 0 : FD_LOG_ERR(( "error closing `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
188 0 : }
189 :
190 0 : if( FD_UNLIKELY( -1==closedir( dir ) ) ) FD_LOG_ERR(( "closedir (%i-%s)", errno, fd_io_strerror( errno ) ));
191 0 : }
192 :
193 : static void
194 : fini( config_t * const config,
195 0 : int pre_init ) {
196 0 : (void)pre_init;
197 :
198 : /* Not used by fdctl but might be created by other debugging tools
199 : on the system. */
200 :
201 0 : char normal_page_mount_path[ PATH_MAX ];
202 0 : FD_TEST( fd_cstr_printf_check( normal_page_mount_path, PATH_MAX, NULL, "%s/.normal", config->hugetlbfs.mount_path ) );
203 :
204 0 : const char * mount_path[ 3 ] = {
205 0 : config->hugetlbfs.huge_page_mount_path,
206 0 : config->hugetlbfs.gigantic_page_mount_path,
207 0 : normal_page_mount_path,
208 0 : };
209 :
210 0 : for( ulong i=0UL; i<3UL; i++ ) {
211 0 : FILE * fp = fopen( "/proc/self/mounts", "r" );
212 0 : if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "failed to open `/proc/self/mounts`" ));
213 :
214 0 : char line[ 4096 ];
215 0 : while( FD_LIKELY( fgets( line, 4096UL, fp ) ) ) {
216 0 : if( FD_UNLIKELY( strlen( line )==4095UL ) ) FD_LOG_ERR(( "line too long in `/proc/self/mounts`" ));
217 0 : if( FD_UNLIKELY( strstr( line, mount_path[ i ] ) ) ) {
218 0 : FD_LOG_NOTICE(( "RUN: `umount %s`", mount_path[ i ] ));
219 0 : if( FD_UNLIKELY( umount( mount_path[ i ] ) ) ) {
220 0 : if( FD_LIKELY( errno==EBUSY ) ) {
221 0 : warn_mount_users( mount_path[ i ] );
222 :
223 0 : FD_LOG_ERR(( "Unmount of hugetlbfs at `%s` failed because the mount is still in use. "
224 0 : "You can unmount it by killing all processes that are actively using files in "
225 0 : "the mount and running `fdctl configure fini hugetlbfs` again, or unmount "
226 0 : "manually with `umount %s`", mount_path[ i ], mount_path[ i ] ));
227 0 : } else {
228 0 : FD_LOG_ERR(( "umount of hugetlbfs at `%s` failed (%i-%s)", mount_path[ i ], errno, fd_io_strerror( errno ) ));
229 0 : }
230 0 : }
231 0 : }
232 0 : }
233 :
234 0 : if( FD_UNLIKELY( ferror( fp ) ) )
235 0 : FD_LOG_ERR(( "error reading `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
236 0 : if( FD_LIKELY( fclose( fp ) ) )
237 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
238 :
239 0 : FD_LOG_NOTICE(( "RUN: `rmdir %s`", mount_path[ i ] ));
240 0 : if( FD_UNLIKELY( rmdir( mount_path[ i ] ) && errno!=ENOENT ) )
241 0 : FD_LOG_ERR(( "error removing hugetlbfs mount at `%s` (%i-%s)", mount_path[ i ], errno, fd_io_strerror( errno ) ));
242 0 : }
243 :
244 0 : FD_LOG_NOTICE(( "RUN: `rmdir %s`", config->hugetlbfs.mount_path ));
245 0 : if( FD_UNLIKELY( rmdir( config->hugetlbfs.mount_path ) && errno!=ENOENT ) )
246 0 : FD_LOG_ERR(( "error removing hugetlbfs directory at `%s` (%i-%s)", config->hugetlbfs.mount_path, errno, fd_io_strerror( errno ) ));
247 0 : }
248 :
249 : static configure_result_t
250 0 : check( config_t * const config ) {
251 0 : char const * mount_path[ 2 ] = {
252 0 : config->hugetlbfs.huge_page_mount_path,
253 0 : config->hugetlbfs.gigantic_page_mount_path,
254 0 : };
255 :
256 0 : static char const * MOUNT_PAGE_SIZE[ 2 ] = {
257 0 : "pagesize=2M",
258 0 : "pagesize=1024M",
259 0 : };
260 :
261 0 : ulong numa_node_cnt = fd_shmem_numa_cnt();
262 0 : ulong required_min_size[ 2 ] = {0};
263 0 : for( ulong i=0UL; i<numa_node_cnt; i++ ) {
264 0 : required_min_size[ 0 ] += PAGE_SIZE[ 0 ] * fd_topo_huge_page_cnt( &config->topo, i, 0 );
265 0 : required_min_size[ 1 ] += PAGE_SIZE[ 1 ] * fd_topo_gigantic_page_cnt( &config->topo, i );
266 0 : }
267 :
268 0 : struct stat st;
269 0 : int result1 = stat( mount_path[ 0 ], &st );
270 0 : if( FD_UNLIKELY( result1 && errno!=ENOENT ) )
271 0 : PARTIALLY_CONFIGURED( "failed to stat `%s` (%i-%s)", mount_path[ 0 ], errno, fd_io_strerror( errno ) );
272 0 : int result2 = stat( mount_path[ 1 ], &st );
273 0 : if( FD_UNLIKELY( result2 && errno!=ENOENT ) )
274 0 : PARTIALLY_CONFIGURED( "failed to stat `%s` (%i-%s)", mount_path[ 1 ], errno, fd_io_strerror( errno ) );
275 :
276 0 : if( FD_UNLIKELY( result1 && result2 ) )
277 0 : NOT_CONFIGURED( "mounts `%s` and `%s` do not exist", mount_path[ 0 ], mount_path[ 1 ] );
278 0 : else if( FD_UNLIKELY( result1 ) )
279 0 : PARTIALLY_CONFIGURED( "mount `%s` does not exist", mount_path[ 0 ] );
280 0 : else if( FD_UNLIKELY( result2 ) )
281 0 : PARTIALLY_CONFIGURED( "mount `%s` does not exist", mount_path[ 1 ] );
282 :
283 0 : CHECK( check_dir( config->hugetlbfs.mount_path, config->uid, config->gid, S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR ) );
284 0 : for( ulong i=0UL; i<2UL; i++ ) {
285 0 : CHECK( check_dir( mount_path[ i ], config->uid, config->gid, S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR ) );
286 :
287 0 : FILE * fp = fopen( "/proc/self/mounts", "r" );
288 0 : if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "failed to open `/proc/self/mounts`" ));
289 :
290 0 : char line[ 4096 ];
291 0 : int found = 0;
292 0 : while( FD_LIKELY( fgets( line, 4096UL, fp ) ) ) {
293 0 : if( FD_UNLIKELY( strlen( line )==4095UL ) ) FD_LOG_ERR(( "line too long in `/proc/self/mounts`" ));
294 0 : if( FD_UNLIKELY( strstr( line, mount_path[ i ] ) ) ) {
295 0 : found = 1;
296 :
297 0 : char * saveptr;
298 0 : char * device = strtok_r( line, " ", &saveptr );
299 0 : if( FD_UNLIKELY( !device ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
300 0 : if( FD_UNLIKELY( strcmp( device, "none" ) ) ) {
301 0 : if( FD_UNLIKELY( fclose( fp ) ) )
302 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
303 0 : PARTIALLY_CONFIGURED( "mount `%s` is on unrecognized device, expected `none`", mount_path[ i ] );
304 0 : }
305 :
306 0 : char * path1 = strtok_r( NULL, " ", &saveptr );
307 0 : if( FD_UNLIKELY( !path1 ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
308 0 : if( FD_UNLIKELY( strcmp( path1, mount_path[ i ] ) ) ) {
309 0 : if( FD_UNLIKELY( fclose( fp ) ) )
310 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
311 0 : PARTIALLY_CONFIGURED( "mount `%s` is on unrecognized path, expected `%s`", path1, mount_path[ i ] );
312 0 : }
313 :
314 0 : char * type = strtok_r( NULL, " ", &saveptr );
315 0 : if( FD_UNLIKELY( !type ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
316 0 : if( FD_UNLIKELY( strcmp( type, "hugetlbfs" ) ) ) {
317 0 : if( FD_UNLIKELY( fclose( fp ) ) )
318 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
319 0 : PARTIALLY_CONFIGURED( "mount `%s` has unrecognized type, expected `hugetlbfs`", mount_path[ i ] );
320 0 : }
321 :
322 0 : char * options = strtok_r( NULL, " ", &saveptr );
323 0 : if( FD_UNLIKELY( !options ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
324 :
325 0 : char * saveptr2;
326 0 : char * rw = strtok_r( options, ",", &saveptr2 );
327 0 : if( FD_UNLIKELY( !rw ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
328 0 : if( FD_UNLIKELY( strcmp( rw, "rw" ) ) ) {
329 0 : if( FD_UNLIKELY( fclose( fp ) ) )
330 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
331 0 : PARTIALLY_CONFIGURED( "mount `%s` is not mounted read/write, expected `rw`", mount_path[ i ] );
332 0 : }
333 :
334 0 : char * seclabel = strtok_r( NULL, ",", &saveptr2 );
335 0 : if( FD_UNLIKELY( !seclabel ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
336 :
337 0 : char * relatime;
338 0 : if( FD_LIKELY( !strcmp( seclabel, "seclabel" ) ) ) {
339 0 : relatime = strtok_r( NULL, ",", &saveptr2 );
340 0 : if( FD_UNLIKELY( !relatime ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
341 0 : } else {
342 0 : relatime = seclabel;
343 0 : }
344 :
345 0 : if( FD_UNLIKELY( strcmp( relatime, "relatime" ) ) ) {
346 0 : if( FD_UNLIKELY( fclose( fp ) ) )
347 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
348 0 : PARTIALLY_CONFIGURED( "mount `%s` is not mounted with `relatime`, expected `relatime`", mount_path[ i ] );
349 0 : }
350 :
351 0 : char * pagesize = strtok_r( NULL, ",", &saveptr2 );
352 0 : if( FD_UNLIKELY( !pagesize ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
353 0 : if( FD_UNLIKELY( strcmp( pagesize, MOUNT_PAGE_SIZE[ i ] ) ) ) {
354 0 : if( FD_UNLIKELY( fclose( fp ) ) )
355 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
356 0 : PARTIALLY_CONFIGURED( "mount `%s` has unrecognized pagesize, expected `%s` %s", mount_path[ i ], MOUNT_PAGE_SIZE[ i ], pagesize );
357 0 : }
358 :
359 0 : char * _min_size = strtok_r( NULL, ",", &saveptr2 );
360 0 : if( FD_UNLIKELY( !_min_size ) ) FD_LOG_ERR(( "error parsing `/proc/self/mounts`, line `%s`", line ));
361 0 : if( FD_UNLIKELY( strncmp( "min_size=", _min_size, 9UL ) ) ) {
362 0 : if( FD_UNLIKELY( fclose( fp ) ) )
363 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
364 0 : PARTIALLY_CONFIGURED( "mount `%s` has unrecognized min_size, expected at least `min_size=%lu`", mount_path[ i ], required_min_size[ i ] );
365 0 : }
366 :
367 0 : char * endptr;
368 0 : ulong min_size = strtoul( _min_size+9, &endptr, 10 );
369 0 : if( FD_UNLIKELY( *endptr ) ) {
370 0 : if( FD_UNLIKELY( fclose( fp ) ) )
371 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
372 0 : PARTIALLY_CONFIGURED( "mount `%s` has malformed min_size, expected `min_size=%lu`", mount_path[ i ], required_min_size[ i ] );
373 0 : }
374 :
375 0 : if( FD_UNLIKELY( min_size<required_min_size[ i ] ) ) {
376 0 : if( FD_UNLIKELY( fclose( fp ) ) )
377 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
378 0 : PARTIALLY_CONFIGURED( "mount `%s` has min_size `%lu`, expected at least `min_size=%lu`", mount_path[ i ], min_size, required_min_size[ i ] );
379 0 : }
380 :
381 0 : break;
382 0 : }
383 0 : }
384 :
385 0 : if( FD_UNLIKELY( ferror( fp ) ) )
386 0 : FD_LOG_ERR(( "error reading `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
387 0 : if( FD_LIKELY( fclose( fp ) ) )
388 0 : FD_LOG_ERR(( "error closing `/proc/self/mounts` (%i-%s)", errno, fd_io_strerror( errno ) ));
389 :
390 0 : if( FD_UNLIKELY( !found ) )
391 0 : PARTIALLY_CONFIGURED( "mount `%s` not found in `/proc/self/mounts`", mount_path[ i ] );
392 0 : }
393 :
394 0 : CONFIGURE_OK();
395 0 : }
396 :
397 : configure_stage_t hugetlbfs = {
398 : .name = "hugetlbfs",
399 : .always_recreate = 0,
400 : .enabled = NULL,
401 : .init_perm = init_perm,
402 : .fini_perm = fini_perm,
403 : .init = init,
404 : .fini = fini,
405 : .check = check,
406 : };
|