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