0.2.37 - add support for fast install
This commit is contained in:
Generated
+2
-1
@@ -1685,7 +1685,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_installer"
|
||||
version = "0.2.36"
|
||||
version = "0.2.37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arg_parser",
|
||||
@@ -1694,6 +1694,7 @@ dependencies = [
|
||||
"fscommon",
|
||||
"gpt",
|
||||
"libc",
|
||||
"libredox",
|
||||
"pkgar",
|
||||
"pkgar-core",
|
||||
"pkgar-keys",
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "redox_installer"
|
||||
version = "0.2.36"
|
||||
version = "0.2.37"
|
||||
description = "A Redox filesystem builder"
|
||||
license = "MIT"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
@@ -32,6 +32,7 @@ fatfs = "0.3.0"
|
||||
fscommon = "0.1.1"
|
||||
gpt = "3.0.0"
|
||||
libc = "0.2.70"
|
||||
libredox = "0.1"
|
||||
pkgar = "0.1.17"
|
||||
pkgar-core = "0.1.17"
|
||||
pkgar-keys = "0.1.17"
|
||||
|
||||
+61
-34
@@ -1,9 +1,10 @@
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use pkgar::{ext::EntryExt, PackageHead};
|
||||
use pkgar_core::PackageSrc;
|
||||
use pkgar_keys::PublicKeyFile;
|
||||
use redox_installer::{with_whole_disk, Config, DiskOption};
|
||||
use redox_installer::{try_fast_install, with_redoxfs_mount, with_whole_disk, Config, DiskOption};
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
io::{self, Read, Write},
|
||||
@@ -279,6 +280,8 @@ fn main() {
|
||||
|
||||
let password_opt = choose_password();
|
||||
|
||||
let instant = std::time::Instant::now();
|
||||
|
||||
let bootloader_bios = {
|
||||
let path = root_path.join("boot").join("bootloader.bios");
|
||||
if path.exists() {
|
||||
@@ -316,45 +319,69 @@ fn main() {
|
||||
efi_partition_size: None,
|
||||
skip_partitions: false, // TODO?
|
||||
};
|
||||
let res = with_whole_disk(&disk_path, &disk_option, |mount_path| -> Result<()> {
|
||||
let mut config: Config = Config::from_file(&root_path.join("filesystem.toml"))?;
|
||||
|
||||
// Copy filesystem.toml, which is not packaged
|
||||
let mut files = vec!["filesystem.toml".to_string()];
|
||||
|
||||
// Copy files from locally installed packages
|
||||
package_files(&root_path, &mut config, &mut files)
|
||||
// TODO: implement Error trait
|
||||
.map_err(|err| anyhow!("failed to read package files: {err}"))?;
|
||||
|
||||
// Perform config install (after packages have been converted to files)
|
||||
eprintln!("configuring system");
|
||||
let cookbook: Option<&'static str> = None;
|
||||
redox_installer::install_dir(config, mount_path, cookbook)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
|
||||
|
||||
// Sort and remove duplicates
|
||||
files.sort();
|
||||
files.dedup();
|
||||
|
||||
// Install files
|
||||
let mut buf = vec![0; 4 * MIB as usize];
|
||||
for (i, name) in files.iter().enumerate() {
|
||||
eprintln!("copy {} [{}/{}]", name, i, files.len());
|
||||
|
||||
let src = root_path.join(name);
|
||||
let dest = mount_path.join(name);
|
||||
copy_file(&src, &dest, &mut buf)?;
|
||||
let res = with_whole_disk(&disk_path, &disk_option, |mut fs| {
|
||||
// Fast install method via filesystem clone
|
||||
let mut last_percent = 0;
|
||||
if try_fast_install(&mut fs, move |used, used_old| {
|
||||
let percent = (used * 100) / used_old;
|
||||
if percent != last_percent {
|
||||
eprint!(
|
||||
"\r{}%: {} MB/{} MB",
|
||||
percent,
|
||||
used / 1000 / 1000,
|
||||
used_old / 1000 / 1000
|
||||
);
|
||||
last_percent = percent;
|
||||
}
|
||||
})? {
|
||||
eprintln!("\rfinished installing using fast mode");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
eprintln!("finished installing, unmounting filesystem");
|
||||
// Slow install method via file copy
|
||||
with_redoxfs_mount(fs, |mount_path| {
|
||||
let mut config: Config = Config::from_file(&root_path.join("filesystem.toml"))?;
|
||||
|
||||
Ok(())
|
||||
// Copy filesystem.toml, which is not packaged
|
||||
let mut files = vec!["filesystem.toml".to_string()];
|
||||
|
||||
// Copy files from locally installed packages
|
||||
package_files(&root_path, &mut config, &mut files)
|
||||
// TODO: implement Error trait
|
||||
.map_err(|err| anyhow!("failed to read package files: {err}"))?;
|
||||
|
||||
// Perform config install (after packages have been converted to files)
|
||||
eprintln!("configuring system");
|
||||
let cookbook: Option<&'static str> = None;
|
||||
redox_installer::install_dir(config, mount_path, cookbook)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
|
||||
|
||||
// Sort and remove duplicates
|
||||
files.sort();
|
||||
files.dedup();
|
||||
|
||||
// Install files
|
||||
let mut buf = vec![0; 4 * MIB as usize];
|
||||
for (i, name) in files.iter().enumerate() {
|
||||
eprintln!("copy {} [{}/{}]", name, i, files.len());
|
||||
|
||||
let src = root_path.join(name);
|
||||
let dest = mount_path.join(name);
|
||||
copy_file(&src, &dest, &mut buf)?;
|
||||
}
|
||||
|
||||
eprintln!("finished installing, unmounting filesystem");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(()) => {
|
||||
eprintln!("installer_tui: installed successfully");
|
||||
eprintln!(
|
||||
"installer_tui: installed successfully in {:?}",
|
||||
instant.elapsed()
|
||||
);
|
||||
process::exit(0);
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
+95
-8
@@ -9,7 +9,7 @@ pub use crate::config::package::PackageConfig;
|
||||
pub use crate::config::Config;
|
||||
use crate::disk_wrapper::DiskWrapper;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use pkg::Library;
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use redoxfs::{unmount_path, Disk, DiskIo, FileSystem};
|
||||
@@ -374,6 +374,17 @@ XDG_VIDEOS_DIR="$HOME/Videos"
|
||||
}
|
||||
|
||||
pub fn with_redoxfs<D, T, F>(disk: D, password_opt: Option<&[u8]>, callback: F) -> Result<T>
|
||||
where
|
||||
D: Disk + Send + 'static,
|
||||
F: FnOnce(FileSystem<D>) -> Result<T>,
|
||||
{
|
||||
let ctime = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
||||
let fs = FileSystem::create(disk, password_opt, ctime.as_secs(), ctime.subsec_nanos())
|
||||
.map_err(syscall_error)?;
|
||||
callback(fs)
|
||||
}
|
||||
|
||||
pub fn with_redoxfs_mount<D, T, F>(fs: FileSystem<D>, callback: F) -> Result<T>
|
||||
where
|
||||
D: Disk + Send + 'static,
|
||||
F: FnOnce(&Path) -> Result<T>,
|
||||
@@ -388,10 +399,6 @@ where
|
||||
fs::create_dir(&mount_path)?;
|
||||
}
|
||||
|
||||
let ctime = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
||||
let fs = FileSystem::create(disk, password_opt, ctime.as_secs(), ctime.subsec_nanos())
|
||||
.map_err(syscall_error)?;
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let join_handle = {
|
||||
let mount_path = mount_path.clone();
|
||||
@@ -492,7 +499,7 @@ pub fn fetch_bootloaders(
|
||||
pub fn with_whole_disk<P, F, T>(disk_path: P, disk_option: &DiskOption, callback: F) -> Result<T>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
F: FnOnce(&Path) -> Result<T>,
|
||||
F: FnOnce(FileSystem<DiskIo<fscommon::StreamSlice<DiskWrapper>>>) -> Result<T>,
|
||||
{
|
||||
let target = get_target();
|
||||
|
||||
@@ -677,6 +684,84 @@ where
|
||||
with_redoxfs(disk_redoxfs, disk_option.password_opt, callback)
|
||||
}
|
||||
|
||||
/// Try fast install using live disk memory
|
||||
pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
||||
fs: &mut redoxfs::FileSystem<D>,
|
||||
mut progress: F,
|
||||
) -> Result<bool> {
|
||||
use libredox::{call::MmapArgs, flag};
|
||||
use std::os::fd::AsRawFd;
|
||||
use syscall::PAGE_SIZE;
|
||||
|
||||
let phys = env::var("DISK_LIVE_ADDR")
|
||||
.ok()
|
||||
.and_then(|x| usize::from_str_radix(&x, 16).ok())
|
||||
.unwrap_or(0);
|
||||
let size = env::var("DISK_LIVE_SIZE")
|
||||
.ok()
|
||||
.and_then(|x| usize::from_str_radix(&x, 16).ok())
|
||||
.unwrap_or(0);
|
||||
if phys == 0 || size == 0 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let start = (phys / PAGE_SIZE) * PAGE_SIZE;
|
||||
let end = phys
|
||||
.checked_add(size)
|
||||
.context("phys + size overflow")?
|
||||
.next_multiple_of(PAGE_SIZE);
|
||||
let size = end - start;
|
||||
|
||||
let original = unsafe {
|
||||
//TODO: unmap this memory
|
||||
let file = fs::File::open("/scheme/memory/physical")?;
|
||||
let base = libredox::call::mmap(MmapArgs {
|
||||
fd: file.as_raw_fd() as usize,
|
||||
addr: core::ptr::null_mut(),
|
||||
offset: start as u64,
|
||||
length: size,
|
||||
prot: flag::PROT_READ,
|
||||
flags: flag::MAP_SHARED,
|
||||
})
|
||||
.map_err(|err| anyhow!("failed to mmap livedisk: {}", err))?;
|
||||
|
||||
std::slice::from_raw_parts(base as *const u8, size)
|
||||
};
|
||||
|
||||
struct DiskLive {
|
||||
original: &'static [u8],
|
||||
}
|
||||
|
||||
impl redoxfs::Disk for DiskLive {
|
||||
unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<usize> {
|
||||
let offset = (block * redoxfs::BLOCK_SIZE) as usize;
|
||||
if offset + buffer.len() > self.original.len() {
|
||||
return Err(syscall::Error::new(syscall::EINVAL));
|
||||
}
|
||||
buffer.copy_from_slice(&self.original[offset..offset + buffer.len()]);
|
||||
Ok(buffer.len())
|
||||
}
|
||||
|
||||
unsafe fn write_at(&mut self, _block: u64, _buffer: &[u8]) -> syscall::Result<usize> {
|
||||
Err(syscall::Error::new(syscall::EINVAL))
|
||||
}
|
||||
|
||||
fn size(&mut self) -> syscall::Result<u64> {
|
||||
Ok(self.original.len() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
let mut fs_old = redoxfs::FileSystem::open(DiskLive { original }, None, None, false)?;
|
||||
let size_old = fs_old.header.size();
|
||||
let free_old = fs_old.allocator().free() * redoxfs::BLOCK_SIZE;
|
||||
let used_old = size_old - free_old;
|
||||
redoxfs::clone(&mut fs_old, fs, move |used| {
|
||||
progress(used, used_old);
|
||||
})?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn install_inner(
|
||||
config: Config,
|
||||
output: &Path,
|
||||
@@ -700,8 +785,10 @@ fn install_inner(
|
||||
efi_partition_size: config.general.efi_partition_size,
|
||||
skip_partitions: config.general.skip_partitions.unwrap_or(false),
|
||||
};
|
||||
with_whole_disk(output, &disk_option, move |mount_path| {
|
||||
install_dir(config, mount_path, cookbook)
|
||||
with_whole_disk(output, &disk_option, move |fs| {
|
||||
with_redoxfs_mount(fs, move |mount_path| {
|
||||
install_dir(config, mount_path, cookbook)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user