procfs/sys/vm.rs
1//! Memory management tuning buffer and cache management
2//!
3//! The files in this directory can be used to tune
4//! the operation of the virtual memory (VM) subsystem of the Linux kernel
5//! and the write out of dirty data to disk.
6
7use std::fmt;
8use std::str;
9
10use crate::{read_value, write_value, ProcResult};
11
12/// The amount of free memory in the system that should be reserved for users with the capability cap_sys_admin.
13///
14/// # Example
15///
16/// ```
17/// use procfs::sys::vm::admin_reserve_kbytes;
18///
19/// assert_ne!(admin_reserve_kbytes().unwrap(), 0);
20/// ```
21pub fn admin_reserve_kbytes() -> ProcResult<usize> {
22 read_value("/proc/sys/vm/admin_reserve_kbytes")
23}
24
25/// Set the amount of free memory in the system that should be reserved for users with the capability cap_sys_admin.
26pub fn set_admin_reserve_kbytes(kbytes: usize) -> ProcResult<()> {
27 write_value("/proc/sys/vm/admin_reserve_kbytes", kbytes)
28}
29
30/// Force all zones are compacted such that free memory is available in contiguous blocks where possible.
31///
32/// This can be important for example in the allocation of huge pages
33/// although processes will also directly compact memory as required.
34///
35/// Present only if the kernel was configured with CONFIG_COMPACTION.
36pub fn compact_memory() -> ProcResult<()> {
37 write_value("/proc/sys/vm/compact_memory", 1)
38}
39
40/// drop clean caches, dentries, and inodes from memory, causing that memory to become free.
41#[derive(Clone, Copy, Debug, PartialEq, Eq)]
42pub enum DropCache {
43 /// default
44 Default = 0,
45 /// free pagecache
46 PageCache = 1,
47 /// free dentries and inodes
48 Inodes = 2,
49 /// free pagecache, dentries and inodes
50 All = 3,
51 /// disable
52 Disable = 4,
53}
54
55impl fmt::Display for DropCache {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 write!(
58 f,
59 "{}",
60 match self {
61 DropCache::Default => 0,
62 DropCache::PageCache => 1,
63 DropCache::Inodes => 2,
64 DropCache::All => 3,
65 DropCache::Disable => 4,
66 }
67 )
68 }
69}
70
71impl str::FromStr for DropCache {
72 type Err = &'static str;
73
74 fn from_str(s: &str) -> Result<Self, Self::Err> {
75 s.parse().map_err(|_| "Fail to parse drop cache").and_then(|n| match n {
76 0 => Ok(DropCache::Default),
77 1 => Ok(DropCache::PageCache),
78 2 => Ok(DropCache::Inodes),
79 3 => Ok(DropCache::All),
80 4 => Ok(DropCache::Disable),
81 _ => Err("Unknown drop cache value"),
82 })
83 }
84}
85
86/// Causes the kernel to drop clean caches, dentries, and inodes from memory,
87/// causing that memory to become free.
88///
89/// This can be useful for memory management testing and performing reproducible filesystem benchmarks.
90/// Because writing to this file causes the benefits of caching to be lost,
91/// it can degrade overall system performance.
92pub fn drop_caches(drop: DropCache) -> ProcResult<()> {
93 write_value("/proc/sys/vm/drop_caches", drop)
94}
95
96/// The maximum number of memory map areas a process may have.
97///
98/// Memory map areas are used as a side-effect of calling malloc,
99/// directly by mmap, mprotect, and madvise, and also when loading shared libraries.
100///
101/// # Example
102///
103/// ```
104/// use procfs::sys::vm::max_map_count;
105///
106/// assert_ne!(max_map_count().unwrap(), 0);
107/// ```
108pub fn max_map_count() -> ProcResult<u64> {
109 read_value("/proc/sys/vm/max_map_count")
110}
111
112/// Set the maximum number of memory map areas a process may have.
113///
114/// Memory map areas are used as a side-effect of calling malloc,
115/// directly by mmap, mprotect, and madvise, and also when loading shared libraries.
116pub fn set_max_map_count(count: u64) -> ProcResult<()> {
117 write_value("/proc/sys/vm/max_map_count", count)
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use std::str::FromStr;
124
125 #[test]
126 fn test() {
127 use std::path::Path;
128 if Path::new("/proc/sys/vm/admin_reserve_kbytes").exists() {
129 admin_reserve_kbytes().unwrap();
130 }
131 if Path::new("/proc/sys/vm/max_map_count").exists() {
132 max_map_count().unwrap();
133 }
134
135 for v in 0..5 {
136 let s = format!("{}", v);
137 let dc = DropCache::from_str(&s).unwrap();
138 assert_eq!(format!("{}", dc), s);
139 }
140 }
141}