all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Christian Ebner <c.ebner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v3 1/4] traffic control: use factored out shared rate limiter
Date: Wed, 12 Nov 2025 12:53:50 +0100	[thread overview]
Message-ID: <20251112115353.277514-7-c.ebner@proxmox.com> (raw)
In-Reply-To: <20251112115353.277514-1-c.ebner@proxmox.com>

The shared rate limiter implementation was factored out into a
dedicated crate so it can be easily reused for other code paths, e.g.
the s3 client implementation.

Use that implementation and drop the now dead code.

No functional changes intended.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
Reviewed-by: Hannes Laimer <h.laimer@proxmox.com>
Tested-by: Hannes Laimer <h.laimer@proxmox.com>
---
Changes since version 2:
- no changes

 Cargo.toml                       |   3 +
 debian/control                   |   1 -
 pbs-client/Cargo.toml            |   3 +-
 pbs-client/src/http_client.rs    |   3 +-
 src/tools/mod.rs                 |   4 -
 src/tools/shared_rate_limiter.rs | 122 -------------------------------
 src/traffic_control_cache.rs     |   8 +-
 7 files changed, 11 insertions(+), 133 deletions(-)
 delete mode 100644 src/tools/shared_rate_limiter.rs

diff --git a/Cargo.toml b/Cargo.toml
index 28fdbf546..c02991d2a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -74,6 +74,7 @@ proxmox-network-api = "1"
 proxmox-notify = "1"
 proxmox-openid = "1"
 proxmox-product-config = "1"
+proxmox-rate-limiter = "1.0.0"
 proxmox-rest-server = { version = "1.0.1", features = [ "templates" ] }
 # some use "cli", some use "cli" and "server", pbs-config uses nothing
 proxmox-router = { version = "3.2.2", default-features = false }
@@ -227,6 +228,7 @@ proxmox-network-api = { workspace = true, features = [ "impl" ] }
 proxmox-notify = { workspace = true, features = [ "pbs-context" ] }
 proxmox-openid.workspace = true
 proxmox-product-config.workspace = true
+proxmox-rate-limiter = { workspace = true, features = [ "shared-rate-limiter" ] }
 proxmox-rest-server = { workspace = true, features = [ "rate-limited-stream" ] }
 proxmox-router = { workspace = true, features = [ "cli", "server"] }
 proxmox-s3-client.workspace = true
@@ -288,6 +290,7 @@ proxmox-rrd-api-types.workspace = true
 #proxmox-notify = { path = "../proxmox/proxmox-notify" }
 #proxmox-openid = { path = "../proxmox/proxmox-openid" }
 #proxmox-product-config = { path = "../proxmox/proxmox-product-config" }
+#proxmox-rate-limiter = { path = "../proxmox/proxmox-rate-limiter" }
 #proxmox-rest-server = { path = "../proxmox/proxmox-rest-server" }
 #proxmox-router = { path = "../proxmox/proxmox-router" }
 #proxmox-rrd = { path = "../proxmox/proxmox-rrd" }
diff --git a/debian/control b/debian/control
index 2149dd768..b996e66b7 100644
--- a/debian/control
+++ b/debian/control
@@ -81,7 +81,6 @@ Build-Depends: debhelper (>= 12~),
                librust-proxmox-http-1+http-helpers-dev (>= 1.0.2-~~),
                librust-proxmox-http-1+proxmox-async-dev (>= 1.0.2-~~),
                librust-proxmox-http-1+rate-limited-stream-dev (>= 1.0.2-~~),
-               librust-proxmox-http-1+rate-limiter-dev (>= 1.0.2-~~),
                librust-proxmox-http-1+websocket-dev (>= 1.0.2-~~),
                librust-proxmox-human-byte-1+default-dev,
                librust-proxmox-io-1+default-dev (>= 1.0.1-~~),
diff --git a/pbs-client/Cargo.toml b/pbs-client/Cargo.toml
index 4c6c80983..233969f65 100644
--- a/pbs-client/Cargo.toml
+++ b/pbs-client/Cargo.toml
@@ -36,10 +36,11 @@ pathpatterns.workspace = true
 proxmox-async.workspace = true
 proxmox-auth-api.workspace = true
 proxmox-compression.workspace = true
-proxmox-http = { workspace = true, features = [ "body", "rate-limiter" ] }
+proxmox-http = { workspace = true, features = [ "body" ] }
 proxmox-human-byte.workspace = true
 proxmox-io = { workspace = true, features = [ "tokio" ] }
 proxmox-log = { workspace = true }
