ksud: allow to set upperdir and workdir for overlayfs

This commit is contained in:
weishu
2024-02-01 18:02:10 +08:00
parent aca505c3e6
commit 9f04482b90
3 changed files with 48 additions and 12 deletions

View File

@@ -25,6 +25,8 @@ pub const MODULE_UPDATE_TMP_IMG: &str = concatcp!(WORKING_DIR, "update_tmp.img")
// warning: this directory should not change, or you need to change the code in module_installer.sh!!! // warning: this directory should not change, or you need to change the code in module_installer.sh!!!
pub const MODULE_UPDATE_TMP_DIR: &str = concatcp!(ADB_DIR, "modules_update/"); pub const MODULE_UPDATE_TMP_DIR: &str = concatcp!(ADB_DIR, "modules_update/");
pub const SYSTEM_RW_DIR: &str = concatcp!(MODULE_DIR, ".rw/");
pub const TEMP_DIR: &str = "/debug_ramdisk"; pub const TEMP_DIR: &str = "/debug_ramdisk";
pub const TEMP_DIR_LEGACY: &str = "/sbin"; pub const TEMP_DIR_LEGACY: &str = "/sbin";

View File

@@ -10,13 +10,13 @@ use crate::{
utils::{self, ensure_clean_dir, ensure_dir_exists}, utils::{self, ensure_clean_dir, ensure_dir_exists},
}; };
fn mount_partition(partition: &str, lowerdir: &Vec<String>) -> Result<()> { fn mount_partition(partition_name: &str, lowerdir: &Vec<String>) -> Result<()> {
if lowerdir.is_empty() { if lowerdir.is_empty() {
warn!("partition: {partition} lowerdir is empty"); warn!("partition: {partition_name} lowerdir is empty");
return Ok(()); return Ok(());
} }
let partition = format!("/{partition}"); let partition = format!("/{partition_name}");
// if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately // if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately
if Path::new(&partition).read_link().is_ok() { if Path::new(&partition).read_link().is_ok() {
@@ -24,7 +24,15 @@ fn mount_partition(partition: &str, lowerdir: &Vec<String>) -> Result<()> {
return Ok(()); return Ok(());
} }
mount::mount_overlay(&partition, lowerdir) let mut workdir = None;
let mut upperdir = None;
let system_rw_dir = Path::new(defs::SYSTEM_RW_DIR);
if system_rw_dir.exists() {
workdir = Some(system_rw_dir.join(partition_name).join("workdir"));
upperdir = Some(system_rw_dir.join(partition_name).join("upperdir"));
}
mount::mount_overlay(&partition, lowerdir, workdir, upperdir)
} }
pub fn mount_systemlessly(module_dir: &str) -> Result<()> { pub fn mount_systemlessly(module_dir: &str) -> Result<()> {

View File

@@ -11,6 +11,7 @@ use log::{info, warn};
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use procfs::process::Process; use procfs::process::Process;
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
pub struct AutoMountExt4 { pub struct AutoMountExt4 {
target: String, target: String,
@@ -81,7 +82,13 @@ pub fn umount_dir(src: impl AsRef<Path>) -> Result<()> {
} }
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlayfs(lower_dirs: &[String], lowest: &str, dest: impl AsRef<Path>) -> Result<()> { pub fn mount_overlayfs(
lower_dirs: &[String],
lowest: &str,
upperdir: Option<PathBuf>,
workdir: Option<PathBuf>,
dest: impl AsRef<Path>,
) -> Result<()> {
let lowerdir_config = lower_dirs let lowerdir_config = lower_dirs
.iter() .iter()
.map(|s| s.as_ref()) .map(|s| s.as_ref())
@@ -89,13 +96,21 @@ pub fn mount_overlayfs(lower_dirs: &[String], lowest: &str, dest: impl AsRef<Pat
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(":"); .join(":");
info!( info!(
"mount overlayfs on {}, options={}", "mount overlayfs on {:?}, lowerdir={}, upperdir={:?}, workdir={:?}",
dest.as_ref().display(), dest.as_ref(),
lowerdir_config lowerdir_config,
upperdir,
workdir
); );
let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?; let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?;
let fs = fs.as_fd(); let fs = fs.as_fd();
fsconfig_set_string(fs, "lowerdir", lowerdir_config)?; fsconfig_set_string(fs, "lowerdir", lowerdir_config)?;
if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) {
if upperdir.exists() && workdir.exists() {
fsconfig_set_string(fs, "upperdir", upperdir.display().to_string())?;
fsconfig_set_string(fs, "workdir", workdir.display().to_string())?;
}
}
fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
fsconfig_create(fs)?; fsconfig_create(fs)?;
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
@@ -180,7 +195,7 @@ fn mount_overlay_child(
return Ok(()); return Ok(());
} }
// merge modules and stock // merge modules and stock
if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, mount_point) { if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) {
warn!("failed: {:#}, fallback to bind mount", e); warn!("failed: {:#}, fallback to bind mount", e);
bind_mount(stock_root, mount_point)?; bind_mount(stock_root, mount_point)?;
} }
@@ -188,7 +203,12 @@ fn mount_overlay_child(
} }
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlay(root: &String, module_roots: &Vec<String>) -> Result<()> { pub fn mount_overlay(
root: &String,
module_roots: &Vec<String>,
workdir: Option<PathBuf>,
upperdir: Option<PathBuf>,
) -> Result<()> {
info!("mount overlay for {}", root); info!("mount overlay for {}", root);
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?; std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
let stock_root = "."; let stock_root = ".";
@@ -208,7 +228,8 @@ pub fn mount_overlay(root: &String, module_roots: &Vec<String>) -> Result<()> {
mount_seq.sort(); mount_seq.sort();
mount_seq.dedup(); mount_seq.dedup();
mount_overlayfs(module_roots, root, root).with_context(|| "mount overlayfs for root failed")?; mount_overlayfs(module_roots, root, upperdir, workdir, root)
.with_context(|| "mount overlayfs for root failed")?;
for mount_point in mount_seq.iter() { for mount_point in mount_seq.iter() {
let Some(mount_point) = mount_point else { let Some(mount_point) = mount_point else {
continue; continue;
@@ -241,7 +262,12 @@ pub fn umount_dir(_src: &str) -> Result<()> {
} }
#[cfg(not(any(target_os = "linux", target_os = "android")))] #[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn mount_overlay(_dest: &String, _lower_dirs: &Vec<String>) -> Result<()> { pub fn mount_overlay(
_root: &String,
_module_roots: &Vec<String>,
_workdir: Option<PathBuf>,
_upperdir: Option<PathBuf>,
) -> Result<()> {
unimplemented!() unimplemented!()
} }