public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Kefu Chai <k.chai@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Kefu Chai <tchaikov@gmail.com>
Subject: [PATCH pve-cluster v3 01/13] pmxcfs-rs: add pmxcfs-api-types crate
Date: Mon, 23 Mar 2026 19:32:16 +0800	[thread overview]
Message-ID: <20260323113239.942866-2-k.chai@proxmox.com> (raw)
In-Reply-To: <20260323113239.942866-1-k.chai@proxmox.com>

Add pmxcfs-api-types crate which provides foundational shared types:
- PmxcfsError: Error type for startup/configuration errors
  (System and Configuration variants only)
- errno module: io::Error constructors (enoent, eexist, eacces, etc.)
- VmType: VM type enum (Qemu, Lxc)
- VmEntry: VM registry entry (vm_id, vm_type, node, version)
- MemberInfo: Corosync cluster member information
- NodeSyncInfo: Per-node DFSM state snapshot for cluster sync

Also adds workspace root files: Cargo.toml, Makefile, .gitignore,
rustfmt.toml.

All other crates depend on these shared type definitions.

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
---
 src/pmxcfs-rs/.cargo/config.toml            |  8 ++
 src/pmxcfs-rs/.gitignore                    |  2 +
 src/pmxcfs-rs/Cargo.toml                    | 39 +++++++++
 src/pmxcfs-rs/Makefile                      | 39 +++++++++
 src/pmxcfs-rs/pmxcfs-api-types/Cargo.toml   | 19 ++++
 src/pmxcfs-rs/pmxcfs-api-types/README.md    | 17 ++++
 src/pmxcfs-rs/pmxcfs-api-types/src/errno.rs | 75 ++++++++++++++++
 src/pmxcfs-rs/pmxcfs-api-types/src/error.rs | 15 ++++
 src/pmxcfs-rs/pmxcfs-api-types/src/lib.rs   | 97 +++++++++++++++++++++
 src/pmxcfs-rs/rustfmt.toml                  |  1 +
 10 files changed, 312 insertions(+)
 create mode 100644 src/pmxcfs-rs/.cargo/config.toml
 create mode 100644 src/pmxcfs-rs/.gitignore
 create mode 100644 src/pmxcfs-rs/Cargo.toml
 create mode 100644 src/pmxcfs-rs/Makefile
 create mode 100644 src/pmxcfs-rs/pmxcfs-api-types/Cargo.toml
 create mode 100644 src/pmxcfs-rs/pmxcfs-api-types/README.md
 create mode 100644 src/pmxcfs-rs/pmxcfs-api-types/src/errno.rs
 create mode 100644 src/pmxcfs-rs/pmxcfs-api-types/src/error.rs
 create mode 100644 src/pmxcfs-rs/pmxcfs-api-types/src/lib.rs
 create mode 100644 src/pmxcfs-rs/rustfmt.toml