+proxmox-rate-limiter = { workspace = true, features = [ "rate-limiter" ] }
 proxmox-router = { workspace = true, features = [ "cli", "server" ] }
 proxmox-schema.workspace = true
 proxmox-sys.workspace = true
diff --git a/pbs-client/src/http_client.rs b/pbs-client/src/http_client.rs
index 4599bf226..af53f74e0 100644
--- a/pbs-client/src/http_client.rs
+++ b/pbs-client/src/http_client.rs
@@ -31,8 +31,9 @@ use proxmox_async::broadcast_future::BroadcastFuture;
 use proxmox_http::client::HttpsConnector;
 use proxmox_http::uri::{build_authority, json_object_to_query};
 use proxmox_http::Body;
-use proxmox_http::{ProxyConfig, RateLimiter};
+use proxmox_http::ProxyConfig;
 use proxmox_log::{error, info, warn};
+use proxmox_rate_limiter::RateLimiter;
 
 use pbs_api_types::percent_encoding::DEFAULT_ENCODE_SET;
 use pbs_api_types::{Authid, RateLimitConfig, Userid};
diff --git a/src/tools/mod.rs b/src/tools/mod.rs
index 739086cf0..6a975bde2 100644
--- a/src/tools/mod.rs
+++ b/src/tools/mod.rs
@@ -16,10 +16,6 @@ use pbs_datastore::manifest::BackupManifest;
 pub mod config;
 pub mod disks;
 pub mod fs;
-
-mod shared_rate_limiter;
-pub use shared_rate_limiter::SharedRateLimiter;
-
 pub mod statistics;
 pub mod systemd;
 pub mod ticket;
diff --git a/src/tools/shared_rate_limiter.rs b/src/tools/shared_rate_limiter.rs
deleted file mode 100644
index db754728b..000000000
--- a/src/tools/shared_rate_limiter.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-use std::mem::MaybeUninit;
-use std::path::PathBuf;
-use std::time::{Duration, Instant};
-
-use anyhow::{bail, Error};
-use nix::sys::stat::Mode;
-
-use proxmox_sys::fs::{create_path, CreateOptions};
-
-use proxmox_http::{RateLimit, RateLimiter, ShareableRateLimit};
-use proxmox_shared_memory::{check_subtype, initialize_subtype};
-use proxmox_shared_memory::{Init, SharedMemory, SharedMutex};
-
-// openssl::sha::sha256(b"Proxmox Backup SharedRateLimiter v1.0")[0..8];
-pub const PROXMOX_BACKUP_SHARED_RATE_LIMITER_MAGIC_1_0: [u8; 8] =
-    [6, 58, 213, 96, 161, 122, 130, 117];
-
-const BASE_PATH: &str = pbs_buildcfg::rundir!("/shmem/tbf");
-
-// Wrap RateLimiter, so that we can provide an Init impl
-#[repr(C)]
-struct WrapLimiter(RateLimiter);
-
-impl Init for WrapLimiter {
-    fn initialize(this: &mut MaybeUninit<Self>) {
-        // default does not matter here, because we override later
-        this.write(WrapLimiter(RateLimiter::new(1_000_000, 1_000_000)));
-    }
-}
-
-#[repr(C)]
-struct SharedRateLimiterData {
-    magic: [u8; 8],
-    tbf: SharedMutex<WrapLimiter>,
-    padding: [u8; 4096 - 104],
-}
-
-impl Init for SharedRateLimiterData {
-    fn initialize(this: &mut MaybeUninit<Self>) {
-        unsafe {
-            let me = &mut *this.as_mut_ptr();
-            me.magic = PROXMOX_BACKUP_SHARED_RATE_LIMITER_MAGIC_1_0;
-            initialize_subtype(&mut me.tbf);
-        }
-    }
-
-    fn check_type_magic(this: &MaybeUninit<Self>) -> Result<(), Error> {
-        unsafe {
-            let me = &*this.as_ptr();
-            if me.magic != PROXMOX_BACKUP_SHARED_RATE_LIMITER_MAGIC_1_0 {
-                bail!("SharedRateLimiterData: wrong magic number");
-            }
-            check_subtype(&me.tbf)?;
-            Ok(())
-        }
-    }
-}
-
-/// Rate limiter designed for shared memory ([SharedMemory])
-///
-/// The actual [RateLimiter] is protected by a [SharedMutex] and
-/// implements [Init]. This way we can share the limiter between
-/// different processes.
-pub struct SharedRateLimiter {
-    shmem: SharedMemory<SharedRateLimiterData>,
-}
-
-impl SharedRateLimiter {
-    /// Creates a new mmap'ed instance.
-    ///
-    /// Data is mapped in `/var/run/proxmox-backup/shmem/tbf/<name>` using
-    /// `TMPFS`.
-    pub fn mmap_shmem(name: &str, rate: u64, burst: u64) -> Result<Self, Error> {
-        let mut path = PathBuf::from(BASE_PATH);
-
-        let user = pbs_config::backup_user()?;
-
-        let dir_opts = CreateOptions::new()
-            .perm(Mode::from_bits_truncate(0o770))
-            .owner(user.uid)
-            .group(user.gid);
-
-        create_path(&path, Some(dir_opts), Some(dir_opts))?;
-
-        path.push(name);
-
-        let file_opts = CreateOptions::new()
-            .perm(Mode::from_bits_truncate(0o660))
-            .owner(user.uid)
-            .group(user.gid);
-
-        let shmem: SharedMemory<SharedRateLimiterData> = SharedMemory::open(&path, file_opts)?;
-
-        shmem.data().tbf.lock().0.update_rate(rate, burst);
-
-        Ok(Self { shmem })
-    }
-}
-
-impl ShareableRateLimit for SharedRateLimiter {
-    fn update_rate(&self, rate: u64, bucket_size: u64) {
-        self.shmem
-            .data()
-            .tbf
-            .lock()
-            .0
-            .update_rate(rate, bucket_size);
-    }
-
-    fn traffic(&self) -> u64 {
-        self.shmem.data().tbf.lock().0.traffic()
-    }
-
-    fn register_traffic(&self, current_time: Instant, data_len: u64) -> Duration {
-        self.shmem
-            .data()
-            .tbf
-            .lock()
-            .0
-            .register_traffic(current_time, data_len)
-    }
-}
diff --git a/src/traffic_control_cache.rs b/src/traffic_control_cache.rs
index 830a8c043..bc52d37ee 100644
--- a/src/traffic_control_cache.rs
+++ b/src/traffic_control_cache.rs
@@ -8,7 +8,7 @@ use std::time::Instant;
 use anyhow::Error;
 use cidr::IpInet;
 
