Skip to content

Commit

Permalink
generator: call modprobe for compression modules
Browse files Browse the repository at this point in the history
Apparently the kernel sometimes doesn't load the appropriate
compression algorithm (see systemd#50, systemd#53). Let's do an explicit modprobe
call, similarly to what we do for the zram module itself.

The operation is minimalistic, and we only load the modules for algs
that were explicitly configured (on the assumption that the default
alg has to be loaded already), and not known to the kernel.

Hopefully fixes systemd#53.
  • Loading branch information
keszybz committed Jan 13, 2021
1 parent 32a5c2f commit cd44ae6
Showing 1 changed file with 63 additions and 0 deletions.
63 changes: 63 additions & 0 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::config::Device;
use anyhow::{anyhow, Context, Result};
use log::{info, warn};
use std::cmp;
use std::collections::HashSet;
use std::fs;
use std::os::unix::fs::symlink;
use std::path::Path;
Expand Down Expand Up @@ -90,6 +91,31 @@ pub fn run_generator(devices: &[Device], output_directory: &Path, fake_mode: boo
< max_device
{}
}

let compressions: Vec<&String> = devices
.iter()
.filter(|device| !device.compression_algorithm.is_none())
.map(|device| device.compression_algorithm.as_ref().unwrap())
.collect::<HashSet<_>>()
.into_iter()
.collect();

if !compressions.is_empty() {
let known = get_known_compressions(None)?;

for compression in compressions.into_iter().filter(|c| !known.contains(c)) {
let status = Command::new("modprobe")
.arg(format!("crypto-{}", compression))
.status()
.context("Failed to spawn modprobe")?;
if !status.success() {
warn!(
"modprobe crypt-{} failed, ignoring: code {}",
compression, status
);
}
}
}
}

Ok(())
Expand Down Expand Up @@ -245,3 +271,40 @@ Where={mount_point:?}

Ok(())
}

fn get_known_compressions(path: Option<&Path>) -> Result<Vec<String>> {
let path = path.unwrap_or(Path::new("/sys/block/zram0/comp_algorithm"));

let content = fs::read_to_string(path).with_context(|| format!("Failed to read {:?}", path))?;
Ok(content
.split_whitespace()
.map(|e| {
if e.starts_with("[") && e.ends_with("]") {
e[1..e.len() - 1].to_string()
} else {
e.to_string()
}
})
.collect())
}

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

#[test]
fn test_get_known_compressions() {
let mut file = tempfile::NamedTempFile::new().unwrap();

file.write(
b"\
lzo [lzo-rle] lz4 lz4hc 842 zstd
",
)
.unwrap();
file.flush().unwrap();
let ans = get_known_compressions(Some(file.path())).unwrap();
assert_eq!(ans, ["lzo", "lzo-rle", "lz4", "lz4hc", "842", "zstd"]);
}
}

0 comments on commit cd44ae6

Please sign in to comment.