mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 01:43:22 +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
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use std::{
|
use std::path::{Path, PathBuf};
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::file::BundleFile;
|
use super::file::BundleFile;
|
||||||
use crate::arch::Arch;
|
use crate::{arch::Arch, util::hard_link_or_copy};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct AsterBin {
|
pub struct AsterBin {
|
||||||
@ -87,7 +84,7 @@ impl AsterBin {
|
|||||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||||
let file_name = self.path.file_name().unwrap();
|
let file_name = self.path.file_name().unwrap();
|
||||||
let copied_path = base.as_ref().join(file_name);
|
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 {
|
Self {
|
||||||
path: PathBuf::from(file_name),
|
path: PathBuf::from(file_name),
|
||||||
arch: self.arch,
|
arch: self.arch,
|
||||||
|
@ -7,6 +7,8 @@ use std::{
|
|||||||
|
|
||||||
use sha2::{Digest, Sha256};
|
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.
|
/// A trait for files in a bundle. The file in a bundle should have it's digest and be validatable.
|
||||||
pub trait BundleFile {
|
pub trait BundleFile {
|
||||||
fn path(&self) -> &PathBuf;
|
fn path(&self) -> &PathBuf;
|
||||||
@ -57,7 +59,7 @@ impl Initramfs {
|
|||||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||||
let name = self.path.file_name().unwrap();
|
let name = self.path.file_name().unwrap();
|
||||||
let dest = base.as_ref().join(name);
|
let dest = base.as_ref().join(name);
|
||||||
fs::copy(&self.path, dest).unwrap();
|
hard_link_or_copy(&self.path, dest).unwrap();
|
||||||
Self {
|
Self {
|
||||||
path: PathBuf::from(name),
|
path: PathBuf::from(name),
|
||||||
..self
|
..self
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use std::{
|
use std::path::{Path, PathBuf};
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
use crate::util::hard_link_or_copy;
|
||||||
};
|
|
||||||
|
|
||||||
use super::file::BundleFile;
|
use super::file::BundleFile;
|
||||||
|
|
||||||
@ -63,8 +62,7 @@ impl AsterVmImage {
|
|||||||
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
pub fn copy_to(self, base: impl AsRef<Path>) -> Self {
|
||||||
let file_name = self.path.file_name().unwrap();
|
let file_name = self.path.file_name().unwrap();
|
||||||
let copied_path = base.as_ref().join(file_name);
|
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();
|
||||||
fs::remove_file(&self.path).unwrap();
|
|
||||||
Self {
|
Self {
|
||||||
path: PathBuf::from(file_name),
|
path: PathBuf::from(file_name),
|
||||||
typ: self.typ,
|
typ: self.typ,
|
||||||
|
@ -17,7 +17,7 @@ use crate::{
|
|||||||
bin::{AsterBin, AsterBinType, AsterBzImageMeta, AsterElfMeta},
|
bin::{AsterBin, AsterBinType, AsterBzImageMeta, AsterElfMeta},
|
||||||
file::BundleFile,
|
file::BundleFile,
|
||||||
},
|
},
|
||||||
util::get_current_crate_info,
|
util::{get_current_crate_info, hard_link_or_copy},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn make_install_bzimage(
|
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 {
|
} else {
|
||||||
// Copy the ELF file.
|
// 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 {
|
if elf.arch() == Arch::X86_64 {
|
||||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||||||
scheme::{ActionChoice, BootProtocol},
|
scheme::{ActionChoice, BootProtocol},
|
||||||
Config,
|
Config,
|
||||||
},
|
},
|
||||||
util::get_current_crate_info,
|
util::{get_current_crate_info, hard_link_or_copy},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create_bootdev_image(
|
pub fn create_bootdev_image(
|
||||||
@ -42,7 +42,7 @@ pub fn create_bootdev_image(
|
|||||||
|
|
||||||
// Copy the initramfs to the boot directory.
|
// Copy the initramfs to the boot directory.
|
||||||
if let Some(init_path) = &initramfs_path {
|
if let Some(init_path) = &initramfs_path {
|
||||||
fs::copy(
|
hard_link_or_copy(
|
||||||
init_path.as_ref().to_str().unwrap(),
|
init_path.as_ref().to_str().unwrap(),
|
||||||
iso_root.join("boot").join("initramfs.cpio.gz"),
|
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.
|
// Copy the kernel image to the boot directory.
|
||||||
let target_path = iso_root.join("boot").join(&target_name);
|
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::{
|
use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{BufRead, BufReader, Write},
|
io::{BufRead, BufReader, Result, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::Command,
|
||||||
};
|
};
|
||||||
@ -290,3 +290,24 @@ impl Drop for DirGuard {
|
|||||||
std::env::set_current_dir(&self.0).unwrap();
|
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