mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 09:53:24 +00:00
Enhance OSDK performance by using hard link instead of copy
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
7601509e6e
commit
9d82ac8958
@ -1,12 +1,9 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::file::BundleFile;
|
||||
use crate::arch::Arch;
|
||||
use crate::{arch::Arch, util::hard_link_or_copy};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct AsterBin {
|
||||
@ -87,7 +84,7 @@ impl AsterBin {
|
||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||
let file_name = self.path.file_name().unwrap();
|
||||
let copied_path = base.as_ref().join(file_name);
|
||||
fs::copy(&self.path, copied_path).unwrap();
|
||||
hard_link_or_copy(&self.path, copied_path).unwrap();
|
||||
Self {
|
||||
path: PathBuf::from(file_name),
|
||||
arch: self.arch,
|
||||
|
@ -7,6 +7,8 @@ use std::{
|
||||
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::util::hard_link_or_copy;
|
||||
|
||||
/// A trait for files in a bundle. The file in a bundle should have it's digest and be validatable.
|
||||
pub trait BundleFile {
|
||||
fn path(&self) -> &PathBuf;
|
||||
@ -57,7 +59,7 @@ impl Initramfs {
|
||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||
let name = self.path.file_name().unwrap();
|
||||
let dest = base.as_ref().join(name);
|
||||
fs::copy(&self.path, dest).unwrap();
|
||||
hard_link_or_copy(&self.path, dest).unwrap();
|
||||
Self {
|
||||
path: PathBuf::from(name),
|
||||
..self
|
||||
|
@ -1,9 +1,8 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::util::hard_link_or_copy;
|
||||
|
||||
use super::file::BundleFile;
|
||||
|
||||
@ -63,8 +62,7 @@ impl AsterVmImage {
|
||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||
let file_name = self.path.file_name().unwrap();
|
||||
let copied_path = base.as_ref().join(file_name);
|
||||
fs::copy(&self.path, copied_path).unwrap();
|
||||
fs::remove_file(&self.path).unwrap();
|
||||
hard_link_or_copy(&self.path, copied_path).unwrap();
|
||||
Self {
|
||||
path: PathBuf::from(file_name),
|
||||
typ: self.typ,
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
||||
bin::{AsterBin, AsterBinType, AsterBzImageMeta, AsterElfMeta},
|
||||
file::BundleFile,
|
||||
},
|
||||
util::get_current_crate_info,
|
||||
util::{get_current_crate_info, hard_link_or_copy},
|
||||
};
|
||||
|
||||
pub fn make_install_bzimage(
|
||||
@ -115,7 +115,7 @@ pub fn make_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin, strip: b
|
||||
}
|
||||
} else {
|
||||
// Copy the ELF file.
|
||||
std::fs::copy(elf.path(), &result_elf_path).unwrap();
|
||||
hard_link_or_copy(elf.path(), &result_elf_path).unwrap();
|
||||
}
|
||||
|
||||
if elf.arch() == Arch::X86_64 {
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
scheme::{ActionChoice, BootProtocol},
|
||||
Config,
|
||||
},
|
||||
util::get_current_crate_info,
|
||||
util::{get_current_crate_info, hard_link_or_copy},
|
||||
};
|
||||
|
||||
pub fn create_bootdev_image(
|
||||
@ -42,7 +42,7 @@ pub fn create_bootdev_image(
|
||||
|
||||
// Copy the initramfs to the boot directory.
|
||||
if let Some(init_path) = &initramfs_path {
|
||||
fs::copy(
|
||||
hard_link_or_copy(
|
||||
init_path.as_ref().to_str().unwrap(),
|
||||
iso_root.join("boot").join("initramfs.cpio.gz"),
|
||||
)
|
||||
@ -63,7 +63,7 @@ pub fn create_bootdev_image(
|
||||
_ => {
|
||||
// Copy the kernel image to the boot directory.
|
||||
let target_path = iso_root.join("boot").join(&target_name);
|
||||
fs::copy(aster_bin.path(), target_path).unwrap();
|
||||
hard_link_or_copy(aster_bin.path(), target_path).unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs::{self, File},
|
||||
io::{BufRead, BufReader, Write},
|
||||
io::{BufRead, BufReader, Result, Write},
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
@ -290,3 +290,24 @@ impl Drop for DirGuard {
|
||||
std::env::set_current_dir(&self.0).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to create a hard link from `from` to `to`.
|
||||
/// If the hard link operation fails (e.g., due to crossing file systems),
|
||||
/// it falls back to performing a file copy.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `from`: The source file path.
|
||||
/// - `to`: The destination file path.
|
||||
///
|
||||
/// # Returns
|
||||
/// - `Ok(0)` if the hard link is successfully created (no data was copied).
|
||||
/// - `Ok(size)` where `size` is the number of bytes copied if the hard link failed and a copy was performed.
|
||||
/// - `Err(error)` if an error occurred during the copy operation.
|
||||
pub fn hard_link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> {
|
||||
if fs::hard_link(&from, &to).is_err() {
|
||||
info!("Copying {:?} -> {:?}", from.as_ref(), to.as_ref());
|
||||
return fs::copy(from, to);
|
||||
}
|
||||
info!("Linking {:?} -> {:?}", from.as_ref(), to.as_ref());
|
||||
Ok(0)
|
||||
}
|
||||
|
Reference in New Issue
Block a user