diff options
Diffstat (limited to 'pkgs/by-name/i3')
| -rw-r--r-- | pkgs/by-name/i3/i3bar-river-patched/0001-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch (renamed from pkgs/by-name/i3/i3bar-river-patched/0002-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch) | 33 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3bar-river-patched/0001-revert-use-std-io-pipe.patch | 67 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3bar-river-patched/package.nix | 24 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3status-rust-patched/package.nix | 13 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3status-rust-patched/patches/0001-disk_space-Support-btrfs-backend.patch | 190 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3status-rust-patched/patches/0002-memory-Directly-convert-reported-memory-usage-into-b.patch | 117 | ||||
| -rw-r--r-- | pkgs/by-name/i3/i3status-rust-patched/patches/0003-memory-Avoid-estimating-available-memory-use-kernel-.patch | 49 |
7 files changed, 381 insertions, 112 deletions
diff --git a/pkgs/by-name/i3/i3bar-river-patched/0002-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch b/pkgs/by-name/i3/i3bar-river-patched/0001-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch index 6f4bd528..7bfdd7bc 100644 --- a/pkgs/by-name/i3/i3bar-river-patched/0002-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch +++ b/pkgs/by-name/i3/i3bar-river-patched/0001-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch @@ -1,4 +1,4 @@ -From b8568a2b626bd4d5f50ee24c304d19177bda5d4b Mon Sep 17 00:00:00 2001 +From 8ae692a461fad2f23231d50b78bb706408facfe6 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz <benedikt.peetz@b-peetz.de> Date: Tue, 20 May 2025 19:58:57 +0200 Subject: [PATCH] feat(crate::bar): Put the leftmost block in the middle of the @@ -7,21 +7,21 @@ Subject: [PATCH] feat(crate::bar): Put the leftmost block in the middle of the This is a workaround for the limitation in the i3 blocks protocol, as this does not allow for centred blocks. --- - src/bar.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 53 insertions(+), 11 deletions(-) + src/bar.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/bar.rs b/src/bar.rs -index fb88150..e66c2cf 100644 +index 96533e3..76f8025 100644 --- a/src/bar.rs +++ b/src/bar.rs -@@ -344,16 +344,56 @@ impl Bar { +@@ -338,16 +338,55 @@ impl Bar { } // Display the blocks - render_blocks( - &cairo_ctx, -- ss, -- &self.output, +- &ss.config, +- palette, - ss.blocks_cache.get_computed(), - &mut self.blocks_btns, - offset_left, @@ -36,8 +36,8 @@ index fb88150..e66c2cf 100644 + + let other_start = render_blocks( + &cairo_ctx, -+ ss, -+ &self.output, ++ &ss.config, ++ palette, + blocks, + &mut self.blocks_btns, + offset_left, @@ -49,7 +49,9 @@ index fb88150..e66c2cf 100644 + // left, if the others are spanning over the middle. + let mut start = (width_f / 2.0) - (first_block.full.width / 2.0); + if start + first_block.full.width > other_start { -+ start = other_start - first_block.full.width - first_block.block.separator_block_width as f64; ++ start = other_start ++ - first_block.full.width ++ - first_block.block.separator_block_width as f64; + } + + first_block.full.render( @@ -57,10 +59,7 @@ index fb88150..e66c2cf 100644 + RenderOptions { + x_offset: start, + bar_height: height_f, -+ fg_color: first_block -+ .block -+ .color -+ .unwrap_or(sfo!(ss, &self.output, color)), ++ fg_color: first_block.block.color.unwrap_or(palette.color), + bg_color: first_block.block.background, + r_left: ss.config.blocks_r, + r_right: ss.config.blocks_r, @@ -81,7 +80,7 @@ index fb88150..e66c2cf 100644 self.viewport .set_destination(conn, self.width as i32, self.height as i32); -@@ -428,7 +468,7 @@ fn render_blocks( +@@ -422,7 +461,7 @@ fn render_blocks( offset_left: f64, full_width: f64, full_height: f64, @@ -90,7 +89,7 @@ index fb88150..e66c2cf 100644 context.rectangle(offset_left, 0.0, full_width - offset_left, full_height); context.clip(); -@@ -513,6 +553,7 @@ fn render_blocks( +@@ -507,6 +546,7 @@ fn render_blocks( } // Render blocks @@ -98,7 +97,7 @@ index fb88150..e66c2cf 100644 buttons.clear(); for series in blocks_computed { let s_len = series.blocks.len(); -@@ -560,6 +601,7 @@ fn render_blocks( +@@ -550,6 +590,7 @@ fn render_blocks( } context.reset_clip(); diff --git a/pkgs/by-name/i3/i3bar-river-patched/0001-revert-use-std-io-pipe.patch b/pkgs/by-name/i3/i3bar-river-patched/0001-revert-use-std-io-pipe.patch deleted file mode 100644 index e1564753..00000000 --- a/pkgs/by-name/i3/i3bar-river-patched/0001-revert-use-std-io-pipe.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 017ed59239e48ca689af36f1ddaec877a3c86175 Mon Sep 17 00:00:00 2001 -From: Benedikt Peetz <benedikt.peetz@b-peetz.de> -Date: Tue, 20 May 2025 17:10:47 +0200 -Subject: [PATCH] Revert "use std::io::pipe" - -This reverts commit c9cee90d765198cf72c5a5155ee0d8ab566d98a9 as this -commit requires rustc 1.87.0 ---- - src/main.rs | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) - -diff --git a/src/main.rs b/src/main.rs -index 4a86593..2e7aeb2 100644 ---- a/src/main.rs -+++ b/src/main.rs -@@ -18,8 +18,8 @@ mod text; - mod utils; - mod wm_info_provider; - --use std::io::{self, ErrorKind, Read}; --use std::os::fd::AsRawFd; -+use std::io::{self, ErrorKind}; -+use std::os::fd::{AsRawFd, RawFd}; - use std::path::PathBuf; - - use clap::Parser; -@@ -40,7 +40,7 @@ struct Cli { - fn main() -> anyhow::Result<()> { - let args = Cli::parse(); - -- let (mut sig_read, sig_write) = io::pipe()?; -+ let [sig_read, sig_write] = pipe(libc::O_NONBLOCK | libc::O_CLOEXEC)?; - signal_hook::low_level::pipe::register(SIGUSR1, sig_write)?; - - let mut conn = Connection::connect()?; -@@ -55,8 +55,12 @@ fn main() -> anyhow::Result<()> { - Ok(event_loop::Action::Keep) - }); - -- el.register_with_fd(sig_read.as_raw_fd(), move |ctx| { -- sig_read.read_exact(&mut [0u8]).unwrap(); -+ el.register_with_fd(sig_read, move |ctx| { -+ let mut buf = [0u8]; -+ assert_eq!( -+ unsafe { libc::read(sig_read, buf.as_mut_ptr().cast(), 1) }, -+ 1 -+ ); - ctx.state.toggle_visibility(ctx.conn); - Ok(event_loop::Action::Keep) - }); -@@ -104,3 +108,13 @@ fn main() -> anyhow::Result<()> { - el.run(&mut conn, &mut state)?; - unreachable!(); - } -+ -+// TODO: remove once Rust 1.87.0 is stable -+fn pipe(flags: libc::c_int) -> io::Result<[RawFd; 2]> { -+ let mut fds = [0; 2]; -+ if unsafe { libc::pipe2(fds.as_mut_ptr(), flags) } == -1 { -+ Err(io::Error::last_os_error()) -+ } else { -+ Ok(fds) -+ } -+} --- -2.49.0 - diff --git a/pkgs/by-name/i3/i3bar-river-patched/package.nix b/pkgs/by-name/i3/i3bar-river-patched/package.nix index 88af5d8a..26f11ab3 100644 --- a/pkgs/by-name/i3/i3bar-river-patched/package.nix +++ b/pkgs/by-name/i3/i3bar-river-patched/package.nix @@ -13,35 +13,23 @@ rustPlatform, pkg-config, pango, - fetchpatch2, }: rustPlatform.buildRustPackage { pname = "i3bar-river-patched"; version = "1.1.0-unstable-2025-05-20"; src = fetchFromGitHub { - owner = "MaxVerevkin"; + owner = "bpeetz"; repo = "i3bar-river"; - rev = "73446cac559b10adf4beb5567a816d1be5273457"; - hash = "sha256-NxlFKTnd2erHtSG56aWlZEkWVzBqe2hqQuVAWDdBq2c="; + rev = "d460a9a283426e9474a0034a146d09816e92f571"; + hash = "sha256-E04b2FzEhOX5NyE/VpEGdg27Sg+1+lSSRZbGyX6PXrk="; }; - useFetchCargoVendor = true; - cargoHash = "sha256-8sub8cXC/1iDY6v/9opO4FiLAo9CFrGJSDPNQydGvhQ="; + cargoHash = "sha256-jIB4XH67FmtPxAatHkuW8v5mNgr/KsyriaBNZ5t2dLo="; cargoPatches = [ - # Add a separate theme for unfocused outputs. - (fetchpatch2 { - name = "Add support for special theme for unfocused outputs"; - url = "https://patch-diff.githubusercontent.com/raw/MaxVerevkin/i3bar-river/pull/44.patch"; - hash = "sha256-yH3K52kAXGW19maP77gOTHSauqQX7Px8qCZDua6wo4w="; - }) - - # TODO(@bpeetz): Remove this patch once the rustc update hits unstable. <2025-05-20> - ./0001-revert-use-std-io-pipe.patch - - # TODO(@bpeetz): Open an issues, whether something like that could be upstreamed. <2025-05-20> - ./0002-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch + # TODO(@bpeetz): Open an issues, whether something like that could be up-streamed. <2025-05-20> + ./0001-feat-crate-bar-Put-the-leftmost-block-in-the-middle-.patch ]; # Remove the WMs that I don't use. diff --git a/pkgs/by-name/i3/i3status-rust-patched/package.nix b/pkgs/by-name/i3/i3status-rust-patched/package.nix index 9f172d49..1d0a42bc 100644 --- a/pkgs/by-name/i3/i3status-rust-patched/package.nix +++ b/pkgs/by-name/i3/i3status-rust-patched/package.nix @@ -18,17 +18,10 @@ i3status-rust.overrideAttrs (final: prev: { (prev.patches or []) ++ [ # Btrfs support for disk_space block. - (fetchpatch2 { - name = "disk_space: Support btrfs backend"; - url = "https://patch-diff.githubusercontent.com/raw/greshake/i3status-rust/pull/2159.patch"; - hash = "sha256-S2/biX6FTLJNfI9QVgwr+V8IGMRnSFIZnTrhc+1LvqQ="; - }) + ./patches/0001-disk_space-Support-btrfs-backend.patch # Correctly calculate the used memory. - (fetchpatch2 { - name = "memory: Avoid estimating available memory, use kernel estimate instead"; - url = "https://patch-diff.githubusercontent.com/raw/greshake/i3status-rust/pull/2160.patch"; - hash = "sha256-1wB2KpXhC/UIxAgRioOYj/bnrzRSuaHAdbeoZ2O5E/Y="; - }) + ./patches/0002-memory-Directly-convert-reported-memory-usage-into-b.patch + ./patches/0003-memory-Avoid-estimating-available-memory-use-kernel-.patch ]; }) diff --git a/pkgs/by-name/i3/i3status-rust-patched/patches/0001-disk_space-Support-btrfs-backend.patch b/pkgs/by-name/i3/i3status-rust-patched/patches/0001-disk_space-Support-btrfs-backend.patch new file mode 100644 index 00000000..8ef0af2e --- /dev/null +++ b/pkgs/by-name/i3/i3status-rust-patched/patches/0001-disk_space-Support-btrfs-backend.patch @@ -0,0 +1,190 @@ +From 78d2936b67064e3b5e700a2859d00ea3dd6eda4c Mon Sep 17 00:00:00 2001 +From: Benedikt Peetz <benedikt.peetz@b-peetz.de> +Date: Sun, 18 May 2025 20:22:04 +0200 +Subject: [PATCH 1/3] disk_space: Support btrfs backend + +Btrfs is too smart for the statvfs based backend (i.e., only counting +blocks leads to wrong numbers). + +For example, a btrfs disk with a lot of de-duplicated blocks (via the copy +on write mechanism) might have a drastically over-reported disk usage. + +The btrfs backend is currently implemented by parsing the output of the +`btrfs filesystem usage --raw` command. This is suboptimal, as this now +relies on the command output not changing. + +Vendoring the algorithm used internally by the `btrfs` command does not +seem to be a reasonable alternative, considering that the code[1] is +rather complex, low level and would require semi-constant maintenance. +Additionally, the c code would need bindings to be usable from rust. + +I assume, that the `btrfs` command output will stay rather similar in +the future, as a lot of tools rely on directly parsing it (see the +various scripts in the issue, this commit fixes). + +[1]: https://github.com/kdave/btrfs-progs/blob/eeab081e9d9fbdf4583122ed1caedf541383cf2d/cmds/filesystem-usage.c#L442 + +Fixes: #1654 +--- + src/blocks/disk_space.rs | 112 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 101 insertions(+), 11 deletions(-) + +diff --git a/src/blocks/disk_space.rs b/src/blocks/disk_space.rs +index 79bfebd27..da0d3f518 100644 +--- a/src/blocks/disk_space.rs ++++ b/src/blocks/disk_space.rs +@@ -12,6 +12,7 @@ + //! `alert` | A value which will trigger critical block state | `10.0` + //! `info_type` | Determines which information will affect the block state. Possible values are `"available"`, `"free"` and `"used"` | `"available"` + //! `alert_unit` | The unit of `alert` and `warning` options. If not set, percents are used. Possible values are `"B"`, `"KB"`, `"KiB"`, `"MB"`, `"MiB"`, `"GB"`, `"Gib"`, `"TB"` and `"TiB"` | `None` ++//! `backend` | The backend to use when querying disk usage. Possible values are `"vfs"` (like `du(1)`) and `"btrfs"` | `"vfs"` + //! + //! Placeholder | Value | Type | Unit + //! -------------|--------------------------------------------------------------------|--------|------- +@@ -63,9 +64,12 @@ + + // make_log_macro!(debug, "disk_space"); + ++use std::cell::OnceCell; ++ + use super::prelude::*; + use crate::formatting::prefix::Prefix; + use nix::sys::statvfs::statvfs; ++use tokio::process::Command; + + #[derive(Copy, Clone, Debug, Deserialize, SmartDefault)] + #[serde(rename_all = "lowercase")] +@@ -76,11 +80,20 @@ pub enum InfoType { + Used, + } + ++#[derive(Copy, Clone, Debug, Deserialize, SmartDefault)] ++#[serde(rename_all = "lowercase")] ++pub enum Backend { ++ #[default] ++ Vfs, ++ Btrfs, ++} ++ + #[derive(Deserialize, Debug, SmartDefault)] + #[serde(deny_unknown_fields, default)] + pub struct Config { + #[default("/".into())] + pub path: ShellString, ++ pub backend: Backend, + pub info_type: InfoType, + pub format: FormatConfig, + pub format_alt: Option<FormatConfig>, +@@ -128,17 +141,9 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + loop { + let mut widget = Widget::new().with_format(format.clone()); + +- let statvfs = statvfs(&*path).error("failed to retrieve statvfs")?; +- +- // Casting to be compatible with 32-bit systems +- #[allow(clippy::unnecessary_cast)] +- let (total, used, available, free) = { +- let total = (statvfs.blocks() as u64) * (statvfs.fragment_size() as u64); +- let used = ((statvfs.blocks() as u64) - (statvfs.blocks_free() as u64)) +- * (statvfs.fragment_size() as u64); +- let available = (statvfs.blocks_available() as u64) * (statvfs.block_size() as u64); +- let free = (statvfs.blocks_free() as u64) * (statvfs.block_size() as u64); +- (total, used, available, free) ++ let (total, used, available, free) = match config.backend { ++ Backend::Vfs => get_vfs(&*path)?, ++ Backend::Btrfs => get_btrfs(&path).await?, + }; + + let result = match config.info_type { +@@ -205,3 +210,88 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + } + } + } ++ ++fn get_vfs<P>(path: &P) -> Result<(u64, u64, u64, u64)> ++where ++ P: ?Sized + nix::NixPath, ++{ ++ let statvfs = statvfs(path).error("failed to retrieve statvfs")?; ++ ++ // Casting to be compatible with 32-bit systems ++ #[allow(clippy::unnecessary_cast)] ++ { ++ let total = (statvfs.blocks() as u64) * (statvfs.fragment_size() as u64); ++ let used = ((statvfs.blocks() as u64) - (statvfs.blocks_free() as u64)) ++ * (statvfs.fragment_size() as u64); ++ let available = (statvfs.blocks_available() as u64) * (statvfs.block_size() as u64); ++ let free = (statvfs.blocks_free() as u64) * (statvfs.block_size() as u64); ++ ++ Ok((total, used, available, free)) ++ } ++} ++ ++async fn get_btrfs(path: &str) -> Result<(u64, u64, u64, u64)> { ++ const OUTPUT_CHANGED: &str = "Btrfs filesystem usage output format changed"; ++ ++ fn remove_estimate_min(estimate_str: &str) -> Result<&str> { ++ estimate_str.trim_matches('\t') ++ .split_once("\t") ++ .ok_or(Error::new(OUTPUT_CHANGED)) ++ .map(|v| v.0) ++ } ++ ++ macro_rules! get { ++ ($source:expr, $name:expr, $variable:ident) => { ++ get!(@pre_op (|a| {Ok::<_, Error>(a)}), $source, $name, $variable) ++ }; ++ (@pre_op $function:expr, $source:expr, $name:expr, $variable:ident) => { ++ if $source.starts_with(concat!($name, ":")) { ++ let (found_name, variable_str) = ++ $source.split_once(":").ok_or(Error::new(OUTPUT_CHANGED))?; ++ ++ let variable_str = $function(variable_str)?; ++ ++ debug_assert_eq!(found_name, $name); ++ $variable ++ .set(variable_str.trim().parse().error(OUTPUT_CHANGED)?) ++ .map_err(|_| Error::new(OUTPUT_CHANGED))?; ++ } ++ }; ++ } ++ ++ let filesystem_usage = Command::new("btrfs") ++ .args(["filesystem", "usage", "--raw", path]) ++ .output() ++ .await ++ .error("Failed to collect btrfs filesystem usage info")? ++ .stdout; ++ ++ { ++ let final_total = OnceCell::new(); ++ let final_used = OnceCell::new(); ++ let final_free = OnceCell::new(); ++ ++ let mut lines = filesystem_usage.lines(); ++ while let Some(line) = lines ++ .next_line() ++ .await ++ .error("Failed to read output of btrfs filesystem usage")? ++ { ++ let line = line.trim(); ++ ++ // See btrfs-filesystem(8) for an explanation for the rows. ++ get!(line, "Device size", final_total); ++ get!(line, "Used", final_used); ++ get!(@pre_op remove_estimate_min, line, "Free (estimated)", final_free); ++ } ++ ++ Ok(( ++ *final_total.get().ok_or(Error::new(OUTPUT_CHANGED))?, ++ *final_used.get().ok_or(Error::new(OUTPUT_CHANGED))?, ++ // HACK(@bpeetz): We also return the free disk space as the available one, because btrfs ++ // does not tell us which disk space is reserved for the fs. <2025-05-18> ++ *final_free.get().ok_or(Error::new(OUTPUT_CHANGED))?, ++ *final_free.get().ok_or(Error::new(OUTPUT_CHANGED))?, ++ )) ++ } ++} +-- +2.49.0 + diff --git a/pkgs/by-name/i3/i3status-rust-patched/patches/0002-memory-Directly-convert-reported-memory-usage-into-b.patch b/pkgs/by-name/i3/i3status-rust-patched/patches/0002-memory-Directly-convert-reported-memory-usage-into-b.patch new file mode 100644 index 00000000..00a50e92 --- /dev/null +++ b/pkgs/by-name/i3/i3status-rust-patched/patches/0002-memory-Directly-convert-reported-memory-usage-into-b.patch @@ -0,0 +1,117 @@ +From fccc34618103126d9374a5361a5870ccf8030fa0 Mon Sep 17 00:00:00 2001 +From: Benedikt Peetz <benedikt.peetz@b-peetz.de> +Date: Mon, 19 May 2025 21:26:57 +0200 +Subject: [PATCH 2/3] memory: Directly convert reported memory usage into bytes + +`/proc/meminfo` states that it's report values are in KB, when +they actually are in KiB. Previously, this inconsistency leaked into the +whole code for this block (which had to add `* 1024` after nearly every +assignment). Now this inconsistency is contained to the `Memstate` +structure. +--- + src/blocks/memory.rs | 53 +++++++++++++++++++++++--------------------- + 1 file changed, 28 insertions(+), 25 deletions(-) + +diff --git a/src/blocks/memory.rs b/src/blocks/memory.rs +index 801e61de0..8cf32f9ba 100644 +--- a/src/blocks/memory.rs ++++ b/src/blocks/memory.rs +@@ -112,8 +112,8 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + loop { + let mem_state = Memstate::new().await?; + +- let mem_total = mem_state.mem_total as f64 * 1024.; +- let mem_free = mem_state.mem_free as f64 * 1024.; ++ let mem_total = mem_state.mem_total as f64; ++ let mem_free = mem_state.mem_free as f64; + + // TODO: possibly remove this as it is confusing to have `mem_total_used` and `mem_used` + // htop and such only display equivalent of `mem_used` +@@ -126,8 +126,7 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + min(mem_state.mem_available, mem_state.mem_total) + } else { + mem_state.mem_free +- } as f64 +- * 1024.; ++ } as f64; + + // While zfs_arc_cache can be considered "available" memory, + // it can only free a maximum of (zfs_arc_cache - zfs_arc_min) amount. +@@ -137,14 +136,14 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + .saturating_sub(mem_state.zfs_arc_min) as f64; + let mem_avail = mem_avail + zfs_shrinkable_size; + +- let pagecache = mem_state.pagecache as f64 * 1024.; +- let reclaimable = mem_state.s_reclaimable as f64 * 1024.; +- let shmem = mem_state.shmem as f64 * 1024.; ++ let pagecache = mem_state.pagecache as f64; ++ let reclaimable = mem_state.s_reclaimable as f64; ++ let shmem = mem_state.shmem as f64; + + // See https://lore.kernel.org/lkml/1455827801-13082-1-git-send-email-hannes@cmpxchg.org/ + let cached = pagecache + reclaimable - shmem + zfs_shrinkable_size; + +- let buffers = mem_state.buffers as f64 * 1024.; ++ let buffers = mem_state.buffers as f64; + + // same logic as htop + let used_diff = mem_free + buffers + pagecache + reclaimable; +@@ -157,14 +156,14 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + // account for ZFS ARC cache + let mem_used = mem_used - zfs_shrinkable_size; + +- let swap_total = mem_state.swap_total as f64 * 1024.; +- let swap_free = mem_state.swap_free as f64 * 1024.; +- let swap_cached = mem_state.swap_cached as f64 * 1024.; ++ let swap_total = mem_state.swap_total as f64; ++ let swap_free = mem_state.swap_free as f64; ++ let swap_cached = mem_state.swap_cached as f64; + let swap_used = swap_total - swap_free - swap_cached; + + // Zswap usage +- let zswap_compressed = mem_state.zswap_compressed as f64 * 1024.; +- let zswap_decompressed = mem_state.zswap_decompressed as f64 * 1024.; ++ let zswap_compressed = mem_state.zswap_compressed as f64; ++ let zswap_decompressed = mem_state.zswap_decompressed as f64; + + let zswap_comp_ratio = if zswap_compressed != 0.0 { + zswap_decompressed / zswap_compressed +@@ -310,19 +309,23 @@ impl Memstate { + .and_then(|x| u64::from_str(x).ok()) + .error("failed to parse /proc/meminfo")?; + ++ // These values are reported as “kB” but are actually “kiB”. ++ // Convert them into bytes to avoid having to handle this later. ++ // Source: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo#s2-proc-meminfo ++ const KIB: u64 = 1024; + match name { +- "MemTotal:" => mem_state.mem_total = val, +- "MemFree:" => mem_state.mem_free = val, +- "MemAvailable:" => mem_state.mem_available = val, +- "Buffers:" => mem_state.buffers = val, +- "Cached:" => mem_state.pagecache = val, +- "SReclaimable:" => mem_state.s_reclaimable = val, +- "Shmem:" => mem_state.shmem = val, +- "SwapTotal:" => mem_state.swap_total = val, +- "SwapFree:" => mem_state.swap_free = val, +- "SwapCached:" => mem_state.swap_cached = val, +- "Zswap:" => mem_state.zswap_compressed = val, +- "Zswapped:" => mem_state.zswap_decompressed = val, ++ "MemTotal:" => mem_state.mem_total = val * KIB, ++ "MemFree:" => mem_state.mem_free = val * KIB, ++ "MemAvailable:" => mem_state.mem_available = val * KIB, ++ "Buffers:" => mem_state.buffers = val * KIB, ++ "Cached:" => mem_state.pagecache = val * KIB, ++ "SReclaimable:" => mem_state.s_reclaimable = val * KIB, ++ "Shmem:" => mem_state.shmem = val * KIB, ++ "SwapTotal:" => mem_state.swap_total = val * KIB, ++ "SwapFree:" => mem_state.swap_free = val * KIB, ++ "SwapCached:" => mem_state.swap_cached = val * KIB, ++ "Zswap:" => mem_state.zswap_compressed = val * KIB, ++ "Zswapped:" => mem_state.zswap_decompressed = val * KIB, + _ => (), + } + +-- +2.49.0 + diff --git a/pkgs/by-name/i3/i3status-rust-patched/patches/0003-memory-Avoid-estimating-available-memory-use-kernel-.patch b/pkgs/by-name/i3/i3status-rust-patched/patches/0003-memory-Avoid-estimating-available-memory-use-kernel-.patch new file mode 100644 index 00000000..8943796d --- /dev/null +++ b/pkgs/by-name/i3/i3status-rust-patched/patches/0003-memory-Avoid-estimating-available-memory-use-kernel-.patch @@ -0,0 +1,49 @@ +From b7ae3bd9672e7e1a3fc8e75d90b5bcbe75e6febf Mon Sep 17 00:00:00 2001 +From: Benedikt Peetz <benedikt.peetz@b-peetz.de> +Date: Mon, 19 May 2025 21:29:54 +0200 +Subject: [PATCH 3/3] memory: Avoid estimating available memory, use kernel + estimate instead + +`free`, `btop` and other tools (like the `sysinfo` rust library) +use `mem_total - mem_avail` to calculate the used memory. As explained +in the already linked [kernel commit][1], `mem_avail` is an estimate of +the available memory based on the current way the kernel handles +memory. + +The previous logic for calculating used memory tried to estimate +this based on `mem_free`, `buffers`, `pagecache` and +`reclaimable`. Unfortunately, as the kernel commit message predicts, +this user space estimate bitrots, as the kernel memory usage patterns change. + +Thus, we now simply use the kernel estimate `mem_avail` as we know that +that is in-sync with the relevant kernel internals. + +[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 +--- + src/blocks/memory.rs | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/src/blocks/memory.rs b/src/blocks/memory.rs +index 8cf32f9ba..94d8a5fe3 100644 +--- a/src/blocks/memory.rs ++++ b/src/blocks/memory.rs +@@ -145,13 +145,9 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + + let buffers = mem_state.buffers as f64; + +- // same logic as htop +- let used_diff = mem_free + buffers + pagecache + reclaimable; +- let mem_used = if mem_total >= used_diff { +- mem_total - used_diff +- } else { +- mem_total - mem_free +- }; ++ // Userspace should use `mem_avail` for estimating the memory that is available. ++ // See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 ++ let mem_used = mem_total - mem_avail; + + // account for ZFS ARC cache + let mem_used = mem_used - zfs_shrinkable_size; +-- +2.49.0 + |
