All of lore.kernel.org
 help / color / mirror / Atom feed
From: marcandre.lureau@redhat.com
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com,
	stefanha@redhat.com,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [RFC v3 29/32] qga/rust: implement {get,set}-vcpus in Rust (example)
Date: Tue,  7 Sep 2021 16:19:40 +0400	[thread overview]
Message-ID: <20210907121943.3498701-30-marcandre.lureau@redhat.com> (raw)
In-Reply-To: <20210907121943.3498701-1-marcandre.lureau@redhat.com>

From: Marc-André Lureau <marcandre.lureau@redhat.com>

This is a rewrite of the C version (using the nix & winapi crates).

The main difference is that Rust doesn't let you mix const/mut logic,
the way transfer_vcpu in C does. The Rust version does introduce some
duplication, but is also more strict and can prevent mistakes.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qga/commands-posix.c  | 152 ---------------------------------------
 qga/commands-win32.c  |  71 -------------------
 qga/commands.c        |  14 ++++
 tests/unit/test-qga.c |   2 +
 Cargo.lock            |   2 +
 qga/Cargo.toml        |   6 ++
 qga/qmp/mod.rs        |  20 +++++-
 qga/qmp/vcpus.rs      | 161 ++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 204 insertions(+), 224 deletions(-)
 create mode 100644 qga/qmp/vcpus.rs

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 75dbaab68e..97ca70e762 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2371,146 +2371,6 @@ error:
     return NULL;
 }
 
-/* Transfer online/offline status between @vcpu and the guest system.
- *
- * On input either @errp or *@errp must be NULL.
- *
- * In system-to-@vcpu direction, the following @vcpu fields are accessed:
- * - R: vcpu->logical_id
- * - W: vcpu->online
- * - W: vcpu->can_offline
- *
- * In @vcpu-to-system direction, the following @vcpu fields are accessed:
- * - R: vcpu->logical_id
- * - R: vcpu->online
- *
- * Written members remain unmodified on error.
- */
-static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
-                          char *dirpath, Error **errp)
-{
-    int fd;
-    int res;
-    int dirfd;
-    static const char fn[] = "online";
-
-    dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
-    if (dirfd == -1) {
-        error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
-        return;
-    }
-
-    fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
-    if (fd == -1) {
-        if (errno != ENOENT) {
-            error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
-        } else if (sys2vcpu) {
-            vcpu->online = true;
-            vcpu->can_offline = false;
-        } else if (!vcpu->online) {
-            error_setg(errp, "logical processor #%" PRId64 " can't be "
-                       "offlined", vcpu->logical_id);
-        } /* otherwise pretend successful re-onlining */
-    } else {
-        unsigned char status;
-
-        res = pread(fd, &status, 1, 0);
-        if (res == -1) {
-            error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
-        } else if (res == 0) {
-            error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
-                       fn);
-        } else if (sys2vcpu) {
-            vcpu->online = (status != '0');
-            vcpu->can_offline = true;
-        } else if (vcpu->online != (status != '0')) {
-            status = '0' + vcpu->online;
-            if (pwrite(fd, &status, 1, 0) == -1) {
-                error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
-                                 fn);
-            }
-        } /* otherwise pretend successful re-(on|off)-lining */
-
-        res = close(fd);
-        g_assert(res == 0);
-    }
-
-    res = close(dirfd);
-    g_assert(res == 0);
-}
-
-GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
-{
-    GuestLogicalProcessorList *head, **tail;
-    const char *cpu_dir = "/sys/devices/system/cpu";
-    const gchar *line;
-    g_autoptr(GDir) cpu_gdir = NULL;
-    Error *local_err = NULL;
-
-    head = NULL;
-    tail = &head;
-    cpu_gdir = g_dir_open(cpu_dir, 0, NULL);
-
-    if (cpu_gdir == NULL) {
-        error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir);
-        return NULL;
-    }
-
-    while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) {
-        GuestLogicalProcessor *vcpu;
-        int64_t id;
-        if (sscanf(line, "cpu%" PRId64, &id)) {
-            g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/"
-                                                    "cpu%" PRId64 "/", id);
-            vcpu = g_malloc0(sizeof *vcpu);
-            vcpu->logical_id = id;
-            vcpu->has_can_offline = true; /* lolspeak ftw */
-            transfer_vcpu(vcpu, true, path, &local_err);
-            QAPI_LIST_APPEND(tail, vcpu);
-        }
-    }
-
-    if (local_err == NULL) {
-        /* there's no guest with zero VCPUs */
-        g_assert(head != NULL);
-        return head;
-    }
-
-    qapi_free_GuestLogicalProcessorList(head);
-    error_propagate(errp, local_err);
-    return NULL;
-}
-
-int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
-{
-    int64_t processed;
-    Error *local_err = NULL;
-
-    processed = 0;
-    while (vcpus != NULL) {
-        char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
-                                     vcpus->value->logical_id);
-
-        transfer_vcpu(vcpus->value, false, path, &local_err);
-        g_free(path);
-        if (local_err != NULL) {
-            break;
-        }
-        ++processed;
-        vcpus = vcpus->next;
-    }
-
-    if (local_err != NULL) {
-        if (processed == 0) {
-            error_propagate(errp, local_err);
-        } else {
-            error_free(local_err);
-        }
-    }
-
-    return processed;
-}
-
 void qmp_guest_set_user_password(const char *username,
                                  const char *password,
                                  bool crypted,
@@ -2946,18 +2806,6 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
     return NULL;
 }
 
-GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
-
-int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return -1;
-}
-
 void qmp_guest_set_user_password(const char *username,
                                  const char *password,
                                  bool crypted,
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 4e84afd83b..33a3fd7218 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -1816,77 +1816,6 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
     }
 }
 
-GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
-{
-    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pslpi, ptr;
-    DWORD length;
-    GuestLogicalProcessorList *head, **tail;
-    Error *local_err = NULL;
-    int64_t current;
-
-    ptr = pslpi = NULL;
-    length = 0;
-    current = 0;
-    head = NULL;
-    tail = &head;
-
-    if ((GetLogicalProcessorInformation(pslpi, &length) == FALSE) &&
-        (GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
-        (length > sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION))) {
-        ptr = pslpi = g_malloc0(length);
-        if (GetLogicalProcessorInformation(pslpi, &length) == FALSE) {
-            error_setg(&local_err, "Failed to get processor information: %d",
-                       (int)GetLastError());
-        }
-    } else {
-        error_setg(&local_err,
-                   "Failed to get processor information buffer length: %d",
-                   (int)GetLastError());
-    }
-
-    while ((local_err == NULL) && (length > 0)) {
-        if (pslpi->Relationship == RelationProcessorCore) {
-            ULONG_PTR cpu_bits = pslpi->ProcessorMask;
-
-            while (cpu_bits > 0) {
-                if (!!(cpu_bits & 1)) {
-                    GuestLogicalProcessor *vcpu;
-
-                    vcpu = g_malloc0(sizeof *vcpu);
-                    vcpu->logical_id = current++;
-                    vcpu->online = true;
-                    vcpu->has_can_offline = true;
-
-                    QAPI_LIST_APPEND(tail, vcpu);
-                }
-                cpu_bits >>= 1;
-            }
-        }
-        length -= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
-        pslpi++; /* next entry */
-    }
-
-    g_free(ptr);
-
-    if (local_err == NULL) {
-        if (head != NULL) {
-            return head;
-        }
-        /* there's no guest with zero VCPUs */
-        error_setg(&local_err, "Guest reported zero VCPUs");
-    }
-
-    qapi_free_GuestLogicalProcessorList(head);
-    error_propagate(errp, local_err);
-    return NULL;
-}
-
-int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return -1;
-}
-
 static gchar *
 get_net_error_message(gint error)
 {
diff --git a/qga/commands.c b/qga/commands.c
index 117c219ac4..d5ad904480 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -573,3 +573,17 @@ GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
 
     return read_data;
 }
