diff --git a/src/libs/kata-types/src/annotations/mod.rs b/src/libs/kata-types/src/annotations/mod.rs index c8d63125b9..16af5ab28a 100644 --- a/src/libs/kata-types/src/annotations/mod.rs +++ b/src/libs/kata-types/src/annotations/mod.rs @@ -308,6 +308,14 @@ pub const KATA_ANNO_CFG_DISABLE_NEW_NETNS: &str = /// A sandbox annotation to specify how attached VFIO devices should be treated. pub const KATA_ANNO_CFG_VFIO_MODE: &str = "io.katacontainers.config.runtime.vfio_mode"; +/// A sandbox annotation used to specify prefetch_files.list host path container image +/// being used, +/// and runtime will pass it to Hypervisor to search for corresponding prefetch list file. +/// "io.katacontainers.config.hypervisor.prefetch_files.list" +/// = "/path/to//xyz.com/fedora:36/prefetch_file.list" +pub const KATA_ANNO_CFG_HYPERVISOR_PREFETCH_FILES_LIST: &str = + "io.katacontainers.config.hypervisor.prefetch_files.list"; + /// A helper structure to query configuration information by check annotations. #[derive(Debug, Default, Deserialize)] pub struct Annotation { @@ -673,6 +681,9 @@ impl Annotation { hv.machine_info.validate_entropy_source(value)?; hv.machine_info.entropy_source = value.to_string(); } + KATA_ANNO_CFG_HYPERVISOR_PREFETCH_FILES_LIST => { + hv.prefetch_list_path = value.to_string(); + } // Hypervisor Memory related annotations KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY => { match byte_unit::Byte::from_str(value) { diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index 98ae2cc793..7818b897ce 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -979,6 +979,13 @@ pub struct Hypervisor { #[serde(default, flatten)] pub shared_fs: SharedFsInfo, + /// A sandbox annotation used to specify prefetch_files.list host path container image + /// being used, and runtime will pass it to Hypervisor to search for corresponding + /// prefetch list file: + /// prefetch_list_path = /path/to//xyz.com/fedora:36/prefetch_file.list + #[serde(default)] + pub prefetch_list_path: String, + /// Vendor customized runtime configuration. #[serde(default, flatten)] pub vendor: HypervisorVendor, @@ -1022,6 +1029,10 @@ impl ConfigOps for Hypervisor { hv.network_info.adjust_config()?; hv.security_info.adjust_config()?; hv.shared_fs.adjust_config()?; + resolve_path!( + hv.prefetch_list_path, + "prefetch_list_path `{}` is invalid: {}" + )?; } else { return Err(eother!("Can not find plugin for hypervisor {}", hypervisor)); } @@ -1056,6 +1067,10 @@ impl ConfigOps for Hypervisor { "Hypervisor control executable `{}` is invalid: {}" )?; validate_path!(hv.jailer_path, "Hypervisor jailer path `{}` is invalid: {}")?; + validate_path!( + hv.prefetch_list_path, + "prefetch_files.list path `{}` is invalid: {}" + )?; } else { return Err(eother!("Can not find plugin for hypervisor {}", hypervisor)); } diff --git a/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs b/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs index 16f9c48dd4..008443b874 100644 --- a/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs +++ b/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs @@ -3,7 +3,7 @@ // // SPDX-License-Identifier: Apache-2.0 // -use std::{fs, sync::Arc}; +use std::{fs, path::Path, sync::Arc}; use super::{Rootfs, TYPE_OVERLAY_FS}; use crate::{ @@ -28,6 +28,8 @@ const NYDUS_ROOTFS_V6: &str = "v6"; const SNAPSHOT_DIR: &str = "snapshotdir"; const KATA_OVERLAY_DEV_TYPE: &str = "overlayfs"; +// nydus prefetch file list name +const NYDUS_PREFETCH_FILE_LIST: &str = "prefetch_file.list"; pub(crate) struct NydusRootfs { guest_path: String, @@ -42,6 +44,9 @@ impl NydusRootfs { cid: &str, rootfs: &Mount, ) -> Result { + let prefetch_list_path = + get_nydus_prefetch_files(h.hypervisor_config().await.prefetch_list_path).await; + let share_fs_mount = share_fs.get_share_fs_mount(); let extra_options = NydusExtraOptions::new(rootfs).context("failed to parse nydus extra options")?; @@ -59,7 +64,7 @@ impl NydusRootfs { rafs_meta.to_string(), rafs_mnt, extra_options.config.clone(), - None, + prefetch_list_path, ) .await .context("failed to do rafs mount")?; @@ -151,3 +156,67 @@ impl Rootfs for NydusRootfs { Ok(()) } } + +// Check prefetch files list path, and if invalid, discard it directly. +// As the result of caller `rafs_mount`, it returns `Option`. +async fn get_nydus_prefetch_files(nydus_prefetch_path: String) -> Option { + // nydus_prefetch_path is an annotation and pod with it will indicate + // that prefetch_files will be included. + if nydus_prefetch_path.is_empty() { + info!(sl!(), "nydus prefetch files path not set, just skip it."); + + return None; + } + + // Ensure the string ends with "/prefetch_files.list" + if !nydus_prefetch_path.ends_with(format!("/{}", NYDUS_PREFETCH_FILE_LIST).as_str()) { + info!( + sl!(), + "nydus prefetch file path no {:?} file exist.", NYDUS_PREFETCH_FILE_LIST + ); + + return None; + } + + // ensure the prefetch_list_path is a regular file. + let prefetch_list_path = Path::new(nydus_prefetch_path.as_str()); + if !prefetch_list_path.is_file() { + info!( + sl!(), + "nydus prefetch list file {:?} not a regular file", &prefetch_list_path + ); + + return None; + } + + return Some(prefetch_list_path.display().to_string()); +} + +#[cfg(test)] +mod tests { + use super::*; + use std::{fs::File, path::PathBuf}; + use tempfile::tempdir; + + #[tokio::test] + async fn test_get_nydus_prefetch_files() { + let temp_dir = tempdir().unwrap(); + let prefetch_list_path01 = temp_dir.path().join("nydus_prefetch_files"); + // /tmp_dir/nydus_prefetch_files/ + std::fs::create_dir_all(prefetch_list_path01.clone()).unwrap(); + // /tmp_dir/nydus_prefetch_files/prefetch_file.list + let prefetch_list_path02 = prefetch_list_path01 + .as_path() + .join(NYDUS_PREFETCH_FILE_LIST); + let file = File::create(prefetch_list_path02.clone()); + assert!(file.is_ok()); + + let prefetch_file = + get_nydus_prefetch_files(prefetch_list_path02.as_path().display().to_string()).await; + assert!(prefetch_file.is_some()); + assert_eq!(PathBuf::from(prefetch_file.unwrap()), prefetch_list_path02); + + drop(file); + temp_dir.close().unwrap_or_default(); + } +}