kanit

Toy init system
Log | Files | Refs | README | LICENSE

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 }