-use proxmox_http::{RateLimiter, ShareableRateLimit};
+use proxmox_rate_limiter::{RateLimiter, ShareableRateLimit, SharedRateLimiter};
 use proxmox_section_config::SectionConfigData;
 
 use proxmox_time::{parse_daily_duration, DailyDuration, TmEditor};
@@ -17,8 +17,6 @@ use pbs_api_types::TrafficControlRule;
 
 use pbs_config::ConfigVersionCache;
 
-use crate::tools::SharedRateLimiter;
-
 pub type SharedRateLimit = Arc<dyn ShareableRateLimit>;
 
 /// Shared traffic control cache singleton.
@@ -110,7 +108,9 @@ fn create_limiter(
     burst: u64,
 ) -> Result<SharedRateLimit, Error> {
     if use_shared_memory {
-        let limiter = SharedRateLimiter::mmap_shmem(name, rate, burst)?;
+        let user = pbs_config::backup_user()?;
+        let base_path = pbs_buildcfg::rundir!("/shmem/tbf");
+        let limiter = SharedRateLimiter::mmap_shmem(name, rate, burst, user, base_path)?;
         Ok(Arc::new(limiter))
     } else {
         Ok(Arc::new(Mutex::new(RateLimiter::new(rate, burst))))
-- 
2.47.3



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


  parent reply	other threads:[~2025-11-12 11:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-12 11:53 [pbs-devel] [PATCH proxmox{, -backup} v3 0/9] shared rate limiter for s3 client instances Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox v3 1/5] rate-limiter: add crate for traffic rate limiter implementations Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox v3 2/5] rate-limiter: avoid division by zero in traffic updater Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox v3 3/5] http: drop factored out rate limiter implementation Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox v3 4/5] rest-server: optionally depend on factored out shared rate limiter Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox v3 5/5] s3-client: add shared rate limiter via https connector Christian Ebner
2025-11-12 11:53 ` Christian Ebner [this message]
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox-backup v3 2/4] api: config: update s3 endpoint rate limits in config Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox-backup v3 3/4] datastore: s3: set rate limiter options for s3 client Christian Ebner
2025-11-12 11:53 ` [pbs-devel] [PATCH proxmox-backup v3 4/4] ui: expose rate and burst limits for s3 endpoints Christian Ebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251112115353.277514-7-c.ebner@proxmox.com \
    --to=c.ebner@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal