// Copyright 2024, The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! This module provides functions to load zram stats. #[cfg(test)] mod tests; use std::ops::Deref; use crate::zram::SysfsZramApi; /// Error from loading zram stats. #[derive(Debug, thiserror::Error)] pub enum Error { /// Stat file format is invalid. #[error("failed to parse")] Parse, /// Failed to read stat file. #[error("failed to read: {0}")] Io(#[from] std::io::Error), } type Result = std::result::Result; fn parse_next( iter: &mut impl Iterator>, ) -> Result { iter.next().ok_or(Error::Parse)?.parse().map_err(|_| Error::Parse) } fn parse_next_optional( iter: &mut impl Iterator>, ) -> Result> { iter.next().map(|v| v.parse()).transpose().map_err(|_| Error::Parse) } /// Loads /sys/block/zram0/disksize pub fn load_total_zram_size() -> Result { let contents = Z::read_disksize()?; contents.trim().parse().map_err(|_| Error::Parse) } /// Stats from /sys/block/zram0/mm_stat #[derive(Debug, Default, PartialEq, Eq)] pub struct ZramMmStat { /// Uncompressed size of data stored in this disk. This excludes same-element-filled pages /// (same_pages) since no memory is allocated for them. Unit: bytes pub orig_data_size: u64, /// Compressed size of data stored in this disk. pub compr_data_size: u64, /// The amount of memory allocated for this disk. This includes allocator fragmentation and /// metadata overhead, allocated for this disk. So, allocator space efficiency can be calculated /// using compr_data_size and this statistic. Unit: bytes pub mem_used_total: u64, /// The maximum amount of memory ZRAM can use to store The compressed data. pub mem_limit: u32, /// The maximum amount of memory zram have consumed to store the data. /// /// In zram_drv.h we define max_used_pages as atomic_long_t which could be negative, but /// negative value does not make sense for the variable. pub mem_used_max: i64, /// The number of same element filled pages written to this disk. No memory is allocated for /// such pages. pub same_pages: u64, /// The number of pages freed during compaction. pub pages_compacted: u32, /// The number of incompressible pages. /// Start supporting from v4.19. pub huge_pages: Option, /// The number of huge pages since zram set up. /// Start supporting from v5.15. pub huge_pages_since: Option, } impl ZramMmStat { /// Parse /sys/block/zram0/mm_stat. pub fn load() -> Result { let contents = Z::read_mm_stat()?; let mut values = contents.split_whitespace(); Ok(ZramMmStat { orig_data_size: parse_next(&mut values)?, compr_data_size: parse_next(&mut values)?, mem_used_total: parse_next(&mut values)?, mem_limit: parse_next(&mut values)?, mem_used_max: parse_next(&mut values)?, same_pages: parse_next(&mut values)?, pages_compacted: parse_next(&mut values)?, huge_pages: parse_next_optional(&mut values)?, huge_pages_since: parse_next_optional(&mut values)?, }) } } /// Stats from /sys/block/zram0/bd_stat #[derive(Debug, Default, PartialEq, Eq)] pub struct ZramBdStat { /// Size of data written in backing device. Unit: page pub bd_count_pages: u64, /// The number of reads from backing device. Unit: page pub bd_reads_pages: u64, /// The number of writes to backing device. Unit: page pub bd_writes_pages: u64, } impl ZramBdStat { /// Parse /sys/block/zram0/bd_stat. pub fn load() -> Result { let contents = Z::read_bd_stat()?; let mut values = contents.split_whitespace(); Ok(ZramBdStat { bd_count_pages: parse_next(&mut values)?, bd_reads_pages: parse_next(&mut values)?, bd_writes_pages: parse_next(&mut values)?, }) } }