From 44575e4535a83f9ef96b37ab9709d37a34763a0a Mon Sep 17 00:00:00 2001 From: YuQiang Date: Wed, 20 Sep 2023 17:32:28 +0800 Subject: [PATCH] feat: notifying incosistent fs version problem with exit code If acceld converts with different fs version cache, leading to an inconsistent fs version problem when merging into boostrap layer. So we need to notify acceld that an inconsistent version occured and handle this error. Signed-off-by: YuQiang --- Cargo.lock | 1 + rafs/Cargo.toml | 1 + rafs/src/metadata/mod.rs | 30 ++++++++++++++++++++++-------- src/bin/nydus-image/main.rs | 10 ++++++++-- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e672579084e..4413c54deb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1217,6 +1217,7 @@ dependencies = [ "nydus-utils", "serde", "serde_json", + "thiserror", "vm-memory", "vmm-sys-util", ] diff --git a/rafs/Cargo.toml b/rafs/Cargo.toml index 4581d5e0524..7424a811172 100644 --- a/rafs/Cargo.toml +++ b/rafs/Cargo.toml @@ -20,6 +20,7 @@ serde = { version = "1.0.110", features = ["serde_derive", "rc"] } serde_json = "1.0.53" vm-memory = "0.10" fuse-backend-rs = "^0.10.3" +thiserror = "1" nydus-api = { version = "0.3", path = "../api" } nydus-storage = { version = "0.6", path = "../storage", features = ["backend-localfs"] } diff --git a/rafs/src/metadata/mod.rs b/rafs/src/metadata/mod.rs index c04c3b4da1d..4f22b3cc754 100644 --- a/rafs/src/metadata/mod.rs +++ b/rafs/src/metadata/mod.rs @@ -17,8 +17,10 @@ use std::path::{Component, Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; use std::time::Duration; +use thiserror::Error; use anyhow::bail; +use anyhow::Result as AnyhowResult; use fuse_backend_rs::abi::fuse_abi::Attr; use fuse_backend_rs::api::filesystem::Entry; use nydus_api::{ConfigV2, RafsConfigV2}; @@ -397,18 +399,28 @@ pub struct RafsSuperConfig { pub is_tarfs_mode: bool, } +#[derive(Error, Debug)] +pub enum MergeError { + #[error("Inconsistent RAFS version:{0}")] + InconsisentFsVersion(String), + #[error("Different Digest Akgorithm:{0}")] + DifferentDigestAlgorithm(String), + #[error(transparent)] + Other(#[from] Error), +} + impl RafsSuperConfig { /// Check compatibility for two RAFS filesystems. - pub fn check_compatibility(&self, meta: &RafsSuperMeta) -> Result<()> { + pub fn check_compatibility(&self, meta: &RafsSuperMeta) -> AnyhowResult<(), MergeError> { if self.chunk_size != meta.chunk_size { - return Err(einval!(format!( + return Err(MergeError::InconsisentFsVersion(format!( "Inconsistent configuration of chunk_size: {} vs {}", self.chunk_size, meta.chunk_size ))); } if self.explicit_uidgid != meta.explicit_uidgid() { - return Err(einval!(format!( + return Err(MergeError::InconsisentFsVersion(format!( "Using inconsistent explicit_uidgid setting {:?}, target explicit_uidgid setting {:?}", self.explicit_uidgid, meta.explicit_uidgid() @@ -416,15 +428,15 @@ impl RafsSuperConfig { } if u32::from(self.version) != meta.version { - return Err(einval!(format!( + let meta_version = RafsVersion::try_from(meta.version); + return Err(MergeError::InconsisentFsVersion(format!( "Using inconsistent RAFS version {:?}, target RAFS version {:?}", - self.version, - RafsVersion::try_from(meta.version)? + self.version, meta_version ))); } if self.version == RafsVersion::V5 && self.digester != meta.get_digester() { - return Err(einval!(format!( + return Err(MergeError::DifferentDigestAlgorithm(format!( "RAFS v5 can not support different digest algorithm due to inode digest, {} vs {}", self.digester, meta.get_digester() @@ -433,7 +445,9 @@ impl RafsSuperConfig { let is_tarfs_mode = meta.flags.contains(RafsSuperFlags::TARTFS_MODE); if is_tarfs_mode != self.is_tarfs_mode { - return Err(einval!(format!("Using inconsistent RAFS TARFS mode"))); + return Err(MergeError::InconsisentFsVersion( + "Using inconsistent RAFS TARFS mode".to_string(), + )); } Ok(()) diff --git a/src/bin/nydus-image/main.rs b/src/bin/nydus-image/main.rs index 200b5cc3784..093ee58ae16 100644 --- a/src/bin/nydus-image/main.rs +++ b/src/bin/nydus-image/main.rs @@ -31,7 +31,7 @@ use nydus_builder::{ BuildContext, BuildOutput, Builder, ConversionType, DirectoryBuilder, Feature, Features, HashChunkDict, Merger, Prefetch, PrefetchPolicy, StargzBuilder, TarballBuilder, WhiteoutSpec, }; -use nydus_rafs::metadata::{RafsSuper, RafsSuperConfig, RafsVersion}; +use nydus_rafs::metadata::{MergeError, RafsSuper, RafsSuperConfig, RafsVersion}; use nydus_storage::backend::localfs::LocalFs; use nydus_storage::backend::BlobBackend; use nydus_storage::device::{BlobFeatures, BlobInfo}; @@ -759,7 +759,13 @@ fn main() -> Result<()> { } } } else if let Some(matches) = cmd.subcommand_matches("merge") { - Command::merge(matches, &build_info) + let result = Command::merge(matches, &build_info); + if let Err(e) = result { + if let Some(MergeError::InconsisentFsVersion(_)) = e.downcast_ref::() { + std::process::exit(2); + } + } + Ok(()) } else if let Some(matches) = cmd.subcommand_matches("check") { Command::check(matches, &build_info) } else if let Some(matches) = cmd.subcommand_matches("export") {