1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Memory management tuning buffer and cache management
//!
//! The files in this directory can be used to tune
//! the operation of the virtual memory (VM) subsystem of the Linux kernel
//! and the write out of dirty data to disk.

use std::fmt;
use std::str;

use crate::{read_value, write_value, ProcResult};

/// The amount of free memory in the system that should be reserved for users with the capability cap_sys_admin.
///
/// # Example
///
/// ```
/// use procfs::sys::vm::admin_reserve_kbytes;
///
/// assert_ne!(admin_reserve_kbytes().unwrap(), 0);
/// ```
pub fn admin_reserve_kbytes() -> ProcResult<usize> {
    read_value("/proc/sys/vm/admin_reserve_kbytes")
}

/// Set the amount of free memory in the system that should be reserved for users with the capability cap_sys_admin.
pub fn set_admin_reserve_kbytes(kbytes: usize) -> ProcResult<()> {
    write_value("/proc/sys/vm/admin_reserve_kbytes", kbytes)
}

/// Force all zones are compacted such that free memory is available in contiguous blocks where possible.
///
/// This can be important for example in the allocation of huge pages
/// although processes will also directly compact memory as required.
///
/// Present only if the kernel was configured with CONFIG_COMPACTION.
pub fn compact_memory() -> ProcResult<()> {
    write_value("/proc/sys/vm/compact_memory", 1)
}

/// drop clean caches, dentries, and inodes from memory, causing that memory to become free.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum DropCache {
    /// default
    Default = 0,
    /// free pagecache
    PageCache = 1,
    /// free dentries and inodes
    Inodes = 2,
    /// free pagecache, dentries and inodes
    All = 3,
    /// disable
    Disable = 4,
}

impl fmt::Display for DropCache {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                DropCache::Default => 0,
                DropCache::PageCache => 1,
                DropCache::Inodes => 2,
                DropCache::All => 3,
                DropCache::Disable => 4,
            }
        )
    }
}

impl str::FromStr for DropCache {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse()
            .map_err(|_| "Fail to parse drop cache")
            .and_then(|n| match n {
                0 => Ok(DropCache::Default),
                1 => Ok(DropCache::PageCache),
                2 => Ok(DropCache::Inodes),
                3 => Ok(DropCache::All),
                4 => Ok(DropCache::Disable),
                _ => Err("Unknown drop cache value"),
            })
    }
}

/// Causes the kernel to drop clean caches, dentries, and inodes from memory,
/// causing that memory to become free.
///
/// This can be useful for memory management testing and performing reproducible filesystem benchmarks.
/// Because writing to this file causes the benefits of caching to be lost,
/// it can degrade overall system performance.
pub fn drop_caches(drop: DropCache) -> ProcResult<()> {
    write_value("/proc/sys/vm/drop_caches", drop)
}

/// The maximum number of memory map areas a process may have.
///
/// Memory map areas are used as a side-effect of calling malloc,
/// directly by mmap, mprotect, and madvise, and also when loading shared libraries.
///
/// # Example
///
/// ```
/// use procfs::sys::vm::max_map_count;
///
/// assert_ne!(max_map_count().unwrap(), 0);
/// ```
pub fn max_map_count() -> ProcResult<u64> {
    read_value("/proc/sys/vm/max_map_count")
}

/// Set the maximum number of memory map areas a process may have.
///
/// Memory map areas are used as a side-effect of calling malloc,
/// directly by mmap, mprotect, and madvise, and also when loading shared libraries.
pub fn set_max_map_count(count: u64) -> ProcResult<()> {
    write_value("/proc/sys/vm/max_map_count", count)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test() {
        use std::path::Path;
        if Path::new("/proc/sys/vm/admin_reserve_kbytes").exists() {
            admin_reserve_kbytes().unwrap();
        }
        if Path::new("/proc/sys/vm/max_map_count").exists() {
            max_map_count().unwrap();
        }
    }
}