On Sat, Sep 20, 2025 at 04:29:55PM +0200, Paolo Bonzini wrote:
> Date: Sat, 20 Sep 2025 16:29:55 +0200
> From: Paolo Bonzini <[email protected]>
> Subject: [PATCH 4/7] rust: migration: add high-level migration wrappers
> X-Mailer: git-send-email 2.51.0
> 
> Instead of dealing with pre/post callbacks, allow devices to
> implement a snapshot/restore mechanism; this has two main
> advantages:
> 
> - it can be easily implemented via procedural macros
> 
> - there can be generic implementations to deal with various
>   kinds of interior-mutable containers, from BqlRefCell to Mutex,
>   so that C code does not see Rust concepts such as Mutex<>.
> 
> Using it is easy; you can implement the snapshot/restore trait
> ToMigrationState and declare your state like:
> 
>      regs: Migratable<Mutex<MyDeviceRegisters>>
> 
> Migratable<> allows dereferencing to the underlying object with
> no run-time cost.
> 
> Note that Migratable<> actually does not accept ToMigrationState,
> only the similar ToMigrationStateShared trait that the user will mostly
> not care about.  This is required by the fact that pre/post callbacks
> take a &self, and ensures that the argument is a Mutex or BqlRefCell
> (including an array or Arc<> thereof).
> 
> Signed-off-by: Paolo Bonzini <[email protected]>
> ---
>  rust/Cargo.lock                  |   1 +
>  rust/migration/Cargo.toml        |   1 +
>  rust/migration/meson.build       |   1 +
>  rust/migration/src/lib.rs        |   3 +
>  rust/migration/src/migratable.rs | 430 +++++++++++++++++++++++++++++++
>  5 files changed, 436 insertions(+)
>  create mode 100644 rust/migration/src/migratable.rs

The entire wrapper is quite nice. So,

Reviewed-by: Zhao Liu <[email protected]>


Only a few comments for comments inline:

> +// Interior-mutable types only require ToMigrationState for the inner type!
> +

extra blank line.

> +impl<T: ToMigrationState> ToMigrationState for Mutex<T> {
> +    type Migrated = T::Migrated;
> +
> +    fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> 
> Result<(), InvalidError> {
> +        self.lock().unwrap().snapshot_migration_state(target)
> +    }

Or maybe your previous sentence is worth commenting on here:

// For non-BQL-protected device we cannot know that another
// thread isn't taking the lock. So, always acquire the lock.

> +    fn restore_migrated_state_mut(
> +        &mut self,
> +        source: Self::Migrated,
> +        version_id: u8,
> +    ) -> Result<(), InvalidError> {
> +        self.restore_migrated_state(source, version_id)
> +    }
> +}
> +
> +impl<T: ToMigrationState> ToMigrationStateShared for Mutex<T> {
> +    fn restore_migrated_state(
> +        &self,
> +        source: Self::Migrated,
> +        version_id: u8,
> +    ) -> Result<(), InvalidError> {
> +        self.lock()
> +            .unwrap()
> +            .restore_migrated_state_mut(source, version_id)
> +    }
> +}
> +


Reply via email to