diff --git a/src/server/pull.rs b/src/server/pull.rs index d18c6d64..3117f7d2 100644 --- a/src/server/pull.rs +++ b/src/server/pull.rs @@ -28,8 +28,8 @@ use pbs_datastore::{check_backup_owner, DataStore, StoreProgress}; use pbs_tools::sha::sha256; use super::sync::{ - LocalSource, RemoteSource, RemovedVanishedStats, SkipInfo, SkipReason, SyncSource, - SyncSourceReader, SyncStats, + check_namespace_depth_limit, LocalSource, RemoteSource, RemovedVanishedStats, SkipInfo, + SkipReason, SyncSource, SyncSourceReader, SyncStats, }; use crate::backup::{check_ns_modification_privs, check_ns_privs}; use crate::tools::parallel_handler::ParallelHandler; @@ -735,21 +735,7 @@ pub(crate) async fn pull_store(mut params: PullParameters) -> Result MAX_NAMESPACE_DEPTH { - bail!( - "Syncing would exceed max allowed namespace depth. ({}+{} > {})", - ns_layers_to_be_pulled, - target_depth, - MAX_NAMESPACE_DEPTH - ); - } + check_namespace_depth_limit(¶ms.source.get_ns(), ¶ms.target.ns, &namespaces)?; errors |= old_max_depth != params.max_depth; // fail job if we switched to backwards-compat mode namespaces.sort_unstable_by_key(|a| a.name_len()); diff --git a/src/server/sync.rs b/src/server/sync.rs index ee40d0b9..bd68dda4 100644 --- a/src/server/sync.rs +++ b/src/server/sync.rs @@ -547,3 +547,24 @@ impl std::fmt::Display for SkipInfo { ) } } + +/// Check if a sync from source to target of given namespaces exceeds the global namespace depth limit +pub(crate) fn check_namespace_depth_limit( + source_namespace: &BackupNamespace, + target_namespace: &BackupNamespace, + namespaces: &[BackupNamespace], +) -> Result<(), Error> { + let target_ns_depth = target_namespace.depth(); + let sync_ns_depth = namespaces + .iter() + .map(BackupNamespace::depth) + .max() + .map_or(0, |v| v - source_namespace.depth()); + + if sync_ns_depth + target_ns_depth > MAX_NAMESPACE_DEPTH { + bail!( + "Syncing would exceed max allowed namespace depth. ({sync_ns_depth}+{target_ns_depth} > {MAX_NAMESPACE_DEPTH})", + ); + } + Ok(()) +}