rootfs.rs (1659B)
1 use async_trait::async_trait; 2 use blocking::unblock; 3 use log::{info, warn}; 4 use nix::mount::{MsFlags, mount}; 5 use nix::unistd::{AccessFlags, access}; 6 7 use kanit_common::error::{Context, ErrorKind, Result}; 8 use kanit_executor::join_all; 9 use kanit_unit::{Dependencies, Unit}; 10 11 use crate::mounts::{MountAction, MountEntry, is_fs_mounted, parse_mounts}; 12 use crate::oneshot::Clock; 13 use crate::unit_name; 14 15 pub struct RootFs; 16 17 async fn remount_entry(entry: MountEntry<'_>) -> Result<()> { 18 if is_fs_mounted(entry.fs_file).await? && !entry.mount(MountAction::Remount).await? { 19 warn!("failed to remount {}", entry.fs_file); 20 } 21 22 Ok(()) 23 } 24 25 #[async_trait] 26 impl Unit for RootFs { 27 unit_name!("rootfs"); 28 29 fn dependencies(&self) -> Dependencies { 30 Dependencies::new().after(Clock.name()).clone() 31 } 32 33 async fn start(&mut self) -> Result<()> { 34 if access("/", AccessFlags::W_OK).is_ok() { 35 return Ok(()); // rootfs already writable 36 } 37 38 info!("remounting rootfs as rw"); 39 40 unblock(move || { 41 mount( 42 Some(""), // ignored in remount 43 "/", 44 Some(""), 45 MsFlags::MS_REMOUNT, 46 Some("rw"), 47 ) 48 }) 49 .await 50 .context("failed to remount rootfs")?; 51 52 info!("remounting filesystems"); 53 54 let fstab = async_fs::read_to_string("/etc/fstab") 55 .await 56 .context_kind("failed to read fstab", ErrorKind::Recoverable)?; 57 58 // TODO; leak probably bad 59 join_all(parse_mounts(fstab.leak())?.into_iter().map(remount_entry)).await; 60 61 Ok(()) 62 } 63 }