factorize mounting read-only filesystems (squashfs, erofs)

This commit is contained in:
Mikaël Cluseau
2026-06-11 11:35:50 +02:00
parent ee03452591
commit ee0ff1373f
4 changed files with 40 additions and 28 deletions
+3 -3
View File
@@ -16,8 +16,8 @@ mkdir -p tmp/dl $dist
linux=tmp/dl/linux-$linux_v linux=tmp/dl/linux-$linux_v
modules=tmp/dl/modules-$linux_v modules=tmp/dl/modules-$linux_v
[ -e $linux ] || curl -o $linux https://dkl.novit.io/dist/kernels/6.18.34 [ -e $linux ] || curl -o $linux https://dkl.novit.io/dist/kernels/6.18.35
[ -e $modules ] || curl -o $modules https://dkl.novit.io/dist/layers/modules/6.18.34 # TODO .erofs [ -e $modules ] || curl -o $modules https://dkl.novit.io/dist/layers/modules/6.18.35.erofs
rm -fr $dir rm -fr $dir
mkdir $dir mkdir $dir
@@ -36,7 +36,7 @@ mv $dir.cpio.zst $dist/initrd
cp $linux $dist/vmlinuz cp $linux $dist/vmlinuz
ukify build --output $uki --os-release "Direktil DHCP" \ ukify build --output $uki --os-release "Direktil DHCP" \
--linux $linux --initrd $dist/initrd --cmdline "console=tty0 console=ttyS0,115200" --linux $linux --initrd $dist/initrd
MB=$(( 2**20 )) MB=$(( 2**20 ))
sz=$(( ( $(stat -c %s $uki) + MB ) / MB + 2 )) sz=$(( ( $(stat -c %s $uki) + MB ) / MB + 2 ))
+1 -1
View File
@@ -21,7 +21,7 @@ networks:
ip li set lo up ip li set lo up
- name: main - name: main
interfaces: interfaces:
- var: iface - var: ifaces
n: -1 n: -1
udev: !has ID_NET_NAME_MAC udev: !has ID_NET_NAME_MAC
script: | script: |
+33 -3
View File
@@ -4,7 +4,7 @@ use std::collections::BTreeSet as Set;
use std::convert::Infallible; use std::convert::Infallible;
use std::os::unix::fs::symlink; use std::os::unix::fs::symlink;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio::{fs, process::Command}; use tokio::{fs, io::AsyncReadExt, process::Command};
use crate::{cmd::version::version_string, dklog, input, utils}; use crate::{cmd::version::version_string, dklog, input, utils};
use dkl::bootstrap::Config; use dkl::bootstrap::Config;
@@ -154,7 +154,8 @@ use std::path::Path;
async fn mount_modules(modules: &str, kernel_version: &str) -> Result<()> { async fn mount_modules(modules: &str, kernel_version: &str) -> Result<()> {
info!("mounting modules"); info!("mounting modules");
mount(Some(modules), "/modules", "squashfs", None).await;
mount_ro_fs(modules, "/modules").await?;
fs::create_dir_all("/lib/modules").await?; fs::create_dir_all("/lib/modules").await?;
let modules_path = &format!("/modules/lib/modules/{kernel_version}"); let modules_path = &format!("/modules/lib/modules/{kernel_version}");
@@ -243,6 +244,35 @@ async fn mount<S: AsRef<Path>>(
.await .await
} }
async fn mount_ro_fs(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
let src = src.as_ref();
let dst = dst.as_ref();
// identify RO fs type
let mut buf = [0u8; 1028];
fs::File::open(src)
.await
.map_err(|e| format_err!("open {}: {e}", src.display()))?
.read_exact(&mut buf)
.await
.map_err(|e| format_err!("read {}: {e}", src.display()))?;
let fstype = if buf[1024..1028] == 0xE0F5E1E2u32.to_le_bytes() {
"erofs"
} else {
"squashfs"
};
if let Err(e) = fs::create_dir_all(dst).await {
error!("failed to create dir {dst}: {e}", dst = dst.display());
}
let mut cmd = Command::new("mount");
cmd.args(["-t", fstype]).arg(src).arg(dst);
try_exec_cmd(cmd).await
}
async fn start_daemon(prog: &str, args: &[&str]) { async fn start_daemon(prog: &str, args: &[&str]) {
let (cmd_str, mut cmd) = cmd_str(prog, args); let (cmd_str, mut cmd) = cmd_str(prog, args);
retry_or_ignore(async || { retry_or_ignore(async || {
@@ -253,7 +283,7 @@ async fn start_daemon(prog: &str, args: &[&str]) {
.await; .await;
} }
async fn try_exec_cmd(mut cmd: tokio::process::Command) -> Result<()> { async fn try_exec_cmd(mut cmd: Command) -> Result<()> {
info!( info!(
"# {} {}", "# {} {}",
cmd.as_std().get_program().to_string_lossy(), cmd.as_std().get_program().to_string_lossy(),
+3 -21
View File
@@ -3,7 +3,7 @@ use log::{debug, info, warn};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tokio::{ use tokio::{
fs, fs,
io::{AsyncBufReadExt, AsyncReadExt, AsyncWrite, AsyncWriteExt, BufReader}, io::{AsyncBufReadExt, AsyncWrite, AsyncWriteExt, BufReader},
}; };
use dkl::{ use dkl::{
@@ -13,7 +13,7 @@ use dkl::{
bootstrap::Config, bootstrap::Config,
}; };
use super::{exec, mount, retry, retry_or_ignore, try_exec, try_exec_cmd}; use super::{exec, mount, mount_ro_fs, retry, retry_or_ignore, try_exec, try_exec_cmd};
use crate::{fs::walk_dir, utils}; use crate::{fs::walk_dir, utils};
pub async fn bootstrap(cfg: Config) { pub async fn bootstrap(cfg: Config) {
@@ -340,25 +340,7 @@ impl LayerMounter<'_> {
.await .await
}; };
retry(async || { retry(async || mount_ro_fs(&mount_src, &tgt_dir).await).await;
let mut buf = [0u8; 1028];
fs::File::open(&mount_src)
.await
.map_err(|e| format_err!("open {}: {e}", mount_src.display()))?
.read_exact(&mut buf)
.await
.map_err(|e| format_err!("read {}: {e}", mount_src.display()))?;
let fstype = if buf[1024..1028] == 0xE0F5E1E2u32.to_le_bytes() {
"erofs"
} else {
"squashfs"
};
mount(Some(&mount_src), &tgt_dir, fstype, None).await;
Ok(())
})
.await;
if !self.lower_dir.is_empty() { if !self.lower_dir.is_empty() {
self.lower_dir.push(':'); self.lower_dir.push(':');