Use new mount api

This commit is contained in:
LoveSy
2024-02-01 00:22:25 +08:00
parent c1a2cbf1e4
commit 4d4bd4793f
4 changed files with 62 additions and 148 deletions

View File

@@ -853,6 +853,7 @@ dependencies = [
"jwalk", "jwalk",
"libc", "libc",
"log", "log",
"loopdev",
"nom", "nom",
"procfs", "procfs",
"regex", "regex",
@@ -862,7 +863,6 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha256", "sha256",
"sys-mount",
"tempdir", "tempdir",
"which", "which",
"zip 0.6.4", "zip 0.6.4",
@@ -1463,17 +1463,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "smart-default"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@@ -1508,19 +1497,6 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "sys-mount"
version = "2.0.2"
source = "git+https://github.com/tiann/sys-mount?branch=loopfix#c7c4048e4a4ffdf8b108a85956363a75f2c554f0"
dependencies = [
"bitflags 1.3.2",
"libc",
"loopdev",
"smart-default",
"thiserror",
"tracing",
]
[[package]] [[package]]
name = "tempdir" name = "tempdir"
version = "0.3.7" version = "0.3.7"
@@ -1599,37 +1575,6 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.16.0" version = "1.16.0"

View File

@@ -39,11 +39,11 @@ chrono = "0.4"
hole-punch = { git = "https://github.com/tiann/hole-punch" } hole-punch = { git = "https://github.com/tiann/hole-punch" }
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
sys-mount = { git = "https://github.com/tiann/sys-mount", branch = "loopfix" }
rustix = { version = "0.38", features = ["all-apis"] } rustix = { version = "0.38", features = ["all-apis"] }
# some android specific dependencies which compiles under unix are also listed here for convenience of coding # some android specific dependencies which compiles under unix are also listed here for convenience of coding
android-properties = { version = "0.2.2", features = ["bionic-deprecated"] } android-properties = { version = "0.2.2", features = ["bionic-deprecated"] }
procfs = "0.16" procfs = "0.16"
loopdev = { git = "https://github.com/tiann/loopdev", branch = "loopfix" }
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13" android_logger = "0.13"

View File

@@ -1,5 +1,7 @@
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use log::{info, warn}; use log::{info, warn};
#[cfg(target_os = "android")]
use std::path::PathBuf;
use std::{collections::HashMap, path::Path}; use std::{collections::HashMap, path::Path};
use crate::module::prune_modules; use crate::module::prune_modules;

View File

@@ -1,11 +1,11 @@
use anyhow::{bail, Ok, Result}; use anyhow::{anyhow, bail, Ok, Result};
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use anyhow::Context; use anyhow::Context;
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use retry::delay::NoDelay; use retry::delay::NoDelay;
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use sys_mount::{unmount, FilesystemType, Mount, MountFlags, Unmount, UnmountFlags}; use rustix::{fd::AsFd, fs::CWD, mount::*};
use crate::defs::KSU_OVERLAY_SOURCE; use crate::defs::KSU_OVERLAY_SOURCE;
use log::{info, warn}; use log::{info, warn};
@@ -14,49 +14,32 @@ use procfs::process::Process;
use std::path::Path; use std::path::Path;
pub struct AutoMountExt4 { pub struct AutoMountExt4 {
mnt: String, target: String,
#[cfg(any(target_os = "linux", target_os = "android"))]
mount: Option<Mount>,
auto_umount: bool, auto_umount: bool,
} }
impl AutoMountExt4 { impl AutoMountExt4 {
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub fn try_new(src: &str, mnt: &str, auto_umount: bool) -> Result<Self> { pub fn try_new(source: &str, target: &str, auto_umount: bool) -> Result<Self> {
let result = Mount::builder() let new_loopback = loopdev::LoopControl::open()?.next_free()?;
.fstype(FilesystemType::from("ext4")) new_loopback.with().attach(source)?;
.flags(MountFlags::empty()) let lo = new_loopback.path().ok_or(anyhow!("no loop"))?;
.create_loop(true) let fs = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC)?;
.mount(src, mnt) let fs = fs.as_fd();
.map(|mount| { fsconfig_set_string(fs, "source", lo)?;
Ok(Self { fsconfig_create(fs)?;
mnt: mnt.to_string(), let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
mount: Some(mount), move_mount(
auto_umount, mount.as_fd(),
}) "",
}); CWD,
if let Err(e) = result { target,
println!("- Mount failed: {e}, retry with system mount"); MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
let result = std::process::Command::new("mount") )?;
.arg("-t") Ok(Self {
.arg("ext4") target: target.to_string(),
.arg(src) auto_umount,
.arg(mnt) })
.status();
if let Err(e) = result {
Err(anyhow::anyhow!(
"mount partition: {src} -> {mnt} failed: {e}"
))
} else {
Ok(Self {
mnt: mnt.to_string(),
mount: None,
auto_umount,
})
}
} else {
result.unwrap()
}
} }
#[cfg(not(any(target_os = "linux", target_os = "android")))] #[cfg(not(any(target_os = "linux", target_os = "android")))]
@@ -66,18 +49,8 @@ impl AutoMountExt4 {
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub fn umount(&self) -> Result<()> { pub fn umount(&self) -> Result<()> {
if let Some(ref mount) = self.mount { unmount(self.target.as_str(), UnmountFlags::DETACH)?;
mount Ok(())
.unmount(UnmountFlags::empty())
.map_err(|e| anyhow::anyhow!(e))
} else {
let result = std::process::Command::new("umount").arg(&self.mnt).status();
if let Err(e) = result {
Err(anyhow::anyhow!("umount: {} failed: {e}", self.mnt))
} else {
Ok(())
}
}
} }
} }
@@ -86,7 +59,7 @@ impl Drop for AutoMountExt4 {
fn drop(&mut self) { fn drop(&mut self) {
log::info!( log::info!(
"AutoMountExt4 drop: {}, auto_umount: {}", "AutoMountExt4 drop: {}, auto_umount: {}",
self.mnt, self.target,
self.auto_umount self.auto_umount
); );
if self.auto_umount { if self.auto_umount {
@@ -98,18 +71,7 @@ impl Drop for AutoMountExt4 {
#[allow(dead_code)] #[allow(dead_code)]
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
fn mount_image(src: &str, target: &str, autodrop: bool) -> Result<()> { fn mount_image(src: &str, target: &str, autodrop: bool) -> Result<()> {
if autodrop { AutoMountExt4::try_new(src, target, autodrop)?;
Mount::builder()
.fstype(FilesystemType::from("ext4"))
.create_loop(true)
.mount_autodrop(src, target, UnmountFlags::empty())
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
} else {
Mount::builder()
.fstype(FilesystemType::from("ext4"))
.mount(src, target)
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
}
Ok(()) Ok(())
} }
@@ -146,28 +108,37 @@ fn mount_overlayfs(
dest.as_ref().display(), dest.as_ref().display(),
options options
); );
Mount::builder() let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?;
.fstype(FilesystemType::from("overlay")) let fs = fs.as_fd();
.data(&options) fsconfig_set_string(fs, "lowerdir", lower_dirs.join(":"))?;
.flags(MountFlags::RDONLY) fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
.mount(KSU_OVERLAY_SOURCE, dest.as_ref()) fsconfig_create(fs)?;
.with_context(|| { let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
format!( move_mount(
"mount overlayfs on {} options {} failed", mount.as_fd(),
dest.as_ref().display(), "",
options CWD,
) dest.as_ref(),
})?; MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
)?;
Ok(()) Ok(())
} }
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_tmpfs(dest: impl AsRef<Path>) -> Result<()> { pub fn mount_tmpfs(dest: impl AsRef<Path>) -> Result<()> {
info!("mount tmpfs on {}", dest.as_ref().display()); info!("mount tmpfs on {}", dest.as_ref().display());
Mount::builder() let fs = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC)?;
.fstype(FilesystemType::from("tmpfs")) let fs = fs.as_fd();
.mount(KSU_OVERLAY_SOURCE, dest.as_ref()) fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
.with_context(|| format!("mount tmpfs on {} failed", dest.as_ref().display()))?; fsconfig_create(fs)?;
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
move_mount(
mount.as_fd(),
"",
CWD,
dest.as_ref(),
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
)?;
Ok(()) Ok(())
} }
@@ -178,16 +149,12 @@ fn bind_mount(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
from.as_ref().display(), from.as_ref().display(),
to.as_ref().display() to.as_ref().display()
); );
Mount::builder() let tree = open_tree(
.flags(MountFlags::BIND) CWD,
.mount(from.as_ref(), to.as_ref()) from.as_ref(),
.with_context(|| { OpenTreeFlags::OPEN_TREE_CLOEXEC | OpenTreeFlags::OPEN_TREE_CLONE,
format!( )?;
"bind mount failed: {} -> {}", move_mount(tree.as_fd(), "", CWD, to.as_ref(), MoveMountFlags::empty())?;
from.as_ref().display(),
to.as_ref().display()
)
})?;
Ok(()) Ok(())
} }