[pbs-devel] [PATCH v6 proxmox-backup 63/65] client: pxar: set cache limit based on nofile rlimit

Christian Ebner c.ebner at proxmox.com
Tue May 14 12:34:19 CEST 2024


The lookahead cache size requires the resource limit for open file
handles to be high in order to allow for efficient reuse of unchanged
file payloads.

Increase the nofile soft limit to the hard limit and dynamically adapt
the cache size to the new soft limit minus the half of the previous
soft limit.

The `PxarCreateOptions` and the `Archiver` are therefore extended by
an additional field to store the maximum cache size, with fallback to
a default size of 512 entries.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
 pbs-client/src/pxar/create.rs                 |  7 ++++++-
 proxmox-backup-client/src/main.rs             | 21 ++++++++++++++++---
 .../src/proxmox_restore_daemon/api.rs         |  1 +
 pxar-bin/src/main.rs                          |  1 +
 4 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/pbs-client/src/pxar/create.rs b/pbs-client/src/pxar/create.rs
index 9349dd8bb..d326d5ac0 100644
--- a/pbs-client/src/pxar/create.rs
+++ b/pbs-client/src/pxar/create.rs
@@ -57,6 +57,8 @@ pub struct PxarCreateOptions {
     pub skip_e2big_xattr: bool,
     /// Reference state for partial backups
     pub previous_ref: Option<PxarPrevRef>,
+    /// Maximum number of lookahead cache entries
+    pub max_cache_size: Option<usize>,
 }
 
 pub type MetadataArchiveReader = Arc<dyn ReadAt + Send + Sync + 'static>;
@@ -172,6 +174,7 @@ struct Archiver {
     suggested_boundaries: Option<mpsc::Sender<u64>>,
     previous_payload_index: Option<DynamicIndexReader>,
     cached_entries: Vec<CacheEntry>,
+    max_cache_size: usize,
     cached_hardlinks: HashSet<HardLinkInfo>,
     cached_range: Range<u64>,
     cached_last_chunk: Option<ReusableDynamicEntry>,
@@ -292,6 +295,7 @@ where
         previous_payload_index,
         suggested_boundaries,
         cached_entries: Vec::new(),
+        max_cache_size: options.max_cache_size.unwrap_or(MAX_CACHE_SIZE),
         cached_range: Range::default(),
         cached_last_chunk: None,
         cached_hardlinks: HashSet::new(),
@@ -743,7 +747,7 @@ impl Archiver {
         }
 
         // Avoid having to many open file handles in cached entries
-        if self.cached_entries.len() > MAX_CACHE_SIZE {
+        if self.cached_entries.len() > self.max_cache_size {
             log::debug!("Max cache size reached, reuse cached entries");
             self.flush_cached_reusing_if_below_threshold(encoder, true)
                 .await?;
@@ -2018,6 +2022,7 @@ mod tests {
                 previous_payload_index,
                 suggested_boundaries: Some(suggested_boundaries),
                 cached_entries: Vec::new(),
+                max_cache_size: 512,
                 cached_range: Range::default(),
                 cached_last_chunk: None,
                 cached_hardlinks: HashSet::new(),
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index 1423e6f0f..359b2afcf 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -41,7 +41,7 @@ use pbs_client::tools::{
         crypto_parameters, format_key_source, get_encryption_key_password, KEYFD_SCHEMA,
         KEYFILE_SCHEMA, MASTER_PUBKEY_FD_SCHEMA, MASTER_PUBKEY_FILE_SCHEMA,
     },
-    CHUNK_SIZE_SCHEMA, REPO_URL_SCHEMA,
+    raise_nofile_limit, CHUNK_SIZE_SCHEMA, REPO_URL_SCHEMA,
 };
 use pbs_client::{
     delete_ticket_info, parse_backup_detection_mode_specification, parse_backup_specification,
@@ -1074,7 +1074,8 @@ async fn create_backup(
                     .start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
 
                 let mut previous_ref = None;
-                if detection_mode.is_metadata() {
+                let max_cache_size = if detection_mode.is_metadata() {
+                    let old_rlimit = raise_nofile_limit()?;
                     if let Some(ref manifest) = previous_manifest {
                         // BackupWriter::start created a new snapshot, get the one before
                         if let Some(backup_time) = client.previous_backup_time().await? {
@@ -1099,7 +1100,20 @@ async fn create_backup(
                             .await?
                         }
                     }
-                }
+
+                    if old_rlimit.rlim_max <= 4096 {
+                        log::info!(
+                            "resource limit for open file handles low: {}",
+                            old_rlimit.rlim_max,
+                        );
+                    }
+
+                    Some(usize::try_from(
+                        old_rlimit.rlim_max - old_rlimit.rlim_cur / 2,
+                    )?)
+                } else {
+                    None
+                };
 
                 let pxar_options = pbs_client::pxar::PxarCreateOptions {
                     device_set: devices.clone(),
@@ -1108,6 +1122,7 @@ async fn create_backup(
                     skip_lost_and_found,
                     skip_e2big_xattr,
                     previous_ref,
+                    max_cache_size,
                 };
 
                 let upload_options = UploadOptions {
diff --git a/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs b/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
index 956c3246a..49aa96b58 100644
--- a/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
+++ b/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
@@ -356,6 +356,7 @@ fn extract(
                         skip_lost_and_found: false,
                         skip_e2big_xattr: false,
                         previous_ref: None,
+                        max_cache_size: None,
                     };
 
                     let pxar_writer = TokioWriter::new(writer);
diff --git a/pxar-bin/src/main.rs b/pxar-bin/src/main.rs
index 2a5403467..c08aee4f6 100644
--- a/pxar-bin/src/main.rs
+++ b/pxar-bin/src/main.rs
@@ -365,6 +365,7 @@ async fn create_archive(
         skip_lost_and_found: false,
         skip_e2big_xattr: false,
         previous_ref: None,
+        max_cache_size: None,
     };
 
     let source = PathBuf::from(source);
-- 
2.39.2





More information about the pbs-devel mailing list