solana_core/
resource_limits.rs1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum ResourceLimitError {
5 #[cfg(unix)]
6 #[error(
7 "unable to increase the nofile limit to {desired} from {current}; setrlimit() error: \
8 {error}"
9 )]
10 Nofile {
11 desired: libc::rlim_t,
12 current: libc::rlim_t,
13 error: libc::c_int,
14 },
15}
16
17#[cfg(not(unix))]
18pub fn adjust_nofile_limit(_enforce_nofile_limit: bool) -> Result<(), ResourceLimitError> {
19 Ok(())
20}
21
22#[cfg(unix)]
23pub fn adjust_nofile_limit(enforce_nofile_limit: bool) -> Result<(), ResourceLimitError> {
24 let desired_nofile = 1_000_000;
30
31 fn get_nofile() -> libc::rlimit {
32 let mut nofile = libc::rlimit {
33 rlim_cur: 0,
34 rlim_max: 0,
35 };
36 if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut nofile) } != 0 {
37 warn!("getrlimit(RLIMIT_NOFILE) failed");
38 }
39 nofile
40 }
41
42 let mut nofile = get_nofile();
43 let current = nofile.rlim_cur;
44 if current < desired_nofile {
45 nofile.rlim_cur = desired_nofile;
46 let return_value = unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &nofile) };
47 if return_value != 0 {
48 let error = ResourceLimitError::Nofile {
49 desired: desired_nofile,
50 current,
51 error: return_value,
52 };
53
54 if cfg!(target_os = "macos") {
55 error!(
56 "{error}. On macOS you may need to run |sudo launchctl limit maxfiles \
57 {desired_nofile} {desired_nofile}| first",
58 );
59 } else {
60 error!("{error}");
61 };
62
63 if enforce_nofile_limit {
64 return Err(error);
65 }
66 }
67
68 nofile = get_nofile();
69 }
70 info!("Maximum open file descriptors: {}", nofile.rlim_cur);
71 Ok(())
72}
73
74#[cfg(target_os = "linux")]
78fn try_adjust_ulimit_memlock(min_required: usize) -> bool {
79 fn get_memlock() -> libc::rlimit {
80 let mut memlock = libc::rlimit {
81 rlim_cur: 0,
82 rlim_max: 0,
83 };
84 if unsafe { libc::getrlimit(libc::RLIMIT_MEMLOCK, &mut memlock) } != 0 {
85 log::warn!("getrlimit(RLIMIT_MEMLOCK) failed");
86 }
87 memlock
88 }
89
90 let mut memlock = get_memlock();
91 let current = memlock.rlim_cur as usize;
92 if current < min_required {
93 memlock.rlim_cur = min_required as u64;
94 memlock.rlim_max = min_required as u64;
95 if unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &memlock) } != 0 {
96 log::warn!(
97 "Unable to increase the maximum memory lock limit to {min_required} from {current}"
98 );
99
100 if cfg!(target_os = "macos") {
101 log::warn!(
102 "On mac OS you may need to run |sudo launchctl limit memlock {min_required} \
103 {min_required}| first"
104 );
105 }
106 return false;
107 }
108
109 memlock = get_memlock();
110 log::info!("Bumped maximum memory lock limit: {}", memlock.rlim_cur);
111 }
112 true
113}
114
115pub fn check_memlock_limit_for_disk_io(required_size: usize) -> bool {
116 #[cfg(target_os = "linux")]
117 {
118 try_adjust_ulimit_memlock(required_size)
120 }
121 #[cfg(not(target_os = "linux"))]
122 {
123 let _ = required_size;
124 false
125 }
126}