diff --git a/src/pmxcfs-rs/.cargo/config.toml b/src/pmxcfs-rs/.cargo/config.toml
new file mode 100644
index 000000000..a439c97b2
--- /dev/null
+++ b/src/pmxcfs-rs/.cargo/config.toml
@@ -0,0 +1,8 @@
+[source]
+[source.debian-packages]
+directory = "/usr/share/cargo/registry"
+[source.crates-io]
+replace-with = "debian-packages"
+
+[profile.release]
+debug=true
diff --git a/src/pmxcfs-rs/.gitignore b/src/pmxcfs-rs/.gitignore
new file mode 100644
index 000000000..1e7caa9ea
--- /dev/null
+++ b/src/pmxcfs-rs/.gitignore
@@ -0,0 +1,2 @@
+Cargo.lock
+target/
diff --git a/src/pmxcfs-rs/Cargo.toml b/src/pmxcfs-rs/Cargo.toml
new file mode 100644
index 000000000..da2b9440a
--- /dev/null
+++ b/src/pmxcfs-rs/Cargo.toml
@@ -0,0 +1,39 @@
+# Workspace root for pmxcfs Rust implementation
+[workspace]
+members = [
+    "pmxcfs-api-types",  # Shared types and error definitions
+]
+resolver = "2"
+
+[workspace.package]
+version = "9.0.6"
+edition = "2024"
+authors = ["Proxmox Support Team <support@proxmox.com>"]
+license = "AGPL-3.0"
+repository = "https://git.proxmox.com/?p=pve-cluster.git"
+rust-version = "1.85"
+
+[workspace.dependencies]
+# Internal workspace dependencies
+pmxcfs-api-types = { path = "pmxcfs-api-types" }
+
+# Error handling
+thiserror = "2.0"
+
+# System integration
+libc = "0.2"
+
+[workspace.lints.clippy]
+uninlined_format_args = "warn"
+
+[profile.release]
+lto = true
+codegen-units = 1
+opt-level = 3
+strip = true
+
+[profile.dev]
+opt-level = 1
+debug = true
+
+[patch.crates-io]
diff --git a/src/pmxcfs-rs/Makefile b/src/pmxcfs-rs/Makefile
new file mode 100644
index 000000000..eaa96317f
--- /dev/null
+++ b/src/pmxcfs-rs/Makefile
@@ -0,0 +1,39 @@
+.PHONY: all test lint clippy fmt check build clean help
+
+# Default target
+all: check build
+
+# Run all tests
+test:
+	cargo test --workspace
+
+# Lint with clippy (using proxmox-backup style: only fail on correctness issues)
+clippy:
+	cargo clippy --workspace -- -A clippy::all -D clippy::correctness
+
+# Check code formatting
+fmt:
+	cargo fmt --all --check
+
+# Full quality check (format + lint + test)
+check: fmt clippy test
+
+# Build release version
+build:
+	cargo build --workspace --release
+
+# Clean build artifacts
+clean:
+	cargo clean
+
+# Show available targets
+help:
+	@echo "Available targets:"
+	@echo "  all      - Run check and build (default)"
+	@echo "  test     - Run all tests"
+	@echo "  clippy   - Run clippy linter"
+	@echo "  fmt      - Check code formatting"
+	@echo "  check    - Run fmt + clippy + test"
+	@echo "  build    - Build release version"
+	@echo "  clean    - Clean build artifacts"
+	@echo "  help     - Show this help message"
diff --git a/src/pmxcfs-rs/pmxcfs-api-types/Cargo.toml b/src/pmxcfs-rs/pmxcfs-api-types/Cargo.toml
new file mode 100644
index 000000000..cdce7951a
--- /dev/null
+++ b/src/pmxcfs-rs/pmxcfs-api-types/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "pmxcfs-api-types"
+description = "Shared types and error definitions for pmxcfs"
+
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
+# Error handling
+thiserror.workspace = true
+
+# System integration
+libc.workspace = true
diff --git a/src/pmxcfs-rs/pmxcfs-api-types/README.md b/src/pmxcfs-rs/pmxcfs-api-types/README.md
new file mode 100644
index 000000000..d89902c22
--- /dev/null
+++ b/src/pmxcfs-rs/pmxcfs-api-types/README.md
@@ -0,0 +1,17 @@
+# pmxcfs-api-types
+
+This crate provides shared types used across all pmxcfs crates. Having
+them in a dedicated crate with no internal dependencies avoids circular
+dependencies between the higher-level crates.
+
+`VmType` does not include OpenVZ (historically `VMTYPE_OPENVZ = 2` in
+the C implementation); it was dropped in PVE 4.0 in favour of LXC.
+
+`PmxcfsError` covers startup and configuration errors only. FUSE-layer
+errno values are expressed as `std::io::Error` using the helpers in the
+`errno` submodule.
+
+## References
+
+- [`src/pmxcfs/status.h`](../pmxcfs/status.h) — `VMTYPE_*` constants, `CFS_MAX_STATUS_SIZE`
+- [`src/pmxcfs/dfsm.h`](../pmxcfs/dfsm.h) — `dfsm_node_info_t` (maps to `NodeSyncInfo`)
diff --git a/src/pmxcfs-rs/pmxcfs-api-types/src/errno.rs b/src/pmxcfs-rs/pmxcfs-api-types/src/errno.rs
new file mode 100644
index 000000000..7e735c111
--- /dev/null
+++ b/src/pmxcfs-rs/pmxcfs-api-types/src/errno.rs
@@ -0,0 +1,75 @@
+//! Convenience constructors for POSIX errno values as io::Error.
+//!
+//! Replaces the repeated `std::io::Error::from_raw_os_error(libc::ENOENT).into()`
+//! pattern in operational methods throughout the workspace.
+use std::io;
+
+/// ENOENT — No such file or directory
+#[must_use]
+#[inline]
+pub fn enoent() -> io::Error {
+    io::Error::from_raw_os_error(libc::ENOENT)
+}
+
+/// EEXIST — File already exists
+#[must_use]
+#[inline]
+pub fn eexist() -> io::Error {
+    io::Error::from_raw_os_error(libc::EEXIST)
+}
+
+/// EACCES — Permission denied
+#[must_use]
+#[inline]
+pub fn eacces() -> io::Error {
+    io::Error::from_raw_os_error(libc::EACCES)
+}
+
+/// ENOTEMPTY — Directory not empty
+#[must_use]
+#[inline]
+pub fn enotempty() -> io::Error {
+    io::Error::from_raw_os_error(libc::ENOTEMPTY)
+}
+
+/// EIO — Input/output error
+#[must_use]
+#[inline]
+pub fn eio() -> io::Error {
+    io::Error::from_raw_os_error(libc::EIO)
+}
+
+/// EISDIR — Is a directory
+#[must_use]
+#[inline]
+pub fn eisdir() -> io::Error {
+    io::Error::from_raw_os_error(libc::EISDIR)
+}
+
+/// EINVAL — Invalid argument
+#[must_use]
+#[inline]
+pub fn einval() -> io::Error {
+    io::Error::from_raw_os_error(libc::EINVAL)
+}
+
+/// EPERM — Operation not permitted
+#[must_use]
+#[inline]
+pub fn eperm() -> io::Error {
+    io::Error::from_raw_os_error(libc::EPERM)
+}
+
+/// EFBIG — File too large
+#[must_use]
+#[inline]
+pub fn efbig() -> io::Error {
+    io::Error::from_raw_os_error(libc::EFBIG)
+}
+
+/// Arbitrary errno value
+#[must_use]
+#[inline]
+pub fn os_err(errno: libc::c_int) -> io::Error {
+    io::Error::from_raw_os_error(errno)
+}
diff --git a/src/pmxcfs-rs/pmxcfs-api-types/src/error.rs b/src/pmxcfs-rs/pmxcfs-api-types/src/error.rs
new file mode 100644
index 000000000..1d3ec01f1
--- /dev/null
+++ b/src/pmxcfs-rs/pmxcfs-api-types/src/error.rs
@@ -0,0 +1,15 @@
+use thiserror::Error;
+
+/// Error types for pmxcfs operations
+///
+/// Only variants that are actively used in the codebase are defined here.
+/// Operational/FUSE errors use `std::io::Error` with errno helpers from
+/// `pmxcfs_api_types::errno` instead.
+#[derive(Error, Debug)]
+pub enum PmxcfsError {
+    #[error("Configuration error: {0}")]
+    Configuration(String),
+
+    #[error("System error: {0}")]
+    System(String),
+}
diff --git a/src/pmxcfs-rs/pmxcfs-api-types/src/lib.rs b/src/pmxcfs-rs/pmxcfs-api-types/src/lib.rs
new file mode 100644
index 000000000..76c2cea84
--- /dev/null
+++ b/src/pmxcfs-rs/pmxcfs-api-types/src/lib.rs
@@ -0,0 +1,97 @@
+mod error;
+
+pub mod errno;
+
+pub use error::PmxcfsError;
+
+/// Current unix timestamp in seconds, truncated to u32 to match C's `time_t` usage.
+pub fn unix_now_secs() -> u32 {
+    std::time::SystemTime::now()
+        .duration_since(std::time::UNIX_EPOCH)
+        .unwrap_or_default()
+        .as_secs() as u32
+}
+
+/// Maximum size for status data (matches C implementation)
+/// From status.h: #define CFS_MAX_STATUS_SIZE (32 * 1024)
+pub const CFS_MAX_STATUS_SIZE: usize = 32 * 1024;
+
+/// VM/CT types
+///
+/// Note: OpenVZ was historically supported (VMTYPE_OPENVZ = 2 in C implementation)
+/// but was removed in PVE 4.0 in favor of LXC. Only QEMU and LXC are currently supported.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum VmType {
+    Qemu,
+    Lxc,
+}
+
+impl VmType {
+    /// Returns the directory name where config files are stored
+    #[must_use]
+    #[inline]
+    pub fn config_dir(&self) -> &'static str {
+        match self {
+            Self::Qemu => "qemu-server",
+            Self::Lxc => "lxc",
+        }
+    }
+}
+
+impl std::fmt::Display for VmType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Qemu => write!(f, "qemu"),
+            Self::Lxc => write!(f, "lxc"),
+        }
+    }
+}
+
+impl TryFrom<u32> for VmType {
+    type Error = std::io::Error;
+
+    fn try_from(value: u32) -> std::io::Result<Self> {
+        match value {
+            1 => Ok(VmType::Qemu),
+            3 => Ok(VmType::Lxc),
+            _ => Err(std::io::Error::other(format!("unknown VM type: {value}"))),
+        }
+    }
+}
+
+/// VM/CT entry for vmlist
+#[derive(Debug, Clone)]
+pub struct VmEntry {
+    pub vm_id: u32,
+    pub vm_type: VmType,
+    pub node: String,
+    /// Per-VM version counter (increments when this VM's config changes)
+    pub version: u32,
+}
+
+/// Information about a cluster member
+///
+/// This is a shared type used by both cluster and DFSM modules
+#[derive(Debug, Clone)]
+pub struct MemberInfo {
+    pub node_id: u32,
+    pub pid: u32,
+    pub joined_at: u64,
+}
+
+/// Node synchronization info for DFSM state sync
+///
+/// Used during DFSM synchronization to track which nodes have provided state
+/// and whether synchronization has completed for that node.
+#[derive(Debug, Clone)]
+pub struct NodeSyncInfo {
+    pub node_id: u32,
+    pub pid: u32,
+    /// Serialized DFSM state snapshot for this node, exchanged during cluster synchronization.
+    /// Variable-size; `None` until this node's state has been received.
+    /// Maps to C's `dfsm_node_info_t.state + state_len` in `dfsm.h`.
+    pub state: Option<Vec<u8>>,
+    /// Whether this node has been marked as synchronized.
+    /// Set by the DFSM after `process_state_update` confirms the node is up to date.
+    pub synced: bool,
+}
diff --git a/src/pmxcfs-rs/rustfmt.toml b/src/pmxcfs-rs/rustfmt.toml
new file mode 100644
index 000000000..f216078d9
--- /dev/null
+++ b/src/pmxcfs-rs/rustfmt.toml
@@ -0,0 +1 @@
+edition = "2024"
-- 
2.47.3





  reply	other threads:[~2026-03-23 11:32 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-23 11:32 [PATCH pve-cluster v3 00/13] Rewrite pmxcfs with Rust Kefu Chai
2026-03-23 11:32 ` Kefu Chai [this message]
2026-03-23 11:32 ` [PATCH pve-cluster v3 02/13] pmxcfs-rs: add pmxcfs-config crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 03/13] pmxcfs-rs: add pmxcfs-logger crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 04/13] pmxcfs-rs: add pmxcfs-rrd crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 05/13] pmxcfs-rs: add pmxcfs-memdb crate Kefu Chai
2026-03-23 11:32 ` SPAM: [PATCH pve-cluster v3 06/13] pmxcfs-rs: add pmxcfs-status and pmxcfs-test-utils crates Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 07/13] pmxcfs-rs: add pmxcfs-services crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 08/13] pmxcfs-rs: add pmxcfs-ipc crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 09/13] pmxcfs-rs: add pmxcfs-dfsm crate Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 10/13] pmxcfs-rs: vendor patched rust-corosync for CPG compatibility Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 11/13] pmxcfs-rs: add pmxcfs main daemon binary Kefu Chai
2026-03-23 11:32 ` [PATCH pve-cluster v3 13/13] pmxcfs-rs: add project documentation Kefu Chai

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=20260323113239.942866-2-k.chai@proxmox.com \
    --to=k.chai@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    --cc=tchaikov@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal