blob: 9e0ab0b5e67fc5731bc77dafcddecad4a9dd4c11 [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Implement sysfs save/restore functionality.
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use anyhow::{Context, Result};
use log::{debug, warn};
const SWAPPINESS_PATH: &str = "/proc/sys/vm/swappiness";
/// This simple object remembers the original value of the swappiness file, so
/// that upon being dropped it can be restored.
pub struct Swappiness {
file: File,
swappiness: i32,
}
impl Swappiness {
/// Create a new Swappiness object, which reads and saves the original value.
/// When this object is dropped, the value read here will be restored.
pub fn new() -> Result<Self> {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(SWAPPINESS_PATH)
.context("Failed to open swappiness file")?;
let swappiness = Self::read_swappiness(&mut file)?;
debug!("Saved original swappiness: {}", swappiness);
Ok(Self { file, swappiness })
}
/// Set the current swappiness value.
pub fn set_swappiness(&mut self, value: i32) -> Result<()> {
self.file
.seek(SeekFrom::Start(0))
.context("Failed to seek swappiness file")?;
writeln!(self.file, "{}", value).context("Failed to write swappiness")?;
Ok(())
}
/// Internal helper function to read the current swappiness value.
fn read_swappiness(file: &mut File) -> Result<i32> {
let mut s = String::with_capacity(10);
file.seek(SeekFrom::Start(0))
.context("Failed to seek swappiness file")?;
file.read_to_string(&mut s)
.context("Failed to read swappiness file")?;
s.trim()
.parse::<i32>()
.context("Failed to convert swappiness file to int")
}
}
impl Drop for Swappiness {
fn drop(&mut self) {
debug!("Restoring swappiness to {}", self.swappiness);
if let Err(e) = self.set_swappiness(self.swappiness) {
warn!("Failed to restore swappiness: {}", e);
}
}
}