/
githubmirror
/
virtiofsd
Обзор
Документация
Войти
/
githubmirror
/
virtiofsd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/limits.rs
89 строк
3 KB
Hanna Czenczek
Set guest FD limit based on actual total FD limit
04 июн 2025, 18:24
04 июн 2025, 18:24
c0c8ca2
Код
Авторство
О чём код?
// SPDX-License-Identifier: BSD-3-Clause use libc::{getrlimit, rlim_t, rlimit, setrlimit, RLIMIT_NOFILE}; use std::mem::MaybeUninit; use std::{cmp, fs, io}; // Default number of open files (RLIMIT_NOFILE) const DEFAULT_NOFILE: rlim_t = 1_000_000; /// Gets the maximum number of open files. fn get_max_nofile() -> Result<rlim_t, String> { let path = "/proc/sys/fs/nr_open"; let max_str = fs::read_to_string(path).map_err(|error| format!("Reading {path}: {error:?}"))?; max_str .trim() .parse() .map_err(|error| format!("Parsing {path}: {error:?}")) } /// Gets the hard limit of open files. fn get_nofile_limits() -> Result<rlimit, String> { let mut limits = MaybeUninit::<rlimit>::zeroed(); let ret = unsafe { getrlimit(RLIMIT_NOFILE, limits.as_mut_ptr()) }; if ret != 0 { return Err(format!("getrlimit: {}", io::Error::last_os_error())); } Ok(unsafe { limits.assume_init() }) } /// Sets the limit of open files to the given value. fn setup_rlimit_nofile_to(nofile: rlim_t) -> Result<(), String> { let rlimit = rlimit { rlim_cur: nofile, rlim_max: nofile, }; let ret = unsafe { setrlimit(RLIMIT_NOFILE, &rlimit) }; if ret < 0 { Err(format!( "Failed to increase the limit: {:?}", io::Error::last_os_error() )) } else { Ok(()) } } /// Set the limit of open files to the given value, returning the actual limit. pub fn setup_rlimit_nofile(nofile: Option<u64>) -> Result<u64, String> { let max_nofile = get_max_nofile()?; let rlimit { rlim_cur, rlim_max } = get_nofile_limits()?; let target_limit = if let Some(nofile) = nofile { if nofile == 0 { return Ok(rlim_cur); // '--rlimit-nofile=0' leaves the resource limit unchanged } nofile } else { if DEFAULT_NOFILE <= rlim_cur { return Ok(rlim_cur); // the user has already setup the soft limit higher than the target } cmp::min(DEFAULT_NOFILE, max_nofile) }; if target_limit > max_nofile { return Err(format!("It cannot be increased above {max_nofile}")); } let new_limit = if let Err(error) = setup_rlimit_nofile_to(target_limit) { if nofile.is_some() { // Error attempting to setup user-supplied value return Err(error); } else { warn!( "Failure when trying to set the limit to {target_limit}, \ the hard limit ({rlim_max}) of open file descriptors is used instead." ); setup_rlimit_nofile_to(rlim_max).map_err(|error| { format!("Cannot increase the soft limit to the hard limit: {error}") })?; rlim_max } } else { target_limit }; Ok(new_limit) }