+
+#ifndef CONFIG_WITH_RUST
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+    error_setg(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
+{
+    error_setg(errp, QERR_UNSUPPORTED);
+    return 0;
+}
+#endif
diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c
index a22ab8c82c..47fd8eb717 100644
--- a/tests/unit/test-qga.c
+++ b/tests/unit/test-qga.c
@@ -308,6 +308,7 @@ static void test_qga_info(gconstpointer fix)
 
 static void test_qga_get_vcpus(gconstpointer fix)
 {
+#ifdef CONFIG_WITH_RUST
     const TestFixture *fixture = fix;
     QDict *ret;
     QList *list;
@@ -324,6 +325,7 @@ static void test_qga_get_vcpus(gconstpointer fix)
     g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id"));
 
     qobject_unref(ret);
+#endif
 }
 
 static void test_qga_get_fsinfo(gconstpointer fix)
diff --git a/Cargo.lock b/Cargo.lock
index 8752dbf2ac..f3d2631865 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -92,6 +92,8 @@ version = "0.1.0"
 dependencies = [
  "common",
  "hostname",
+ "nix",
+ "winapi",
 ]
 
 [[package]]
diff --git a/qga/Cargo.toml b/qga/Cargo.toml
index 387af59a30..0661b8b7c6 100644
--- a/qga/Cargo.toml
+++ b/qga/Cargo.toml
@@ -8,6 +8,12 @@ publish = false
 common = { path = "../rust/common" }
 hostname = "0.3.1"
 
+[target."cfg(unix)".dependencies]
+nix = "0.20.0"
+
+[target."cfg(windows)".dependencies]
+winapi = { version = "0.3.9", features = ["sysinfoapi", "winnt"] }
+
 [lib]
 path = "lib.rs"
 crate-type = ["staticlib"]
diff --git a/qga/qmp/mod.rs b/qga/qmp/mod.rs
index c192e4247d..5b4f17a07d 100644
--- a/qga/qmp/mod.rs
+++ b/qga/qmp/mod.rs
@@ -1,6 +1,6 @@
 use common::*;
 
-use crate::qapi_ffi;
+use crate::{qapi::NewPtr, qapi_ffi};
 
 mod hostname;
 
@@ -8,3 +8,21 @@ mod hostname;
 extern "C" fn qmp_guest_get_host_name(errp: *mut *mut ffi::Error) -> *mut qapi_ffi::GuestHostName {
     qmp!(hostname::get(), errp)
 }
+
+mod vcpus;
+
+#[no_mangle]
+extern "C" fn qmp_guest_get_vcpus(
+    errp: *mut *mut ffi::Error,
+) -> *mut qapi_ffi::GuestLogicalProcessorList {
+    qmp!(vcpus::get(), errp)
+}
+
+#[no_mangle]
+extern "C" fn qmp_guest_set_vcpus(
+    vcpus: *const qapi_ffi::GuestLogicalProcessorList,
+    errp: *mut *mut ffi::Error,
+) -> libc::c_longlong {
+    let vcpus = unsafe { from_qemu_none(NewPtr(vcpus)) };
+    qmp!(vcpus::set(vcpus), errp, -1)
+}
diff --git a/qga/qmp/vcpus.rs b/qga/qmp/vcpus.rs
new file mode 100644
index 0000000000..f86838355e
--- /dev/null
+++ b/qga/qmp/vcpus.rs
@@ -0,0 +1,161 @@
+#[cfg(unix)]
+use std::fs::OpenOptions;
+#[cfg(unix)]
+use std::io::ErrorKind;
+#[cfg(unix)]
+use std::os::unix::fs::FileExt;
+
+#[cfg(windows)]
+use winapi::um::{sysinfoapi, winnt};
+
+use crate::*;
+
+#[cfg(target_os = "linux")]
+fn get_sysfs_cpu_path(id: i64) -> String {
+    format!("/sys/devices/system/cpu/cpu{}", id)
+}
+
+#[cfg(target_os = "linux")]
+fn set_vcpu(vcpu: &qapi::GuestLogicalProcessor) -> Result<()> {
+    let path = get_sysfs_cpu_path(vcpu.logical_id);
+    std::fs::metadata(&path)?;
+
+    let path = format!("{}/online", path);
+    match OpenOptions::new().read(true).write(true).open(&path) {
+        Ok(file) => {
+            let mut buf = [0u8; 1];
+            file.read_exact_at(&mut buf, 0)?;
+            let online = buf[0] != 0;
+            if vcpu.online != online {
+                buf[0] = if vcpu.online { b'1' } else { b'0' };
+                file.write_all_at(&buf, 0)?;
+            }
+        }
+        Err(e) => {
+            if e.kind() != ErrorKind::NotFound {
+                return Err(e.into());
+            } else if !vcpu.online {
+                return err!(format!(
+                    "logical processor #{} can't be offlined",
+                    vcpu.logical_id
+                ));
+            }
+        }
+    }
+
+    Ok(())
+}
+
+#[cfg(not(target_os = "linux"))]
+fn set_vcpu(_vcpu: &qapi::GuestLogicalProcessor) -> Result<()> {
+    err!("unimplemented")
+}
+
+pub(crate) fn set(vcpus: Vec<qapi::GuestLogicalProcessor>) -> Result<i64> {
+    let mut processed = 0;
+
+    for vcpu in &vcpus {
+        if let Err(e) = set_vcpu(vcpu) {
+            if processed != 0 {
+                break;
+            }
+            return Err(e);
+        }
+
+        processed += 1;
+    }
+
+    Ok(processed)
+}
+
+#[cfg(target_os = "linux")]
+pub(crate) fn get() -> Result<Vec<qapi::GuestLogicalProcessor>> {
+    use nix::unistd::sysconf;
+
+    let mut vcpus = vec![];
+    let nproc_conf = match sysconf(unsafe { std::mem::transmute(libc::_SC_NPROCESSORS_CONF) })? {
+        Some(nproc) => nproc,
+        None => {
+            return err!("Indefinite number of processors.");
+        }
+    };
+
+    for logical_id in 0..nproc_conf {
+        let path = get_sysfs_cpu_path(logical_id);
+        if std::fs::metadata(&path).is_err() {
+            continue;
+        }
+
+        let path = format!("{}/online", path);
+        let (online, can_offline) = match OpenOptions::new().read(true).open(&path) {
+            Ok(file) => {
+                let mut buf = [0u8; 1];
+                file.read_exact_at(&mut buf, 0)?;
+                (buf[0] != 0, Some(true))
+            }
+            Err(e) => {
+                if e.kind() != ErrorKind::NotFound {
+                    return Err(e.into());
+                }
+                (true, Some(false))
+            }
+        };
+
+        vcpus.push(qapi::GuestLogicalProcessor {
+            logical_id,
+            online,
+            can_offline,
+        });
+    }
+
+    Ok(vcpus)
+}
+
+#[cfg(target_os = "windows")]
+fn get_logical_processor_info() -> Result<Vec<winnt::SYSTEM_LOGICAL_PROCESSOR_INFORMATION>> {
+    unsafe {
+        let mut needed_size = 0;
+        sysinfoapi::GetLogicalProcessorInformation(std::ptr::null_mut(), &mut needed_size);
+        let struct_size = std::mem::size_of::<winnt::SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;
+        if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
+            return err!("Failed to get processor information");
+        }
+
+        let nstruct = needed_size / struct_size;
+        let mut buf = Vec::with_capacity(nstruct as usize);
+        let result = sysinfoapi::GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
+        if result == 0 {
+            return err!("Failed to get processor information");
+        }
+
+        let nstruct = needed_size / struct_size;
+        buf.set_len(nstruct as usize);
+        Ok(buf)
+    }
+}
+
+#[cfg(target_os = "windows")]
+pub(crate) fn get() -> Result<Vec<qapi::GuestLogicalProcessor>> {
+    let mut vcpus = vec![];
+
+    get_logical_processor_info()?.iter().map(|info| {
+        for _ in 0..info.ProcessorMask.count_ones() {
+            vcpus.push(qapi::GuestLogicalProcessor {
+                logical_id: vcpus.len() as i64,
+                online: true,
+                can_offline: Some(false),
+            });
+        }
+    });
+
+    if vcpus.is_empty() {
+        return err!("Guest reported zero VCPUs");
+    }
+
+    Ok(vcpus)
+}
+
+#[cfg(not(any(target_os = "linux", target_os = "windows")))]
+pub(crate) fn get() -> Result<Vec<qapi::GuestLogicalProcessor>> {
+    err!("unimplemented")
+}
-- 
2.33.0.113.g6c40894d24



  parent reply	other threads:[~2021-09-07 12:53 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-07 12:19 [RFC v3 00/32] Rust binding for QAPI and qemu-ga QMP handler examples marcandre.lureau
2021-09-07 12:19 ` [RFC v3 01/32] RFC: docs: add supported host CPUs section marcandre.lureau
2021-09-07 12:33   ` Peter Maydell
2021-09-13 11:32     ` Marc-André Lureau
2021-09-13 11:46       ` Peter Maydell
2021-09-07 12:19 ` [RFC v3 02/32] build-sys: add HAVE_IPPROTO_MPTCP marcandre.lureau
2021-09-08 12:01   ` Markus Armbruster
2021-09-13 13:02   ` Paolo Bonzini
2021-09-07 12:19 ` [RFC v3 03/32] scripts/qapi: teach c_param_type() to return const argument type marcandre.lureau
2021-09-08 12:10   ` Markus Armbruster
2021-09-08 14:33     ` Marc-André Lureau
2021-09-07 12:19 ` [RFC v3 04/32] glib-compat: add G_SIZEOF_MEMBER marcandre.lureau
2021-09-08 12:16   ` Markus Armbruster
2021-09-08 13:49     ` Marc-André Lureau
2021-09-07 12:19 ` [RFC v3 05/32] scripts/qapi: add QAPISchemaVisitor.visit_module_end marcandre.lureau
2021-09-08 12:26   ` Markus Armbruster
2021-09-07 12:19 ` [RFC v3 06/32] scripts/qapi: add a CABI module marcandre.lureau
2021-09-07 12:19 ` [RFC v3 07/32] scripts/qapi: generate CABI dump for C types marcandre.lureau
2021-09-07 12:19 ` [RFC v3 08/32] tests: build qapi-cabi (C ABI dump) marcandre.lureau
2021-09-07 12:19 ` [RFC v3 09/32] build-sys: add i686 cpu target marcandre.lureau
2021-09-08 13:45   ` Peter Maydell
2021-09-07 12:19 ` [RFC v3 10/32] build-sys: add --with-rust{-target} & basic build infrastructure marcandre.lureau
2021-09-08 14:00   ` Peter Maydell
2021-09-08 14:21     ` Marc-André Lureau
2021-09-07 12:19 ` [RFC v3 11/32] build-sys: add a cargo-wrapper script marcandre.lureau
2021-09-07 12:19 ` [RFC v3 12/32] rust: provide a common crate for QEMU marcandre.lureau
2021-09-10  1:18   ` Alistair Francis
2021-09-10  7:43     ` Marc-André Lureau
2021-09-13 17:11   ` Paolo Bonzini
2021-09-14 11:34     ` Marc-André Lureau
2021-09-07 12:19 ` [RFC v3 13/32] rust: use vendored-sources marcandre.lureau
2021-09-08 15:38   ` Ian Jackson
2021-09-08 15:47     ` Marc-André Lureau
2021-09-08 15:55       ` Ian Jackson
2021-09-08 16:15         ` Marc-André Lureau
2021-09-08 16:22           ` Peter Maydell
2021-09-08 16:22           ` Ian Jackson
2021-09-08 16:20     ` Marc-André Lureau
2021-09-08 16:29       ` Ian Jackson
2021-09-08 16:34         ` Marc-André Lureau
2021-09-08 16:50           ` Ian Jackson
2021-09-08 19:33             ` Marc-André Lureau
2021-09-09 16:02   ` Peter Maydell
2021-09-09 16:29     ` Marc-André Lureau
2021-09-09 16:53       ` Daniel P. Berrangé
2021-09-09 17:04         ` Ian Jackson
2021-09-13 14:21       ` Paolo Bonzini
2021-09-09 16:49     ` Daniel P. Berrangé
2021-09-09 17:02       ` Ian Jackson
2021-09-07 12:19 ` [RFC v3 14/32] scripts/qapi: add QAPISchemaIfCond.rsgen() marcandre.lureau
2021-09-08 12:33   ` Markus Armbruster
2021-09-08 14:06     ` Marc-André Lureau
2021-09-07 12:19 ` [RFC v3 15/32] scripts/qapi: strip trailing whitespaces marcandre.lureau
2021-09-07 12:19 ` [RFC v3 16/32] scripts/qapi: add Rust FFI bindings generation marcandre.lureau
2021-09-07 12:19 ` [RFC v3 17/32] scripts/qapi: learn to generate ABI dump for Rust FFI marcandre.lureau
2021-09-07 12:19 ` [RFC v3 18/32] tests: generate Rust bindings marcandre.lureau
2021-09-07 12:19 ` [RFC v3 19/32] tests: check Rust and C CABI diffs marcandre.lureau
2021-09-07 12:19 ` [RFC v3 20/32] scripts/qapi: generate high-level Rust bindings marcandre.lureau
2021-09-07 12:19 ` [RFC v3 21/32] tests/rust: build a common library, checking bindings compile marcandre.lureau
2021-09-07 12:19 ` [RFC v3 22/32] qga: build qapi-cabi binary (ABI from C) marcandre.lureau
2021-09-07 12:19 ` [RFC v3 23/32] qga/rust: build and link an empty static library marcandre.lureau
2021-09-07 12:19 ` [RFC v3 24/32] qga/rust: generate QGA QAPI types FFI bindings marcandre.lureau
2021-09-07 12:19 ` [RFC v3 25/32] qga/rust: build a qga-cabi-rs executable (ABI from Rust) marcandre.lureau
2021-09-07 12:19 ` [RFC v3 26/32] qga/rust: check the Rust C binding marcandre.lureau
2021-09-07 12:19 ` [RFC v3 27/32] qga/rust: build high-level Rust QAPI types marcandre.lureau
2021-09-07 12:19 ` [RFC v3 28/32] qga/rust: implement get-host-name in Rust (example) marcandre.lureau
2021-09-07 12:19 ` marcandre.lureau [this message]
2021-09-07 12:19 ` [RFC v3 30/32] tests/vm: add Rust to FreeBSD VM marcandre.lureau
2021-09-07 12:19 ` [RFC v3 31/32] tests/vm: bump fedora VM to f32 marcandre.lureau
2021-09-07 12:19 ` [RFC v3 32/32] tests/vm: add Rust to Fedora marcandre.lureau
2021-09-08 13:22 ` [RFC v3 00/32] Rust binding for QAPI and qemu-ga QMP handler examples Markus Armbruster
2021-09-08 13:55   ` Marc-André Lureau
2021-09-09 10:31     ` Markus Armbruster
2021-09-09 15:22       ` Marc-André Lureau

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=20210907121943.3498701-30-marcandre.lureau@redhat.com \
    --to=marcandre.lureau@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.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.