From: Stefan Reiter <s.reiter@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH proxmox-backup-qemu 3/4] add state serializing and loading functions
Date: Thu, 22 Oct 2020 17:34:19 +0200 [thread overview]
Message-ID: <20201022153420.16971-4-s.reiter@proxmox.com> (raw)
In-Reply-To: <20201022153420.16971-1-s.reiter@proxmox.com>
For dirty-bitmap migration, QEMU also needs to move the static state of
the library to the target. proxmox_{import,export}_state provide a means
of accessing said data in a serialized fashion.
QEMU treats the state as some unknown quantity of bytes and the result
does not need to be human-readable, so we encode it with 'bincode',
which is based on serde.
Since the quantity is only known *after* serialization, we have to
allocate the buffer ourselves. This is handled by Box::leak-ing a Rust
allocated buffer and cleaning up via the explicit
proxmox_free_state_buf function.
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
I'm not sure we use 'bincode' anywhere else, but it is packaged for debian
already and seemed like a good fit. Alternatively, we could of course use our
already existing dependency on serde_json and just serialize to a JSON string.
Cargo.toml | 1 +
current-api.h | 20 ++++++++++++++++++++
src/commands.rs | 19 +++++++++++++++++++
src/lib.rs | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 74 insertions(+)
diff --git a/Cargo.toml b/Cargo.toml
index d51ba93..ca93b36 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,3 +28,4 @@ proxmox-backup = { git = "git://git.proxmox.com/git/proxmox-backup.git", tag = "
#proxmox-backup = { path = "../proxmox-backup" }
serde_json = "1.0"
tokio = { version = "0.2.9", features = [ "blocking", "fs", "io-util", "macros", "rt-threaded", "signal", "stream", "tcp", "time", "uds" ] }
+bincode = "1.0"
diff --git a/current-api.h b/current-api.h
index d77eff6..77e8c4b 100644
--- a/current-api.h
+++ b/current-api.h
@@ -263,6 +263,26 @@ void proxmox_backup_write_data_async(ProxmoxBackupHandle *handle,
int *result,
char **error);
+/**
+ * Serialize all state data into a byte buffer. Can be loaded again with
+ * proxmox_import_state. Use for migration for example.
+ *
+ * Length of the returned buffer is written to buf_size. Returned buffer must
+ * be freed with proxmox_free_state_buf.
+ */
+uint8_t *proxmox_export_state(uintptr_t *buf_size);
+
+/**
+ * Free a buffer acquired from proxmox_export_state.
+ */
+void proxmox_free_state_buf(uint8_t *buf);
+
+/**
+ * Load state serialized by proxmox_export_state. If loading fails, a message
+ * will be logged to stderr, but the function will not fail.
+ */
+void proxmox_import_state(const uint8_t *buf, uintptr_t buf_size);
+
/**
* Open connection to the backup server (sync)
*
diff --git a/src/commands.rs b/src/commands.rs
index f7e0f62..7a24b7c 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -16,6 +16,9 @@ use crate::upload_queue::*;
use lazy_static::lazy_static;
lazy_static!{
+ // Note: Any state stored here that needs to be sent along with migration
+ // needs to be specified in (de)serialize_state as well!
+
static ref PREVIOUS_CSUMS: Mutex<HashMap<String, [u8;32]>> = {
Mutex::new(HashMap::new())
};
@@ -35,6 +38,22 @@ pub struct ImageUploadInfo {
}
+pub(crate) fn serialize_state() -> Vec<u8> {
+ let prev_csums = &*PREVIOUS_CSUMS.lock().unwrap();
+ let prev_crypt_digest = &*PREVIOUS_CRYPT_CONFIG_DIGEST.lock().unwrap();
+ bincode::serialize(&(prev_csums, prev_crypt_digest)).unwrap()
+}
+
+pub(crate) fn deserialize_state(data: &[u8]) -> Result<(), Error> {
+ let (prev_csums, prev_crypt_digest) = bincode::deserialize(data)?;
+ let mut prev_csums_guard = PREVIOUS_CSUMS.lock().unwrap();
+ let mut prev_crypt_digest_guard = PREVIOUS_CRYPT_CONFIG_DIGEST.lock().unwrap();
+ *prev_csums_guard = prev_csums;
+ *prev_crypt_digest_guard = prev_crypt_digest;
+ Ok(())
+}
+
+
// Note: We alway register/upload a chunk containing zeros
async fn register_zero_chunk(
client: Arc<BackupWriter>,
diff --git a/src/lib.rs b/src/lib.rs
index b9ca905..8511cbf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -967,3 +967,37 @@ pub extern "C" fn proxmox_restore_read_image_at_async(
callback_info.send_result(result);
});
}
+
+/// Serialize all state data into a byte buffer. Can be loaded again with
+/// proxmox_import_state. Use for migration for example.
+///
+/// Length of the returned buffer is written to buf_size. Returned buffer must
+/// be freed with proxmox_free_state_buf.
+#[no_mangle]
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn proxmox_export_state(buf_size: *mut usize) -> *mut u8 {
+ let data = commands::serialize_state().into_boxed_slice();
+ unsafe { *buf_size = data.len(); }
+ Box::leak(data).as_mut_ptr()
+}
+
+/// Load state serialized by proxmox_export_state. If loading fails, a message
+/// will be logged to stderr, but the function will not fail.
+#[no_mangle]
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn proxmox_import_state(buf: *const u8, buf_size: usize) {
+ let data = unsafe { std::slice::from_raw_parts(buf, buf_size) };
+ // ignore errors, just log what happened
+ if let Err(err) = commands::deserialize_state(data) {
+ eprintln!("error deserializing PBS state - {}", err);
+ }
+}
+
+/// Free a buffer acquired from proxmox_export_state.
+#[no_mangle]
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn proxmox_free_state_buf(buf: *mut u8) {
+ if !buf.is_null() {
+ unsafe { Box::from_raw(buf); }
+ }
+}
--
2.20.1
next prev parent reply other threads:[~2020-10-22 15:35 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-22 15:34 [pve-devel] [PATCH 0/4] Keep dirty-bitmaps for PBS during migration Stefan Reiter
2020-10-22 15:34 ` [pve-devel] [PATCH qemu 1/4] migration/block-dirty-bitmap: fix larger granularity bitmaps Stefan Reiter
2020-10-22 15:34 ` [pve-devel] [PATCH qemu 2/4] PVE: Migrate dirty bitmap state via savevm Stefan Reiter
2020-10-22 15:34 ` Stefan Reiter [this message]
2020-10-28 21:51 ` [pve-devel] applied: [PATCH proxmox-backup-qemu 3/4] add state serializing and loading functions Thomas Lamprecht
2020-10-22 15:34 ` [pve-devel] [PATCH qemu-server 4/4] migrate: enable dirty-bitmap migration Stefan Reiter
2020-10-29 18:13 ` [pve-devel] applied-series: [PATCH 0/4] Keep dirty-bitmaps for PBS during migration Thomas Lamprecht
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=20201022153420.16971-4-s.reiter@proxmox.com \
--to=s.reiter@proxmox.com \
--cc=pve-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.